使用Visual Studio C ++ 2008 Express:
我正在尝试在如下编译的构建中执行最后的链接步骤:
使用foo.lib
开关静态编译库.dll
(构建不会生成/MD
)。 foo.lib
的构建成功。 .lib
文件和标头被发送到下面库的项目可以找到它们的目录。 foo.lib
源代码是用非托管C ++编写的。
库bar.dll
被编译为带有/MD /LD
开关的动态库。 bar.dll
取决于foo.lib
导出的符号。 bar.dll
和foo.lib
都是使用VS2008 Express工具链中相同的cl.exe
和link.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.lib
为LLVM 3.1,foo.lib
为bar.dll
(libgl-gdi
)版本来自llvmpipe
分支的Mesa(目标是生成master
上运行的opengl32.dll
。我已满足所有构建依赖项,如下所示:
我还根据需要为每个项目自定义了构建环境变量并确保它们始终只使用llvmpipe
开关而不是/MD
或其他一些开关来选择错误的C运行时库。
答案 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