Symbolic links from each target dir to common resources dir - cmake

I need to create symbolic links to directory common_resources which contains textures, fonts, 3D models, shaders, and is located in my CMAKE_SOURCE_DIR. I have to put such a link into all of my compiled binary target's working directories (~50 directories).
I can probably do it one-by-one by adding this ADD_CUSTOM_TARGET to each subfolder
ADD_CUSTOM_TARGET( common_resources ALL COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/common_resources ${CMAKE_CURRENT_BINARY_DIR}/common_resources )
but I do not want to do it because:
I don't want to to edit all those CMakeList.txt files and
I don't want to create so many custom targets for no reason. I use Code::Blocks IDE and I already have very long list of targets to select from, which makes it difficult to work with.

The answer is two-fold:
Write a function wrapping the custom command.
You have to automatically iterate over all sub-directories, see https://stackoverflow.com/a/7788165/2799037 how to do that. Call your function for every sub-directory.
Your second concern is probably a misconception. custom_command does not add a new target, that is only custom_target.

Related

CMake: How to include only one header directory

It seems the CMake include_directories will add not only the passed directory but also all its sub directories to the include list.
Is there a way to add only one directory (without its sub directories), i.e. some sort on include_directory command?
As indicated in the documentation, only the folders indicated int he command are added, not the subfolders. Of course, if you have a subfolder foo and someone does #include <foo/bar.h, then the file will be included.
Consider using target_include_directories as it is more flexible and better, as it targets one target, and if the target is reused, then dependent includes may also be carried to the dependent targets (depending on PUBLIC/PRIVATE/INTERFACE).

Code generator generating its own CMake files and targets

Let's assume I have a script that generates a set of source files forming a target I want to link against in a CMakeLists.txt. If the file names are known to the latter then the usual add_custom_target() and add_custom_command() commands will make it possible to use the generated files as target sources.
Let's assume, though, that only the generator script knows the file names and locations. How can a target library be generated so that the parent CMakeLists.txt can link against it without its knowing the actual file names?
Note that the dependency topic isn't in this question's scope as the script knows itself when to regenerate or not. It's not the finest use of CMake, but it's sufficient in this use case.
Idea #1
The script also generates a generated.cmake file included by the parent one using include(generated.cmake). Problem: CMake doesn't find generated.cmake as it isn't existing at configuration time.
Idea #2
Similar to idea #1, but the script is called with the execute_process() so that generated.cmake is present at configuration time. Problem: The script is not called anymore at subsequent builds, thus ignoring possible changes to its input.
Idea #3
The script passes back a list of targets and files that is somehow considered by the parent CMakeLists.txt. So far I couldn't find a way to do so.
The solution I came with is eventually a mixture of all three ideas.
Solution to idea #1's problem
execute_process() actually ensures that generated_targets.cmake is present at configure time.
Solution to idea #2's and #3's problems
As stated in this answer to "Add dependency to the CMake-generated build-system itself", the CMAKE_CONFIGURE_DEPENDS directory property can be edited to add files whose touching re-triggers the configure step.
The key success factor is that this property can be set after the initial execute_process() call so that the script can identify and list its input dependencies (in an output file) that are then added to CMAKE_CONFIGURE_DEPENDS, hence also solving the input dependency problem.
Resulting pseudo code
# The script generates:
# - <output_dir>/cmake/input_files
# - <output_dir>/cmake/generated_targets.cmake
execute_process(
COMMAND myScript
--output-dir ${CMAKE_CURRENT_BINARY_DIR}/generated
)
# Mark the input files as configure step dependencies so that the execute_process
# commands are retriggered on input file change.
file(STRINGS ${CMAKE_CURRENT_BINARY_DIR}/generated/cmake/input_files _input_files)
set_property(
DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${_input_files}
)
# Add the generated CMake targets.
include(${CMAKE_CURRENT_BINARY_DIR}/generated/cmake/generated_targets.cmake)

Adding sources to a list variable in cmake vs. directly in add_executable

Why is it recommended to add sources to a list first, rather than directly to the executable?
PROJECT( helloworld )
SET( hello_SRCS hello.cpp )
ADD_EXECUTABLE( hello ${hello_SRCS} )
Why not just skip the SET line altogether?
I have seen this practice often enough to also think that it’s considered a good practice. For example, if you use the CLion IDE (which actually uses CMakeLists.txt as its project structure file), you’ll see that when you create a new project it creates a SOURCE_FILES variable by default.
One reason I can think of as to why this is a good practice is that if you want to build the same files into several targets. For example, you might want to have both static and shared binaries for your lib, so if you have a SOURCE_FILES var you just have to write something like:
add_library(myLibStatic STATIC ${SOURCE_FILES})
add_library(myLibShared SHARED ${SOURCE_FILES})

Can CMakeLists.txt depend on a file parsed by a function?

I am rather new to CMake, starting off for the first time with a larger project consisting of many subprojects.
For particular reasons (described below for the curious) I already have a set of include files that contain info about the source files needed for each CMake target (lib or exe) – and, for now, I prefer to (re)use these files (reason also described below)
Writing a function to parse these files and add their content as source files to the targets was a surprisingly easy task.
But – now the Problem:
Obviously I want to have each targets CMakeLists.txt depend on the particular include file, that generates the list of source files, so that changes on the include file will be detected as if it were changes to CMakeLists.txt itself, but I simply can’t find any references on how to accomplish that.
N.B.: I found AddFileDependencies but that is for adding dependencies on source files, not the CMakeLists.txt. However, CMake itself can figure out dependencies to included .cmake file somehow, so I figured, it should be possible to do somehow.
Background for the curious:
For this project (quite a number of libraries used by quite a number of executable targets, all organized as subprojects) I was using QMake (without actually using Qt itself) for setting up makefiles. Doing so I was able to use Qt Creator while still being able to generate Visual Studio Solution/Project files automagically. We’re also still in progress of evaluating different IDEs and the choice has not been made yet. But the most important reason to use a generator like QMake / CMake was not being forced to set up the VS files for all these subprojects manually.
Although I needed to trick QMake sometimes to do what I wanted to, things went quite well - even for the VS solution - except for one thing: Visual Studio messes up dependencies on Flex/Bison and other files using custom build rules. It keeps recompiling the Flex/Bison/other files saying „command line changed“ – which I gave up trying to fix.
For this reason I thougt, I’d try CMake as a generator instead, which looks very promising so far – although not having builtin precompiled header support in CMake is somewhat ridiculous these days (off topic, I know).
Since Qt Creators CMake support is by far not as good as the support for QMake projects, I firgured, using the approach of parsing the .pri files containing the source file list would enable me using QMake and CMake side by side – especially since the remaining project settings are rather less complicated than on most open source projects.
There's a nice trick which does exactly what you need. It's based on the idea I found in the git-revision module of #rpavlik see this so question
This is the overall idea:
Create a dummy timestamp file
Add a custom command which touches the timestamp whenever the input .pri file changes
include the timestamp file in your CMakeLists.txt
A possible implementation:
set(input_pri_file <path-to-the-input-pri-file>)
set(timestamp_file ${CMAKE_CURRENT_BINARY_DIR}/timestamp.cmake)
add_custom_command(
OUTPUT ${timestamp_file}
COMMAND ${CMAKE_COMMAND} -E touch ${timestamp_file}
MAIN_DEPENDENCY ${input_pri_file}
VERBATIM
COMMENT "Updating timestamp.cmake"
)
if(NOT EXISTS "${timestamp_file}")
file(WRITE ${timestamp_file} "") # create initial empty file
endif()
include(${timestamp_file})
# create the file list from input_pri_file
....
# use the file list
add_executable(main ${filelist})
Here's what happens when the .pri file changes:
the change triggers the execution of the custom command
which updates the timestamp
because the CMakeLists includes the timestamp it is dependent on it
so updating the timestamp triggers a re-configuration of the CMakeLists.txt
I use the configure_file() if I have some input that should retrigger CMake's configuration process. See e.g. How to make CMake reconfiguration depend on custom file? and configure_file()'s unit test
So in your case it would look something like:
configure_file(SomeInput.pri ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri)
Then you use ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri to generate the sources. Just make sure you do not add COPYONLY, because then configuration won't retrigger on changes of SomeInput.pri.
EDIT: Alternatively use - a relative new addition - the CMAKE_CONFIGURE_DEPENDS directory property.

Recursive Makefile - Passing Variables to the Root Makefile

Currently i am having problems with a makefile due to some unexpected recursion and the neccessary collection of filenames. I want to call recursively a Makefile in the root folder of my project and that one should go through every possible subfolder (and their subfolders...) with the goal to collect all files and write them to a variable to be used as "targets" or dependent files.
For example: /Makefile goes through /Source, /Source/Boot and finds /Source/Boot/Boot.s (-> one target is therefore /Source/Boot/Boot.o) and it goes on with /Source/Kernel and finds /Source/Kernel/Foo.c (-> second target is therefore /Source/Kernel/Foo.o). I can compile these files in the Makefiles in the subfolders, but i need to link them when my root Makefile returns to the root.
So the question is, how can i pass adequately the paths to these object files to the root makefile to link them?
Recursively called makefiles can't pass info back to their caller (unless you resort to a hack, like using external files to collect the object file names).
Have a look at the paper Mark linked to. It shows a way of organising your project to do what you want, in a maintainable way.