cmake - CPack : Ignoring files using regex

标签 cmake

(抱歉:从 CMake 邮件列表交叉发布)

我正在尝试了解 CMake 的正则表达式实现;我有一个包含 4 个文件夹和 2 个文本文件的文件夹,如下所示:

build/  
projectA/  
CMakeLists.txt  
extrafiles/  
README  
temp/

CMakeLists.txt 的一行是:

set(CPACK_SOURCE_IGNORE_FILES "[^projectA]$")

在随后生成的源包中,存在 build/projectA/extrafiles,但 temp/ 而 2 个文本文件则不是。我正在尝试进入正则表达式将忽略文件夹中除 projectA/READMECMakeLists.txt 之外的所有内容的阶段,但目前无法弄清楚我的正则表达式如何 提供的是给出这些结果。

我想这归结为如何使用正则表达式匹配整个字符串。我意识到文档说匹配不在括号内的任何字符,这就是我猜错的地方......

进一步探索

在尝试理解 CMake 的正则表达式实现时,我想我应该从第一原则开始,做一些简单的事情。

如果我这样做

set(CPACK_SOURCE_IGNORE_FILES projectA)

那么文件夹 projectA 不会出现在我的源包中(如预期);但是,如果我这样做

set(CPACK_SOURCE_IGNORE_FILES ^projectA$)

set(CPACK_SOURCE_IGNORE_FILES ^/projectA/$)

然后projectA确实出现。我不明白的 ^ (行首)和 $ (行尾)是什么?

更多

很明显,projectA 实际上并不是我的项目的名称,但当我将项目文件夹物理重命名为 projectA 时,上述所有内容都成立。但是,当我更换

set(CPACK_SOURCE_IGNORE_FILES projectA)

set(CPACK_SOURCE_IGNORE_FILES <name of my project>)

并将我的实际项目文件夹从 projectA 重命名为其实际名称,我最终得到一个 tarball!啊!我完全知道 CMake 对我玩什么奇怪的把戏,但我只想哭。

任何见解都将不胜感激!

独立示例

As requested作者:Fraser,这是一个独立的示例,显示了我所描述的 2 个“功能”。但是,我确实知道我正在以稍微不标准的方式运行 CMake,以便将与各个构建相关的所有内容放在一起,因此,如果有任何证据证明以更标准的方式运行 CMake 可以消除这些问题,我会有兴趣看看他们。

第 1 步:创建文件

创建树:

cd ~
mkdir 
cd projectA
mkdir projectA    

创建C文件,并将其保存为~/projectA/projectA/helloworld.c:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("!!!Hello World!!!\n"); /* prints !!!Hello World!!! */
    printf("!!!Hello CMake!!!\n"); /* prints !!!Hello CMake!!! */
    return 0;
}

创建一个不需要编译的文件,并将其保存为~/projectA/test.sh:

#A non compiled program
echo "Hello world!"

创建~/projectA/CMakeLists.txt:

cmake_minimum_required (VERSION 2.6)
project (HelloWorld) 

set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/projectAinstall")

add_executable(helloworld projectA/helloworld.c)
install(TARGETS helloworld DESTINATION .)

include(InstallRequiredSystemLibraries)
set(CPACK_GENERATOR "TGZ")
set(CPACK_SOURCE_GENERATOR "TGZ")

include(CPack)

第2步:编译

~/projectA中,运行:

chris@chris:~/projectA$ cmake -H. -Bbuild

然后:

make -C build && make -C build package && make -C build package_source

这会在 build 文件夹中生成 2 个 tarball。将它们移至其他位置并解压它们,会在二进制 tarball 中显示 helloworld(如预期),以及来自 ~/projectA/projectA所有内容源 tarball,包括 test.sh,它不会被编译(Fraser 似乎对此感到惊讶)

第 3 步:随机测试

修改 CMakeLists.txt 以包含

set(CPACK_SOURCE_IGNORE_FILES "projectA")

并重新运行上面的 CMake/Make 命令会产生一个空的源 tarball,但具有与上面相同的二进制 tarball。我现在意识到,更改目录树以使顶级目录为 testproject (因此与其子文件夹不同)不会导致空的源 tarball,并且仅删除 CPACK_SOURCE_IGNORE_FILES

中列出的文件

最佳答案

我认为您无法实现使用CPACK_SOURCE_IGNORE_FILES之后的目标(虽然我不确定)。正如您正确指出的那样,CMake 的正则表达式处理允许排除字符组,但我认为它不允许否定整个模式。 [请参阅编辑末尾的更新答案。]

话虽如此,我想您可以在 install 中列出您希望排除的所有文件夹。命令。不像排除“projectA”之外的所有内容那样强大,但语法仍然如下:

install(DIRECTORY .
        DESTINATION the_install_subdir
        REGEX "build|extrafiles|temp+" EXCLUDE)

关于空的 tarball,我想你可能有 <name of my project>既作为项目的根目录又作为子目录?因此,在您的示例中,如果您将项目命名为“projectA”,那么您将拥有“projectA/build”、“projectA/projectA”等。

如果是这样,正则表达式将在完整路径上运行,因此项目中的所有文件都将包含 projectA/在他们的路径内。

至于哭……好吧,我只能建议你控制住自己,振作起来! :-)

<小时/>

编辑:为了回应评论,这里有一个使用 install 的快速示例。实现目标的命令:

install(DIRECTORY projectA
        DESTINATION the_install_subdir)
install(FILES CMakeLists.txt README DESTINATION the_install_subdir)
<小时/>

进一步编辑:

好吧,你的例子很有帮助 - 我确实误解了你在做什么。我没有意识到你实际上正在制作两个不同的目标(“package”和“package_source”)。我原以为您正在通过执行类似的操作来创建二进制包

cpack -G DEB

并且您正在通过执行以下操作创建另一个包

cpack -G TGZ

它们都构建了二进制包。我的错误——我应该更加注意。抱歉!


至于您的具体问题:

问题1

It seems to me that installing files / directories that aren't compiled but are at the same level as the folder containing all the compiled files (i.e. bin), and then ignoring the bin folder using CPACK_SOURCE_IGNORE_FILES results in an empty tarball - is this correct?

我认为这意味着:“执行 set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_BINARY_DIR}") 会导致空 tarball 吗?”答案可能是否定的。

因为CPACK_SOURCE_IGNORE_FILES代表一个正则表达式,我确信在某些情况下生成的正则表达式可以匹配项目中的每个文件,这会导致一个空的 tarball。不过我认为这不太可能。

如果,而不是通过变量 ${CMAKE_BINARY_DIR} 使用 bin 目录的完整路径如果您只给出文件夹名称,那么很有可能出现空 tarball。假设您将 bin 目录称为“build”并具有 set(CPACK_SOURCE_IGNORE_FILES "build") 。如果您的项目位于 ~/test_builds/projectA ,那么正则表达式“build”将匹配项目中的每个文件,因为每个文件都包含“test_builds”;导致一个空的 tarball。

我认为这是每次生成空 tarball 时问题的症结所在。无论正则表达式试图实现什么目的,它实际上最终都会匹配并排除所有文件。


问题2

It also seems that files in the CMAKE_SOURCE_DIR which aren't 'installed' don't end up in the binary tarball but do end up in the source tarball

是的,“package_source”确实是二进制包的不同目标。默认情况下,它包含 ${CMAKE_SOURCE_DIR} 中的所有 文件。 ,而“package”目标仅包含通过 install 添加的项目命令。在这里,术语“源文件”可能有点用词不当,因为它表示源树中的所有文件 - 不仅仅是 .c、.cc、.cxx 等。


原始问题

我认为毕竟有一个相当安全的方法来实现你最初的目标!如果您使用 file(GLOB ...) 要生成根目录中所有文件/文件夹的非递归列表,然后删除那些您希望保留在源包中的文件/文件夹,您应该能够使用剩余的列表作为 CPACK_SOURCE_IGNORE_FILES 的正则表达式值:

file(GLOB SourceIgnoreFiles "${CMAKE_SOURCE_DIR}/*")
set(SourceKeepFiles "${CMAKE_SOURCE_DIR}/projectA"
                    "${CMAKE_SOURCE_DIR}/CMakeLists.txt"
                    "${CMAKE_SOURCE_DIR}/README")
list(REMOVE_ITEM SourceIgnoreFiles ${SourceKeepFiles})
# Escape any '.' characters
string(REPLACE "." "\\\\." SourceIgnoreFiles "${SourceIgnoreFiles}")
set(CPACK_SOURCE_IGNORE_FILES "${SourceIgnoreFiles}")


希望这现在对您有用。再次抱歉误导了您。

关于cmake - CPack : Ignoring files using regex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17935748/

相关文章:

c++ - CMake 在 macOS High Sierra 上找不到 wxWidgets 库

c++ - Clion:如何正确地将图像、xml、资源...添加到 cmake

git - 了解 git 和 checkout

cmake - 如何使 CMake 重新配置依赖于自定义文件?

c++ - 使用 CMAKE 如何使用 CHECK_LIBRARY_EXISTS 来检查 C++ 库?

linux - 包库和头文件安装在哪里?

检查 C 头文件是否具有函数 - 使用 CMake

c# - 在 CMake 中导入的外部 msproject 无法构建

cmake - 使用 cmake 链接库

c++ - 使用源代码构建的 CMake configure_file