4

I need to modify some of my project's sources during compilation. It'd be better if I get to modify them between preprocessing and compilation, but I know it's harder to achieve (The solution proposed here is not optimal for me) so I can settle with a pre-preprocessing step.

Since the source files are to be modified, I need to create a copy of them, modify that copy then run the build on this copy. My current solution is:

Prior to cmake invocation, I copy most of the project root contents' to a separate directory. This is required because there are many script invocations during the build so I need to keep most of the project hierarchy intact. Since there are many files and many of them will not be modified, I first copy all files as symbolic links (cp -sR), then hard copy all .c and .h files. Then I just cd to that directory and invoke cmake and make as usual.

The problem here is that since cmake is not aware that it's working on copies of the actual source, the generated Makefile doesn't check whether the actual source was updated. So I need a full rebuild (Full project tree copy and cmake invocation) whenever I modify a single source file.

This can probably be solved by adding a custom command for each hard copied source file that depends on the actual source file, and recopies it after being modified. I guess it's okay, but it really is... ugly, and requires lots of cmake additions. I don't think what I'm trying to do is so exotic, so I believe there is a better option that could work with little changes to my cmake. I'd also like to hear ideas regarding post preprocessor step invocation.

EDIT: A simplified example case.

This is the project tree:

CMakeLists.txt
src/
    CMakeLists.txt
    file1.c
    file1.c
python/
    script.py

The root CMakeLists.txt is add_subdirectory(src/). The src/CMakeLists.txt is add_executable(myexe file1.c file2.c).

I need to execute python python/script.py for each source file, so it should be called on src/file1.c and src/file2.c.

My current solution is a build script as follows:

rm -r build_dir
mkdir build_dir
cp -rt build_dir CMakeLists.txt src/ python/
cd build_dir
cmake .
make # ...

Plus an invocation of python/script.py (prebuild add_custom_command) which globs for the relevant files itself, then processes them.

Community
  • 1
  • 1
Jong
  • 9,045
  • 3
  • 34
  • 66
  • 1
    You should not do this. Try something different, but this violates basic principles of CMake. You should keep your source separate from your build (out-of-source build). Copying files around after configuration in the source directory causes trouble. – usr1234567 Mar 02 '17 at 21:15
  • @usr1234567 which part are you referring to? *adding a custom command for each hard copied source file that depends on the actual source file, and recopies it after being modified*? – Jong Mar 02 '17 at 21:20
  • 1
    Your whole idea. Don't modify the source directory, copy it to the build directory. – usr1234567 Mar 02 '17 at 21:51
  • I haven't got the question's point.You need to make CMake aware about actual sources, and how intermediate ones depends from them. Yes, one of the simplest ways is to use `add_custom_command` for that. `I guess it's okay, but it really is... ugly, and requires lots of cmake additions.` - **What exactly is ugly**? Writting `add_custom_command` for every source file? You may wrap that into the macro, then repeat this macro for every source. You may enter list of sources manually, or use `file(GLOB)` for that. So, what an actual problem is? – Tsyvarev Mar 02 '17 at 22:41
  • @Tsyvarev I call it ugly because it requires technical handling with files which is something cmake should be doing for you. Post preprocessor modifications is easy with make, so I'm sure it can be done with cmake properly, without messing with files directly. – Jong Mar 03 '17 at 16:14
  • You could make 3 separate custom targets, one to pre-process your files, one to edit them, and one to build the edited files. Another option is to use a shell/perl/python/etc script to control your "pre-build" activities, and use CMake to call that and the final build. I think though you've answered the question yourself in your last paragraph. As @Tsyvarev mentioned, it's not ugly but it will take some thought to encapsulate what you want to do in to macros or custom commands. – nega Mar 03 '17 at 17:05
  • `I'm sure it can be done with cmake properly, without messing with files directly.` - Could you provide some **concrete (toy) example** of what do you have? And what do you want to *tell CMake*, so it would do desired things. Like: "Hey, there are header and source files in `intermediate/` directory. Actually, they are copied from corresponded files in `origin/` directory. So, whenever an intermediate file is used, check its origin file. And if the origin file is newer than intermediate one, update the intermediate file before use it." – Tsyvarev Mar 03 '17 at 17:48
  • @Tsyvarev added an example – Jong Mar 03 '17 at 20:27
  • Hm, after the first build (`make`), why do you need to clean build directory? CMake will perfectly see which files after `cp` has been updated. – Tsyvarev Mar 03 '17 at 21:42
  • It is not described what changes are necessary, but is it possible to split the problem: Generate source files with the new information and include/link them to the other static sources? – Th. Thielemann Mar 08 '17 at 07:23
  • [I have tried to add an answer to the question you linked](https://stackoverflow.com/a/73575085/11107541) and found the existing answer insufficient. My answer has plenty of problems, but you can check it out and see if it interests you. – starball Sep 01 '22 at 20:30

0 Answers0