10

I'm having some problems statically linking ncurses to one of my programs

Here's a really simple sample program:

#include<ncurses.h>


int main(){

    initscr();
    printw("Hello world\n");
    refresh();
    getch();
    endwin();
    return 0;
}

When I compile it with

gcc -static -lncurses hello_curses.c -o curses

I get these errors:

/tmp/ccwHJ6o1.o: In function `main':
curses_hello.c:(.text+0x5): undefined reference to `initscr'
curses_hello.c:(.text+0x14): undefined reference to `printw'
curses_hello.c:(.text+0x1b): undefined reference to `stdscr'
curses_hello.c:(.text+0x20): undefined reference to `wrefresh'
curses_hello.c:(.text+0x27): undefined reference to `stdscr'
curses_hello.c:(.text+0x2c): undefined reference to `wgetch'
curses_hello.c:(.text+0x31): undefined reference to `endwin'
collect2: ld returned 1 exit status

I'm a little confused why this isn't working. What am I missing here?

mdogg
  • 595
  • 2
  • 6
  • 16
  • Are you using `-static` because you want the C libraries linked in statically too? – Troubadour Aug 18 '10 at 17:50
  • yea everything needs to statically linked – mdogg Aug 18 '10 at 18:14
  • Possible duplicate of [Why does the order in which libraries are linked sometimes cause errors in GCC?](http://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc) – n. m. could be an AI Sep 29 '16 at 05:48

3 Answers3

32

You need to pass -l options at the end of the command line:

gcc -static hello_curses.c -o curses -lncurses

When the compiler encounters -lfoo, it links in all the symbols from foo that have been requested by a previous file. If you put -lfoo at the beginning, no symbol has been requested yet, so no symbol gets linked.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
  • thanks! that allows it to compile. However when I try to run it in my enviroment I get "Error opening terminal: vt102." Is this a problem with libncurses not being linked properly? – mdogg Aug 18 '10 at 18:45
  • @mdogg: FWIW, it runs fine for me so I would say it's not the static linking per se. – Troubadour Aug 18 '10 at 19:05
  • It works when I'm in my normal enviroment, but when I run it under a really stripped down enviroment I get this error. I think it has something to do with the lack of shared libraries, but I'm not really sure. – mdogg Aug 18 '10 at 19:31
  • 1
    @mdogg: the ncurses library needs additional data files that describe the various terminal types. You need to either install the terminfo or termcap description for `vt102` (and any other terminal type you will need) or pass the terminal description in the environment (`$TERMCAP` or `$TERMINFO`). The [ncurses FAQ](http://invisible-island.net/ncurses/ncurses.faq.html#big_terminfo) may help. – Gilles 'SO- stop being evil' Aug 18 '10 at 20:23
  • 1
    yep, that was the problem. I added the termcap info into /usr/share and it worked. Thanks a alot! – mdogg Aug 18 '10 at 21:01
7

Edit:

I think the real problem is that you need to specify your -l option at the end of the command. I just tried it the way you had it and reproduced your error. If I put -l:libncurses.a at the end of the line then it works. All without the -static option BTW.


I think what is happening is that you have a dynamic library for ncurses but you have used the -static option which means to not use any dynamic libraries. I suspect you do not actually have a static version of the ncurses library i.e. one ending with a .a suffix.

If you want to link with the static version (.a) of ncurses rather than the dynamic version (.so) then temporarily remove the symlink for libncurses.so so that the linker picks up the .a file instead. Alternatively copy the .a file somewhere else and add that to an earlier search path.

Alternatively if your linker supports it (eg. ld) then you could specify -l:libncurses.a instead of -lncurses.

Troubadour
  • 13,334
  • 2
  • 38
  • 57
  • Thanks for the response troubadour. I initially thought that the problem was that the static library wasn't installed, but it is in /usr/lib. I'll try adding it to an earlier search path – mdogg Aug 18 '10 at 17:55
  • @mdogg: I now think the issue is where the `-l` option appears. [@Gilles' answer](http://stackoverflow.com/questions/3514852/statically-link-ncurses-to-program/3515002#3515002) is in agreement. – Troubadour Aug 18 '10 at 18:00
  • you can also just add the path to your .a archive without `-l` preceding it at all and it'll link that static library into your program. e.g. `gcc hello_curses.c -o curses /path/to/libncurses.a` – Wyatt Ward Jan 01 '18 at 21:06
5

I just spent a few hours on an ARM processor, trying to get it to work, as the accepted answer didn't work for me.

Here are my findings:

Apparently

gcc -static hello_curses.c -o curses -lncurses

works on an x64 processor, but not on an ARM processor.

When I tried with the above line, I still got all the "undefined reference errors" (and a lot more) of the OP.

You need to also link against libtinfo.a, and note that sequence matters.
This is the correct command line that works:

gcc -static hello_curses.c -o curses -lncurses -ltinfo

If you mix up the sequence, then it won't work...

gcc -static hello_curses.c -o curses -ltinfo -lncurses 

undefined reference to `unctrl'

Of course this also works if you use the :lib syntax

This compiles

gcc -static hello_curses.c -o curses -l:libncursesw.a -l:libtinfo.a

This does not compile

gcc -static hello_curses.c -o curses -l:libtinfo.a -l:libncursesw.a 

Oh how I like gcc...
This program should never have been allowed to graduate from kindergarden

(.text+0x2a8): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_pair': (.text+0x2ac): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_pair': (.text+0x50a): undefined reference to tparm' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_pair': (.text+0x518): undefined reference to _nc_putp' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_color': (.text+0x552): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_color': (.text+0x556): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_color': (.text+0x5e4): undefined reference to tparm' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioninit_color': (.text+0x5f2): undefined reference to _nc_putp' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioncan_change_color': (.text+0x740): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioncan_change_color': (.text+0x744): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functionhas_colors': (.text+0x768): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functionhas_colors': (.text+0x76c): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In functioncolor_content': (.text+0x7c2): undefined reference to cur_term' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o):(.text+0x7c6): more undefined references tocur_term' follow /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In function _nc_do_color': (.text+0x8de): undefined reference to tparm' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In function _nc_do_color': (.text+0x8e6): undefined reference to tputs' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In function _nc_do_color': (.text+0x958): undefined reference to tputs' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In function set_foreground_color': (.text+0x62): undefined reference totputs' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_color.o): In function set_background_color': (.text+0xa2): undefined reference totputs' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_hline.o): In function whline': (.text+0xec): undefined reference toacs_map' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_hline.o): In function whline': (.text+0xf0): undefined reference toacs_map' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_add_wch.o): In function wadd_wch': (.text+0x4fe): undefined reference to TABSIZE' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_add_wch.o): In function wadd_wch': (.text+0x502): undefined reference to TABSIZE' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_add_wch.o): In function wecho_wchar': (.text+0x6d8): undefined reference to TABSIZE' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_add_wch.o): In function wecho_wchar': (.text+0x6dc): undefined reference to TABSIZE' /usr/lib/gcc/arm-linux-gnueabihf/4.8/../../../arm-linux-gnueabihf/libncursesw.a(lib_wunctrl.o): In function wunctrl': (.text+0x30): undefined reference tounctrl' collect2: error: ld returned 1 exit status

Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
  • Hey, this helped me a lot. I'm on x64, but I was getting a mess of undefined references as well and adding -ltinfo fixed all of it. – LT 'syreal' Jones Nov 26 '22 at 18:19
  • @LT 'syreal' Jones: I'm wondering what causes this... – Stefan Steiger Nov 28 '22 at 09:10
  • Thank the -l:libtinfo.a was the solution for me: `cc -static -std=c99 -Wall -Wextra -pedantic -Os -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -o mtm vtparser.c mtm.c pair.c -lutil -l:libncursesw.a -l:libtinfo.a` – Tinmarino Jan 06 '23 at 15:22