Having trouble linking to a static library with GCC - c

I'm working on a big project with glfw but I have been stymied trying to link to a static library with gcc, hence this toy example. I'm not sure why I'm having so much trouble with such a simple thing.
This is the extent of my source code:
#include <stdio.h>
#include <ft2build.h>
#include FT_FREETYPE_H
int main(){
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
printf("ERROR::FREETYPE: Could not init FreeType Library\n");
}
FT_Face face;
if (FT_New_Face(ft, "fonts/arial.ttf", 0, &face))
{
printf("ERROR::FREETYPE: Failed to load font\n");
}
return 0;
}
I'm running Linux Mint. I downloaded the FreeType library and built it using CMake and my version of GCC. The libfretype.a file is in a subdirectory called junk. The headers are in a subdirectory called include.
We compile it with the following:
gcc -Wall -Wextra -g -v -Iinclude -Ljunk vex.c -lfreetype -o vex
and I get a ton of errors like sfnt.c:(.text+0x218): undefined reference to 'png_get_error_ptr' .
Thanks in advance for telling me the silly mistake I made.

It basically means that the implementation of the function png_get_error_ptr is missing. So, the compiler could not generate an executable because some code is missing.
The function png_get_error_ptr is implemented in a library named libpng. Sometimes, some libraries have some dependencies on another project, in the general case, you need to include all the dependencies to your build to resolve the linker errors.
You need to include these libraries in the linker:
gcc -Wall -Wextra -g -v -Iinclude -Ljunk vex.c -lfreetype -lpng -lz -o vex
^ ^
-lz is to link against zlib because libpng rely on zlib if I remember correctly.
http://libpng.org/pub/png/libpng-manual.txt

Related

gcc undefined reference to portaudio functions

I am trying to use portaudio in one of my projects. Unfortunately, I cannot compile my main.c file.
Error: "undefined reference to 'Pa_Initialize'" (Pa_Initialize is a function from the portaudio library)
My working directory includes the .a file from portaudio as well as the portaudio.h.
My current gcc command: gcc main.c libportaudio.a -lm -o main
Update: these are the includes in my main.c
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
If you get an undefined reference error, you have probably already integrated the header file portaudio.h.
As Kurt E. Clothier already mentioned, you must also mention the libraries inside your gcc command. According to the portaudio website, the gcc command is
gcc main.c libportaudio.a -lrt -lm -lasound -ljack -pthread -o main
I was able to fix the issue by rebuilding the portaudio library.

C pluginsystem: symbol lookup error

I am writing a plugin system which is separated other 3 modules:
plugin_system.c - the core of the system
list.c - contains a linked list implementation for plugins' storage
plugin_interface.h - contains the declaration needed by plugins, has no source file associated with
plugin_interface.h only contains only of types and the function:
extern int plugin_register(PluginManager *plug_manager, const char *name, Plugin *plug);
which is defined in plugin_system.c
When loading a plugin, the plugin system look for a funcion init_plugname() and call it, that function must call plugin_register to register the plugin.
The program is compiled with complex recursive Makefiles (not the best idea), but what I try to achieve is:
I compile the plugin system object in the main program folder, it is then linked with the main program. From make execution:
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -fPIC -c -o /home/kowa/code/reseaux/projet/ringo/c/bin/list.o list.c
gcc -Wall -O2 -std=gnu99 -D DEBUG -g -fPIC -c -o /home/kowa/code/reseaux/projet/ringo/c/bin/plugin_system.o plugin_system.c
A plugin is compiled with gcc -fPIC -c -o plugname.o plugname.c plug_system.o followed by gcc -o plugname.so plugname.o plug_system.o -shared
I try to load the plugin in my main program and get this error:
symbol lookup error: ./plugins/zyva.so: undefined symbol: exists
exists is a function in the list module used by the plugin_system module to store plugins, the plugin_register function mentionned aboved calls it.
I've never done that kind of system before and I'm not an expert in shared library, I guess the problem is from how I compile the whole project, I may miss some linkage...
I just forgot to link the plugin with list.o which is used by the plugin_system.o...

No undefined references when compiling shared library

Im wondering why Im getting no undefined references when compiling as a shared library using -shared as an option for gcc. Consider the following case:
#include <confuse.h>
int
main(int argc, char **argv)
{
cfg_opt_t opts[1];
cfg_t *cfg = cfg_init(opts, CFGF_NOCASE);
return 0;
}
libconfuse is needed here in order to run the program properly. If im compiling it as a "normal" application without specifying that libconfuse is needed (-lconfuse) im getting the following (from my perspective regular) error:
$ gcc -Wall -Wno-unused-variable test.c -o test
/tmp/ccTVz6an.o: In function `main':
test.c:(.text+0x20): undefined reference to `cfg_init'
collect2: error: ld returned 1 exit status
If im compiling the same code as a shared library im not getting any error message regarding the library:
$ gcc -Wall -Wno-unused-variable test.c -o test.so -shared
$ echo $?
0
Can someone please bring light into darkness?
You are compiling a (shared) library, not a program, and libraries are expected not to be complete, so undefined references do not prevent the shared library from building.
Yes, it may sound a bit surprising, particularly if you come from a OS (Windows?) where the shared libraries are always fully linked, but that's how ELF works.
If you want to ensure that all your references are are resolved when building a shared library you can use the linker option --no-undefined:
gcc -Wall -Wno-unused-variable test.c -o test.so -shared -Wl,--no-undefined
Note that libraries used to resolve references when linking a shared library will be added to the header of that library, as NEEDED entries, and then linked automatically when using that library. See objdump -p for details.
With shared libraries (not static ones), you could link a library libA.so into your other library libB.so.
So you could compile your shared library as:
gcc -Wall -Wno-unused-variable -fPIC test.c \
-o libmytest.so -shared -lconfuse
Later you would link that library to some main.c with
gcc -Wall main.c -lmytest -L. -o myprog
or you could load it at runtime, using dlopen(3) on ./libmytest.so (read the man page about why ./ is significant to dlopen)
Simple explanations are in the Program Library HowTo. But Drepper's paper: How to Write Shared Libraries is the best reference.
And it is permitted for a shared library (or even a static one) to have undefined references, since quite often the user of that library would explicitly link the lower level libraries needed by it.

How do I link GLFW

I am trying to link GLFW to my C program.
The docs seem to suggest #include<GLFW/glfw3.h> however I have installed 2.7.2 (from my distro's repository) and don't have that header file:
find / -name *glfw* 2> /dev/null
/usr/lib/libglfw.so.2.6
/usr/lib/libglfw.a
/usr/lib/libglfw.so
/usr/lib/pkgconfig/libglfw.pc
/usr/lib/libglfw.so.2
/usr/include/GL/glfw.h
/usr/share/doc/libglfw-dev
/usr/share/doc/libglfw2
/var/cache/apt/archives/libglfw2_2.7.2-1_i386.deb
/var/cache/apt/archives/libglfw-dev_2.7.2-1_i386.deb
/var/lib/dpkg/info/libglfw2.list
/var/lib/dpkg/info/libglfw2.postinst
/var/lib/dpkg/info/libglfw-dev.md5sums
/var/lib/dpkg/info/libglfw2.postrm
/var/lib/dpkg/info/libglfw2.md5sums
/var/lib/dpkg/info/libglfw2.shlibs
/var/lib/dpkg/info/libglfw-dev.list
I tried #include<GL/glfw.h> but I still get undefined reference to 'glfwLoadTexture2D'
How do I link to GLFW and use glfwLoadTexture2D()?
An #include does nothing for the linker; it just brings in declarations, not the actual functions.
The documentation indicates that GLFW uses pkg-config (not surprising; #elmindreda knows her stuff), so your compilation line should be something like:
$ cc `pkg-config --cflags glfw3` -o foo foo.c `pkg-config --static --libs glfw3`
Also note that since the library uses pkg-config, you're not supposed to "care" about details such as where the header and library files are located on your particular installation. Just ask using the --cflags and --libs modes, and you will get the proper locations returned, as the example above indicates.
You are mixing up compilation and linking. If you were missing headers, you would probably have errors a lot sooner than the linking stage.
"Undefined reference" results from symbols not being found by the linker. The most likely cause is you not telling gcc that it should link to the GLFW libraries:
gcc myfile.c -lglfw
When I am on Linux, I compile opengl/glfw projects like this:
gcc main.c -lGL -lglfw
When I am on windows, I compile them by writing:
gcc main.c libglfw3.a -lopengl32 -lgdi32
and I put libglfw3.a file in the same directory where main.c is. I have read people say that they couldn't link properly before writing
-lopengl32 -lgdi32 -luser32 -lkernel32 -lws2_32.
Another thing which may be worth mentioning is that I couldn't link glfw libraries when I downloaded 32bit glfw binaries. When I downloaded 64bit glfw binaries everything worked fine. I have a 64 bit machine and a x86_64-w64-mingw32. I have read comments from people with the opposite experience, where they weren't able to link glfw libraries when they downloaded 64bit binaries, but they were able to link them after downloading 32bit binaries. My advice would be to try both.

Cannot compile using ALSA

I am trying to create an C application on Debian GNU/Linux which uses the PortAudio interface. To do this I must compile my program with gcc -lrt -lasound -ljack -lpthread -o YOUR_BINARY main.c libportaudio.a from this docs.
For this I installed libasound2-dev, and I checked where the files are using apt-file search libasound.so, this is the output:
lib32asound2: /usr/lib32/libasound.so.2
lib32asound2: /usr/lib32/libasound.so.2.0.0
lib32asound2-dev: /usr/lib32/libasound.so
libasound2: /usr/lib/x86_64-linux-gnu/libasound.so.2
libasound2: /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0
libasound2-dev: /usr/lib/x86_64-linux-gnu/libasound.so
So the libasound should be installed correctly, but when I compile my program with this makefile:
DMXTest: main.c libdmx.a
gcc -static -Wall main.c -L. -ldmx -lusb -lrt -lasound -ljack -lfftw3 -g -o main libportaudio.a
I get the following error: /usr/bin/ld: cannot find -lasound.
How can I link this library correctly?
You don't have libasound.a for -static, you will need that, or you can almost certainly just remove -static from the Makefile (likely in LDFLAGS or CFLAGS).
There's is a related Debian bug 522544, and a related Ubuntu bug #993959.
You may be able to build your own libasound from source, though as it also uses other libraries (notably libpthread.so, librt.so and libdl.so) I suspect it may remove some functionality when you build it statically, though it's supported with ./configure --enable-static at build time
(or try --enable-shared=no --enable-static=yes).
FWIW, the use of static binaries is "discouraged" by the glibc maintainers, though I don't agree...
To compile my code i used the following command
gcc -o rec_mic rec_mic.c -lasound
and it works perfectly, without create my own static library.

Resources