How do I generate a clean (ready to release) build in CMake? - cmake

For the record, because this seems like there should be an obvious, well-known way to do it: I can't find any docs on how to do this - all I find is people looking to do a "clean" of their built files when I search for this.
When you build out-of-source in CMake, the resulting directory does not exclusively contain your built executable and other files. CMake leaves all its cache and makefiles, as well as other intermediate files, lying around - for example, the CMakeFiles directory, the CMakeCache.txt, Makefiles, .cbp, .ilk, .pdb, etc. - meaning if I wanted to release the results of said build, I'd need to (automatically or manually) either remove excess cmake files, or copy all my generated files elsewhere manually, before I am ready to release. This would be tedious for projects that require a specific structure in the output directory, or have many output files (e.g. an assets folder full of dozens of built asset files - now polluted with CMakeFiles et al.)
When building with CMake, can I not only perform an out-of-source build where intermediate files (as seen above) end up out-of-source, but where the resulting cmake binary directory is also separate and kept free of polluting by CMake and extra compiler output? (e.g. resulting in a build/output directory that cleanly contains all the actual built files with proper directory structure.)

Related

Generating compile_commands.json without generating build files

I'd like to generate a compile_commands.json file for use with the clangd language server. However, EXPORT_COMPILE_COMMANDS only works for the make and ninja build systems. When building a project that uses a different build system it would be convenient to also be able to generate compile_commands.json files as if I was using make or ninja without actually generating any build files that interfere with the build system that I'm using to perform the build.
What is the most convenient way to do this with cmake?
I think your only option here is to have a different build folder with Ninja or Makefile to generates the compile_commands.json and have a different build folder for your "actual" build.
The thing is, CMake is a generator, and it doesn't support mixed builds; and in fact, it should not. If they do that, you will end up having random artifacts from different build systems inside the build folder that might eventually conflicts with each others.
That being said, you are aware that what you get in Ninja-based compile_commands.json is not going to be fully relevant to your "actual" build system that you want to use. I can see it being useful, but not the same for sure.

globbing files autogenerated by a sub_directory binary

I have the following problem, I have a separate cmake project that generates c++ files and I want to glob them into a library that uses them. Right now this is done in this manner
add_subdirectory(generator)
add_custom_target(run-generator ... byproduct GENERATED_FILES)
include(files.txt)
target_link_libraries(library ${GENERATED_FILES})
The include files.txt is actually a set(GENERATED_FILES all_autogen_files), right now they're fixed but in the future they might change. That is what I would want to have is something like
add_subdirectory(generator)
execute_process(generator_binary ... commands)
file(glob ${GENERATED_FILES} output_location_of_gen_files)
target_link_libraries(library ${GENERATED_FILES})
As I understood execute_process runs on the spot is read, so this would generate all the files before the file(glob) but I don't know how would I go about actually building the generator binary before the execute process, since right now what builds it before is that it is a dependency on the target_link_libraries
The only way this could possibly work is if you create a superbuild, i.e. a CMake project that builds everything with ExternalProjects. The reason is that you can't create new targets or add sources to existing targets during the build.
With a superbuild you need at least 3 separate CMake projects: One that builds the generator and then generates the files, one that globs the generated files and builds the rest of your build artifacts, and the superbuild project that adds both with ExternalProject_Add. By setting the dependencies correctly you can then ensure that the project that uses the generated files is configured after the generating project has been built.
However, globbing in CMake is discouraged anyway, so listing the files explicitly is the proper way to do it. If your code-generator starts generating new files then they should be added to the list manually in the same commit, as otherwise even with CONFIGURE_DEPENDS it is not guaranteed that the new files will be built when using globbing and the ExternalProject approach.

Why doesn't CMake-generated make clean delete files created with configure_file

I'm using CMake for a project, and generating some configuration .h files with a configure_file() command. This works well enough, but - if I make clean, the generated file is not deleted - nor is it overwritten when I invoke cmake again with different parameters (or ccmake and so on).
Why is this the case, and how can I force re-generation of configure_file output files - when necessary / always?
It seems this may happen if the files are generated under the source folder rather than under the build folder. I think CMake treated the (generated) files it found as source files - or at least, not build files (see #Tsyvarev's comment), so they must not be deleted/altered.

How do I exclude my build directory from CPack's source release?

I just realized that my CPack release's package-version-Source.tar.Z file was 1.4 gigabytes in size. It turns out it's including my entire build directory, including experimental binaries, previous releases, etc., all in each of the tarballs.
How do I exclude my build directory (and preferably also my .vscode and .git directories) from the CPack release? My CPack lines in CMakeLists.txt look like this:
include (InstallRequiredSystemLibraries)
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set (CPACK_PACKAGE_VERSION_MAJOR "${Pwr_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Pwr_VERSION_MINOR}")
include (CPack)
I was facing the same situation, though the size of the resulting source tarbal was less than yours, a couple hundred MB.
My solution was adding a line before
include(CPack)
In your case, it will look like this
set(CPACK_SOURCE_IGNORE_FILES "build")
include(CPack)
Since "build" is regex, not only your build directory will be excluded, files and directories with names matching build will too, for instance, build-dbg, mybuildetc..

CMake build and project directories

I wonder to know why projects structures has folders like bin and lib but normally (at least in tutorials I saw), people creates a folder named build and use cmake ...
Is it the right way to use ${CMAKE_BINARY_DIR}/bin or ${CMAKE_SOURCE_DIR}/bin to build a project?
You're right, people using CMake often do build in a different directory (e.g. one called build). That's called "out of source" building, and it's useful because it helps keep built artifacts out of your source tree so you don't check them in.
As for bin and lib, those are the conventional names on Unix-like systems for directories storing executable files and libraries respectively. It's good to keep your build artifacts separated this way because it makes it clear where to look for things you can run vs. things you can build against. A common setup in CMake would be to have a build directory containing bin and lib within--if your build rules are set up properly, CMake will create bin and lib when you run your build.