CPack:使用正则表达式忽略文件 [英] CPack: Ignoring files using regex

查看:66
本文介绍了CPack:使用正则表达式忽略文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

(apologies: cross-posted from CMake mailing list)

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

I'm trying to get my head round CMake's regex implementation; I have a folder containing 4 folders and 2 text files as follows:

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

CMakeLists.txt的一行是:

One line of CMakeLists.txt is:

set(CPACK_SOURCE_IGNORE_FILES "[^projectA]$")

在随后生成的源代码包中,存在 build/ projectA/ extrafiles ,但是 temp/,而2个文本文件不是.我正试图进入一个正则表达式将忽略文件夹中除 projectA/ README CMakeLists.txt 之外的所有内容的阶段,但目前无法解决我的正则表达式如何提供的结果就是这些结果.

In my source package that is then subsequently generated, build/, projectA/ and extrafiles are present, but temp/ and the 2 text files are not. I'm trying to get to a stage where the regex will ignore everything in the folder except for projectA/, README and CMakeLists.txt, but can't work out at the moment how the regex I've supplied is giving those results.

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

I guess what this boils down to is how to match a whole string using regex. I realise that the docs say Matches any character(s) not inside the brackets which is where I guess I'm going wrong...

进一步的探索

在试图理解CMake的正则表达式实现时,我认为我将从第一条原则开始做一些简单的事情.

In trying to understand CMake's regex implementation, I thought I'd start from 1st principles and do some easy stuff.

如果我愿意

set(CPACK_SOURCE_IGNORE_FILES projectA)

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

then the folder projectA doesn't appear in my source package (as expected); however, if I do

set(CPACK_SOURCE_IGNORE_FILES ^projectA$)

set(CPACK_SOURCE_IGNORE_FILES ^/projectA/$)

然后 projectA 出现.我不理解的 ^ (行的开头)和 $ (行的末尾)是什么?

then projectA does appear. What is it about the ^ (beginning of line) and $ (end of line) that I'm not understanding?

更多

很明显, projectA 实际上不是我的项目名称,但是当我将项目文件夹物理重命名为 projectA 时,以上所有内容都适用.但是,当我更换

As probably obvious, projectA is not actually the name of my project, but everything above holds true when I physically rename my project folder to projectA. But, when I replace

set(CPACK_SOURCE_IGNORE_FILES projectA)

使用

set(CPACK_SOURCE_IGNORE_FILES <name of my project>)

并将我的实际项目文件夹从 projectA 重命名为其实际名称,最后得到一个 empty 压缩包!啊!我绝对不知道CMake在玩什么奇怪的把戏,但我只是想哭.

and rename my actual project folder from projectA to its actual name, I end up with an empty tarball! Argh! I have absolutely no idea what strange tricks CMake is playing on me, but I just want to cry.

任何见识将不胜感激!

自包含示例

按弗雷泽的要求,这是一个自包含的示例,其中显示了两个我已经描述了功能".但是,我确实知道我以一种稍微非标准的方式运行CMake,以便使所有与单个构建有关的事情保持在一起,因此,如果有任何证据证明以更标准的方式运行CMake可以消除这些问题,有兴趣看到他们.

As requested by Fraser, a self contained example showing 2 of the 'features' I've described. However, I do know that I'm running CMake in a slightly non-standard way, in order to keep everything to do with individual builds together, so if there's any proof running CMake in a more standard way eliminates these problems I'd be interested to see them.

第1步:创建文件

创建树:

cd ~
mkdir 
cd projectA
mkdir projectA    

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

Create C file, and save it as ~/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 :

create a file that won't need compiling, and save it as ~/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 中显示 everything .源tarball,包括不会编译的 test.sh (Fraser对此感到惊讶)

this results in 2 tarballs in the build folder. Moving these somewhere else and untarring them shows helloworld in the binary tarball (as expected), and everything from the ~/projectA/projectA in the source tarball, including test.sh which won't get compiled (which Fraser seemed surprised about)

第3步:随机测试

修改 CMakeLists.txt 以包括

set(CPACK_SOURCE_IGNORE_FILES "projectA")

并重新运行上面的CMake/Make命令将导致源tarball空,但具有与上述相同的二进制tarball.我现在已经意识到,更改目录树以使顶级目录为 testproject (与它的子文件夹有所不同),不会会导致空的源压缩文件,并且只会删除 CPACK_SOURCE_IGNORE_FILES

and rerunning the CMake / Make commands above results in an empty source tarball, but with the same binary tarball as above. I have now realised that changing the directory tree so that the top level directory is testproject (and so different to its child folder) doesn't result in an empty source tarball, and does only remove the files listed in CPACK_SOURCE_IGNORE_FILES

推荐答案

我认为使用 CPACK_SOURCE_IGNORE_FILES 后,您无法实现自己的目标(尽管我不确定).正如您正确地指出的那样,CMake的正则表达式处理允许排除字符组,但我认为它不允许否定整个模式. [请参见编辑后的最新答案.]

I don't think you can achieve what you're after using CPACK_SOURCE_IGNORE_FILES (although I'm not certain). As you rightly noted, CMake's regex handling allows for excluding groups of characters, but I don't think it allows for negating whole patterns. [See updated answer at the end of the edits.]

话虽如此,我想您可以在 install 命令中列出要排除的所有文件夹.除了排除"projectA"以外的所有内容,它不但健壮,而且仍然是以下语法:

That being said, I guess you can list all the folders you wish to exclude in your install command. Not as robust as excluding everything except "projectA", but still here's the syntax:

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

关于空的tarball,我想您可能同时具有<我的项目名称> 作为项目的根目录和子目录?因此,在您的示例中,如果您将项目命名为"projectA",那么您将拥有"projectA/build","projectA/projectA"等.

Regarding the empty tarball, I imagine that you maybe have <name of my project> both as your project's root dir and as a subdir? So in your example, if you called your project "projectA", then you'd have "projectA/build", "projectA/projectA", etc.

如果是这样,则正则表达式将在完整路径上工作,因此项目中的所有文件将在其路径中包含 projectA/.

If so, the regex will work on the full path, and hence all files within your project will contain projectA/ within their paths.

关于哭泣……好吧,我只能建议您抓紧自己,振作起来!:-)

As for the crying... well, I can only advise you to get a grip and pull yourself together! :-)

针对这些评论,下面是使用 安装 命令以实现目标:

In response to the comments, here's a quick example of using the install command to achieve the goal:

install(DIRECTORY projectA
        DESTINATION the_install_subdir)
install(FILES CMakeLists.txt README DESTINATION the_install_subdir)


进一步

好的,您的榜样很有帮助-我确实误解了您的所作所为.我没有意识到您实际上是在创建两个不同的目标("package"和"package_source").我以为你是通过做类似

OK, your example helps a lot - I had indeed misunderstood what you were doing. I hadn't picked up that you were actually making 2 different targets ("package" and "package_source"). I had thought you were creating the binary package by doing something like

cpack -G DEB

并且您正在通过其他方式创建另一个程序包

and that you were creating the other package by doing

cpack -G TGZ

这两个都构建二进制包.我的错误-我应该多加注意.抱歉!

These both build the binary package. My mistake - I should have paid more attention. Sorry!


至于您的具体问题:


As for your specific questions:

问题1

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

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}")会导致空的压缩包?"答案可能不是.

I take this to mean: "Should doing set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_BINARY_DIR}") result in an empty tarball?" The answer is probably not.

因为 CPACK_SOURCE_IGNORE_FILES 代表一个正则表达式,所以我确信在某些情况下,结果正则表达式可以匹配项目中的每个文件,这将导致一个空的压缩包.但是我想这不太可能.

Because CPACK_SOURCE_IGNORE_FILES represents a regex, I'm sure there are cases where the resultant regex could match every file in the project, and this would cause an empty tarball. However I imagine it's fairly unlikely.

如果不是通过变量 $ {CMAKE_BINARY_DIR} 使用bin目录的完整路径,而只是给文件夹名,那么出现空的压缩包的可能性会更大.假设您将bin目录称为"build",并进行了 set(CPACK_SOURCE_IGNORE_FILES"build").如果您的项目位于〜/test_builds/projectA 中,则正则表达式"build"将匹配项目中的每个文件,因为每个文件都包含"test_builds";导致一个空的压缩包.

If, rather than using the full path to your bin dir via the variable ${CMAKE_BINARY_DIR} you were to just give the folder name, there would be a much greater chance of an empty tarball. Say you call your bin dir "build" and have set(CPACK_SOURCE_IGNORE_FILES "build"). If your project lived in say ~/test_builds/projectA, then the regex "build" would match every file in the project since each contains "test_builds"; resulting in an empty tarball.

我认为这是每次您生成空的tarball时都会遇到的问题.不管正则表达式试图达到什么目的,它实际上都会匹配并排除所有文件.

I think this is the crux of issue each time you've generated an empty tarball. Whatever the regex is trying to achieve, it actually ends up matching and excluding all files.


问题2

CMAKE_SOURCE_DIR 中未安装"的文件似乎也不会最终出现在二进制tarball中,而是最终出现在源tarball中

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} 中包含 all 个文件,而"package"目标仅包含通过 install 命令添加的项目.在这里,源文件"一词可能有点用词不当,因为它表示源树中的所有文件-不仅是.c,.cc,.cxx等.

Yes, the "package_source" is indeed a different target to the binary package. It by default contains all files in the ${CMAKE_SOURCE_DIR}, whereas the "package" target contains only items added via install commands. Here, the term "source files" is probably a slight misnomer since it means all files in the source tree - not just .c, .cc, .cxx, etc.


原始问题

我认为毕竟有一种相当安全的方法可以实现您的原始目标!如果您将 file(GLOB ...) 生成根目录中所有文件/文件夹的非递归列表,然后删除要保留在源包中的文件/文件夹,您应该可以将其余列表用作 CPACK_SOURCE_IGNORE_FILES 的正则表达式值:

I think there's a reasonably safe way to achieve your original aim after all! If you use file(GLOB ...) to generate a non-recursive list of all files/folders in your root, then remove those you wish to keep in the source package, you should be able to use the remaining list as the regex value of 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}")


希望这现在对您有用.再次误导您.


Hopefully this should now work for you. Sorry again for the misdirections.

这篇关于CPack:使用正则表达式忽略文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆