Introduction
I’ve been interested for a while on how to optimize builds, and one thing that I thought about is to have a central ninja build.ninja
that can drive the build for everything. It seems like the topic has been discussed before, both on the Ninja’s GitHub Issues page and on the maillist here, and the conclusion was that it’s not possible.
However, I still wanted to try it. This is the top ninja file that I was playing it:
subninja release_32/build.ninja
subninja release_64/build.ninja
build all: phony release_32/all release_64/all
default all
The problems
The first big problem I faced was that the files are relative to the top ninja file. This was solved by setting CMAKE_NINJA_OUTPUT_PATH_PREFIX
. The next problem problem was that I had duplicated rule names (like cmake_object_order_depends_target_libninja-re2c
).
At this point I tried different combinations of regex and simple replace scripts to try and patch the ninja files, but I couldn’t get anything working. So as any person with too much enthusiasm would do, I figured it’s time to make a project that could parse and edit in place ninja files.
Here it is for anyone interested (disclaimer: very early and untested, made the minimum necessary work to get something working). In the end, I managed to make something that looks like it works, but I wouldn’t trust it to use it on a real build.
What I’m hoping is that CMake could be changed so it would generate files that would solve (some of) the following problems that I found:
1. Duplicated rules names
Like I’ve mentioned before, CMake generated rules named like cmake_..
. What I did is to add a prefix to each rule, much more like CMAKE_NINJA_OUTPUT_PATH_PREFIX
. I think this could be solved pretty easily with something like CMAKE_NINJA_OUTPUT_RULE_PREFIX
with the same logic.
2. Rule that builds CMakeLists.txt
Right now there’s a rule that looks like this
build /home/tachyon/repos/ninja/build-cmake/src_32/CMakeLists.txt /usr/share/cmake-3.27/Modules/BasicConfigVersion-AnyNewerVersion.cmake.in ..... : phony
This is a problem because more than one configuration will try to “generate” those files. To be honest I don’t understand why this exists in the first place, but it’s probably important.
One thing I did to “solve” a part of the problem is to make symlinks of the source directory (ln -s $PWD/.. src_32
) and pass it to CMake (-S src_32
) for each configuration, but I can’t tell if this is actually an okay thing to do. This still didn’t solve it building files in /usr/share/cmake..
, so I just mangled the path to those with a prefix that “soft” broke it.
3. Files that are generated in source
This will result in multiple rules generating the same files, which is fair enough. I have no solution for this other than not doing that. While not ideal, I could absolutely live with this in my projects. Generating the file in the build directory sounds already like a good idea for me.
Conclusion
The final questions would be:
- Do you see better solutions for these problems?
- Do you see any other problem that might arise?
- Could CMake implement changes that would make this easier and less error prone?
Edit: I used “rule” when I actually meant edge.