将程序链接到静态库,将自身链接到另一个库 [英] Link a program to a static library, linking itself to another library

查看:134
本文介绍了将程序链接到静态库,将自身链接到另一个库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Windows(VS2015)上创建一个可以读取多种文件格式的程序(C ++). 为此,我创建了一个解决方案,其中包含MyProgram项目(主程序)和MyLibrary项目(其中包含多个用于不同文件格式的解析器). 在MyProgram中,我根据程序输入创建一些解析器对象.

一切正常.

但是,我尝试创建一个新的文件格式解析器(NiftiParser),该解析器使用我下载并编译的外部库nifticlib(作为静态库).

因此,我创建了NiftiParser类,该类实现了一些方法,并且在内部调用了nifticlib. 我在项目属性中添加了include dir和library dir,并且编译时没有错误. 然后,我得到了一个已经创建的Parser.lib.

但是,当我尝试编译MyProgram时,出现有关nifticlib库的某些功能无法解析的错误:

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 ========== 

我不确定为什么会这样.我试图将include的路径和nifticlib的库目录添加到MyProgram项目中,但是仍然存在一些问题.

我不确定要了解Visual Studio(我以前在Linux上工作过)的编译/链接过程是什么.

在我看来,仅当项目是静态库时,才对项目进行编译,而链接部分仅在我尝试编译程序本身时发生. 我说的对吗?

此外,我不确定nifticlib应该在哪里链接.应该到Parser.lib(我在其中使用库的功能)还是直接到程序?

谢谢.

PS:另外,我注意到我的nifticlib安装目录仅包含标头和.lib.我是否也需要在其中包含.cpp,或者功能已经包含在.lib中?

好吧,显然,将某些内容构建为静态库不会将其链接到任何内容,所以这可能就是为什么我在编译Parser.lib时没有遇到任何问题的原因,因为它没有链接到nifticlib,但是MyProgram需要它. 所以我应该只在我的Parser项目中包括nitficlib的include目录,并将Parser.lib和nifticlib放在MyProgram项目中吗?

解决方案

Visual Studio的编译/链接与Linux工具链中的编译/链接没有太大区别.在制作二进制文件(可执行文件或动态库)时,必须解析所有外部符号.在GCC中,您必须将库指示给链接器.命令行选项-lmath将告诉链接器从为库搜索设置的路径之一加载 libmath.a ,并在构建可执行映像时使用它.

类似地,在VS中,您不仅需要设置库目录的路径,还需要显式指示库文件.这通常是在项目属性->链接器->输入->其他依赖项上完成的.请注意,在Windows中,您只需要输入完整的库名( MyLib.lib ),而不是 lib .a

还请注意,在Windows中,您不能链接到动态库(.dll)的二进制文件.您将需要一个导入库(.lib).

创建静态库时,工具链不会解析外部引用.这就是为什么.lib在没有引用nifticlib的情况下可以很好地编译的原因.

关于应该在哪里链接nifticlib,取决于具体情况.如果只有MyLibrary会使用nifticlib的功能,将其与静态库链接是明智的.但是,如果有一天您希望直接在MyProgram中使用nifticlib中的某些功能,则在链接时可能会发生冲突.在这种情况下,仅在构建MyProgram时才需要链接nifticlib.

经验法则可以这样表示:

  • 如果只有MyLibrary使用nifticlib的标头,则将您的库与第三方库链接起来
  • 如果MyProgram还使用nifticlib的标头(并实际上从它们中调用函数),则在构建MyProgram时最好链接nifticlib

这不是一个严格的描述,情况更复杂,但基本知识是这样的.

不,当您从其他项目链接到该库时,不需要在构建静态库时使用的cpp文件.库.cpp的内容已经以目标代码的形式包含在静态lib文件中.

如果您希望将静态库与其他静态库中的外部链接起来,则需要转到项目属性->库管理器->常规->其他依赖项,并放置外部.lib在那里

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

这篇关于将程序链接到静态库,将自身链接到另一个库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆