我正在尝试使用CMake构建一个自定义项目,该项目涉及使用emscripten为我的C ++库提供javascript绑定。
这就是我希望我的CMakeLists.txt文件实现
指定文件的来源位置(完成)
设置要使用的相关编译器以及编译器标志等(完成)
使用自定义构建生成新的cpp文件(详细步骤如下)
interface/glue.cpp
interface/glue_wrapper.cpp
f
中的每个标头文件${my_header_files}
,将#include "f"
附加到文件interface/glue_wrapper.cpp
interface/glue_wrapper.cpp
中的最终条目应为#include "glue.cpp"
使用自定义构建通过使用以下逻辑生成我的javascript文件:
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中指定的所需功能?
答案 0 :(得分:3)
似乎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
此自定义命令生成的文件。它说:&#34;自定义命令生成这些文件。&#34;
COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${ALL_SOURCES} interface/glue_wrapper.cpp --post-js glue.js -o output.js
COMMAND
参数引入了要执行的命令的命令行。它说:&#34;这是你必须做的,以生成OUTPUT
中列出的文件。&#34;
DEPENDS ${ALL_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/interface/glue_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
DEPENDS
部分介绍了命令的依赖关系(先决条件)。其后面的每个项目都是一个文件,它是命令的依赖项。它说:&#34;如果缺少这些文件中的任何一个,或者这些文件中的任何比输出文件的任何更新,则必须重新执行此命令运行&#34;
特别注意对${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
的依赖,我稍后会再回过头来看。
COMMENT "Building ${PROJECT}.js"
这纯粹是文档 - 它将在执行自定义命令(= built)时打印。
VERBATIM
)
这告诉CMake正确转义COMMAND
部分中将执行命令的shell的任何特殊字符。基本上,除非你确定你有理由不这样做,否则总是把它放到自定义命令中。
自定义目标
正如我上面提到的,如果某些内容请求输出,CMake只会向构建系统添加自定义命令。正常目标(即库或可执行文件)可以通过在其源文件中列出输出文件来实现。这在自定义命令生成C ++源文件的情况下是典型的,例如来自IDL定义。
自定义命令还可以在其DEPENDS
部分列出另一个自定义命令的输出,从而创建所需的依赖关系。但是,如果&#34; master&#34;的输出将再次包括在内。在某处请求命令。
如果生成的文件实际上是最终产品而不仅仅是普通目标的源文件,则必须在某处指定显式依赖它,以确保生成它。自定义目标所在的位置。它是一个目标(就像可执行文件或库一样),因此它将始终存在于构建系统中。使用基于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
,因此自定义命令创建的规则将包含在构建系统中,并且每次构建JsLibrary
时都会进行检查。如果过期,它将被执行。
${PROJECT_JS_DIR}/${PROJECT}.js
又取决于${CMAKE_CURRENT_BINARY_DIR}/interface/glue.cpp
,因为这是在创建DEPENDS
的自定义命令的.js
部分中指定的。因此,创建glue.cpp
的自定义命令中描述的规则也将包含在构建系统中,并且一切都按预期工作。