whiteShadow whiteShadow - 2 months ago 5
C++ Question

Link a program to a static library, linking itself to another library

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