How to compile readline from source? - c

When I compile readline into my directory /mypath as instructed (./configure --prefix=/mypath; make; make install) I get the following unresolved symbols in it:
ldd -r /mypath/lib/libreadline.so.6.2
linux-vdso.so.1 => (0x00007ffffb186000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f450c62f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f450cc07000)
undefined symbol: UP (/mypath/lib/libreadline.so.6.2)
undefined symbol: PC (/mypath/lib/libreadline.so.6.2)
undefined symbol: BC (/mypath/lib/libreadline.so.6.2)
When I read the readme-file of readline, this seems to be a feature and not a bug:
`--with-curses'
This tells readline that it can find the termcap library functions
(tgetent, et al.) in the curses library, rather than a separate
termcap library. Readline uses the termcap functions, but does not
link with the termcap or curses library itself, allowing applications
which link with readline the to choose an appropriate library.
This option tells readline to link the example programs with the
curses library rather than libtermcap.
I tried it of course with --with-curses but that did not change anything, which is not surprising because it seems to be a setting that only affects some testing programs in readline.
My distribution (debian) however has a readline without undefined symbols, so it is clearly possible to do.
How to create a readline library without unresolved symbols?
Edit:
I have compiled and installed ncurses into the same directory and I have also tried to configure readline with CFLAGS=" -Wl,-rpath=/mypath" and --enable-static, without success.

Those symbols are defined by libncurses, I think. You can probably confirm this like this:
env LD_PRELOAD=/usr/lib/libncurses.so ldd -r /mypath/lib/libreadline.so.6.2
(I think ldd takes preloads into account when checking symbols, but it may not.)
The build script used by Arch Linux is here. It looks like the trick is to use:
make SHLIB_LIBS=/mypath/libncurses.so
There's also some other adjustments to the -rpath options in a build file, so you might need that also.

The make install step is installing the shared library in some directory, often /usr/local/lib/
You need to make the dynamic loader ld.so(8) aware of that. I would suggest add once /usr/local/lib/ into your /etc/ld.so.conf file then running ldconfig after each installation of new shared libraries inside it. See ldconfig(8), ldd(1)
You could also specify some -Wl,-rpath when linking programs with your version of libreadline.so
And when building a shared library you can link it to other shared libraries. On my Debian the system libreadline is linked to libtinfo:
% ldd /lib/x86_64-linux-gnu/libreadline.so.6
linux-vdso.so.1 (0x00007ffffccf3000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f45cffcc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f45cfc23000)
/lib64/ld-linux-x86-64.so.2 (0x00007f45d046c000)
You may want to study the source package of your readline6, since it contains the patches to the building procedure.
BTW, my Debian has a libtinfo5 package (obtained with dpkg -S /lib/x86_64-linux-gnu/libtinfo.so.5)

Related

Why does libc depend on ld.so?

I always think that libc should be an independent dynamic library, until I find this:
$ ldd /lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2 (0x00007fd743c00000)
linux-vdso.so.1 (0x00007fffc75f4000)
Can someone tell me why libc needs ld.so and what function it uses?
ld.so is needed by any application or shared library that is linked with shared libraries:
The programs ld.so and ld-linux.so* find and load the shared
objects (shared libraries) needed by a program, prepare the
program to run, and then run it.
Applications don't normally invoke any functions from ld-linux-x86-64.so, rather it loads the executable and shared libraries and passes the control flow to the application, which is normally C and C++ library runtime initialization code. Such a dependency on ld-linux.so* is established with .interp section of ELF file (see readelf -l /lib/x86_64-linux-gnu/libc.so.6 output) and that is not what ldd shows.
ldd, however, (recursively) shows libraries marked as NEEDED in dynamic section (see readelf -d /lib/x86_64-linux-gnu/libc.so.6 output). On Linux, thread local storage support for shared libraries is implemented by /lib64/ld-linux-x86-64.so.2. That is an implementation detail, but is the reason glibc depends on ld-linux-x86-64.so.

Location of time.h -> localtime() implemenation in Ubuntu?

I am searching for the implementation of localtime() function in time.h. I see that different platforms have different locations for source of c library. I wanted to know the location in Ubuntu 14.04? If by default source is not included in OS, please let me know how to download source or online location of the source.
Thanks.
Check which binary your system uses as libc implementation.
To do so compile a minimal C program and run ldd on it:
ldd a.out
You might get something like this:
linux-vdso.so.1 => (0x00007fff429c6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f21cdcb7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f21ce05e000)
From this you can pull the info libc is proided by libc6.so.6.
Check which package provides this binary.
Search the package providing the file found under 1.:
dpkg -S libc.so.6
You might get:
libc6-i386: /lib32/libc.so.6
libc6:amd64: /lib/x86_64-linux-gnu/libc.so.6
The above output tells you, that there are two packages providing the file. Here it's the 32 bit and 64 bit implementation.
Decide which one you want and do apt-get source this package's sources.
Assuming the package would be libc6, do
apt-get source libc6
and find thre source in a directory inside the current directory.

Unable to found -lGL, how to do without symlink?

I'm compiling a shared library, with a -lGL on the ld command. But it can't find the libGL.so on my system. Nvidia package correctly set libraries path in /etc/ld.so.conf.d/.
Even the output of ldconfig -p | grep libGL.so found it:
libGL.so.1 (libc6,x86-64) => /usr/lib/nvidia-current/libGL.so.1
libGL.so.1 (libc6) => /usr/lib32/nvidia-current/libGL.so.1
libGL.so (libc6,x86-64, OS ABI: Linux 2.4.20) => /usr/lib/x86_64-linux-gnu/libGL.so
libGL.so (libc6,x86-64) => /usr/lib/nvidia-current/libGL.so
libGL.so (libc6, OS ABI: Linux 2.4.20) => /usr/lib32/libGL.so
libGL.so (libc6) => /usr/lib32/nvidia-current/libGL.so
I read almost everywhere that to be able to link with it, i have basically 2 solutions:
Link the nvidia libGL.so to a standard /usr/lib location. That seem wrong for anybody what will try to compile an opengl library. Why the linker is not using the ldconfig cache ?
Append manually the -L/usr/lib/nvidia-current to the library search path. Again, wrong, how can i know every path where the library could be found on all the system ?
So my real question is: What is the standard and automatic approach for linking with a library not in a standard location, but location already register with /etc/ld.so.conf ?
/etc/ld.so.conf is used by /lib/ld.so to resolve shared libraries at runtime, it has nothing to do with linking stuff at compile time.
What is the right way to do is just linking to libGL.so in /usr/lib/x86_64-linux-gnu/ and the application will use the nvidia's libGL.so on runtime. This shouldn't be a problem because the OpenGL interface is stable and symbols are the same in both libraries, its the implementation that is different.

Location of C standard library

In the gcc manual it is given that "The C standard library itself
is stored in ‘/usr/lib/libc.a’". I have gcc installed, but could not find libc.a at the said location. Curious to know where is it located.
I find many .so files in /usr/lib location. What are those?
If you are looking for libc.a:
$ gcc --print-file-name=libc.a
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libc.a
A few things:
gcc and glibc are two different things. gcc is the compiler, glibc are the runtime libraries. Pretty much everything needs glibc to run.
.a files are static libraries, .so means shared object and is the Linux equivalent of a DLL
Most things DON'T link against libc.a, they link against libc.so
Hope that clears it up for you. As for the location, it's almost certainly going to be in /usr/lib/libc.a and / or /usr/lib/libc.so. Like I said, the .so one is the more common.
If you are on RPM based Linux (Red Hat/CentOS/Fedora/SUSE) then you would get the location of the installed glibc with
rpm -ql glibc and rpm -ql glibc-devel .
locate libc.a would get you the location. And to see from where it comes do:
rpm -qf /usr/lib/libc.a
Here is what rpm -qi has to tell about these packages
glibc-devel:
The glibc-devel package contains the object files necessary
for developing programs which use the standard C libraries (which are
used by nearly all programs). If you are developing programs which
will use the standard C libraries, your system needs to have these
standard object files available in order to create the
executables.
Install glibc-devel if you are going to develop programs which will
use the standard C libraries
glibc:
The glibc package contains standard libraries which are used by
multiple programs on the system. In order to save disk space and
memory, as well as to make upgrading easier, common system code is
kept in one place and shared between programs. This particular package
contains the most important sets of shared libraries: the standard C
library and the standard math library. Without these two libraries, a
Linux system will not function.
You need to install package for static libraries separately:
glibc-static.i686
On centos 5.8
$ ls -l /usr/lib/libc.a
-rw-r--r-- 1 root root 2442786 Apr 8 2010 /usr/lib/libc.a
$ rpm -qf /usr/lib/libc.a
glibc-devel-2.3.4-2.43.el4_8.3
You also have to have the glibc-devel package install under RedHat distributions.

Two method for linking a object using GCC?

I've known that I should use -l option for liking objects using GCC.
that is gcc -o test test.c -L./ -lmy
But I found that "gcc -o test2 test.c libmy.so" is working, too.
When I use readelf for those two executable I can't find any difference.
Then why people use -l option for linking objects? Does it have any advantage?
Because you may have either a static or a shared version of the library in your library directory, e. g. libmy.a and libmy.so, or both of them. This is more relevant to system libraries: if you link to libraries in your local build tree, you know which version you build, static or shared, but you may not know other systems' configuration and libraries mix.
In addition to that, some platforms may have different suffixes. So it's better to specify it in a canonical way.
The main reason is, -lname will search for libname.a (or libname.so, etc.) on the library search list. You can add directories to the library search list with the -L option. It's a convenience built into the compiler driver program, making it easier to find libraries that have been installed in standard places on the system.

Resources