CPack: ignoring files using regular expressions

(apologies: cross messages from the CMake mailing list)

I am trying to implement my regular expression implementation of CMake; I have a folder containing 4 folders and 2 text files:

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

One line CMakeLists.txt:

 set(CPACK_SOURCE_IGNORE_FILES "[^projectA]$") 

In the source package, which is then generated, build/ , projectA/ and extrafiles are present, but temp/ and 2 text files are not. I am trying to go to the stage where the regular expression will ignore everything in the folder except projectA/ , README and CMakeLists.txt , but it cannot work at the moment how the regular expression supplied gives these results.

I guess it comes down to how to match an entire string using a regex. I understand the docs say Matches any character(s) not inside the brackets , where I think I'm wrong ...

Further intelligence

In an attempt to understand the implementation of the regular expression CMake, I thought that I would start with the 1st principle and do some simple things.

If i do

 set(CPACK_SOURCE_IGNORE_FILES projectA) 

then the projectA folder projectA not appear in my source package (as expected); however if i do

 set(CPACK_SOURCE_IGNORE_FILES ^projectA$) 

or

 set(CPACK_SOURCE_IGNORE_FILES ^/projectA/$) 

projectA appears . . What are these ^ (beginning of line) and $ (end of line) which I do not understand?

Much more

Obviously, projectA is not really the name of my project, but all of the above matters when I physically rename my project folder to projectA . But when I replace

 set(CPACK_SOURCE_IGNORE_FILES projectA) 

from

 set(CPACK_SOURCE_IGNORE_FILES <name of my project>) 

and rename my actual project folder from projectA to its actual name, I get tar empty ! Argh! I have absolutely no idea what weird tricks CMake is playing on me, but I just want to cry.

Any understanding would be greatly appreciated!

SELF-CONTAINING EXAMPLE

As requested by Fraser, a self-contained example showing 2 of the β€œfeatures” that I described. However, I know that I run CMake in a somewhat non-standard way, in order to relate everything to individual assemblies, so if any evidence of CMake working in a more standard way fix these problems, I would be interested to see them.

Step 1: create files

Create tree:

 cd ~ mkdir cd projectA mkdir projectA 

Create a 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; } 

create a file that does not need compilation and save it as ~/projectA/test.sh :

 #A non compiled program echo "Hello world!" 

create ~/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) 

Step 2: compilation

In ~/projectA run:

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

then

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

this results in 2 files in the build folder. Moving them to another location and helloworld them shows helloworld in the binary archive (as expected) and everything starting with ~/projectA/projectA in the original tarball, including test.sh , which will not be compiled (which Fraser seemed to be surprised about ) / p>

Step 3: random tests

Modify CMakeLists.txt to include

 set(CPACK_SOURCE_IGNORE_FILES "projectA") 

and restarting the CMake / Make commands above results in an empty source tarball, but with the same binary tarball as above. I realized that changing the directory tree so that the top level testproject (and so is different from its child folder) does not create an empty source archive and only deletes the files listed in CPACK_SOURCE_IGNORE_FILES

+4
source share
1 answer

I do not think that you can achieve that after using CPACK_SOURCE_IGNORE_FILES (although I'm not sure). As you rightly pointed out, CMake regex processing allows you to exclude groups of characters, but I don't think it allows you to negate whole patterns. [Cm. Updated answer at the end of editing.]

At the same time, I think you can list all the folders that you want to exclude into the install command. Not as reliable as an exception to everything except "projectA", but still the syntax is:

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

Regarding an empty tarball, I suppose you probably have <name of my project> both your project root directory and subdir as well? Therefore, in your example, if you named your project "projectA", then you will have "projectA / build", "projectA / projectA", etc.

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

As for crying ... well, I can only advise you to grab hold and pull yourself together !:-)


Edit: In response to the comments, here is a brief example of using install to achieve the goal:

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

Further editing:

Well, your example helps a lot - I really misunderstood what you are doing. I did not understand that you are actually doing two different goals ("package" and "package_source"). I thought you were creating a binary package by doing something like

 cpack -G DEB 

and that you created another package by running

 cpack -G TGZ 

Both will build a binary package. My mistake - I should have paid more attention. Excuse me!


Regarding your specific questions:

Question 1

It seems to me that setting files / directories that are not compiled, but at the same level as the folder containing all the compiled files (i.e. bin), and then ignoring the bin folder with CPACK_SOURCE_IGNORE_FILES leads to an empty tarball - this is correct ?

I believe this means: "Should set(CPACK_SOURCE_IGNORE_FILES "${CMAKE_BINARY_DIR}") in an empty tarball?" The answer is probably not that.

Since CPACK_SOURCE_IGNORE_FILES is a regular expression, I am sure that there are cases where the resulting regular expression can match every file in the project, and this will result in an empty tarball. However, I assume this is rather unlikely.

If instead of using the full path to the bin file via the variable ${CMAKE_BINARY_DIR} , you just had to specify the name of the folder, the probability of an empty tarball is much more. Say you call your bin dir "build" and have set(CPACK_SOURCE_IGNORE_FILES "build") . If your project lived in the word ~/test_builds/projectA , then the "assembly" of the regular expression will correspond to each file in the project, since each contains "test_builds"; the result is an empty archive.

I think this is the essence of the problem every time you create an empty tarball. No matter what the regular expression is trying to do, it actually ends in a match and excludes all files.


Question 2

It also seems that files in CMAKE_SOURCE_DIR that are not installed do not fall into the binary archive, but ultimately are in the original tarball

Yes, "package_source" is indeed another target for a binary package. By default, it contains all the files in ${CMAKE_SOURCE_DIR} , while the "package" target contains only items added with install commands. Here, the term "source files" is probably a little incorrect, as it means all the files in the source tree - not only .c, .cc, .cxx, etc.


Original question

I think there is a reasonably safe way to achieve your original goal! If you use file(GLOB ...) to create a non-recursive list of all the files / folders in your root, and then delete the ones you want to keep in the source package, you should be able to use the remaining list as the value of the regular expression 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}") 


Hope this works for you now. Sorry again for the incorrect instructions.

+2
source

Source: https://habr.com/ru/post/1494161/


All Articles