Hello !
First, sorry if this topic is not in the right category.
Quite a long time ago, I built a toolchain for my OS following the tutorial "OS Specific Toolchain" on the Wiki. This allowed me to port a few libraries or programs (dash, tcc, ncurses, nano, lynx). One precision that may be useful : I'm operating on Linux (distro : Ubuntu 14.04 LTS) ; my host compiler/linker is GNU GCC/GNU LD.
However, I faced quite an annoying problem with ncurses. Indeed, ncurses uses terminfo, and then I built terminfo at the same time as ncurses.
Now, the problem is when I compile a program using ncurses with my cross-compiler, I must manually link both ncurses and terminfo ; in constrast, with my host compiler, I just need to link ncurses and then terminfo gets linked automatically. It seems libterminfo behaves as libc : when I compile a program using functions from libc, I don't need to pass the "-lc" argument to GCC. Consequently, I guess that there should exist somewhere a list of libraries LD tries to link automatically if he finds undefined references. The problem is I could find such a list nowhere (well, my method was simplistic : I just looked for files containing strings "ltinfo" or "libterminfo" in /usr directory). I also googled for something like 'ld default linked libraries' but without success. So up to now, the only workaround I could find was to merge libterminfo.a and libc.a into one single file named libc.a : but this is really ugly, I find !
Has anyone here ever faced this problem ? What could be a more clever solution ?
Thanks in advance.
Default compiler libraries
Re: GCC/LD : Which libraries are linked by default ?
Hi yaucos,
If you examine glibc (or whatever standard library Ubuntu installation is using) you'll likely find that it provides the terminfo functionality (rather than being in a separate library) - that is, it's part of the libc. There is a list of default libraries, but it's built into the compiler (rather than being a file) when you compile the compiler. You'll want to #define the LIB_EXEC in your custom gcc/config/myos.h file (or whatever you called it. For instance, my cross-gcc does this:
This means that libpthread, libm and libc are automatically linked into the program such that the full standard library is available. The group options are passed to the linker and handles that libpthread, libm and libc depend on each other: I use static linking and grouping means the libraries are scanned repeatedly in case symbols were not pulled in on the first attempt.
Additionally, the program you are porting likely has problems if it doesn't try to link in a libterminfo if required. Perhaps you need to adjust the pkg-config files or the program itself. I don't know any specifics here so I can't be precise help here.
If you examine glibc (or whatever standard library Ubuntu installation is using) you'll likely find that it provides the terminfo functionality (rather than being in a separate library) - that is, it's part of the libc. There is a list of default libraries, but it's built into the compiler (rather than being a file) when you compile the compiler. You'll want to #define the LIB_EXEC in your custom gcc/config/myos.h file (or whatever you called it. For instance, my cross-gcc does this:
Code: Select all
#define LIB_SPEC "--start-group -lpthread -lm -lc --end-group"
Additionally, the program you are porting likely has problems if it doesn't try to link in a libterminfo if required. Perhaps you need to adjust the pkg-config files or the program itself. I don't know any specifics here so I can't be precise help here.
Re: Default compiler libraries
Thanks sortie for your explanation about modifying myos.h. For those who would subsequently read this post, be aware that gcc expects the libraries you specify in LIB_SPEC to really exist. I could realize it by cleaning GCC and Newlib (+ ncurses) before recompiling everything, having modified myos.h as specified by sortie. I then realized that GCC could no longer produce executables because he missed libtinfo at linking stage. This prevented me from building ncurses because the configure script checks whether the cross-compiler can create executables. So one possible solution is to build GCC and Newlib first without specifying LIB_SPEC, then compiling ncurses, then cleaning GCC and rebuilding it with LIB_SPEC set to "--start-group -ltinfo -lc --end-group" for instance.
Concerning adjusting the program itself (the program I am working on is nano 2.2.6), I have tried it : modifying the Makefiles to link libtinfo is not too difficult (by the way, this is how I built nano the first time).
I analyzed the configure script and it appears that it won't try to link libtinfo on his own initiative. Thus, another solution I figured out yesterday is to play with environment variables when launching nano configuration script : one possible way is to set the LIBS environment variable. However, setting LIBS to "-ltinfo" is not enough (I still get undefined references). I think this has something to do with linking order. Indeed, configure builds the actual LIBS variable (i.e the one used in the Makefiles) in the following way : "$LIBS $CURSES_LIB" which amounts to "-libtinfo -libncurses" in my case. Since libncuses depends on libtinfo, it seems that the right order should be "-libncurses -ltinfo". One possible workaround is to specify LIBS="-lncurses -ltinfo" to configure and then the linker will be called with libraries "-lncurses -ltinfo -lncurses" : I tested and it worked, but I don't know how dirty it is.
Concerning adjusting the program itself (the program I am working on is nano 2.2.6), I have tried it : modifying the Makefiles to link libtinfo is not too difficult (by the way, this is how I built nano the first time).
I analyzed the configure script and it appears that it won't try to link libtinfo on his own initiative. Thus, another solution I figured out yesterday is to play with environment variables when launching nano configuration script : one possible way is to set the LIBS environment variable. However, setting LIBS to "-ltinfo" is not enough (I still get undefined references). I think this has something to do with linking order. Indeed, configure builds the actual LIBS variable (i.e the one used in the Makefiles) in the following way : "$LIBS $CURSES_LIB" which amounts to "-libtinfo -libncurses" in my case. Since libncuses depends on libtinfo, it seems that the right order should be "-libncurses -ltinfo". One possible workaround is to specify LIBS="-lncurses -ltinfo" to configure and then the linker will be called with libraries "-lncurses -ltinfo -lncurses" : I tested and it worked, but I don't know how dirty it is.
Re: Default compiler libraries
You should never add libraries to LIB_SPEC that isn't actually part of the standard library or don't exist. (Actually, my libpthread didn't exist and for compatibility I actually made ld ignore a missing libpthread so I could compile old versions of my OS.)
You are abusing the --start-group and --end-group options. They should only be used if libfoo and libbar both depend on each other. However, in your case libterminfo depends on libc, but libc doesn't depend on libterminfo, so there's no issue. Actually, you really shouldn't be doing this. Either you implement terminfo in your libc, or you fix your ports to link with libterminfo. The best way is to edit the configure script or the Makefile or where the decision to link in libncurses happens, and then do the same for libterminfo. Be sure the -lterminfo happens after the -lncurses. Check if a newer upstream release fixes this, or perhaps send them a request to do so. Unfortunately it looks like libncurses doesn't ship pkg-config files (at least my distro doesn't ship them), which is a shame: They allow specifying such dependencies and programs will automatically pick them up if they are pkg-config aware (as many configure-based packages now are). Instead they ship ncurses5-config and ncursesw5-config programs which are TRASH: They are not cross-compile-capable. When you try to cross-compile, the program inadvertently calls the ncurses5-config program that comes with your distro instead of the generated script that you got when you cross-built libncurses. If libncurses is installed in a non-standard location, they might even try to link in the Linux version as well. This is likely the origin of your problem if ncurses5-config --libs on your distro doesn't report -ltinfo. If nano makes any calls to such programs, you must immediately nuke them from the configure script and replace them with pkg-config calls (if available - you'll have to make manual libncurses pkg-config files) or hard-coded -lncurses -ntinfo calls.
Err, that's a rant. Hopefully it's useful.
You are abusing the --start-group and --end-group options. They should only be used if libfoo and libbar both depend on each other. However, in your case libterminfo depends on libc, but libc doesn't depend on libterminfo, so there's no issue. Actually, you really shouldn't be doing this. Either you implement terminfo in your libc, or you fix your ports to link with libterminfo. The best way is to edit the configure script or the Makefile or where the decision to link in libncurses happens, and then do the same for libterminfo. Be sure the -lterminfo happens after the -lncurses. Check if a newer upstream release fixes this, or perhaps send them a request to do so. Unfortunately it looks like libncurses doesn't ship pkg-config files (at least my distro doesn't ship them), which is a shame: They allow specifying such dependencies and programs will automatically pick them up if they are pkg-config aware (as many configure-based packages now are). Instead they ship ncurses5-config and ncursesw5-config programs which are TRASH: They are not cross-compile-capable. When you try to cross-compile, the program inadvertently calls the ncurses5-config program that comes with your distro instead of the generated script that you got when you cross-built libncurses. If libncurses is installed in a non-standard location, they might even try to link in the Linux version as well. This is likely the origin of your problem if ncurses5-config --libs on your distro doesn't report -ltinfo. If nano makes any calls to such programs, you must immediately nuke them from the configure script and replace them with pkg-config calls (if available - you'll have to make manual libncurses pkg-config files) or hard-coded -lncurses -ntinfo calls.
Err, that's a rant. Hopefully it's useful.
Re: Default compiler libraries
Thanks for answering.
Nano 2.2.6 configure script doesn't use ncurses5-config.
However, it uses pkg-config, but as far as I understand, it has more to do with GLib than with ncurses.
Nano 2.2.6 configure script doesn't use ncurses5-config.
However, it uses pkg-config, but as far as I understand, it has more to do with GLib than with ncurses.
Not sure I understand.sortie wrote:Err, that's a rant.