本文介绍了使用CMake从静态库链接Windows DLL文件,无需手工制作未解析的符号名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我使用Visual&Studio; 2008 SP1(专业版,32位和64位版本)。我正在寻找一个解决方法,我相信是一个非常无益的限制在Visual Studio中。I'm using Visual Studio 2008 SP1 (Professional Edition, both for 32-bit and 64-bitbuilds). I'm seeking a workaround to what I believe is a veryunhelpful "limitation" in Visual Studio.我发现它相当令人惊讶的Visual Studio链接器和编译器没有这样做在DLL文件创建时间,自动扫描所有指定的静态库以与 中相同的方式为所有导出的符号建立导入库和导出文件 和 a StackOverflow comment 。我确认仅仅应用 __ declspec(dllexport)和 __ declspec(dllimport)属性到组成静态库的文件中的类,函数和数据声明。I find it quitesurprising that the Visual Studio linker and compiler does not do this right at DLL filecreation time, to automatically scan all specified static librariesfor all exported symbols in the same manner given in Building anImport Library and Export File and in a StackOverflowcomment. I confirmed that it is not sufficient to simply apply__declspec(dllexport) and __declspec(dllimport) attributes toclass, function, and data declarations in the files that comprise thestatic libraries.链接器不会扫描导出符号的所有静态库,因此不会将它们拉入DLL文件(符号必须由DLL链接命令行上的 .obj 文件引用,或者通过其他方式引用)。没有对每个导出符号的明确引用,仍然可以创建DLL文件,但不创建其关联的导入库文件。The linker does not scan all of the static librariesfor exported symbols and so won't pull them into the DLL file (the symbolshave to be referenced by .obj files on the DLL link command-line orby other means I show below). Without explicit references to eachexported symbol, the DLL file may still be created, but its associatedimport library file is not created.我可以收集,Microsoft建议使用 LIB.EXE 创建 DEF 文件,但不幸的是, LIB.EXE 页面应用约束:From what I can gather, Microsoft is recommending using LIB.EXEto create the DEF file, but unfortunately, the LIB.EXE pageapplies a constraint: 请注意,如果您在创建您的导入库之前创建,在创建您的 .dll 之前,必须传递相同的对象集在构建导入库时通过构建 .dll 时,文件。 Note that if you create your import library in a preliminary step, before creating your .dll, you must pass the same set of object files when building the .dll, as you passed when building the import library.这是一个不幸的约束,假设我也在$ b $中使用 CMake b我的新构建环境。 CMake隐藏了实际上是传递给链接器的的细节(我认为在时间的99%中是一件好事),但在这种情况下,我需要访问一些该信息在 CMake执行时间,而不是之后使用手工制作的脚本或其他脆弱的 skulduggery 。That is an unfortunate constraint given that I am also using CMake inmy new build environment. CMake hides the details of what is actuallypassed to the linker (and I deem that to be a good thing in 99% of thetime), but in this case I need to get access to some of that information atCMake execution time, not afterwards using hand-crafted scripts orother fragile skulduggery.如何强制DLL链接器解析组成 DLL文件的所有静态库中的所有导出符号,这不会导致脆弱性和额外构建逻辑维护烦恼?从全自动化的角度考虑,记住,我需要多次为多个不同的DLL。How do I go about forcing the DLL linker toresolve all exported symbols in all static libraries that comprise theDLL file, that isn't going to result in fragility and additional buildlogic maintenance chores? Think in terms of full-automation here, andkeep in mind that I need to do this multiple times for multipledifferent DLL's.我的问题是: 如何获取最终DLL链接中使用的对象文件和静态库集命令行单独使用CMake语法?How do I obtain the set of object files and static libraries usedon the final DLL link command line using CMake syntax alone? LIB.EXE 行(使用生成 DEF 文件)必须完全匹配在 DLL链接行使用的顺序吗?Does the order of files listed on LIB.EXE line (the one usedto generate the DEF file) have to match exactly that order used onthe DLL link line?可能会遇到使用 LIB.EXE 方法的来生成 DEF 文件?Are there other difficulties that I might encounter from the useof the LIB.EXE approach to generate the DEF file?有没有更好的方式去这不需要调用一个单独的实用程序,如LIB.EXE,之前调用最后链接?我关心的是,为了LIB.EXE重新扫描所有的静态库 ,链接本身之外增加了构建开销,即使它Is there a better way to go about this that does not requirecalling a separate utility, such LIB.EXE, before calling thefinal link? I'm concerned about the added build overhead beyond thelink itself for LIB.EXE to rescan all of the static librariesagain even though it just wrote them out in separate executions. 非回答: 以下是我现在不能考虑的解决方案:The Non-Answers:The following are solutions that I cannot consider right now: 手动指定除了$之外的未引用符号b $ b在原来的 .h 或 .cpp 文件,因为这是 break每次开发人员忘记更新列出的文件(很可能是名称被转换的)符号名称。它将破坏与非用户友好的链接器错误有关未解决的符号这将是昂贵的开发人员调试。这个非回答包括以下方法:Manually specifying the unreferenced symbols anywhere other thanin the original .h or .cpp files, as doing that is going tobreak each time a developer forgets to update the file that liststhe (quite possibly name-mangled) symbol name. And it will breakwith non-user-friendly linker errors about unresolved symbolswhich will be costly for developers to debug. This non-answerincludes the following approaches: 显式添加 .obj 文件到DLL链接命令行(其中的变体包括添加fake .obj 文件,有 dummy引用符号(注意,这是我的旧构建环境今天做的,并且它臭)),和Explicitly added .obj files to the DLL link command-line,(variants of this include adding "fake" .obj files that havedummy references to the otherwise unreferenced but exportedsymbols (and note that this is what my old build environmentdoes today, and it stinks)), and,手工制作 DEF 文件以包含未引用的导出的符号和Handcrafting DEF files to include the unreferenced butexported symbols, and, Linker命令行选项特别引用未引用但导出的符号符号。Linker command-line options that specifically reference theunreferenced but exported symbols symbols. 完全停止使用静态库。我不能在短期内这样做,因为它是从旧的构建环境的一个结构性变化,我正在离开。很可能我会采取这条路线,将来,一旦所有旧的建立环境的残余都在垃圾桶,但这不是我的焦点在这里。Stop using static libraries altogether. I cannot do that in theshort-term, as it is too much of a structural change from the oldbuild environment I am moving away from. It is quite likely I willtake this route in the future, once all remnants of the old buildenvironment are in the "trash bin", but that is not my focus here. 参考资料: 使用DEF文件从DLL导出 模块定义(.def)文件 PRB:无法从静态库导出w / _declspec(dllexport) dumpbin.exe / symbols选项 lib.exe选项 构建导入库和导出文件 制作LINK_FLAGS目标媒体资源Reference material:Exporting from a DLL Using DEF FilesModule Definition (.def) FilesPRB: Can't Export from Static Libraries w/_declspec(dllexport)dumpbin.exe /symbols optionlib.exe optionsBuilding an Import Library and Export FileCMake LINK_FLAGS target property推荐答案我只回答说明你不使用静态库的感觉是正确的。I'm only answering to make it clear your feeling to not use static libraries is correct. DLRdave说它已经在注释中,你的构建系统正在被LIB文件滥用。一个LIB文件很像一个真正的图书馆,你只是走出去与你要求的东西,而不是图书馆里的一切。DLRdave said it already in the comments, your build system is being abused by LIB files. A LIB file is much like a real library, you only walk out with the things you ask for, not everything in the library.如果Visual  Studio  2008工具集中有空白,则说明它不支持部分链接。部分链接的输入是一组OBJ文件,输出是一个单独的OBJ文件,其中包含输入OBJ文件中的所有代码和数据。If there's a gap in the Visual Studio 2008 tool set, it's that it doesn't support partial linking. The input into a partial link is a set of OBJ files and the output is a single OBJ file that contains all the code and data from the input OBJ files.在归档/库和部分链接之间的对于g ++在此问题的答案中描述: g ++部分链接而不是归档?,其中GNU链接器( ld )支持部分链接。The difference between an archive/library and a partial link is described for g++ in the answer to this question: g++ partial linking instead of archives?, where the GNU linker (ld) does support partial linking.至于可能的短期缓解 - 个人而言,我会尝试使用脚本在构建时动态构建DEF文件,方法是使用 LIB / List 或 DUMPBIN / ARCHIVEMEMBERS 以获取obj文件和从该列表生成DEF文件。或者,因为我假设 _declspec(dllexport )被使用,你也可以使用 DUMPBIN / DIRECTIVES / EXPORT 并自行构建DEF文件。As for possible short term mitigation - personally, I would have tried to use scripting to dynamically build the DEF file at build time by using LIB /List or DUMPBIN /ARCHIVEMEMBERS to get the obj files and LIB /DEF to generate the DEF file from that list. Or, as I assume _declspec(dllexport) is being used, you could have also used DUMPBIN /DIRECTIVES, looked for /EXPORT and built the DEF file yourself. 这篇关于使用CMake从静态库链接Windows DLL文件,无需手工制作未解析的符号名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
05-18 03:42