【问题标题】:Changing the layout when creating a TGZ archive创建 TGZ 存档时更改布局
【发布时间】:2012-12-20 15:25:00
【问题描述】:

我使用 CMake 管理具有以下布局的项目:

ProjectA/
  include
  doc
  test
ProjectB
  include
  doc
  test

我想使用 CPack 打包一个 tar.gz source 存档,其布局如下:

include/
ProjectA/
  doc
  test
ProjectB/
  doc
  test

新的顶级包含包含所有包含文件。

我尝试通过CPACK_INSTALL_SCRIPT 运行 CMake 脚本来实现此目的,但此脚本在文件创建之前运行。我在哪里可以连接到 CPack 以获得这种效果?

似乎installmake package_source 的作用没有影响,但它对make package 有影响。不幸的是make package 也将构建和打包 图书馆,这是我不想发生的事情。我想要一个纯粹的 源代码分发ala make dist.

【问题讨论】:

  • 有点不清楚是什么问题。就像 arrowdodger 所说:您应该添加一个带有 DESTINATION 的 install() 调用,CPack 应该选择它并正确合并文件夹。您是否尝试直接运行“CPack -G TGZ”,还是使用“make package”?如果您先指定 'projectA/include/*.h' 或 GLOB 源会发生什么?
  • @Andre 正如我所说:package_source 忽略了installDESTINATIONpackage 尊重它,但也尝试编译我不想要的库。我一直尝试cmake packagecmake package_source 从来没有直接cpack
  • 如果你接受“包”编译你的库,它会给你正确的布局吗?
  • 回答完,才注意到你是专门看源码包创建的。请更新您的问题以使其更清楚。
  • @JohannesS。我试着让它更清楚,并补充了为什么明显的方法会失败。

标签: cmake build-system cpack


【解决方案1】:

您可以在 ProjectAProjectB 的标头上调用 install(DIRECTORY include DESTINATION include) 并将它们安装到同一个目录中。这将导致 CPack 将它们一起放在生成的包中。

更新

好的,我已经用CPACK_INSTALL_SCRIPT 变量做到了。

我创建了以下脚本:

set(CMAKE_SOURCE_DIR @CMAKE_SOURCE_DIR@)

execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/A/ ${CMAKE_SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/B/ ${CMAKE_SOURCE_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/A)
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_SOURCE_DIR}/B)

CMakeLists.txt 中,我用CMAKE_SOURCE_DIR 的实际值填充了它:

configure_file(CPackScript.cmake CPackScript.cmake @ONLY)

最后,我添加了set(CPACK_INSTALL_SCRIPT ${CMAKE_BINARY_DIR}/CPackScript.cmake),瞧!生成的包现在具有include 目录,其中包含来自A/B/ 的标头,而A/B/ 目录不存在。

【讨论】:

  • 我已经这样做了。它不工作。我似乎无法让installDESTINATION 选项对tgz 的创建产生任何影响。我什至可以用一个小例子来重现它。
  • gist.github.com/4360633 这将导致与make package_source 相同的布局。
  • 你在生成的包中得到了什么?空include 目录?或者甚至没有include 目录?会不会是 /build*/ 忽略模式与您的构建目录冲突并混淆了 CPack?
  • 我最终得到了与原版完全相同的布局。有趣的是,如果我执行make package,文件夹会被合并,但这也会打包已编译的库。我想要的只是一个可移植的make dist,它合并了几个目录。
  • 对不起?这是代码已经做的吗?你能详细说明一下吗?
【解决方案2】:

另一种可能的方法是完全绕过 CPack 来生成 TGZ 存档,并简单地使用生成存档的 CMake 自定义目标:

project (MyProject)

set (DIST_TEMP_DIR "${CMAKE_BINARY_DIR}/dist")
make_directory(${DIST_TEMP_DIR})

add_custom_target(dist 
    COMMAND ${CMAKE_COMMAND} -E remove_directory "${DIST_TEMP_DIR}/${PROJECT_NAME}/"
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/ProjectA/include" "${DIST_TEMP_DIR}/${PROJECT_NAME}/include"
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/ProjectA/test" "${DIST_TEMP_DIR}/${PROJECT_NAME}/ProjectA/test"
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/ProjectA/doc" "${DIST_TEMP_DIR}/${PROJECT_NAME}/ProjectB/doc"
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/ProjectB/include" "${DIST_TEMP_DIR}/${PROJECT_NAME}/include"
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/ProjectB/doc" "${DIST_TEMP_DIR}/${PROJECT_NAME}/ProjectA/doc"
    COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/ProjectB/test" "${DIST_TEMP_DIR}/${PROJECT_NAME}/ProjectB/test"
    COMMAND ${CMAKE_COMMAND} -E tar cvz "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.tar.gz"  "${DIST_TEMP_DIR}/${PROJECT_NAME}/"
    COMMENT "Building ${PROJECT_NAME}.tar.gz"
    WORKING_DIRECTORY "${DIST_TEMP_DIR}"
)

自定义目标 dist 首先通过在命令模式下使用多个 copy_directory 命令调用 CMake,在构建文件夹内的临时目录中设置所需的存档结构。然后使用tar命令模式子命令生成tar.gz归档。

【讨论】:

  • 是的,不幸的是我需要运行更复杂的命令,包括循环,所以这不再可行了。通过自定义目标启动另一个 cmake 脚本很糟糕,因为您无法以这种方式加载缓存。我当然可以生成带有正确变量集的脚本,但我们正在迅速接近 hack 阈值。
【解决方案3】:

我不确定究竟是什么不适合你。

这对我来说适用于 Windows 上的 ZIP 生成器。我将尝试找到一台 linux 机器,看看这是否也适用于 TGZ(编辑:确实如此):

目录结构:

CMakeLists.txt
ProjectA/
    doc
        foo.txt
    include
        foo.h
    test
        foo.test
ProjectB/
    doc
        bar.txt
    include
        bar.h
    test
        bar.test

ProjectA/CMakeLists.txt

project( ProjectA )

INSTALL( DIRECTORY include DESTINATION . )
INSTALL( DIRECTORY doc DESTINATION ${PROJECT_NAME}/ )
INSTALL( DIRECTORY test DESTINATION ${PROJECT_NAME}/ )

ProjectB/CMakeLists.txt

project( ProjectB )

INSTALL( DIRECTORY include DESTINATION . )
INSTALL( DIRECTORY doc DESTINATION ${PROJECT_NAME}/ )
INSTALL( DIRECTORY test DESTINATION ${PROJECT_NAME}/ )

CMakeLists.txt:

project( MyProject )

ADD_SUBDIRECTORY(ProjectA)
ADD_SUBDIRECTORY(ProjectB)

INCLUDE(CPack)

如果我创建包,我会得到

MyProject-0.1.1-win32.zip
    MyProject-0.1.1-win32
        include
            bar.h
            foo.h
        ProjectA
            doc
                foo.txt
            test
                foo.test
        ProjectB
            doc
                bar.txt
            test
                bar.test

这是你想要的吗?

源包

对于源包创建,CPack 默认忽略安装命令并安装/复制所有在CPACK_SOURCE_INSTALLED_DIRECTORIES 中指定的目录。此变量包含成对的源目录和目标目录。如果未手动设置,则默认为"${CMAKE_SOURCE_DIR};/"。准确地说,它会覆盖这些目录,忽略 CPACK_SOURCE_IGNORE_FILES 中的所有文件,这些文件默认为所有主要的 VCS 簿记文件(例如,请参阅您的 CPackSourceConfig.cmake)。

可以执行以下操作:

CMakeLists.txt

project( MyProject )

SET( PROJECTS ProjectA ProjectB )

SET(CPACK_SOURCE_INSTALLED_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};/") 
FOREACH( p ${PROJECTS} ) 
    ADD_SUBDIRECTORY( ${p} )
    LIST( APPEND CPACK_SOURCE_INSTALLED_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR/${p}/include include )
ENDFOREACH()


INCLUDE(CPack)

或将CPACK_SOURCE_INSTALLED_DIRECTORIES 的操作添加到相应的项目文件中。

但是:这会将您的包含目录安装到顶级包含目录,但由于通配,仍会在项目目录中创建另一个副本。您可能会为您的doctest 目录创建额外的目录对,并在SET 命令中跳过CPACK_SOURCE_INSTALLED_DIRECTORIES 的初始化。如果这样做,您将需要找到一种方法来安装/复制特定于项目的 CMake 文件。

BIG CAVEAT:如果ProjectAProjectB引用项目本地包含目录(例如,使用INCLUDE_DIRECTORIES(...),您将破坏您的CMake代码,呈现源安装(部分)没用。所以你可能要重新考虑你对顶级包含目录的想法。

【讨论】:

  • 关于本地包含:CMake 系统设置为检测是否已使用包本地或顶级包含。这只是我想要改变的包装步骤。
  • 我不明白(可能缺少某些东西)。如果 ProjectA 的 CMakeLists.txt 包含 include_directories( include ) 和 s.b.想要使用您的源代码包来构建您的软件,将找不到包含,因为它们现在在 ../include 中,对吧?
  • 在找到所有包后,构建系统检查是否存在顶级包含,然后设置一个包含所有包含目录的全局变量(包括所有项目依赖的库)。子项目使用此变量来设置包含路径。
  • 啊,我明白了,这是特定于您的系统的。在我们的设置中,我们实际上使用了将特定于项目的包含目录添加到需要它们的项目的宏。无论如何,我是否正确,现在唯一缺少的部分是项目特定 CMakeLists.txt 的复制?或者我的解决方案中还缺少什么?
  • 我明天试试你的解决方案,然后告诉你。抱歉,圣诞节让事情变慢了。在此期间发放赏金是个坏主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2016-03-04
  • 1970-01-01
相关资源
最近更新 更多