CPack:使用正则表达式忽略文件

时间:2013-07-29 23:09:21

标签: 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之外的所有内容,但目前无法解决正则表达式我有 提供的是给出这些结果。

我想这归结为如何使用正则表达式匹配整个字符串。我意识到文档说Matches any character(s) not inside the brackets这就是我猜我错了...

进一步探索

在试图理解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,一个自成一体的例子,展示了我所描述的两个“特征”。但是,我确实知道我正在以一种略微非标准的方式运行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(如预期的那样),并在源tarball中显示{{1>}的所有,包括~/projectA/projectA不会被编译(弗雷泽似乎感到惊讶)

第3步:随机测试

修改test.sh以包含

CMakeLists.txt

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

中列出的文件

1 个答案:

答案 0 :(得分:2)

我认为你在使用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)

进一步修改:

好的,你的例子很有帮助 - 我确实误解了你在做什么。我没有意识到你实际上在制作2个不同的目标(“package”和“package_source”)。我以为你是通过做类似

的东西来创建二进制包的
cpack -G DEB

并且你正在通过

创建另一个包
cpack -G TGZ

这些都构建了二进制包。我的错 - 我应该多加注意。遗憾!


至于你的具体问题:

问题1

  

在我看来,安装未编译但与包含所有已编译文件(即bin)的文件夹处于同一级别的文件/目录,然后使用CPACK_SOURCE_IGNORE_FILES忽略bin文件夹会导致空的tarball - 这是对的吗?

我认为这意味着:“应该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

  

CMAKE_SOURCE_DIR中未安装的文件似乎不会在二进制tarball中结束但最终会在源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}")


希望这应该适合你。再次抱歉误导。