Link a program to a static library, linking itself to another library - c++

I'm trying to create a program (C++) that can read multiple file formats, on Windows (VS2015).
In order to do that, I created a solution with a Project for MyProgram (which is the main program), and a project for MyLibrary (which contains several parser for different file formats).
In MyProgram I create some parser objects based on the program input.
Everything was working well.
However, I tried to create a new file format parser (NiftiParser) that uses an external library, nifticlib, that I downloaded and compiled (as static library).
So I created my NiftiParser class, that implement some methods, and internally, it calls nifticlib.
I added the include dir and library dir in the project properties, and it compiled without errors.
I then got a Parser.lib that has been created.
However, when I tried to compile MyProgram, I got an error about some functions of nifticlib library not being resolved:
1>------ Build started: Project: Parser, Configuration: Debug x64 ------
1> nifti_parser.cc
1> Parser.vcxproj -> C:\Users\Laurent\Documents\C++-build\Projects\Parser\Debug\Parser.lib
2>------ Build started: Project: MyProgram, Configuration: Debug x64 ------
2>Parser.lib(nifti_parser.obj) : error LNK2019: unresolved external symbol nifti_image_read referenced in function "public: __cdecl NiftiParser::NiftiParser(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0NiftiParser##QEAA#V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
2>C:\Users\Laurent\Documents\C++-build\Projects\Debug\MyProgram.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 1 succeeded, 1 failed, 3 up-to-date, 0 skipped ==========
I'm not sure to understand why this is happening. I tried to add the path of include and the library dir of nifticlib to MyProgram project, but I still have some issue.
I'm not sure to understand what is the compilation/linking process for Visual Studio (I used to work on Linux).
It appears to me that the projects are only compiled if it's a static library, and the linking part only happen when I try to compile the program itself.
Am I right ?
Also, I'm not sure where nifticlib should link. Should it be to the Parser.lib (where I use the functions of the library) or directly to the program ?
Thank you.
PS: Also my noticed that my install directory of nifticlib only contains headers and .lib. Do I need to have the .cpp in there too, or does the functions are already contained in the .lib ?
Edit: Ok, apparently building something as a static library doesn't link it to anything, so that's probably why I didn't get any issue compiling Parser.lib, because it doesn't link to nifticlib, but MyProgram needs it.
So should I only include the include dir of nitficlib in my Parser projects, and put the Parser.lib and nifticlib in my MyProgram project ?

The compilation/linking of Visual Studio does not differ much from what is happening in Linux toolchains. When you are making a binary (an executable or a dynamic library) all external symbols must be resolved. In GCC you must indicate the libraries to your linker. The command line option -lmath will tell linker to load libmath.a from one of the paths set for library search and use it when building your executable image.
Similarly, in VS you need not only to set the path to library directories, but to explicitly indicate the library file as well. This is usually done on project properties -> Linker -> Input -> Additional dependencies. Note that in Windows you just put in the full library name (MyLib.lib), not the part between lib and .a
Also note that in Windows you cannot link to the binary of a dynamic library (.dll). You will need an import library (.lib) for it.
When you are creating a static library, the toolchain does not resolve the external references. That is why you .lib compiled fine without referencing the nifticlib.
As for where you should link the nifticlib, it depends on the circumstances. If only your MyLibrary will ever be using the functions of nifticlib, it is wise to link it with your static library. However, if someday you'll wish to use some function from nifticlib directly in MyProgram, there may be a conflict at link time. In this case you will need to link the nifticlib only when building the MyProgram.
A rule of the thumb can be formulated like this:
If only MyLibrary is using the headers of nifticlib, link your library with third party one
If MyProgram also uses the headers of nifticlib (and actually calls functions from them), it is better to link the nifticlib when building MyProgram
This is not a strict description, and there are more complicated cases, but the basics are like this.
And no, you don't need the cpp files used when building your static library, when you are linking to that library from a different project. The contents of the library .cpp's is already included into static lib file in the form of object code.
Edit: If you do wish to link you static library with the externals from another static library, you need to go to project properties -> Librarian -> General -> Additional dependencies and put the external .lib there

Related

Linking a lib statically in VC++

Probably I am missing here something but that is my first time on Windows that I need to link a lib statically so that the executable won't be dependent on a dll.I do it with LIBPNG.
I do it like this:
I added libpng headers : C/C++ -> Additional Include Directories
Added library directory to the linker: Linker - > General ->
Additional Library Directories
Added linker additional dependencies:Linker -> Input
Compile the exe ok.When calling it I am getting :
"The program can't start because libpng16.dll is missing from your
computer."
Which means libpng hasn't compiled into the executable.How do I fix that without reference the whole pnglib project code into my executable project?
On Windows a .lib is a library file, usually this simply contains code that loads a dll, looksup the exported functions and provides wrappers to them. But, you can build the lib differently so that instead of these wrapper stubs, it contains the actual binary code. The operation and structure of the .lib is the same - what code it contains depends on how its built.
So, if you've built libpng16 as a 'dynamic' lib/dll pair then you will need the dll part when you deploy it. If you built it as a 'static' lib only, then you'll get what you want.
The point is - you need to build the lib in the format you want in the first place. It is not possible to take a lib/dll pair and convert it into a static lib, nor is it possible to merge a dll into your executable. (well, not possible after you've built it - perfectly possibly if you change the lib's settings and recompile to produce in static lib form, of course)

How to use the OpenCV 2.4 static libraries with Visual Studio?

I'm trying to set up OpenCV 2.4 as follows:
I've downloaded and extracted the precompiled package to C:\OpenCV240.
In Visual Studio, I've added C:\OpenCV240\build\include as an additional include directory.
Furthermore, I've added C:\OpenCV240\build\x86\vc10\staticlib as an additional library directory.
And I've specified all available .lib files as additional dependencies.
When I compile my "Hello World" program (which compiles just fine when using the DLLs), I get a lot error messages like this:
1>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: __thiscall std::_Container_base12::~_Container_base12(void)" (??1_Container_base12#std##QAE#XZ) already defined in opencv_core240d.lib(matrix.obj)
What am I doing wrong?
It sounds like you need to specify linking against the static C runtime library in your program.
If OpenCV linked against the static CRT and you use the dynamic one, you get these types of redefinition errors.
To change this setting, open your project's Properties and go to Configuration Properties -> C/C++ -> Code Generation.
Change Runtime Library from Multi-threaded Debug DLL (/MDd) to Multi-threaded Debug (/MTd). Do the same for your other configurations, using the non-Debug variant where appropriate.

C++ linking error unresolved external symbol

I have a project that includes files from a different project. I am getting linking errors...
"unresolved external symbol "public: _cdecl classA::classA(void"
(??()classA ##QEAA#XZ) referenced in function "class classA *_cdecl
functionB(char const*)" (?functionB##YAPEAVClassA##PEBD#Z)...
and other 125 errors of the same type (after the constructor, which is the error I just listed, every function from the class I use is mentioned in one of the link errors).
The path for including the files of the second project is included in my property sheet. That project, on its own, builds fine.
I have tried to add that project to my solution, and add it as a dependency. No help. I have tried to add the dll that it creates in the project - linker - input. No help.
In Configuration properties, the Runtime Library is set to /MTd.
I have even tried to add extern "C" in front of my include. No help.
I have tried to build them with Debug or Release, x64 or Win32. I prefer Release x64 but I'll take anything.
Could you please help me - tell me what am I doing wrong, or where to look to fix this problem ? Thank you very much.
When you build the project which yours depends on, it should produce both a lib and a dll. You need to link that lib with your project. See this thread for a screenshot of how to link the lib in your project.
I found out that my dependencies in the Link - Input were being removed by the fact that I didn't explicitly specify that I can have dependencies in the property sheet. After changing the property sheet, I finally was able to create a dll.

How to compile a static library? ("-static-lib..." equivalent?)

I am using VS2010 and
I have a C++ project that is referencing and using an external C library (dll) by having various entries in the VC++ Directories and Linker sections of the project properties.
Right now my project is building but when it starts, a message box appears :
The program can't start because ExternalCLibrary.dll is missing from your computer. [...]
I would like to know how to do in Visual Studio 2010 the the equivalent of
adding "-static-libgcc -static-libstdc++" to your compiler flags.
It seems to be the solution according to:
The program can't start because libgcc_s_dw2-1.dll is missing
Load your project in Visual Studio.
Right click your project and
choose Properties.
Locate the "Linker" portion of the tree on the
left.
Choose All Configurations and All Platforms from the drop down
menus at the top of the dialog.
Put your additional static library
dependencies in the Input -> Additional Dependencies field, semicolon delimited.
If the libs are not on your lib search path, make appropriate
entries in the General -> Additional Library Directories field, semicolon
delimited.
Apply, save, compile, run.
You can't use dll as a static library ( that's why they are called Dynamic-link library ). In order to compile a static library, you'll the source code of that library. Once you have the source code, go to Project settings, General->Configuration Type and set it to Static Library(.lib). Then in your program, you'll need to add that library by putting the library name in Linker->Input->Additional Dependencies
The two flags passed to gcc as per your question tell gcc to link the runtime library statically to an executable or shared library/dll. This is unlikely to be the problem with your issue as the part of the error message you quoted suggests that ExternalCLibrary.dll isn't being built properly.
If the DLL exists, use a tool like dependency walker to determine which dependency of your DLL can't be loaded; that's the likely culprit.
If ExternalCLibrary.dll doesn't exist then you need to find out where you are supposed to get it from, but if your project builds and it's listed in the project as a dependency then my guess is that it's an issue with the loader not being able to find a dependency of this DLL at runtime.
This process is simple, however you need to be aware of several things. The first thing, if your lib is written in C, in the header files of every source containing C functions us the following.
#ifdef __cplusplus
extern "C" {
#endif
// C functions
#ifdef __cplusplus
}
#endif
Once you've done that, compile the library into a static library using the ar rcs [YOUR OBJECT FILES]. The final thing to do is us the c++ compiler link the library with the object files from your project. Now flags are required to link the library.

ImageMagick static compilation with another project gives linker errors

I've downloaded the ImageMagick source, compiled the wizard to create a Visual Studio solution for static linkage, and included the static library Magick++ project in my sample project (code below). I've also added a dependency on that project and included the .lib file in the solution, nothing helps.
#include <Magick++.h>
int main()
{
Magick::Image image;
bool test = image.isValid();
return 0;
}
This gives several linker errors, such as:
unresolved external symbol "__declspec(dllimport) public: virtual __thiscall Magick::Image::~Image(void)" (__imp_??1Image#Magick##UAE#XZ) referenced in function _main
Why can't it find the implementation?
I'm using Visual Studio 2010 Beta 2.
The problem may rise from that you are using different compiler than the library was compiled with. As your compiler is fairly new, it's very likely it uses different name mangling and can't find method signatures inside the library.
The answer to linking the ImageMagick static libraries is to ensure you link ALL the dependant static libraries as well!
Once you have compiled the solution for ImageMagick static libraries, go to the 'VisualMagick' folder (within the ImageMagick cloned repository) then to to the 'lib' folder there you will see all the _DB_.lib and _RL_.lib files for Debug and Release.
You need to include those names in the 'Additional Dependencies' section for both Release and Debug.
You must also ensure you have the Library folder path in the 'Additional Library Directories' for both Release and Debug.
Another key aspect is to ensure the libraries are built by the same compiler for the same platform architecture as your own application .. (WIN32 or x64).
This error is strange - The compiler is looking for a function from a DLL (__declspec(dllimport)). Are you sure you are using the right header files ?