У меня была такая же проблема с отладкой ncurses в Xcode.Наконец, я нашел для меня хороший способ управления отладкой с помощью Terminal.app, который позволяет отлаживать ncurses.
Как мы знаем, для инициализации и использования ncurses нам нужно запустить наше приложение в терминале.Но Xcode не открывает терминал, когда мы нажимаем кнопку запуска.Итак, если мы запросим переменную среды TERM из кода, мы получим NULL.Вот почему приложение аварийно завершает работу в initscr ().
Но Xcode позволяет нам настроить опцию Launch для схемы Run (Product> Scheme> Edit схема ...> Run) вместо «Ожидание запуска исполняемого файла»по умолчанию "Автоматически":
Теперь мы можем нажать Run в Xcode и после запуска нашего приложения вручную в Terminal.Таким образом, отладчик будет прикреплен к приложению.В этом есть две проблемы:
Если честно, отладчик не присоединится самостоятельно без дополнительных действий и пропустит все точки останова.Но мы можем управлять этим, вызывая getchar () в начале нашей программы.Я решил эту проблему, введя аргумент командной строки, который указывает, что мы отлаживаем в терминале:
for (int argi = 1; argi < argc; argi++)
{
if (strcmp(argv[argi], "--debug-in-terminal") == 0)
{
printf("Debugging in terminal enabled\n");
getchar(); // Without this call debugging will be skipped
break;
}
}
Итак, мы можем включить вызов getchar () только тогда, когда мы хотим отладить внутри Terminal.app
Нам нужно открывать терминал и запускать приложение вручную каждый раз, когда мы нажимаем «Запустить в Xcode».Это действительно раздражает.Итак, я решил автоматизировать его с помощью Pre-actions в настройках схемы Run.Идея состоит в том, чтобы открыть терминал и запустить в нем наше приложение.Но это предварительное действие должно запустить приложение ПОСЛЕ того, как Xcode выполнит действие «Выполнить», чтобы сначала «дождаться запуска исполняемого файла».Поэтому нам нужна фоновая неблокирующая задача с задержкой.Это может быть достигнуто с помощью следующей команды оболочки (и, в конце концов, для запуска в фоновом режиме):
osascript -e 'tell application "Terminal"' -e 'delay 0.5' -e "set currentTab to do script (\"$TARGET_BUILD_DIR/$PRODUCT_NAME --debug-in-terminal\")" -e 'end tell' &
Не забудьте выбрать приложение в списке «Предоставить параметры сборки из», чтобы сделать его доступным важнымпеременные окружения $ TARGET_BUILD_DIR и $ PRODUCT_NAME:
Итак, теперь, когда мы нажимаем Run, Xcode будет ожидать присоединения исполняемого файла, откроется Terminal и наше приложение будет выполнено сопция командной строки --debug-in-terminal и все точки останова будут сработать.
Довольно приятно, но в конце концов будет лучше закрыть это окно терминала, потому что оно будет генерировать новое для каждой отладки.сессия.Давайте сделаем это в схеме «Пост-действия для запуска»:
osascript -e 'activate application "Terminal"' -e 'delay 0.5' -e 'tell application "System Events"' -e 'tell process "Terminal"' -e 'keystroke "w" using {command down}' -e 'end tell' -e 'end tell'
Эта команда просто закрывает окно активного терминала, так что, возможно, эта пост-операцияне требуется, если вы планируете использовать терминал для других целей во время сеанса отладки, потому что вы можете случайно закрыть какое-то важное окно.
И, наконец, идея безопасного кода ncurses, который проверяет,мы можем использовать ncurses или нет:
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
bool IsTerminalAvailable = false; // Check this global variable before ncurses calls
int main(int argc, const char *argv[])
{
for (int argi = 1; argi < argc; argi++)
{
if (strcmp(argv[argi], "--debug-in-terminal") == 0)
{
printf("Debugging in terminal enabled\n");
getchar(); // Without this call debugging will be skipped
break;
}
}
char *term = getenv("TERM");
IsTerminalAvailable = (term != NULL);
if (IsTerminalAvailable)
IsTerminalAvailable = (initscr() != NULL);
// Do some code here....
if (IsTerminalAvailable)
{
printw("Press any key to exit...");
refresh();
getch();
endwin();
}
return 0;
}