我正在尝试使用CMake构建自定义项目,这涉及使用emscripten为我的C++库提供javascript绑定(bind)。
这就是我想要实现的CMakeLists.txt文件
interface/glue.cpp
interface/glue_wrapper.cpp
f
中的每个头文件${my_header_files}
,将#include "f"
附加到文件interface/glue_wrapper.cpp
interface/glue_wrapper.cpp
中的最终条目应为#include "glue.cpp"
interface/glue_wrapper.cpp
${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES} interface/glue_wrapper.cpp --post-js glue.js -o output.js
我在第3步和第4步上花了最后7个小时-均未成功。
这就是我到目前为止(与上面的步骤3和4有关)
# Build Interface
ADD_CUSTOM_COMMAND(
OUTPUT interface/glue.cpp
COMMAND cd interface
COMMAND python ${PLATFORM_PREFIX}/tools/webidl_binder.py ${myclasses_INTERFACE} glue
# Need to loop through list and generate include statements ...
#COMMAND echo "#include <glue.cpp>" > glue_wrapper.cpp
)
# Build JS library
ADD_CUSTOM_COMMAND(
OUTPUT ${PROJECT_JS_DIR}/${PROJECT}.js
COMMAND ${CMAKE_CXX_COMPILER} # Nothing seems to work anyway .... giving up finally :(
)
我正在使用cmake 3.2.1,并在Ubuntu 14.0.4上构建。我正在尝试创建Unix MakeFiles。
我的问题是这样的:
为了实现第3步和第4步中指定的功能,如何修改上面的代码片段?
最佳答案
看来glue_wrapper.cpp
的内容根本不依赖于构建时值,它们纯粹基于CMake时可用的信息(my_header_files
变量的内容)。因此,您可以使用简单的file()
命令在CMake时创建文件:
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/interface/glue_wrapper.cpp) # erase file if it exists
foreach(header IN LISTS my_header_files ITEMS glue.cpp)
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/interface/glue_wrapper.cpp "#include \"${header}\"\n")
endforeach()
用于创建.js库的自定义命令应正常运行:
add_custom_command(
OUTPUT ${PROJECT_JS_DIR}/${PROJECT}.js
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES} interface/glue_wrapper.cpp --post-js glue.js -o output.js
DEPENDS ${ALL_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/interface/glue_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
COMMENT "Building ${PROJECT}.js"
VERBATIM
)
与任何CMake自定义命令一样,只有在某些方面取决于其输出时,它才会包含在构建中(我怀疑这就是您的方法失败的原因)。因此,您应该添加一个自定义目标来驱动命令:
add_custom_target(
JsLibrary ALL
DEPENDS ${PROJECT_JS_DIR}/${PROJECT}.js
COMMENT "Building JsLibrary"
)
那应该是所有必要的。
作为附带说明,请注意
add_custom_command
具有WORKING_DIRECTORY
参数,您应该使用该参数代替COMMAND cd
。自定义命令和自定义目标之间的CMake关系可能需要一些时间才能完全理解,因此我将尝试解释上面代码中的情况。
自定义命令
命令
add_custom_command(OUTPUT x ...)
创建一个生成规则,该规则生成一个输出。基本上,这告诉CMake:如果有人需要
x
文件,请按以下步骤创建它。该命令本身不会向生成的构建系统添加任何内容。它仅向CMake提供有关如何创建文件的信息。
调用的各个组成部分是:
add_custom_command(
OUTPUT ${PROJECT_JS_DIR}/${PROJECT}.js
此自定义命令生成的文件。它说:“custom命令生成这些文件。”
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES} interface/glue_wrapper.cpp --post-js glue.js -o output.js
COMMAND
参数介绍要执行的命令的命令行。它说:“这是产生OUTPUT
中列出的文件所必须要做的。” DEPENDS ${ALL_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/interface/glue_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
DEPENDS
部分介绍命令的依赖关系(先决条件)。紧随其后的每个项目都是一个文件,该文件是命令的依赖项。它说:“如果缺少这些文件中的任何一个,或者如果这些文件中的任何一个比输出文件中的任何新,则必须重新运行此命令。”特别注意对
${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
的依赖,我将在稍后再讨论。 COMMENT "Building ${PROJECT}.js"
这纯粹是文档,将在执行自定义命令(=内置)时打印。
VERBATIM
)
这告诉CMake适当地转义将执行命令的shell的
COMMAND
节中的任何特殊字符。基本上,除非您确实有理由不这么做,否则始终将其放入自定义命令中。自定义目标
如前所述,CMake仅在某些请求其输出的情况下才将自定义命令添加到构建系统。普通目标(例如库或可执行文件)可以通过在源文件中列出输出文件来实现此目的。这在自定义命令例如从IDL定义生成C++源文件的情况下是典型的。
自定义命令还可以在其
DEPENDS
节中列出另一个自定义命令的输出,从而创建所需的依赖关系。但是,只有在某处请求“master”命令的输出时,这两者才会再次包括在内。如果生成的文件实际上是最终产品,而不仅仅是正常目标的源文件,则必须在某处指定对其的显式依赖关系以确保生成了该文件。这就是自定义目标的来源。它是一个目标(就像可执行文件或库一样),因此它将始终存在于构建系统中。当使用基于makefile的生成器时,自定义目标只是一个额外的规则。让我们分析一下我在上面的答案中输入的内容:
add_custom_target(
JsLibrary
JsLibrary
只是目标的符号名称。可以是您想要的任何东西。您将在命令行上键入该名称以构建.js
文件:> make JsLibrary
。ALL
默认情况下,自定义目标不属于
all
调用的make all
目标的一部分;您必须对它们进行make
明确编码。添加ALL
参数将成为make all
的自定义目标部分,我假设您会在此处使用。DEPENDS ${PROJECT_JS_DIR}/${PROJECT}.js
这是关键所在,也是我们首先创建自定义目标的原因。这告诉CMake定制目标取决于生成的文件。现在CMake看到了构建系统一部分所需的文件(即通过自定义命令
JsLibrary
),并查看它是否知道如何创建这样的文件。它找到定制命令,并确保将适当的规则添加到生成的构建系统中。 COMMENT "Building JsLibrary"
)
再次,这是纯粹的文档-每次创建目标时都会打印(即使其所有依赖关系都是最新的,因此也不会进行进一步处理)。
总结
JsLibrary
将包含在构建系统中,因为它是一个自定义目标,并且始终包含自定义目标。这将是make all
的一部分,因为我们在创建时指定了ALL
。JsLibrary
取决于${PROJECT_JS_DIR}/${PROJECT}.js
,因此由custom命令创建的规则将包含在构建系统中,并在每次构建JsLibrary
时进行检查。如果过时,它将被执行。${PROJECT_JS_DIR}/${PROJECT}.js
依次取决于${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
,因为这是在创建DEPENDS
的自定义命令的.js
部分中指定的。因此,在创建glue.cpp
的自定义命令中描述的规则也将包含在构建系统中,并且一切正常。
关于build - CMake自定义构建问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30112274/