简体   繁体   English

使用cmake构建Windows DLL的简单示例

[英]A simple example of using cmake to build a Windows DLL

A couple of years ago I was saddled with building and modifying this huge package from a partner engineering institution located in the NorthEast (perhaps, "Down East"). 几年前,我背负着建立和修改位于NorthEast(也许是“Down East”)的合作伙伴工程机构的庞大包裹的困扰。 This package was built using something called "cmake" with Linux as the target... cmake, IMHO the most amazingly maddening, poorly documented, oddly structured build system I'd ever had the displeasure of working with given my limited abilities (28 years of professional experience with *NIX systems and building lotsa open source code). 这个软件包是用一个名为“cmake”的东西构建的,以Linux为目标... cmake,恕我直言,这是一个令人惊讶的令人抓狂,文档记录错误,构造奇怪的构建系统,因为我有限的能力,我曾经有过不愉快的工作(28年) * NIX系统的专业经验和构建开源代码)。

Then I had to build another project with "cmake" which targeted MSVS. 然后我不得不用“cmake”建立另一个针对MSVS的项目。 Oh, the JOY! 哦,快乐! Finally SOMETHING that could reliably generate those nasty-a**ed "project" and "solution" files. 最后SOMETHING可以可靠地生成那些讨厌的“项目”和“解决方案”文件。 And those same CMakeLists.txt files could re-target Linux! 那些相同的CMakeLists.txt文件可以重新定位Linux! Wow, I've seen the light. 哇,我已经看到了光明。

It's still pretty dark where I am, though. 不过,我现在仍然相当黑暗。 Unless I have a CMakeLists.txt file to start with, I just can't seem to get my head wrapped around starting one from scratch and spending less than a day on that process for the simplest problem. 除非我开始使用CMakeLists.txt文件,否则我似乎无法从头开始,并在该过程中花费不到一天的时间来解决最简单的问题。

I have a task to build a DLL with MSVS that can be accessed from a Python script using ctypes. 我有一个任务是使用MSVS构建一个DLL,可以使用ctypes从Python脚本访问它。 Basically, that means a DLL which has symbols on-board. 基本上,这意味着一个在板上有符号的DLL。 Since I have that 10-year-old bug where my installations of VS 2008 AND VS 2010 cannot create a new C++ project, I figured I'd bend my pick on generating a DLL Solution with cmake. 由于我有一个10年前的错误,我的VS 2008和VS 2010的安装无法创建一个新的C ++项目,我想我会选择用cmake生成DLL解决方案。

I haven't been able to find a modern (aka post cmake 2.8.5) COMPLETE example of building a DLL with cmake, which is supposed to be much better at this task than in the past. 我还没有找到一个现代的(又名post cmake 2.8.5)完整的用cmake构建DLL的例子,这个任务应该比过去好得多。

Dived through the tutorial http://www.cmake.org/cmake/help/cmake_tutorial.html which is horrible because they expect you to write the C++ code while learning the cmake. 潜入教程http://www.cmake.org/cmake/help/cmake_tutorial.html这很糟糕,因为他们希望你在学习cmake的同时编写C ++代码。 (Hey, man! I'm having enough trouble getting cmake to work let along make code that will compile!) The tutorial goes though building a simple binary and then a binary using a library, but it does not generate a DLL. (嘿,伙计!我有足够的麻烦让cmake工作,让make代码将编译!)本教程虽然构建一个简单的二进制文件,然后使用库创建一个二进制文件,但它不会生成DLL。

Reading http://www.cmake.org/Wiki/BuildingWinDLL between the lines, I naively added some code to the CMakeLists.txt file in the lib directory: 在行之间阅读http://www.cmake.org/Wiki/BuildingWinDLL ,我天真地将一些代码添加到lib目录中的CMakeLists.txt文件中:

Before: 之前:

add_library(MathFunctions mysqrt.cxx)

install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

After: 后:

add_library(MathFunctions SHARED mysqrt.cxx)
GENERATE_EXPORT_HEADER( MathFunctions
             BASE_NAME MathFunctions
             EXPORT_MACRO_NAME MathFunctions_EXPORT
             EXPORT_FILE_NAME MathFunctions_Export.h
             STATIC_DEFINE MathFunctions_BUILT_AS_STATIC
)
install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

cmake 3.0.0 and cmake 2.8.12.2 both winge at this file with: cmake 3.0.0和cmake 2.8.12.2这两个winge在这个文件中:

CMake Error at MathFunctions/CMakeLists.txt:2 (GENERATE_EXPORT_HEADER):
  Unknown CMake command "GENERATE_EXPORT_HEADER".

The function appears to be in the cmake installation as GenerateExportHeader.cmake, and no amount of debugging revealed the "why" on this error. 该函数似乎在cmake安装中作为GenerateExportHeader.cmake,并且没有任何调试显示此错误的“原因”。 And I haven't been able to find this error on the Internet. 我无法在互联网上找到此错误。

And that was the first six hours of my day. 那是我一天中的前六个小时。

I finally decided to remove the offending command and try this: 我终于决定删除有问题的命令并试试这个:

add_library(MathFunctions mysqrt.cxx)

install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

Wa-la! WA-LA! cmake configured and generated and MSVS built it successfully and a DLL appeared in the Debug subdirectory of the library directory. cmake已配置并生成,MSVS已成功构建,并且DLL出现在库目录的Debug子目录中。 Kuel. Kuel。

This DLL, however, did not contain the symbols that would allow python/ctypes to access the desired function. 但是,此DLL不包含允许python / ctypes访问所需函数的符号。 After some more rooting around in the BuildingWinDLL page, I managed to elicit the symbols. 在BuildingWinDLL页面中进行了一些工作之后,我设法引出符号。 Python was very happy, and I now have a model for future work even though it is a rude, simple-minded hack! Python非常高兴,我现在有一个未来工作的模型,即使它是一个粗鲁,简单的黑客!

SO, after that long-winded discussion: 在那个冗长的讨论之后:

  • Is the BuildingWinDLL, referring to cmake 2.8.5 and above, simply wrong? 是关于cmake 2.8.5及更高版本的BuildingWinDLL,是不是错了?
  • What was the right way to do this? 这样做的正确方法是什么?
  • Does anybody out there have a simple, "cmake 101" example of creating an MSVS DLL with exported symbols that is not a hack so that I can throw away my hack? 有没有人有一个简单的“cmake 101”示例创建一个MSVS DLL与导出的符号,这不是一个黑客,所以我可以扔掉我的黑客?

PS: very, nice, friendly article composition system here at stackoverflow. PS:非常,漂亮,友好的文章组合系统在stackoverflow。 I will enjoy this, assuming I'm allowed back... 我会喜欢这个,假设我被允许回来......

UPDATE after the answer from steveire: 在steveire回答之后更新:

The original question answered, and I see that I missed a hint in the BuildingWinDLL page. 最初的问题回答了,我看到我错过了BuildingWinDLL页面中的提示。 I also have found that I failed to change one of the fields in the example for my own code. 我还发现我没有为自己的代码更改示例中的一个字段。

So now we're on to the next layer. 所以现在我们进入下一层。 Using the referenced example, the VS2010 solution build complains: 使用引用的示例,VS2010解决方案构建抱怨:

LINK : fatal error LNK1104: cannot open file 'MathFunctions\Debug\MathFunctions.lib'

I gathered from the BuildingWinDLL that the GENERATE_EXPORT_HEADER() was all-singing, all-dancing with regard to building the DLL. 我从BuildingWinDLL收集到,GENERATE_EXPORT_HEADER()在构建DLL时全部都在跳舞。 The .lib file is not being generated, and the .dll that is generated does not contain symbols... 未生成.lib文件,生成的.dll不包含符号...

The BuildingWinDLL page talks about the pre-cmake-2.8.5 process. BuildingWinDLL页面讨论了pre-cmake-2.8.5进程。 The 2.8.5 process noted at the top of the page is how the files at the bottom of the page are now automatically generated using GENERATE_EXPORT_HEADER(). 页面顶部提到的2.8.5过程是如何使用GENERATE_EXPORT_HEADER()自动生成页面底部的文件。 It is still necessary to knit the pieces together, which is not clear to me from the text. 仍然需要将这些碎片编织在一起,这在文中并不清楚。

So MathFunctions_Export.h is generated by the GENERATE_EXPORT_HEADER() cmake command and the particular parameters presented here and creates a C header with a macro for causing symbols to be exported. 因此,MathFunctions_Export.h由GENERATE_EXPORT_HEADER()cmake命令生成,此处显示的特定参数将创建一个带有宏的C头,以便导出符号。 This file apparently has to be explicitly referred to, and symbols to export properly qualified: 显然必须明确引用此文件,并且要正确限定导出的符号:

#include <math.h>
#include <Mathfunctions/MathFunctions_Export.h>

MathFunctions_EXPORT double mysqrt(double v) {
    return sqrt(v);
}

Adding the #include and the *EXPORT qualifier now cause symbols to be exported, and VS now knows to generate the .lib and populate the .dll with symbols. 现在添加#include和* EXPORT限定符会导致符号被导出,VS现在知道生成.lib并用符号填充.dll。

SUCCESS! 成功! Thanks to all who aided in this process and suffered with me in my pain. 感谢所有帮助过这个过程的人,并在我的痛苦中遭受了我的痛苦。

include(GenerateExportHeader)

before using it. 在使用它之前。

http://www.cmake.org/cmake/help/v3.0/module/GenerateExportHeader.html http://www.cmake.org/cmake/help/v3.0/module/GenerateExportHeader.html

CMake builds STATIC libraries by default, so keep the SHARED if you want to build a shared library. CMake默认构建STATIC库,因此如果要构建共享库,请保留SHARED。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM