How do I correctly link in static libraries with g++? - c++

I have a rather complex build I'm trying to do, but I'll simplify it a little bit for this question. I have three c++ files (main.cpp file2.cpp and file3.cpp) that I am trying to compile and link against 3 static libs (libx.a liby.z libz.a) to produce an executable.
There are many dependencies involved.
All three c files are dependent on all 3 libs. libx is dependent on liby and libz. And finally, libx is also dependent on several callback functions contained in file2.cpp.
What command line would build this correctly? I have tried dozens of variations and nothing has satisfied the linker yet.
If it matters, the libs are pure c code compiled with gcc. Sources are c++ and I'm compiling/linking with g++. I have this working correctly as a visual studio project, and am trying to port to linux.

From your post:
g++ main.cpp file2.cpp file3.cpp -lx -ly -lz
However, if static linking is causing you problems, or you need to distribute any of the libs, then you may consider making them shared objects (.so files, commonly called DSOs). In that case, when you build libx.a, for example, compile all the sources to object files, and then combine them with
g++ -shared *.o -o libx.so -ly -lz
(this version assumes that liby.a and libz.a are stills static, and will be combined into libx.so

You may need to use extern "C" { } in your .cpp files to include the header for the C libs.
See Including C Headers in C++ in How To Mix C and C++.

Related

Difference between linking libfdisk.a directly and through -lfdisk

I've made program, which formats storage devices. However, when I've created library (for python GUI) based on this program it starts to show the error:
/usr/bin/ld: fdisk/libfdisk.a(la-label.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
libfdisk.a, which I use, has been built from source util-linux-2.35.
And when -lfdisk is used instead of libfdisk.a, it compiles with no errors.
Compiles with errors:
g++ file1.cpp file2.cpp ... -o package.name ... libfdisk.a
Compiles correctly:
g++ file1.cpp file2.cpp ... -o package.name ... -lfdisk
What the difference between these 2 ways?
But there is another, optional, question about fdisk. When I compile my program (not library) with -lfdisk, program can not create 2 partitions due to error 28 (returns from fdisk_add_partition(...)).
I'll share the code if it needs.
With -lfdisk the linker is asked to figure out which library file exactly to use.
The usual linkers on Linux will prefix lib and then search for files with .so or .a ending in the library path, which because you didn't specify any, will be the system library path (probably /usr/lib/ or similar). If a .so is found, it will be preferred for linking if a static link wasn't requested.
Your other method will explicitly add in the file named libfdisk.a in the current directory. That is a static library, not a shared one, and if you try to build a shared library from it, then you need to have compiled libfdisk.a with -fPIC or if you try to build a PIE executable at least with -fPIE. If you are trying to build a non-PIE executable, then neither flag is required. GCC may be configured to build PIE by default (as a hardening measure).
So you are probably linking two completely different files.

How to use a library with headers and .so files?

I'm new to C and wanted to use a library (MLT Multimedia Framework)
I've built it and it produced the following directories: include lib share
Inside lib there are .so .a .la files
Inside include there are .h files
Now, I'm instructed to do this:
#include <framework/mlt.h> which is inside include/mlt/framework/
Questions:
Why I do I need to place the header file that contains only function prototypes? Where are the real functions then? are they linked someway to the ones included in lib directory?
Where to place my own files and how to compile it?
How to learn more about the topics:
Dynamic/Static libraries
Building / making / installing
How to use any C library
If you don't have the function prototypes, how would the compiler know what functions exist in the library? Short answer is: It doesn't. Longer answer: The compiler doesn't care about library files, static (files ending in .a) or shared (files ending in .so), all it cares about is the current translation unit. It's up to the linker to handle resolving undefined references.
When you use libraries, you include the header files that contain the needed declarations (structures, classes, types, function prototypes) into the source file. The source file plus all included header files forms the translation unit that the compiler uses to generate code. If there are undefined references (for example a call to a function in the library) the compiler adds special information about that to the generated object file. The linker then looks through all object files, and if it finds an unresolved reference it tries to find it in the other object files and the provided libraries. If all definitions are resolved the linker generates the final executable, otherwise it will report the unresolved definitions as errors.
To answer your other questions:
Where to place my own files and how to compile it?
This is two questions, the answer to the first one (about placement of your files) is that it doesn't really matter. For small project with only a few source and header files, it's common to place all files in a common project directory.
The second question, about compiling, there are different ways to do it too. If there are only one or two source files you could use the compiler frontend (e.g. gcc) to compile and link and generate your executable all in one go:
$ gcc -Wall -g source1.c source2.c -o your_program_name
The above command takes two source files, compiles and links them into the program your_program_name.
If you need to use a library, there are one or two things that you need to add to the above command line:
You need to tell the linker to link with the library, this is done with e.g. the -l (lower case L) option:
$ gcc -Wall -g source1.c source2.c -o your_program_name -lthe_library
It's important to note that the_library is the base name of the library. If the library file is named libthe_library.so then only the_library part is needed, the linker will add the other parts automatically.
If the library is not in a standard location, then you need to tell the compiler and linker where the library file are. This is done with the -I (capital i) option to tell the preprocessor where the header files are, and the -L (capital l) where the linker files are.
Something like
$ gcc -Wall -g -Ilocation/of/headers source1.c source2.c -o your_program_name -Llocation/of/libraries -lthe_library
If you have more than a couple of source files, it's common to use so called makefiles that lists all source files, their dependencies, compiler and linker flags, and contain rules on how to build object files and link the final program. Such a makefile could look like
CFLAGS = -Wall -g
LDFLAGS = -g
SOURCES = source1.c source2.c
OBJECTS = $(SOURCES:.c=.o)
TARGET = your_program_name
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(LD) $(LDFLAGS) $^ -o $#
%.o: %.c
$(CC) $(CFLAGS) $< -c -o $#
The above makefile should do just about the same as the previous command line. The big difference is that it's much easier to add more source files, add special rules for special files, and most importantly, the make program will handle dependencies so that if one source file haven't been modified since last build then it won't be compiled. The last bit will make big projects with many source files build much quicker when only one or a few source files has been modified.
How to learn more about the topics [...]
By going to your favorite search engine, and looking for those topics there. I also recommend e.g. Wikipedia.
Of course, if you use an Integrated Development Environment (a.k.a. an IDE) then you don't have to compile from the command line, or to make your own makefiles, the IDE will handle all that for you. It will also have dialogs for the project settings where you can enter include paths and library paths, and what libraries to link with.
Why I do I need to place the header file that contains only function prototypes?
So as to satisfy your compiler for declaration of those functions or declaration of classes. As C++ is static type checking language, they must know the type of objects which they will be using.
Where to place my own files and how to compile it?
You can place you code anywhere in you filesystem; only make sure to include .h files in includes path and lib while compiling. Usually you need to modify your path.
You can check about building on this link:
https://en.wikipedia.org/wiki/GNU_build_system
Check the README file that came with the code. It should tell you how to install it into the system properly. Usually there is an install build target which installs the resulting files into the proper directories.
The usual sequence of commands to build and install most products is:
$ ./configure
$ make
$ sudo make install

Having troubles with mixing library types (static vs. dynamic)

After battling my makefile woes I'm now onto problems with how the two libraries are supposed to interact. So, this is on Linux (CentOS 6.2 - 6.4, not that that seems to make much difference in terms of tools). The project, on the whole, is to be deployed in two flavors
A C++ Static library which is used for linking with other C++ appications (a *.a file)
A shared *.so which is deployed through python using Boost.python
I have everything compiling, but I'm not linking correctly somehow. In the case of the static library, it is built in two ways:
If meant to be linked with other C++ code, -fPIC is not used
If meant to be linked into the python module, use -fPIC
I control this through passing parameters to the make program. Presently, I'm trying to build the boost python module because the static stuff compiles just fine. So, I have dependencies on the boost libraries and zlib. The final linking command looks like this:
g++ -o pythonmod.so -L/boost/boost_libs -L/zlibs -lz -lboost_python -lboost_thread -lboost_regex -lboost_system /path/to/static.a -fPIC -shared [many_objects]
The "many_objects" comes from the various wrappers, and other code, that wraps the "pure" C++ from the boost.python layer in the code. Each of these object files are compiled with -fPIC as well. Their compiled with:
g++ -I/boost/boost_1_47 -I/usr/include/python2.6 -D _linux -MMD -std=c++0x -c -m32 -fPIC <input> -o <output>
The lines compiling the object files for the archive file look quite similar to the above only they do not include the python include directory.
I've found other links here to similar problems and tried the solutions but to no avail thus far. For example, this link uses -Wl,--whole-archive ... -Wl,--no-whole-archive. I tried this solution when I was trying to link in the static library archive before I was compiling it with -fPIC. Now that I'm doing that, I've tried this solution but also to no avail. In each case, every time I load up python and import the module, I get some sort of undefined symbol error --> something went wrong during linking.
How should I mix these libraries together to make the python module work?
After joining the gcc-help mailing list I received the pointer I needed to resolve the issue. The problem turned out to the ordering of the libraries used for linking on the build command line. Basically, the object files generated during the build for the *.so needed to be placed first. Then, the references to the boost and other libraries. Reordering the object files to reference the objects built for wrapping the static library before the other libraries was the key. No longer am I seeing weird "unresolved objects" when loading my python module.
After 4 or 5 years of using Visual Studio, my gcc knowledge had become sufficiently rusty that I'd forgotten the importance of ordering when it comes to linking.

How to make 64 shared 64-bit linux compatible library (*.so), for C++ code

My requirement is to work on some interface .h files. Right now I have .h and .cpp/.cc files in my project.
I need to compile it into shared 64-bit linux compatible library (*.so), using NetBeans/ Eclipse on Linux Fedora.
Since the GCC C++ ABI conventions did slightly change (in particular because of C++ standard libraries evolution, or name mangling convention) from one GCC version to the next (e.g. from g++-4.4 to g++-4.6) your shared library may be dependent upon the version of g++ used to build it
(In practice, the changes are often small inside g++, so you might be non affected)
If you want a symbol to be publicly accessible with dlsym you should preferably declare it extern "C" in your header files (otherwise you should mangle its name).
Regarding how to make a shared library, read documentation like Program Library Howto.
See also this question
And I suggest building your shared libraries with ordinary command-line tools (eg Makefile-s). Don't depend upon a complex IDE like NetBeans/ Eclipse to build them (they are invoking command-line utilities anyway).
If you are compiling a library from the 3 C++ source files called a.cc, b.cc, and c.cc respectively;
g++ -fpic -Wall -c a.cc
g++ -fpic -Wall -c b.cc
g++ -fpic -Wall -c c.cc
g++ -shared -Wl,-soname,libmylib.so.0 -o libmylib.so.0.0.0 a.o b.o c.o
Then you install the library using ldconfig, see man 8 ldconfig
you can then compile the program that uses the libary as follows (but be sure to prefix extern "C" before the class declarations in the header files included in the source code using the library.)
g++ -o myprog main.cc -lmylib
I have tried these compile options with my own sample code, and have been successful.
Basically What is covered in Shared Libraries applies to C++, just replace gcc with g++.
The theory behind all of this is;
Libraries are loaded dynamically when the program is first loaded, as can be confirmed by doing a system call trace on a running program, e.g. strace -o trace.txt ls which will dump a list of the system calls that the program made during execution into a file called trace.txt. At the top of the file you will see that the program (in this case ls) had indeed mmapped all the library's into memory.
Since libraries are loaded dynamically, it is unknown at link time where the library code will exist in the program's virtual address space during run time. Therefore library code must be compiled using position independent code - Hence the -fpic option which tells the translation stage to generate assembly code that has been coded with position independent code in mind. If you tell gcc/g++ to stop after the translation stage, with the -S (upper case S) option, and then look at resulting '.s' file, once with the -fpic option, and once without, you will see the difference (i.e. the dynamic code has #GOTPCREL and #PLT, at least on x86_64).
The linker, of course must be told to link all the ELF relocatatable object types into executable code suitable for use as a Linux shared library.

GCC How to export a function from static library

I want to create a shared library from several static libs using GCC under OS X.
In some static libs, there's no code in shared library call it, I just want to export the symbols in these static libs. This works under debug mode, but doesn't under release mode (especially when I enable the dead code striping). I can understand the reason, gcc think these functions on static libs are never used. but how can I force gcc to include these symbols?
I already tried adding -u option for loader, but it only generates a 'local' symbol. how to make linker generate an export symbol?
Also, I'm wondering if there's a way to add the linker directives in source code, just like the MSVC #pragrma comment(linker, "/INCLUDE:xxxx")
the function I defined in static lib is like:
extern "C"
void test() {}
Thanks in advance!
-Jonny
Have you tried --whole-archive?
Use ar to disassemble the static libraries into their constituent object files. Then link those objects together to make the shared library.
ar -x libstatic.a
(produces a bunch of *.o files)
gcc -shared -olibshared.so *.o # Linux
ld -dylib -olibshared.dylib *.o # Mac OSX