【问题标题】:Compile a set of functions to .LIB and .DLL at the same time同时将一组函数编译成.LIB和.DLL
【发布时间】:2012-02-15 21:41:02
【问题描述】:

有什么预处理技巧或者什么东西可以让你同时编译一组函数,一个lib和dll版本?

【问题讨论】:

    标签: c++ windows visual-c++ dll


    【解决方案1】:

    编译器不必知道您是在制作静态库还是动态库——它只制作目标文件。

    然后您可以获取这些目标文件并将它们传递给库管理器(创建静态库)或链接器(并创建共享对象/DLL),是的,您可以使用相同的目标文件执行这两个操作,只要当您使用链接器定义文件来控制 DLL 导出时。

    使用 Visual Studio 的一种便捷方法是设置一个依赖于静态库的 DLL 项目,并为该依赖项选择 "Use Library Dependency Inputs" 选项,以确保包含所有全局对象,而不仅仅是那些在与导出相同的编译单元中定义。然后文件将只编译一次,但用于构建两个库。 (当然,如果您在使用全局对象时遇到问题,那么您的静态库很可能会被其他消费者破坏。)

    【讨论】:

    • 谢谢,我注意到依赖于静态库的 dll 项目,并会看更多关于:)
    【解决方案2】:

    我不确定如何在 Visual Studio 中执行此操作的详细信息,但基本上您只需要设置两个从相同源代码构建但具有不同构建设置的构建产品,例如启用/禁用 dll 中使用的 declspec() 属性的宏。

    我认为在 Visual Studio 中,这可能表现为您的解决方案中有两个项目。

    【讨论】:

    • 谢谢,那我做两个项目,在同一个代码上,复制修改一个项目,保持项目内部的文件夹组织结构
    【解决方案3】:

    据我所知,您需要创建两个共享相同源文件的独立项目。并使用预处理器符号(例如 _DLL)限定要公开的引用,用空替换静态库或在构建或调用动态库时用 dll_export/dll_import 替换。

    【讨论】:

    • 我一下子就看到了所有的回复,你们都很快:) 谢谢
    【解决方案4】:

    由于库/DLL 选项是 per-configuration 并且单个项目可能有多个配置,您可以通过添加(例如)static-debugdynamic-debug 等来做到这一点.这类似于 CRT 的处理方式,静态和动态,调试和非调试,过去线程化和非线程化。

    为此,您需要使用配置管理器为您的项目添加其他配置,然后您可以进行批量构建并选择您喜欢的任意组合。

    如果您在项目/配置本身(而不是全局项目或拆分属性文件中)有许多自定义设置,您可能希望使用文本编辑器复制现有配置并重命名它们。

    【讨论】:

    • 谢谢@peachykeen 很好的解释:)
    【解决方案5】:

    输出静态库或动态库不依赖于编译器。这是链接器的工作。编译器生成 .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 是有效选项。
    • @BenVoigt 我的意思是,使用__declspec(dllexport) 这样您就可以自动生成导入库。当然,您也可以在 .def 中使用 /EXPORTS。我只是觉得__declspec(dllexport/dllimport) 很方便。而且我不确定您是否可以使用 .def 导出类。你可以吗?关于静态库和导入库:您可以在组合 .lib 中以静态和动态形式具有功能吗?链接器如何判断使用哪一个?你能详细说明一下吗?
    • @BenVoigt 有 /LIB 选项。否则,如何将静态库指定为link.exe?事实上,正如我们在 makefile 中所说的那样,我正在使用这个选项。
    • 导出类是一个错误,而不是一个特性。至于混合 .lib,我的意思是一些符号将是导入的,而其他符号(具有不同名称)将是实际代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 2011-10-19
    • 2013-05-14
    • 2012-07-28
    • 1970-01-01
    相关资源
    最近更新 更多