Предисловие
Уже давно назрела необходимость в удалённой отладке серверных приложений. Задача собственно сводится к тому, что разработку ведём на Windows машине, а пишем для Linux-сервера.
Кросс-компиляция
Настроить кросс-компиляцию оказалось самой простой задачей. Всё, что нам для нужно, это FPC с поддержкой кросс-компиляции на требуемую платформу. Его можно запросто собрать из исходных текстов следующим способом:
make all OS_TARGET=linux
make crossinstall OS_TARGET=linux
make clean OS_TARGET=linux
Единственное “но”, это то, что потребуются CrossBinUtils. Для x86_64-win64->x86_64-linux я взял их из CodeTyphon.
Реализация удалённой отладки
Т.к. у меня стояла задача отлаживать приложение работающее под x86_64-linux с x86_64-win64, то необходимость в экзотических вариантах, вроде gdbserver`а и кроссдебагера, отсутствовала, и я решил воспользоваться простейшим способом – отладкой через SSH. Дело в том, что GDB общается с Lazarus через стандартные потоки ввода-вывода, а их можно элементарно пробросить с удалённой машины через SSH. Да и сам Lazarus предлагает использовать именно этот метод, запуская вместо GDB SSH-клиент с заданными параметрами.
Сразу стоит отметить, что вместо SSH можно использовать и telnet, но требуется telnet-клиент с поддержкой автоматического логина на удалённой машине.
Настройка SSH
В качестве SSH-клиента под Windows я использовал Putty. Я им давно пользуюсь, и он хорошо себя зарекомендовал.
Для начала нужно создать в Putty сессию для доступа к машине, на которой будет выполняться приложение, и сохранить её под каким-нибудь именем. Для реализации входа без пароля нам потребуется пара ключей, для создания которых воспользуемся утилитой PuttyGen. Создаём SSH-2 RSA ключ и сохраняем его публичную и приватную части в файлы (passphrase не требуется). Файл с приватной частью ключа (.ppk) оставляем на нашей машине, прописываем его использование в настройках сессии Connection\SSH\Auth и сохраняем параметры сессии. Файл с публичной частью ключа передаём на удалённую машину и добавляем в доверенные ключи пользователя, под которым будем отлаживать (о том как это делается в Linux есть множество статей – там ничего сложного). Проверяем: при входе через нашу сессию мы должны зайти без запроса пароля.
Собственно для удалённой отладки нам понадобятся еще 2 утилиты Putty: PSCP и PLINK. Первая из них служит для копирования файлов через SSH. PLINK – это консольный SSH-клиент (Сама Putty создаёт в начале обычное окошко где выбирается сессия и производится её настройка) .
Настройка Lazarus
Т.к. компиляция нашей программы выполняется на локальной машине, а запускать и отлаживать её нужно на удалённой, то скомпилированный бинарник нужно как-то передавать. И желательно делать это автоматически сразу после компиляции. В Lazarus зайдём в “Параметры проекта” (Shirt+F11), перейдём в пункт “Параметры компилятора/компиляция” и могли бы вписать в строку “Выполнить после компиляции/команда” что-то вроде "C:\Program Files\Utilits\Putty\PSCP.exe" -load MyDebugSession MyAppFile 192.168.0.2:
(послать наш бинарник в домашний каталог пользователя на удалённой машине). Всё бы хорошо, но посылаемый файл не получает атрибута на выполнение, и соотв. GDB не сможет его запустить. Поэтому вместо этой команды мы создадим небольшой *.bat файл, пропишем в него 2 команды (отсылка и смена прав) и скормим Lazarus`у уже этот батник. Батник получится примерно такого содержания:
PSCP -load
MyDebugSession
MyAppFile
192.168.0.2:
PLINK MyDebugSession
chmod 0777 MyAppFile
Теперь при каждой компиляции нашего приложения оно автоматически переносится на удалённую машину и приобретает права на запуск. Далее нам нужно указать Lazarus`у что мы будем пользоваться удалённой отладкой. Заходим в меню “Параметры…” (Shirt+Ctrl+O), пункт “Отладчик\Общее”. Тип отладчика устанавливаем “GNU debugger through SSH (gdb)”, в поле под ним вписываем полный путь к PLINK.exe, а в ” частные параметры отладчика\Debugger_Startup_Options” вписываем MyDebugSession gdb
.
Это еще не всё, т.к. нужно еще “объяснить” Lazarus`у где именно на удалённой машине будет находиться наше приложение. Для этого заходим в раздел “Запуск\Параметры запуска” и вписываем в поле “Главное приложение” \home\MyDebugUser\MyAppFile
, а в поле “Рабочий каталог” – \home\MyDebugUser\
. Если этого не сделать, то удалённый запуск провалится.
Модификация Lazarus
Несмотря на всё перечисленное в текущей версии Lazarus (r36883) удалённая отладка не работает. Причины этого в следующем. В момент запуска приложения для отладки Lazarus пытается проверить существование файлов отладчика, приложения и каталога приложения. И если отладчик-то он видит, то вот файл приложения и его каталог – нет (они ведь на другой машине и указаны для её файловой системы). Во-вторых, Debugger_Startup_Options применяется после некоторых параметров для GDB, устанавливаемых самим Lazarus`ом (а ведь у нас там имя сессии и команда вызова GDB, вот и получается что параметры GDB применяются к PLINK). В-третьих, при разборе вывода GDB Lazarus использует разделитель строки той OS, для которой он был собран (в моём случае Windows), а через SSH ему приходят данные с разделителем строки той OS, где выполняется приложение (Linux). Ну и наконец именование файлов с исходным кодом: при удалённой отладке GDB начинает возвращать их в файловой системе машины где выполняется, а Lazarus то будет искать их у себя.
Для решения этих проблем мне пришлось написать небольшой патч. Вот только он сделан лишь для случая: отлаживаем под Linux, работая под Windows.
Работа с StdIn/StdOut отлаживаемого приложения
Теперь, когда у нас есть работающий удалённый отладчик, нам хотелось бы еще иметь возможность взаимодействовать с StdIn/StdOut отлаживаемого приложения. Работая под Linux GDB позволяет указывать терминал для отлаживаемого приложения через опцию командной строки –tty=. Именно эту опцию и использует Lazarus под Linux при реализации работы с StdIn/StdOut отлаживаемого приложения. Но я пошел по более простому пути. Использовал отдельную SSH сессию и небольшую утилитку для этих целей.
Порядок действий:
1) На Linux-машине скопировать данную утилиту в /usr/local/bin
2) Зайти на Linux-машину по SSH и узнать имя терминала командой tty
3) На Windows-машине в Lazarus`е, в параметрах запуска отладчика добавить ” –tty=наш терминал”
4) На Linux-машине запустить CFWTerm
5) Начинать отладку на Windows-машине
Дополнительные заметки
- В начале отлаживаемой программы очищать экран консоли, это помогает разделять запуски программы
- При кросс компиляции требуются некоторые библиотеки с целевой OS
- При использование внешнего файла с отладочной информацией его тоже следует перемещать на машину где будет выполняться приложение