I've got a list of object files that I want to package in a library.
How do I do this? I thought I could use ADD_LIBRARY
add_library is the correct answer. To make a static library, you want to do something like this:
add_library(foo STATIC foo.c bar.c baz.c)
Static libraries are becoming a bit obsolete, but "ar" is the command you are looking for.
Related
I'm trying to compile a Windows DLL for code originally intended for a Unix platform. One problem I have is that Windows fopen() defaults to O_TEXT, but Unix defaults to O_BINARY.
Windows recommends two ways to solve this:
Use _set_fmode() function, didn't work for me probably because I could not call it from correct context.
Link with binmode.obj object file. This file is included with the compiler, and the compiler knows where to look for it.
The latter worked for my own code, but it does not seem to work for third party static libraries. Looking at the linker output, I can see that static libraries are included before binmode.obj, but binmode.obj was included before my own object files.
The real solution should be to persuade all external libraries to include binmode.obj, but this is somewhat non-trivial and might incur significant maintenance overhead in the future.
So I'd like to try to move the binmode.obj to the beginning of the linker command line, but this proved to be surprisingly difficult. I've tried:
target_link_libraries( mylib PRIVATE binmode.obj ) - Got correct position, but got renamed to binmode.obj.lib casuing linker error.
Tried making a static library with binmode.obj as a pre-compiled object, but got an error that the file has a relative path. I have no idea how to make it a full path.
Tried adding it as a linker flag in different ways, even including using toolchain file, but it all ended up with binmode.obj being placed after libraries.
I'm now out of ideas and feel I need help with this. Any suggestions how to fix this?
#fabian's comment made me read the right part of CMake documentation, which made me realize that UNKNOWN library type could be used. Using the following code in CMake I could make binmode.obj appear before all libraries:
add_library( binmode_obj UNKNOWN IMPORTED GLOBAL )
set_target_properties( binmode_obj PROPERTIES IMPORTED_LOCATION binmode.obj )
target_link_libraries( mylib PUBLIC binmode_obj )
This solved my problem of trying out if link binmode.obj before libraries might fix my original problem. It didn't, unfortunately. But that is another problem...
I would really like to create a single binary for my application however it depends on libzmq and I am building on OSX, has anyone managed to get an external library linking correctly on a mac?
I did something similar with lua. My aproach is to pass full path to the static library to ghc. In cabal file:
if os(darwin)
ghc-options: /usr/local/lib/liblua5.1.a
According to documentation ghc will pass it to linker:
Files with other suffixes (or without suffixes) are passed straight to
the linker.
However it doesn't work if the library is used in other package which you depend on. So if you are using e.g. zeromq4-haskell package, then you need to modify it locally.
In our build system, we generate multiple .so files (foo.so, bar.so, ...) that are loaded during runtime by the main executable (biz). So the .so files are linked separately.
We also have our own util.a static library, that has some utility functions and global data.
The problem comes when some of the .so want to use util.a data/function, but we can't link each .so to util.a. It's because of the data section: global data must be unique in the program address space. If more than one .so is linked to util.a and has a copy of the data, the program behavior will be very surprising but hard to debug.
We can't link executable (biz) to util.a either. The linker will not put everything to the target, since biz doesn't reference the functions on behalf of .so.
Of course, unless linking util.a with -Wl,-whole-archive. But is there a better way to do this?
Solution 1: consider making util.a a dynamic library util.so.
Solution 2: don't let the linker export any symbols exported by util.a. When using gcc you can achieve this for example by using __attribute__((visibility("hidden"))):
int __attribute__((visibility("hidden"))) helperfunc(void *p);
You can use objdump to check which symbols are exported.
To answer myself's question, the eventual solution was like:
http://lists.gnu.org/archive/html/qemu-devel/2014-09/msg00099.html
TL;DR: Search for all the interesting symbols (that you want to pull from archives) inside the .so objects with nm (1), and inject into the compiling command line with -Wl,-u,$SYMBOL. Note that the -Wl,-u,$SYMBOL arguments need to come before archive names in the command line, so the linker knows that it needs to link them.
I have a static lib (my_static_lib) which I link to an executable binary file. Some of the symbols, but not all, are used in my binary.
A second library, dynamically loaded(my_shared_lib), is expecting to receive some symbols from my_static_lib through symbol injection from the binary. But those symbols are not used by my_binary, so they are stripped off the final bin file.
So, at runtime, my_shared_lib complains that it cannot find __my_stripped_symbols__ and crashes.
Is there a way to force the linker to keep __my_stripped_symbols__? I would prefer something that can be cleanly written in a Makefile.am (autotools)
(-binary file makefile)
-L$(top_builddir)/static_lib -lmy_static_lib --magic-flag-to-keep-stripped-symbol
I do not want to link my_static_lib with my_shared_lib because it will generate strange conflicts in other parts of a rather complex group of executables/shared libraries.
When you link my_static_lib to your application, you want to use the --whole-archive option. It's documented in the ld options docs.
If you're linking with gcc, it looks something like this:
-L$(top_builddir)/static_lib -Wl,-whole-archive -lmy_static_lib -Wl,-no-whole-archive
That will make sure the entire library is kept, and not just the specific functions that your executable uses.
You also need to make sure that the symbols get exported. If the symbols from your static library aren't being exported already, you make need a combination of -fvisibility=hidden and use __attribute__ ((visibility("default"))) to mark up the ones you want exported. You can read a little more about it in the gcc docs
I wanted to try out the Boost::Serialization library for a project I'm working on. I'm also trying to get used to programming in Linux as well. I set up boost in its default locations. I tried compiling the test file they provide here with the command line arguments they provide and it worked fine. In this example they use the .a file.
Then I went to the Serialization page and tried running one of the serialization demos. I ran basically the same commands, except I swapped out the file names and linked against libboost_serialization.a instead of libboost_regex.a, but I got a bunch of errors. After playing with different options and double checking the directories I finally got it to work by replacing the .a with the .so file.
Just for reference, what finally worked for me was this:
g++ /usr/local/lib/libboost_serialization.so sertest.cpp -o sertest
How come for one example I linked against the .a file, and in the other I had to link against the .so?
Because when linking statically, the order in which you specify the libraries and object files does matter. Specifically, a library must be mentioned after object files that use symbols from it.