Create static library including ncurses - c

I want to create a static library implementing a TUI interface using ncurses. I'm new to this topic and applying these answers didn't work
out for me.
rpath
combine multiple libraries
I want to link varViewer.c in a library. I use this code to compile a example file.
Compiling src/example.c and src/viewer/varViewer.c:
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/example.c -o obs/example.o -lncurses
-fsanitize=undefined -fprofile-arcs -ftest-coverage -Winline -O2
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/viewer/varViewer.c -o obs/viewer/varViewer.o -lncurses
-fsanitize=undefined -fprofile-arcs -ftest-coverage -Winline -O2
Linking obs/example.o to bin/example:
gcc -o bin/example -Isrc/viewer/
obs/example.o obs/viewer/varViewer.o -lncurses
-fsanitize=undefined -fprofile-arcs -ftest-coverage -Winline -O2
bin/example works as expected. I tried to compile a suitable object file:
Compiling src/viewer/varViewer.c:
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/viewer/varViewer.c -o lib/objects/varViewer.o
-lncurses -fPIC -O2
and put it into library:
ar -cvr lib/libvarViewer.a lib/objects/varViewer.o
when I try to use it in other projects, a include it using
-L ..../src/viewer/lib -lvarViewer
flags but all references to functions I used from ncurses library and
string.h are undefined:
nm /lib/libvarViewer.a
....
U __snprintf_chk
U __stack_chk_fail
U start_color
U stdscr
U strchr
U strlen
U strncmp
U strncpy
U strnlen
U waddnstr
U wborder
U wclear
U wcolor_set
U wgetnstr
U winsdelln
U winsnstr
U wmove
U wrefresh
What is the correct way to call ar? I already tried to produce a "thin" library using -T option.

The command
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/viewer/varViewer.c -o lib/objects/varViewer.o
-lncurses -fPIC -O2
will simply compile the varViewer.c file and thus, will ignore the libraries because it won't link to a final executable.
Consequently, the object file varViewer.o will have undefined references (U reported in nm as you have shown) to the symbols not defined within varViewer.c. These not only include the libncurses library but also the regular libc library (which provides symbols such as strlen, strncpy, ...). However, remember that libc will be automatically added into your link stage by the compiler unless you explicitly state otherwise.
You could use the command ar x to extract the object files (.o) from other static libraries and then use ar again to generate a new library. While this is possible I don't think that including all the libraries into yours is a good idea. I think that it is better to link against all the libraries needed because that ensures that the application is linked against the latest version available -- while if you embed one library into yours, then will stick to that version until you upgrade it.

Related

Specifying library dependencies with gcc

What is the purpose of specifying library dependencies with gcc?
I have written a shared library, libPulse_IO.so, that calls functions from both libusb-1.0.so and libpcap.so.
i.e. in pulse_IO.c there is stuff like:
#include <libusb-1.0/libusb.h>
#include <pcap.h>
ret = libusb_init(&pdw_io->context);
pdw_io->pcap=pcap_open_live(pdw_io->eth_name, ETH_SNAPLEN, ETH_PROMISCUOUS, ETH_TIMEOUT, pcap_errbuf);
Now when I come to build my library, I notice that it seems to make no difference if I specify -l libusb-1.0 -l pcap in the call to gcc
i.e. I can run (no mention of -l usb-1.0 or -l pcap):
gcc -fPIC -g -Wall -fvisibility=hidden -I../../../g2/src -I../../core/src pulse_IO.c -c -o ../build/linux/debug/pulse_IO.o
gcc -fPIC -g -Wall -fvisibility=hidden -I../../../g2/src -I../../core/src -shared -Wl,-soname,libPulse_IO_dbg.so ../build/linux/debug/pulse_IO.o -o ../build/linux/debug/libPulse_IO_dbg.so
or (-l usb-1.0 or -l pcap specified):
gcc -fPIC -g -Wall -fvisibility=hidden -I../../../g2/src -I../../core/src -lusb-1.0 -lpcap pulse_IO.c -c -o ../build/linux/debug/pulse_IO.o
gcc -fPIC -g -Wall -fvisibility=hidden -I../../../g2/src -I../../core/src -lusb-1.0 -lpcap -shared -Wl,-soname,libPulse_IO_dbg.so ../build/linux/debug/pulse_IO.o ../build/linux/debug/shared.o -o ../build/linux/debug/libPulse_IO_dbg.so
Both instances build without error.
Running ldd in both cases yields the same output:
ldd ../build/linux/debug/libPulse_IO_dbg.so
linux-vdso.so.1 => (0x00007ffea93ee000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd43af68000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd43b53f000)
No mention of a dependency on libusb-1.0.so or libpcap.so - how?
Examining the shared library produced in both instances shows that there are undefined references to the libusb and pcap functions, i.e.
nm ../build/linux/debug/libPulse_IO_dbg.so
U __assert_fail##GLIBC_2.2.5
U atof##GLIBC_2.2.5
U atoi##GLIBC_2.2.5
...
U libusb_init
U libusb_kernel_driver_active
U libusb_open_device_with_vid_pid
...
U pcap_open_live
U pcap_perror
U pcap_sendpacket
U pcap_setfilter
So the library is built in both instances, with or without the -l library specifiers, and in both instances we can see calls to the libusb-1.0 and libpcap functions in the symbol table.
Which brings me back to my original question.. what is the purpose of specifying library dependencies with gcc?
My expectation was that the calls to gcc would have failed without specifying the libusb-1.0 and libpcap library dependencies?

gcc flags equivalent to LD_PRELOAD?

I currently compile a program called do_foo like so:
gcc -Wall -Wextra -g3 -pthread do_foo.c -o do_foo
and I run it like this:
LD_LIBRARY_PATH=.. LD_PRELOAD=libfoo.so ./do_foo
libfoo.so is strange because:
Has a bunch of functions marked with __attribute__((constructor)) and
Intercepts libc functions like malloc, send, etc
Instead of using LD_PRELOAD to link libfoo.so, I'd like to do it at compile time. I would expect to be able to do it like this:
gcc -Wall -Wextra -g3 -L.. -lfoo -pthread do_foo.c -o do_foo_ld
but this doesn't work: none of the ctor functions run and none of the libc functions get intercepted. When I run ldd do_foo_ld, I don't see libfoo.so in the list of libraries linked to it.
What gcc flags are equivalent to LD_PRELOAD? I assume t here is some simple translation between the two, but I haven't been able to find it.
EDIT: I've made some progress with the following:
gcc -Wall -Wextra -g3 -nodefaultlibs -pthread -L.. -lfoo -lc -lgcc do_foo.c -o do_foo_ld
My rationale is that I need to prevent loading libc at first with -nodefaultlibs, then link libfoo.so, then manually pull whatever gets taken out by nodefaultlibs in afterwards. With this, I don't get undefined reference errors about symbols from libc, but I do get the following:
/tmp/ccSsQHmx.o: In function `fun_1':
/my/proj/do_foo.c:217: undefined reference to `pthread_create'
/tmp/ccSsQHmx.o: In function `fun_2':
/my/proj/do_foo.c:269: undefined reference to `pthread_create'
/tmp/ccSsQHmx.o: In function `fun_3':
/my/proj/do_foo.c:281: undefined reference to `pthread_join'
No combination of -pthread -lpthread at various points in the gcc invocation seems to fix it, and I'm not sure why. I thought that nodefaultlibs might mean "prevent any of the default libraries from being linked" rather than just "don't link them yet," so I tried making a new symlink:
ln -s /lib/x86_64-linux-gnu/libpthread.so.0 ../libnotpthread.so
and adding the following:
gcc -Wall -Wextra -g3 -nodefaultlibs -pthread -L.. -lfoo -lnotpthread -lc -lgcc do_foo.c -o do_foo_ld
but no dice.
What am I missing here?
You should put linked libraries after source or object files:
gcc -Wall -Wextra -g3 do_foo.c -L.. -lfoo -pthread -o do_foo_ld
If this fails to work, try the big hammer:
gcc -Wall -Wextra -g3 do_foo.c -Wl,--no-as-needed -L.. -lfoo -Wl,--as-needed -pthread -o do_foo_ld
Modern distroes enable -Wl,--as-needed flag by default which forces -lfoo to be ignored if none of preceding source or object files uses it (in your case there are no files so it's considered to be unused).

Custom C library: can functions in the same library refer to each other?

I've just started to create my own C libraries to keep my commonly used functions tidy. However, I've hit a new problem and I struggled to find information on the best route to take.
I generate my library of two functions using the following:
gcc -I. -c -fpic rand_site.c
gcc -I. -c -fpic rand_spin.c
gcc -shared -o libstatphys.so rand_site.o rand_spin.o
Each of these source files contained a single function. I was hoping to create a third function for my library that uses the two functions above but I'm not sure how to use functions from within the same library.
Am I going about this the right way? What is the best practice for doing this?
Yes, you can.
Create a header file rand_site.h and put the declaration of the function defined in rand_site.c in it.
Create a header file rand_spin.h and put the declaration of the function defined in rand_spin.c in it.
Use #include to include the two .h files in the third file, say foo.c.
Then compile foo.c and add it to the library using:
gcc -I. -c -fpic foo.c
gcc -shared -o libstatphys.so rand_site.o rand_spin.o foo.o
If you would like to create a second shared library that has foo.o, you can use:
gcc -I. -c -fpic foo.c
gcc -shared -o libfoo.so foo.o -lstatphys
If you would like to create an executable using foo.o, you can use:
gcc -I. -c foo.c
gcc foo.o -lstatphys

Does gcc -nostdlib prevent explicit appending of standardlibs?

If I call the GCC Linker with the option -nostdlib does this override any manual/explicit appendecis of standardlibs?
GCC is 4.8.1 from MinGW.
Example:
gcc -nostdlib [MyObjectsAndLibraries] -lmsvcrt -o Outfile
Since libmsvcrt is a standard library, will it be added to the link process or will it be ignored? I can't find any reliable data on this., this is why I would also appreciate some kind of source to this.
In this context, "standard libraries" means the libraries that gcc would implicitely link by default. Libraries explicitely mentioned on the command line will always be linked. In fact, gcc documentation at http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Link-Options.html#Link-Options even points out that unless you really know what you're doing you should add explicitely -lgcc when using -nostdlib, as the compiler may rely on some builtins defined in it:
In other words, when you specify -nostdlib or -nodefaultlibs you should usually specify -lgcc as well. This ensures that you have no unresolved references to internal GCC library subroutines.
Since I found this on Google,
#Virgile's answer is enough, but you may run into linker errors when you link with the style of command you gave. There is two steps to program building: compile and link. You can use GCC to do one or the other or both at the same time.
It is important to note the order of which you specify things. In your build, it may be problematic because your exe never gets linked with msvcrt or gcc. Including two libraries which have potentially the same symbols is also very bad.
Here is canonical build and link statements
gcc -g0 -O2 -Wall -nostdlib -c *.c
gcc -g0 -O2 -Wall -nostdlib -o a.exe *.o -lmsvcrt -lgcc
gcc -g0 -O2 -Wall -nostdlib -o a.exe *.c -lmsvcrt -lgcc
Here is a good reference
https://stackoverflow.com/a/18389266/2262111

Undefined reference to `initscr' Ncurses

I'm trying to compile my project and I use the lib ncurse. And I've got some errors when compiler links files.
Here is my flags line in Makefile:
-W -Wall -Werror -Wextra -lncurses
I've included ncurses.h
Some layouts :
prompt$> dpkg -S curses.h
libslang2-dev:amd64: /usr/include/slcurses.h
libncurses5-dev: /usr/include/ncurses.h
libncurses5-dev: /usr/include/curses.h
prompt$> dpkg -L libncurses5-dev | grep .so
/usr/lib/x86_64-linux-gnu/libncurses.so
/usr/lib/x86_64-linux-gnu/libcurses.so
/usr/lib/x86_64-linux-gnu/libmenu.so
/usr/lib/x86_64-linux-gnu/libform.so
/usr/lib/x86_64-linux-gnu/libpanel.s
And here are my erros :
gcc -W -Wall -Werror -Wextra -I./Includes/. -lncurses -o Sources/NCurses/ncurses_init.o -c Sources/NCurses/ncurses_init.c
./Sources/NCurses/ncurses_init.o: In function `ncruses_destroy':
ncurses_init.c:(.text+0x5): undefined reference to `endwin'
./Sources/NCurses/ncurses_init.o: In function `ncurses_write_line':
ncurses_init.c:(.text+0xc5): undefined reference to `mvwprintw'
./Sources/NCurses/ncurses_init.o: In function `ncurses_init':
ncurses_init.c:(.text+0xee): undefined reference to `initscr'
collect2: error: ld returned 1 exit status
Thanks a lot
You need to change your makefile so that the -lncurses directive comes after your object code on the gcc command line, i.e. it needs to generate the command:
gcc -W -Wall -Werror -Wextra -I./Includes/. -o Sources/NCurses/ncurses_init.o -c Sources/NCurses/ncurses_init.c -lncurses
This is because object files and libraries are linked in order in a single pass.
In C++ , I fixed it just by linking the ncurses library .
Here is the command :
g++ main.cpp -lncurses
I got flags to correct order by using LDLIBS variable:
ifndef PKG_CONFIG
PKG_CONFIG=pkg-config
endif
CFLAGS+=-std=c99 -pedantic -Wall
LDLIBS=$(shell $(PKG_CONFIG) --libs ncurses)
man gcc | grep -A10 "\-l library"
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX
compliance and is not recommended.)
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files
in the order they are specified. Thus, foo.o -lz bar.o searches
library z after file foo.o but
before bar.o. If bar.o refers to functions in z, those functions may not be loaded.

Resources