构建时的Microsoft C ++库符号链接

时间:2012-08-03 18:55:21

标签: c++ visual-studio-2008 linker

使用Visual Studio C ++ 2008 Express:

我正在尝试在如下编译的构建中执行最后的链接步骤:

  • 使用foo.lib开关静态编译库.dll(构建不会生成/MD)。 foo.lib的构建成功。 .lib文件和标头被发送到下面库的项目可以找到它们的目录。 foo.lib源代码是用非托管C ++编写的。

  • bar.dll被编译为带有/MD /LD开关的动态库。 bar.dll取决于foo.lib导出的符号。 bar.dllfoo.lib都是使用VS2008 Express工具链中相同的cl.exelink.exe二进制文件构建的源代码。 bar.dll源代码是用非托管C ++编写的。

  • .obj的所有bar.dll个文件都已成功构建,但在link.exe的最终执行期间会生成bar.dll,我会收到数千< / strong>关于未定义的外部的LNK2001错误。所有未定义的外部都是我期望在标准C ++库中的东西:像std::basic_string构造函数,std::_Throw类,ostream重载运算符,以及on和on。 link.exe表示未定义的外部foo.lib内未定义!

  • 目标是bar.dll在其中包含foo.lib的整个静态链接代码,以及它自己的对象,但动态地依赖{{1}的存在/解析在运行时和MSVCR90.dll

我是否尝试使用此版本设置一个不可能的情况,或者我只是做错了什么?如果这在理论上根本不起作用,请告诉我。否则,请告诉我在最后的链接步骤中我可以尝试确定哪些诊断可以确定MSVCP90.dll无法使用C ++库符号。

修改:更具体的信息:foo.libLLVM 3.1,foo.libbar.dlllibgl-gdi)版本来自llvmpipe分支的Mesa(目标是生成master上运行的opengl32.dll。我已满足所有构建依赖项,如下所示:

  • LLVM构建依赖于CMake作为构建系统,以及Python 2.7。
  • Mesa构建依赖于SCons作为构建系统,LLVM 2.6或更高版本,Python 2.7,pywin32,python-libxml2,bison和flex。除此之外,只有LLVM在运行时出货;其余的只是构建过程中使用的“工具”。

我还根据需要为每个项目自定义了构建环境变量并确保它们始终只使用llvmpipe开关而不是/MD或其他一些开关来选择错误的C运行时库。

3 个答案:

答案 0 :(得分:1)

来自MSDN help

  

定义 _MT _DLL ,以便从标准.h文件中选择运行时例程的多线程和DLL特定版本。此选项还会使编译器将库名称MSVCRT.lib放入.obj文件中。   使用此选项编译的应用程序静态链接到MSVCRT.lib。该库提供了一层代码,允许链接器解析外部引用。实际工作代码包含在MSVCR71.DLL中,该代码必须在运行时提供给与MSVCRT.lib链接的应用程序。

     

当/ MD与_STATIC_CPPLIB定义(/ D_STATIC_CPPLIB)一起使用时,它将导致应用程序与静态多线程标准C ++库(libcpmt.lib)而不是动态版本(msvcprt.lib)链接,同时仍然动态链接到主CRT通过msvcrt.lib。

更具体地说 - 这段摘录:“使用此选项编译的应用程序静态链接到MSVCRT.lib

换句话说 - 你需要将你的foo.lib链接到msvcrt.lib。

答案 1 :(得分:0)

这是与视觉工作室项目混淆的常见点。

/ MD不构建静态库。这是一个可以与visual studio(lib,dll,exe)的任何二进制输出一起使用的标志。它只是意味着你告诉你的二进制文件使用静态CRT(C运行时)。在通常情况下,这是错误的选择,当链接到不静态链接CRT的应用程序或DLL时(使用DYNAMIC CRT),您将遇到链接问题。

请点击此处了解更多信息:

http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=vs.71).aspx

“配置属性/常规/配置”类型下的项目设置下应该有一个设置。这应该是你用来确定你正在构建什么样的二进制文件的东西

答案 2 :(得分:0)

这是一个可以完成您正在尝试的工作示例。

foo.h中:

#ifndef FOO_H
#define FOO_H

extern void print_foo();

#endif

Foo.cpp中:

#include "foo.h"

#include <iostream>

void print_foo() {
  std::cout << "foo" << std::endl;
}

将foo.cpp构建到依赖于动态运行时库的静态库中:

cl /c /MD /EHsc foo.cpp
lib foo.obj

bar.h:

#ifndef BAR_H
#define BAR_H

#ifdef BAR_DLL
#define BARAPI __declspec(dllexport)
#else
#define BARAPI __declspec(dllimport)
#endif

BARAPI void print_bar();

#endif

bar.cpp:

#include "bar.h"

#include <iostream>
#include "foo.h"

BARAPI void print_bar() {
  std::cout << "bar" << std::endl;
  print_foo();
}

将bar.cpp构建到DLL中,该DLL从foo.lib中提取代码并依赖于动态运行时库:

cl /c /MD /EHsc /DBAR_DLL bar.cpp
link /DLL bar.obj foo.lib

一个简单的main.cpp表明它有效:

#include "bar.h"

int main() {
  print_bar();
  return 0;
}

像这样构建:

cl /c /MD /EHsc main.cpp
link main.obj bar.lib

(运行时库应该自动进入,因为/ MD选项应该将对象文件标记为需要动态运行时库。)

main.exe输出:

bar
foo