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

17

几年前,我接手了一个来自东北地区(可能是“下东部”)的合作工程机构建立和修改这个庞大的软件包。该软件包使用名为“cmake”的工具构建,以Linux为目标...... 在我的有限能力下(28年的*NIX系统和构建大量开源代码的专业经验),IMHO,cmake是我曾经遇到过的最令人惊讶、最让人心烦意乱、文档最差、结构最奇怪的构建系统。

然后我需要使用“cmake”构建另一个针对MSVS的项目。哦,真是太棒了!终于有了能够可靠生成那些讨厌的“项目”和“解决方案”文件的工具。而且那些相同的CMakeLists.txt文件也可以重新定位到Linux! 哇,我看到了光明。

虽然我还在黑暗中。除非我有一个CMakeLists.txt文件作为起点,否则我似乎无法掌握从头开始并在最简单的问题上花费不到一天时间的过程。

我有一个任务是使用MSVS构建DLL,可以通过ctypes从Python脚本中访问。基本上,这意味着一个DLL具有内置的符号。由于我遇到了一个十年前的错误,我的VS 2008和VS 2010安装无法创建新的C++项目,我想用cmake生成一个DLL解决方案。

我一直没有找到一个现代(即cmake 2.8.5之后的)完整的例子来构建带有cmake的DLL,这应该比过去更好。

我浏览了http://www.cmake.org/cmake/help/cmake_tutorial.html上的教程,但它很糟糕,因为他们希望你在学习cmake的同时编写C++代码。(嘿,伙计!我已经足够难以让cmake工作,更不用说编写会编译的代码!)该教程介绍了构建简单二进制文件和使用库构建二进制文件的过程,但它没有生成DLL。

在阅读http://www.cmake.org/Wiki/BuildingWinDLL时,我天真地在lib目录下的CMakeLists.txt文件中添加了一些代码:

更改前:

add_library(MathFunctions mysqrt.cxx)

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

之后:

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和cmake 2.8.12.2都会因为这个文件报错:

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

该函数似乎在cmake安装中作为GenerateExportHeader.cmake出现,而且没有任何调试能够揭示这个错误的原因。我也没有在互联网上找到有关此错误的信息。

那就是我一天中的前六个小时。

最终,我决定删除有问题的命令并尝试这个:

add_library(MathFunctions mysqrt.cxx)

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

哇啦!CMake已成功配置、生成并在库目录的Debug子目录中创建了一个DLL,而且MSVS也成功地构建了它。很酷。

但是,这个DLL没有包含允许Python/ctypes访问所需函数的符号。在BuildingWinDLL页面上进行了更多的搜索后,我成功激发了这些符号。Python非常高兴,尽管这只是一个粗鲁、简单的hack,但我现在有了未来工作的模型!

因此,在这场冗长的讨论之后:

  • BuildingWinDLL是否指的是CMake 2.8.5及以上版本,只是错误的?
  • 正确的方法是什么?
  • 有人有一个简单的、"CMake 101"的示例,用于创建带有导出符号的MSVS DLL吗?这不是一个hack,这样我就可以放弃我的hack了?

附注:这里的stackoverflow文章组合系统非常好,友善。假设我被允许回来,我会享受这个系统的。

在steveire的答案之后更新:

原始问题得到了解答,我看到了BuildingWinDLL页面中的一个提示。我还发现我没有改变示例中的一个字段,以适应我的代码。

现在我们进入了下一层。使用所提供的示例,VS2010解决方案构建报错:

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

从BuildingWinDLL中我了解到GENERATE_EXPORT_HEADER()在构建DLL方面是个全能的工具。但.lib文件没有生成,而生成的.dll文件也不含有符号......

BuildingWinDLL页面谈论了pre-cmake-2.8.5时代的过程。页面顶部提到的2.8.5过程是如何使用GENERATE_EXPORT_HEADER()自动生成页面底部文件的。 然而,从文本中我并不清楚如何将这些文件组合起来。

所以MathFunctions_Export.h是通过GENERATE_EXPORT_HEADER() cmake命令和这里给出的特定参数生成的,创建一个用于导出符号的C头文件。这个文件需要明确引用,并且导出的符号要正确限定:

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

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

现在添加#include和*EXPORT限定符会导致符号被导出,VS现在知道生成.lib并用符号填充.dll。

成功了!感谢所有协助我完成这个过程并与我一同承受痛苦的人。


1
最好将此内容重写为直接点到问题核心的问题,并仅提供我们需要的信息,而不是冗长的博客文章。另外,这些标记是否都与您的问题相关?如果不是,它们会吓跑很多人,这些人知道他们对VS2010或Python或其他东西一无所知,认为他们不能回答。 - abarnert
3
дЅ еЏЇиѓЅењЁдЅ зљ„CMakeLists.txtдё­жјЏжЋ‰дє†дёЂдёЄincludeпј€GenerateExportHeaderпј‰гЂ‚ - sakra
1
好吧,妈妈教我要分享,但不幸的是,当我痛苦时我仍然会分享... - The Red Gator in Virginia
@abarnert 我明白你的想法,但我个人认为问题中的额外细节很有帮助。我也一直在寻找使用CMake创建符号导出DLL的方法。我阅读了这个问题中列出的所有相同文档。我发现The Red Gator列出他阅读过的文档和他在这些文档中发现的缺点非常有帮助,因为我也走过类似的道路。知道The Red Gator在这个过程中遇到的问题,让我对提供的解决方案更有信心。我知道我们都有自己的偏好。就我个人而言,我发现额外的叙述非常有帮助! - MikeyE
1个回答

11

谢谢。这样就解决了“未知”错误的问题。我想知道文档中清晰说明了这一步骤在哪里。我在参考的网页中没有找到它。既然它解答了标题,我将其标记为答案。 - The Red Gator in Virginia
哇,这让我感到“困惑”。BuildingWinDLL页面的顶部有这个。CMake文档似乎有一个模式,将示例分成碎片,这使得它们很难跟随。不清楚这两个代码块是属于一起的。 - The Red Gator in Virginia
从文档中不清楚,但如果您想在 Linux 构建中将 DLL 导出和导入定义为无操作,该如何实现? - Matthew Hoggan
@TheRedGatorinVirginia,你有最终可行解决方案的完整代码示例吗?看一眼肯定会对我很有帮助。 - MikeyE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接