Search code examples
c++linuxgcccompilationncurses

G++ Failing to link ncurses even though it has the -lncurses flag


I'm trying to compile an ncurses file using g++. It gives this output which would suggest that it isn't linking correctly. Interestingly it compiles fine under clang++. I have ncurses installed from source and I know that it's working because it compiles under clang. Ignore the warnings at the start of the file, I'm going to work on those next. Also I know that main.cpp is godawful, I'm working on fixing that too.

CC  main.cpp ./main
main.cpp: In function ‘int main(int, char**)’:
main.cpp:34:34: warning: format not a string literal and no format arguments [-Wformat-security]
   34 |  wprintw(window_one, text.c_str());
      |                                  ^
main.cpp:38:34: warning: format not a string literal and no format arguments [-Wformat-security]
   38 |  wprintw(window_two, text.c_str());
      |                                  ^
/usr/bin/ld: /tmp/cct3HGZR.o: in function `main':
/home/ubuntu/side-projects/slides/main.cpp:13: undefined reference to `initscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:14: undefined reference to `cbreak'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:16: undefined reference to `stdscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:16: undefined reference to `keypad'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:18: undefined reference to `start_color'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:19: undefined reference to `init_pair'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:21: undefined reference to `stdscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:21: undefined reference to `wbkgd'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:23: undefined reference to `LINES'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:24: undefined reference to `COLS'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:27: undefined reference to `printw'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:28: undefined reference to `refresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:33: undefined reference to `wmove'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:34: undefined reference to `wprintw'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:35: undefined reference to `wrefresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:37: undefined reference to `COLS'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:37: undefined reference to `COLS'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:37: undefined reference to `LINES'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:38: undefined reference to `wprintw'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:39: undefined reference to `wrefresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:41: undefined reference to `stdscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:41: undefined reference to `wgetch'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:45: undefined reference to `endwin'
/usr/bin/ld: /tmp/cct3HGZR.o: in function `create_newwin(int, int, int, int)':
/home/ubuntu/side-projects/slides/main.cpp:52: undefined reference to `newwin'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:53: undefined reference to `box'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:55: undefined reference to `wrefresh'
/usr/bin/ld: /tmp/cct3HGZR.o: in function `destroy_win(_win_st*)':
/home/ubuntu/side-projects/slides/main.cpp:60: undefined reference to `wborder'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:61: undefined reference to `wrefresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:62: undefined reference to `delwin'
collect2: error: ld returned 1 exit status
make: *** [Makefile:9: all] Error 1

Here's my makefile:

CC = g++
CFLAGS = -g -lncurses -Wall
SRC = main.cpp
OUT = ./main

.PHONY: all
all: ${SRC}
        @echo "CC " ${SRC} ${OUT}
        @${CC} ${CFLAGS} ${SRC} -o ${OUT}
        @echo "Done"

.PHONY: clean
clean:
        @echo "Cleaning Directory"
        @rm -rf ${OUT}
        @echo "Done"

And here's the C++ that I'm trying to compile:

#include <ncurses.h>
#include <string>

WINDOW *create_newwin(int height, int width, int starty, int startx);
void destroy_win(WINDOW *local_win);

int main(int argc, char *argv[]) {
        WINDOW *window_one;
        WINDOW *window_two;
        int startx, starty, width, height;
        int ch;

        initscr();
        cbreak();

        keypad(stdscr, TRUE);

        start_color();
        init_pair(1, COLOR_BLUE, COLOR_RED);

        bkgd(COLOR_PAIR(1));

        height = LINES;
        width = COLS / 2;
        starty = 0;
        startx = 0;
        printw("Press F1 to exit");
        refresh();
        window_one = create_newwin(height, width, starty, startx);

        std::string text = "test";

        wmove(window_one, height / 2, text.size() / 2);
        wprintw(window_one, text.c_str());
        wrefresh(window_one);

        window_two = create_newwin(LINES, COLS / 2, 0, COLS / 2);
        wprintw(window_two, text.c_str());
        wrefresh(window_two);

        while((ch = getch()) != KEY_F(1)) {
                switch(ch) {}
        }

        endwin();
        return 0;
}

WINDOW *create_newwin(int height, int width, int starty, int startx) {
        WINDOW *local_win;

        local_win = newwin(height, width, starty, startx);
        box(local_win, 0, 0);

        wrefresh(local_win);
        return local_win;
}

void destroy_win(WINDOW *local_win) {
        wborder(local_win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
        wrefresh(local_win);
        delwin(local_win);
}

Solution

  • Libraries should normally come last on the g++ command line, otherwise they may not be searched. This is because the linker only searches libraries if there are undefined names in the files it has already looked at - in your case, it hasn't looked at any at the point it comes across the library.

    You probably want a separate makefile variable called LIBS or similar which you tack on the end of the g++ command line.