开发者

Xcode and Curses.h with Error opening terminal

I am开发者_StackOverflow中文版 trying to compile a simple curse project with Xcode.

The program compiles fine with g++ in terminal with the flag -lcurses, and runs fine.

Started of by creating a Command Line Tool with type c++.

imported curses.h into my main.

In the Target"program"Info -> General -> Linked Libraries, libCurses.dylib has been added.

It compiles fine but the terminal window will not open.

In the Debug Console the output is,

Program loaded.

run

[Switching to process 3424]

Error opening terminal: unknown.

Running…

I can go to build folder and just open the program in terminal but is there any way for xcode to open the terminal?

Thanks for any help!


I had the same problem with ncurses debugging in Xcode. Finally I've found a good way for me to manage debugging with Terminal.app that allows to debug ncurses.

As we know, to initialise and use ncurses we need to run our application in terminal. But Xcode doesn't open terminal when we press run button. So, if we request environment variable TERM from code, we'll get NULL. This is why application crashes on initscr().

So, it is needed to launch Terminal.app, execute our process there and attach a debugger to it. It can be achieved through Scheme setup. I did it in Xcode 11.4. I created a new macOS Command Line Tool project based on Language: C++. Also I added libncurses.tbd dependency in Frameworks and Libraries.

Go to Product > Scheme > Edit scheme..., select Run scheme and Run action and navigate to Info tab. You'll see Launch set to Automatically. Change it to Wait for the executable to be launched.

Xcode and Curses.h with Error opening terminal

Select Pre-actions in the Run scheme and add New Run Script Action. Change Provide build settings from from None to your build target. Add the following code there:

osascript -e 'tell application "Terminal"' -e 'delay 0.5' -e 'activate' -e "do script (\"$TARGET_BUILD_DIR/$PRODUCT_NAME\")" -e 'end tell' &

Xcode and Curses.h with Error opening terminal

To optionally close terminal in the end of debugging session select Post-actions in the Run scheme and add New Run Script Action. Add the following code:

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'

Xcode and Curses.h with Error opening terminal

Actually osascript will always create at least two terminal windows but if you will leave the first one opened it will create and destroy the second one with your session automatically through Pre and Post actions.

You will probably also meet a problem with debugger attaching. I don't know exact reason why Xcode don't want to attach debugger when process executes externally but I found this issue. Also I found stdin stream in weird state during debugging session beginning as well. So, I wrote a workaround based on pselect call. I'm asking stdin for any data until it doesn't return success. I found that after these manipulations debugger will feel OK and stdin requests will be OK as well. Here is my code example:

#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include <sys/select.h>
#include <unistd.h>
#include <errno.h>

bool g_has_terminal = false; // Check this global variable before ncurses calls

bool ensure_debugger_attached_woraround(int timeout_ms)
{
    fd_set fd_stdin;
    FD_ZERO(&fd_stdin);
    FD_SET(STDIN_FILENO, &fd_stdin);
    struct timespec timeout = { timeout_ms / 1000, (timeout_ms % 1000) * 1000000 };

    do
    {
        errno = 0;
    }
    while (pselect(STDIN_FILENO + 1, &fd_stdin, NULL, NULL, &timeout, NULL) < 0 && errno == EINTR);

    if (errno != 0)
    {
        fprintf(stderr, "Unexpected error %d", errno);
        return false;
    }

    return true;
}

int main(int argc, const char *argv[])
{
    if (!ensure_debugger_attached_woraround(700))
        return 1;

    char *term = getenv("TERM");

    g_has_terminal = (term != NULL);

    if (g_has_terminal)
        g_has_terminal = (initscr() != NULL);

    // Some ncurses code. Maybe you should terminate if g_has_terminal is not set

    if (g_has_terminal)
    {
        printw("Press any key to exit...");
        refresh();

        getch();

        endwin();
    }

    return 0;
}

ensure_debugger_attached_woraround is called with a timeout 700 milliseconds. I tried different values and found 500 ms is the minimal one to not skip pselect. Maybe this timeout is machine depended I don't know. You can wrap this call by #ifdef ... #endif or by some other checks, maybe by special command line argument check to exclude a little wait overhead in the release mode.


In XCode 8 you can choose to run within the terminal, from the Edit Scheme... Options page.

Xcode and Curses.h with Error opening terminal

Though in my quick testing it doesn't seem to work all that well; it sometimes (not always) seems to 'lose' the debuggee, or the debuggee never starts, and thinks it's still running. If you try to exit, Xcode gets stuck. I have found that if you find and then kill a process called lldb-rpc-server you can avoid having to force-quit.

In more detail (in case this helps anyone) whenever the debuggee fails to start, I open a Terminal and type

ps x | grep lldb

then

kill 12345

where 12345 is the process ID that ps gives me.


There is no terminal to attach to in the Xcode IDE. Instead run the program from a shell (via Terminal application)

./build/Debug/myprogram

If you want to use the IDE debugger (which is just gdb) you can attach to the process. Fist get the process id,

gdb> attach mypid

For a more convenient method, I'll quote Step into Xcode: Mac OS X development

Open the Executables group in the Groups & Files list, select the application, open an Info window, and in the Debugging tab, uncheck Start executable after starting debugger. When you're ready to debug, start the debugger, and then then launch the target application in its friendly environment. In the debugger's gdb console, type attach myprogram, and your debugging sesssion is under way.


Follow on to Peter Hull's answer, selecting "Console - Use Terminal" in the Scheme->Run->Options worked for me too.

Regarding the lldb-rpc-server which does not exit properly: One can simply add the following to the Product->Scheme->Edit Scheme->Run->Post-actions:

ps -ef |grep lldb-rpc-server |grep -v grep | awk '{print $2}' | sort -rn | while read PID ; do kill $PID ; done

This will find the lldb-rpc-server processes, which should be owned by your userid anyway, sort them in reverse order, and simply dispatch them.

Xcode and Curses.h with Error opening terminal

This helped me a lot! I hope it helps someone else too!

-TechnoPak

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜