gpt4 book ai didi

build - CMake自定义构建问题

转载 作者:行者123 更新时间:2023-12-01 23:43:46 26 4
gpt4 key购买 nike

我正在尝试使用CMake构建自定义项目,这涉及使用emscripten为我的C++库提供javascript绑定(bind)。

这就是我想要实现的CMakeLists.txt文件

  • 为我的文件指定源位置(DONE)
  • 设置要使用的相关编译器以及编译器标志等(DONE)
  • 使用自定义生成生成新的cpp文件(以下详细步骤)
  • 使用自定义工具(python脚本)生成interface/glue.cpp
  • 创建一个新的EMPTY文件interface/glue_wrapper.cpp
  • 对于f中的每个头文件${my_header_files},将#include "f"附加到文件interface/glue_wrapper.cpp
  • interface/glue_wrapper.cpp中的最终条目应为#include "glue.cpp"
  • 使用以下逻辑使用自定义版本生成我的javascript文件:
  • 创建一个变量$ {ALL_SOURCES},其中包含上面
  • 中第1步中列出的所有源和第3步中的 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/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com