【问题标题】:CPack: Exclude INSTALL commands from subdirectory (googletest directory)CPack:从子目录(googletest 目录)中排除安装命令
【发布时间】:2016-05-22 12:18:01
【问题描述】:

我在一个项目中使用 CMake,在我的测试用例中使用 googletest。 环顾互联网,将 googletest 源代码复制到存储库的子文件夹中并将其包含在“add_subdirectory(googletest)”中似乎是一种常见的做法。我做到了。

现在我正在使用 CPack 为我的项目生成 debian 包。不幸的是,CPack 生成的包与我的项目一起安装了 googletest。这当然不是我想要的。

查看 googletest 目录,我在那里找到了一些 INSTALL cmake 命令,所以很清楚,为什么会这样。现在的问题是 - 我怎样才能避免它?我不喜欢从 googletest 修改 CMakeLists.txt 文件,因为我必须记住在更新时重新应用我的修改。还有其他方法可以在 CPack 中禁用这些安装吗?

【问题讨论】:

    标签: c++ cmake installation googletest cpack


    【解决方案1】:

    所以有提到的宏选项@Tsyvarev 最初建议here

    # overwrite install() command with a dummy macro that is a nop
    macro (install)
    endmacro ()
    
    # configure build system for external libraries
    add_subdirectory(external)
    
    # replace install macro by one which simply invokes the CMake
    install() function with the given arguments
    macro (install)
      _install(${ARGV})
    endmacro(install)
    

    注意${ARGV}${ARGN} 相同,但文档目前建议使用${ARGN}。此外,宏覆盖将 _ 添加到原始宏名称的事实也没有记录,但它仍然是行为。见代码here

    然而,我从来没有让上面的代码正常工作。它真的做了一些奇怪的事情,并且经常调用install() 两次。

    另一种选择(也未记录)是使用EXCLUDE_FROM_ALL

    add_subdirectory(external EXCLUDE_FROM_ALL)
    

    根据一些评论,我在某处发现这会禁用该子目录的install()。我认为它实际上所做的是默认为所有install() 命令设置EXCLUDE_FROM_ALL,这些命令也可能执行您想要的操作。我还没有真正测试过,但值得一试。

    【讨论】:

    • EXCLUDE_FROM_ALL 运行良好,宏对我不起作用。
    • EXCLUDE_FROM_ALL 为我工作,谢谢。但根据:cmake.org/cmake/help/v3.0/prop_tgt/…,这不是未定义的行为吗
    • 您的意思是无证行为。我认为您无法在 CMake 中避免这种情况。
    【解决方案2】:

    更新:如other answer 中所述, 看来EXCLUDE_FROM_ALL选项是在子目录下子项目中禁用install最直接最正确的方法:

    add_subdirectory(googletest EXCLUDE_FROM_ALL)
    

    以前的解决方案

    如果您在项目的版本中不需要测试(您希望使用 CPack 交付),则有条件地包含 googletest 子目录,并在打包时将条件设置为 false:

    ...
    if(NOT DISABLE_TESTS)
        add_subdirectory(googletest)
    endif()
    

    包装

    cmake -DDISABLE_TESTS=ON <source-dir>
    cpack
    

    或者,如果您想要测试,但不想安装测试基础设施,您可以通过定义同名的宏或函数来禁用install 命令:

    # Replace install() to do-nothing macro.
    macro(install)
    endmacro()
    # Include subproject (or any other CMake code) with "disabled" install().
    add_subdirectory(googletest)
    # Restore original install() behavior.
    macro(install)
        _install(${ARGN})
    endmacro()
    

    CMake mailing 中也提出了这种方法。

    根据 cmets,替换 CMake 命令的方式非常棘手,并且在某些情况下可能不起作用:传递给修改后的 install 的参数解析不正确或恢复 install 不起作用,甚至遵循installs 被禁用。

    【讨论】:

    • 第二件事似乎也禁用了我自己的安装命令,尽管它们是在不同的(不是子)目录中定义的。 install 函数覆盖了哪个范围?可以只覆盖当前目录(包括子目录)吗?
    • Can I overwrite it for the current directory (including subdirectories) only? - 正是这样,函数的定义应该起作用。我稍后会测试。
    • 嗯,实际上函数定义具有全局范围。我已将用于恢复 install() 行为的代码添加到答案帖子中。
    • 这不太行。由于某种原因,它使我在不同子目录中的其他install(DIRECTORY ...) 之一无法安装。
    • 我认为问题在于空格和 CMake 的疯狂引用系统。此外,如果您两次定义 install 宏,则两者都会被调用。在这种情况下没关系,但这有多奇怪?
    【解决方案3】:

    回复有点晚,但我花了太长时间才弄清楚这一点。

    在 googletests 的特定情况下,在顶层 CMakeLists.txt 中指定它就可以了。

    option(INSTALL_GMOCK "Install Googletest's GMock?" OFF)
    option(INSTALL_GTEST "Install Googletest's GTest?" OFF)
    add_subdirectory(googletest)
    

    我在(我认为)CMake 邮件列表中阅读到,以包内的INSTALL_&lt;package name&gt; 为条件进行安装是一种事实上的标准(从现在开始我肯定会遵循这个标准!)。但我现在找不到那个链接。

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-24
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 2014-09-29
      相关资源
      最近更新 更多