Statically linking to libarchive on Windows with MinGW - c++

I've been using libarchive in my project for some time now and it's working great, at the moment I am dynamically linking to it, so on Windows the libarchive.dll file has to present on the system.
I would now like to statically link to the library so I don't have to bother distributing the DLL, but I'm having real trouble trying to achieve this!
Currently, in my make file, I have something like this:
-Lpath/to//libarchive/ -larchive
And this works, but it does a dynamic link. I don't know how to enforce a static link.
I can see in the libarchive directory there are two a files, libarchive.dll.a and libarchive_static.a. I suppose I want to link to libarchive_static.a but I can't seem to specify this, doing -larchive_static in the make file results in linker errors.
I was under the impression that static libraries under windows are lib files, but I get no such file type when I build libarchive.
How can I make a .lib file from libarchive. Also, as an extra question, what is the difference between an a file and a lib file?
Update
To statically link to libarchive, your library command for make should contain:
-Lpath/to//libarchive/ -larchive_static
This will link to the libarchive_static.a file. However, you also need to define LIBARCHIVE_STATIC in your code.
Now the problem is that libarchive depends on the bzip2 libraries (as well as others), and if you do not have a static build of them you will get linker errors something like:
undefined reference to `BZ2_bzCompressInit'
You need a static build of the dependent libraries and a similar command to the linker after the libarchive command:
-Lpath/to/bzip2/ -lbzip2
You can either build bzip2 from source, or do it the easy way and get a pre-built binary from the Gnu32Win project here: http://gnuwin32.sourceforge.net/packages.html

Just add libarchive_static.a explicitly to your link command.
gcc -o YourApp.exe $(OBJS) path/to/libarchive_static.a $(OtherLibs)
".lib" files differ from compiler to compiler (Borland, Microsoft etc.), ".a" is an old "archive" format from UNIX's ar tool. It is now used only for the bundling of static libraries.
Currently, in my make file, I have something ...
And this works, but it does a dynamic link
The .a file actually contains some code for dynamic linking to the .dll file, not the libarchive itself. On the startup the pointers to functions are allocated and dynamic linking is done.

Related

Linker can't find lib in Eclipse/JNI/ANT

I am trying to build a large Java/c++ project involving JNI and ANT in Eclipse, under Linux. One of the source c++ files calls the log10() function for mathematical calculations. The project compiles fine, but fails at linking, where it complains that it cannot find the libm.so library necessary to link log10().
My problem is that I am unable to properly tell Eclipse to link that file, even after the following steps:
Added the correct library path in the linker options,
Added a reference to libm in the linker include list,
Added -lm to the full compile options list,
Set LD_LIBRARY_PATH to point to the library's location,
Copied the library to the current directory.
What am I doing wrong/has anyone had such experiences with correctly linking libs in Eclipse? Any suggestions?
This is a bit confusing.
If you fail to find your library at runtime inside your java environment :
Try loading your .so library inside the java environment before making any calls to log10.
System.LoadLibrary("m");
Notice how I left "lib" and ".so" out.
However, you are complaining of a Linker problem from C++, you cannot link to a dynamic file. You can only link to a static library, or a static export library (so you need a libm.a file to which to link at compile time, and then your program will require libm.so at runtime).
Could you post the exact message you are receiving and when you are receiving it ?

Include a static library in a static library - CodeBlocks

I'm having an issue compiling a static library using Code::Blocks 13.12. I need to use a third party static library from within my own static library. So, I have libOtherLib.a and I'm trying to build libMyLib.a and link in libOtherLib.a. The problem is that the linker is not including libOtherLib.a during the linking phase of the build. Here is some additional information:
I am using the GNU GCC Compiler
In Project build options for the whole project (not specifically Debug or Release)
I have added libOtherLib.a in the Link Libraries list in the Linker Settings
I have added the path to libOtherLib.a in the Search directories -> Linker list
I have added the path to the .h file for libOtherLib.a in the Search directories -> Compiler list
The library compiles completely fine (produces bin/Debug/libMyLib.a with no errors)
Any help would be greatly appreciated. I have an inkling that it is related to this being a Static Library rather than an application (console or otherwise), but I'm not sure how or why. I did change the build target Type to "Console Application" in the Project Properties window and it looked like it was linking in libOtherLib.a, but it had other errors because this code is meant to be a library rather than an application.
Here is the linker command that is executed at the end of the build. libOtherLib.a is not there anywhere, that is the problem, just not sure what the solution is.
ar -r -s bin/Debug/libMyLib.a <all of my .o files>
Possible causes of the problem would also be nice - if this is mostly like the compiler, the linker, the setup or Code::Blocks itself.
When building a static library you are just putting together a bunch of object files into an entity easier to ship and use. There is no linking done when building a static library.
The unresolved references from your library are dealt with when building an application or certain shared objects. You'd just ship your library and require that users also supply the library your library deoends on when building.
If you want to include the library you are depending on in your library you can extract the object files from tgat library and include them into your library. Although technically possible it is questionable if you have the rights to do so. Also, that is normally not the way things are done and I'd recommend against doing so.
You can't link a static library in anoter static library.
However,you can do this:
Suppose MyPrograme.exe need to link static library libMyLib.a,make MyPrograme.exe also link libOtherLib.a.
Since libMyLib.a is static library,there is no need to link libMyLib.a.Just inclue the headers.
When build a static library,it will only be compiled,not be linked.
Despite all this "linking is not the right term for this" philosophy, you can patch Code::Blocks compiler configuration to support this, for example for the GCC/G++ compiler.
http://green-candy.osdn.jp/codeblocks_config.html
The idea is that you replace the "Link object files to static library" script in the "Advanced compiler options" window of GCC with:
rm -f $static_output
$lib_linker -r -s -T $static_output $link_objects
$lib_linker -r -c -T $static_output $link_options
Then you can put the relative path to your "libOtherLib.a" in the "Other linker options" editbox of your projects. This mod is not really officially endorsed but it works in my projects, so you get static libs in static libs just like in MS Visual Studio!

How do I link a library to my project in CodeBlocks & GCC without adding the library source to my project

I am writing a program that uses the hashlib++ library (or will use it) but I don't want to add all of it's source files to my project because it's huge. Is there anyway to link to the hashlib++ source files so that I can use it in my project? I've tried linking to the header directly with a simple
#include "path/to/hashlibpp.h"
But I receive a nifty error for it as soon as I attempt to call any functions from the library. For example:
undefined reference to `sha1wrapper::sha1wrapper()
I am using the Code::Blocks IDE and GCC compiler.
First you have to have the library installed on your machine, already compiled into a static or dynamic library file. You can install from source, or you may find a pre-built package available for your OS (depending on which OS you are using). You will need to know the name of the library.
In the case of hashlib++ they have provided instructions to build a static library from source in their README; see section 3.2.
In most cases, dynamic linking is the best choice. This means that the library is linked with the library at run time, instead of adding the library to your executable when it is compiled (which would make your executable file much larger).
Unfortunately, according to their README.txt, hashlib is only available as a static lib, which limits your choices.
When compiling a program on the command line using gcc, the '-l' option links in a library:
gcc -o MyProg -lhl++ MyProg.c
When using an IDE like Code::Blocks, you normally have to specify the libraries to be linked. See this answer for details on how to do this with Code::Blocks.

Code::Blocks and boost 1.55: static library is not used when dynamic library is present

I have built the boost 1.55 serialzation library with the following command:
b2 --build-dir=build toolset=gcc --with-serialization --layout=tagged link=static threading=multi stage
and got libboost_serialization-mt.a and libboost_wserialization-mt.a in my stage/lib directory - fine. Then I added boost_serialization to my C::B project's linker library list and compiled the boost serialization example and it ran fine from the command line. I then built the dynamic and single thread variants additionally using
b2 --build-dir=build toolset=gcc --with-serialization --layout=tagged link=static,shared threading=multi,single stage
and got more libraries in my stage/lib directory, as expected. What puzzles me is that there is a .so file for every library, even those that should be static. Why is it there? What is it needed for?
When I now compile the project, the executable complains:
error while loading shared libraries: libboost_serialization.so.1.55.0: cannot open shared object file: No such file or directory
The library is definitely there and I might just need to add the path to it to LD_LIBRARY_PATH, but I want to link statically for now. How can I do that?
I also don't quite understand the library naming: I have some libboost_wserialization... libraries in my lib folder and the w prefix to serialization is not described in the library naming section of the current boost getting started page.
Your answers gave me a better understanding of what was going on - now I know where the boost_wserialization libraries came from. I turned out that after doing the second build, all present libraries were shared, and the static libraries were overwritten. That's why I got confused by the "extra" .so files for those libraries which previously were indeed static.
Ok, first question:
Why is there a boost_serialization and boost_wserialization library?
the wserialization library is wchar_t oriented. Put into a separate library because it may not actually be needed.
Why are there multiple shared/static libraries?
The reason you're seeing all those extra shared libraries is because you're invoking b2 with link=static,shared, which instructs boost to build the shared libraries as well as the static libraries. Additionally, adding in the thread=multi causes the building of the mt libraries, which are libraries that should be used when linking to multi-threaded applications.
Why am I getting the run-time link error about libboost_serialization.so.1.55.0?
By default, most unix/linux systems will prefer the use of shared libraries over static libraries when linking, so when you try to link it will prefer to use the shared libraries over the static ones. If you want to force the link of the static library rather than the shared one, you tell the compile-time linker to do that, using:
-Wl,-Bstatic -lboost_serialization -Wl,-Bdynamic
This will cause the linker to look for the static variant of the boost_serialization library, rather than the dynamic one.
Now, because you're using code::blocks, I'd have to look up how to specify these flags on a case-by-case basis, but the most sensible thing to do is to clean the boost build using ./b2 clean and then rebuild, specifying only link=static, then you should end up with only .a files, which will produce stand-alone executables again.
If you want to specify this option for code::blocks, you would need to put them into the Build Settings -> Linker settings -> Other Linker Options field for the project. Simply specifying the library in the libraries field will not work for this case. Additionally, forgetting to pass in the -Wl,-Bdynamic option will cause it to try to link in static versions of some platform libraries, which can lead to build failure if the library in question is not present.
If you want to avoid having to set LD_LIBRARY_PATH to run the binary, you can add the option -Wl,-rpath,/path/to/boost/libraries, to the linker flags which will cause the compiled program to search that directory when trying to resolve the location of libraries.
What puzzles me is that there is a .so file for every library, even
those that should be static. Why is it there? What is it needed for?
You apparently are using someone else's make file. I wrote my own. My build command does not create a ".so" (shared object library). It only creates the ".a" (archive library). The linker knows how to use either.
See man ar. The utility ar builds archives.
See man ld. The utility ld can build shared objects.
You might look for these utility invocations in your build sequence, or ask someone where they are and comment out the use of ld, as you most likely do not need both (and building both will extend your build time unnecessarily). Alternatively, you might temporarily rename the ld command, and try your build. When it can not find the ld command, you might get a useful hint as to where the ld is invoked.
In my make file, the commands look like the following. The comment char is a # at beginning of line. (The string expansions $(AR) and $(LD) allow the use of non-standard utilities.)
$(TARGET_ARCHIVE): $(OBJ)
#echo R10: $(TARGET_ARCHIVE) :from: $(OBJ)
$(AR) crs $(TARGET_ARCHIVE) $(OBJ)
# $(TARGET_OLB) : $(OBJ)
# #echo R00: $(TARGET_OLB) :from: $(OBJ)
# $(LD) -o $(TARGET_OLB) -r $(OBJ)
The archive (.a), when used, is linked directly to and included in your executable. When the executable is loaded, all the referenced symbols of the .a are already in it. (un-referenced symbols and code are not linked in)
The shared object (.so) is not directly linked, but rather your executable gets a handle (or perhaps a file name) to the .so. It is my belief that when your executable is loaded, the .so is not immediately loaded. The .so does not load until the first time your executable references a symbol that is in the .so. At that loading, your app will experience a delay, but probably this late loading is reasonable for most applications.
It is also possible that the .so is already loaded in system memory before you activated your process. In that case, when your executable first references a symbol in the .so, some system code will 'map' the existing in-memory .so to your application -- probably faster than loading it, but I suppose the big benefit is that a .so that is used / referenced by many processes need only be loaded once, saving memory space. The loaded .so has all of its symbols, even if your app does not need all of them.
In either case, your executable will be smaller with .so's, bigger with .a's, but the .so's have some small performance hit for each .so that needs to be loaded or mapped in. With 4 GB in my desktop, the desktop has never felt 'crowded'. It's swap has never been used (afaik). So I generally use .a's.
NOTE: When the linker has access to both an archive (.a) and a shared object (.so) file, the linker will use the .so (and ignore the .a). Probably you can override that preference, but I have not tried. I find it easier to simply move the archive (.a) into a separate (from the .so's) directory, and inform the linker via the -L build option.

g++ Linking vs VisualC++ Linking

I have been trying to get this working for a while now and am unable to find an answer elsewhere, here is my problem.
When I make a static library in Visual C++ any dependencies that this library uses are carried on to the executable program that I link the library to. Here is an example
Test.lib depends on
- SDL
- OpenGL
TestApp.exe links Test.lib
In Visual C++ I do not have to add the dependencies for Test.lib in my TestApp executable, they are carried over and it works great.
However when I port my code to Linux g++ (With the Code::Blocks IDE), if I make a Static Library which is .a in g++, and I make a TestApp that links the library, it gets undefined references to the dependencies.
Is g++ able to do this, and if so what am I missing to have the dependencies carried over to my executable?
As for my settings for my library I simply use the IDE's Static Library setting.
With Microsoft's compiler, header files can have library dependency information in them (source files, too, but this is typically done in headers); this gets compiled into the object file, and the linker understands and applies that information. That can be handy: you don't have to remember long, funky names, and if you compile two source files with incompatible options you may get a library name conflict that the linker will complain about. Most compilers and linkers don't do this kind of thing, and you have to tell the linker explicitly which libraries you want to link with.
Static libraries do not statically link with other libraries. Does that sound right?
However you can pack many object files together with a tool called ar.
What happens on windows is probably because you have the (SDL, opengl32) dlls somewhere in a system env path.