【发布时间】:2012-02-15 21:41:02
【问题描述】:
有什么预处理技巧或者什么东西可以让你同时编译一组函数,一个lib和dll版本?
【问题讨论】:
标签: c++ windows visual-c++ dll
有什么预处理技巧或者什么东西可以让你同时编译一组函数,一个lib和dll版本?
【问题讨论】:
标签: c++ windows visual-c++ dll
编译器不必知道您是在制作静态库还是动态库——它只制作目标文件。
然后您可以获取这些目标文件并将它们传递给库管理器(创建静态库)或链接器(并创建共享对象/DLL),是的,您可以使用相同的目标文件执行这两个操作,只要当您使用链接器定义文件来控制 DLL 导出时。
使用 Visual Studio 的一种便捷方法是设置一个依赖于静态库的 DLL 项目,并为该依赖项选择 "Use Library Dependency Inputs" 选项,以确保包含所有全局对象,而不仅仅是那些在与导出相同的编译单元中定义。然后文件将只编译一次,但用于构建两个库。 (当然,如果您在使用全局对象时遇到问题,那么您的静态库很可能会被其他消费者破坏。)
【讨论】:
我不确定如何在 Visual Studio 中执行此操作的详细信息,但基本上您只需要设置两个从相同源代码构建但具有不同构建设置的构建产品,例如启用/禁用 dll 中使用的 declspec() 属性的宏。
我认为在 Visual Studio 中,这可能表现为您的解决方案中有两个项目。
【讨论】:
据我所知,您需要创建两个共享相同源文件的独立项目。并使用预处理器符号(例如 _DLL)限定要公开的引用,用空替换静态库或在构建或调用动态库时用 dll_export/dll_import 替换。
【讨论】:
由于库/DLL 选项是 per-configuration 并且单个项目可能有多个配置,您可以通过添加(例如)static-debug、dynamic-debug 等来做到这一点.这类似于 CRT 的处理方式,静态和动态,调试和非调试,过去线程化和非线程化。
为此,您需要使用配置管理器为您的项目添加其他配置,然后您可以进行批量构建并选择您喜欢的任意组合。
如果您在项目/配置本身(而不是全局项目或拆分属性文件中)有许多自定义设置,您可能希望使用文本编辑器复制现有配置并重命名它们。
【讨论】:
输出静态库或动态库不依赖于编译器。这是链接器的工作。编译器生成 .obj 文件,这些文件通过链接器链接到(当满足条件时,例如您需要 .exe 的入口点)您想要的内容。
具体来说,MS 链接器link.exe 有几个输出标志:
no flag: .exe is produced;
/LIB: static library .lib produced;
/DLL: dynamic library .dll and import library .lib produced;
如果是/DLL,您还想用__declspec(dllexport) 装饰导出的函数/类,因此链接器会将它们放入导入库中。另外,请注意静态库和导入库并不等同,即使它们都具有 .lib 扩展名。链接器还可以生成其他文件:这里是link to MSDN article on link.exe options。
编辑:正如 Ben 指出的,link.exe /LIB 确实为静态库调用了lib.exe。运行 link /LIB 产生(Windows SDK 7.1 SP1):
D:\Programs\Windows SDK 7.1>link /lib
Microsoft (R) Library Manager Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
usage: LIB [options] [files]
options:
/DEF[:filename]
/ERRORREPORT:{NONE|PROMPT|QUEUE|SEND}
/EXPORT:symbol
/EXTRACT:membername
/INCLUDE:symbol
/LIBPATH:dir
/LIST[:filename]
/LTCG
/MACHINE:{ARM|EBC|IA64|MIPS|MIPS16|MIPSFPU|MIPSFPU16|
SH4|THUMB|X64|X86}
/NAME:filename
/NODEFAULTLIB[:library]
/NOLOGO
/OUT:filename
/REMOVE:membername
/SUBSYSTEM:{BOOT_APPLICATION|CONSOLE|EFI_APPLICATION|
EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|
NATIVE|POSIX|WINDOWS|WINDOWSCE}[,#[.##]]
/VERBOSE
/WX[:NO]
【讨论】:
__declspec(dllexport)来创建DLL,可以使用链接器定义文件。静态库和导入库也是相同文件格式的不同内容(实际上您可以拥有.lib 文件,其中包含导入和目标代码)
/LIB 选项。 Here 是有效选项。
__declspec(dllexport) 这样您就可以自动生成导入库。当然,您也可以在 .def 中使用 /EXPORTS。我只是觉得__declspec(dllexport/dllimport) 很方便。而且我不确定您是否可以使用 .def 导出类。你可以吗?关于静态库和导入库:您可以在组合 .lib 中以静态和动态形式具有功能吗?链接器如何判断使用哪一个?你能详细说明一下吗?
link.exe?事实上,正如我们在 makefile 中所说的那样,我正在使用这个选项。