CMake recursive include of modules - cmake

Is it possible to use the CMake INCLUDE command the same way as in C++.
In all my projects I have to make the same includes:
Example: CMakeLists.txt for "MyApplication"
INCLUDE("FindMyBase")
INCLUDE("FindMyGtk")
In this example FindMyGtk already has "FindMyBase" in it.
So why do I need to include FindMyBase in MyApplication?
Is there a way once one .cmake file has been included that it stays available for all other projects in the chain below?
Update 1: The idea is to avoid searching every time for MyBase if it was already found once.
Update 2: The objective is also to reduce the number of includes. In my example from 2 to 1, but if you have 10 includes then you can reduce them to just 2 if these 2 depend on the other 8.

It pretty much does do that. I visualise include as if you'd pasted the contents of the include file directly into the CMakeLists.txt file where you called it.
In your case, "FindMyBase" is called twice. This often doesn't matter - e.g. if the include file only defines functions or macros it's safe to include multiple times.
If the included file searches for components using CMake's collection of find_XXX functions, then these already do what you want. The result of the search is cached. On subsequent invocations, if this cached result shows that the component has already been found, no further searching is done.
If you want (or have) to avoid including the same file multiple times, you can add include guards to the top of the file in a similar way to C++ include guards:
if(FindMyBaseIncluded)
return()
endif()
set(FindMyBaseIncluded TRUE)
That way, including the file multiple times is almost cost-free.

Related

How to keep CMake generated files?

I'm using add_custom_command() to generate some files. ninja clean removes them, as it should. One of the files is intended as a default/example implementation, to be modified by the user. It is only generated if it does not already exist. I would like for ninja clean not to remove this file.
I have tried a number of things but without success:
add_custom_target(): CMake complains about the missing file unless I name it in BYPRODUCTS, but doing this also leads to removal on clean
set_file_properties(... GENERATED FALSE) doesn't work because CMake complains about the file missing.
set_directory_properties() failed in a similar way: "folder doesn't exist or not yet processed" (it does exist)
I previously generated the example implementation and just let the user copy it or model their code on it. This works, but isn't entirely satisfactory. Is my use-case so unlikely that CMake doesn't support it?
I am afraid you requirment (conceptually, have make create something which make clean does not remove) is rather unusual. I can think of two potential solutions/workarounds.
One, move the file's generation to CMake time. That is, create it using execute_process() instead of add_custom_command(). This may or may not be possible, based on whether the file-generation process (the current custom command) depends on the rest of the build or not.
Two, totally hide the example file's existence from CMake. That is, have the custom command also generate some other file (maybe just a timestamp file) and have its driving custom target depend on that one instead. Do not list the example file as ither the custom command's dependency, output, or byproduct. That way, nothing will depend on it and neither CMake nor Ninja should not care whether it exists or not, so they will not complain or try to clean it up.
If it is an example for the user, it should not be in your build folder, but in the install folder. I don't see why you would need add_custom_command or the other commands you listed.
Therefore, you have to provide install() instructions.
You can then call make install. Cleaning will not remove those and only installing again will overwrite them if necessary.
For those, who come here a long time after the original question was asked (like me), I'll write my solution:
The tool called in add_custom_command generates two files with identical content:
one that is saved in sources, never mentioned anywhere
and one that's marked as byproduct, and then is depended on
So the first one is the file we wanted in the first place.
And the second one is actually used in build process, and gets deleted on clean.
For me the issue is that I actually want to save generated files in VCS so I can track changes. And this approach gives ne what I need.

CMake: Best method for "subprojecting" files

I'm learning/vetting CMake at the moment as I'm thinking of migrating our code to it. One thing we do a lot of with our current make system is to "subproject" common code files. For example, we have a lot of shared, generic headers (plus some c/cpp files) which get included in every project we create. I want to replicate this in CMake but I don't see an easy way of doing it. To be precise, I want to do something like:
Parent CMakeLists.txt
add_subdirectory(shared_folder shared_build_folder)
#Next line should somehow add in the files reference in the shared_folder
add_executable([specific files for this project] build_folder)
Child CMakeLists.txt (shared_folder)
#Somehow have a list of files here that get added to the parent project
So far I've found various "ways" of doing this, but all seem a little hacky. I'm coming to the conclusion that this is in fact the way I have to do things and CMake isn't really geared towards this style of development. For clarity, most of my solutions involve doing something like creating a variable at the parent level which consists of a list of files. This variable (via some shenanigans) can get "passed" to/from any children, filled in and then when I call add_exectuable I use that variable to add the files.
All my solutions involve quite a few macros/functions and seemingly quite a bit of overhead. Is this something other people have tried? Any clues on the best approach for doing this?
Thanks
Andrew
We were facing the exact same problem and after some time of crying we accepted the CMake-way and it resulted in a better structured project even if it meant to change some parts of our structure.
When using sub-directories the targets are automatically exported throughout the whole project (even in subsequent other add_subdirectory-calls) once the add_subdirectory-statement was processed: sub-projects which contain common code are creating libraries.
There is also the PARENT_SCOPE which you can use to export variables to parent CMakeLists.txt
For "other" things we simulated the FindPackage-mechanism by including .cmake-files into the main CMakeLists.txt with include. In doing so we can provide variables easily, change the include_directories and do other fancy things global to the project.
As there are no dependencies between cmake-variables, we don't use cmake to configure the source (features of the project), but only the build (compiler, includes, libraries...). This split was the key element of our build-system-refactoring.

duplicate symbol _fopen_file_func on C code, in objective-c project

In my IOS project i'm use multiple statics frameworks than use minizip in her code.
when i compile i have an error for a duplicate symbol.
if this error is due to a class, it's really simple (rename class, repair the error )
But in my case, the duplicate symbole provide from the "minizip" files ( like ioapi.c, zip.c unzip.c ) they are load in the frameworks.
How can it's possible to work correctly in this case ?
Thanks for your help.
This is the downside of Objective-C's single name-space.
If you can get an any of the header files, remove or rename them.
If you cannot get at them, you'll need to get the sources and rename/rebuid them, or use another library.
#Pixman: Look closely at the files you have (most recently) imported into your project.
I found a situation where two versions of the same files (i.e., ioapi.c, ioapi.h, mztools.c, mztools.h, unzip.c, unzip.h, zip.c, zip.h) were integrated into the project (at different levels) - therefore producing duplicate symbols.
These duplicated files already existed (in support of another file decompression need) so I removed the second copy of these files from the project, and the problem with duplicate symbols went away (as you would expect).
One way to see if duplicate file (and likely symbol) names exist in your project is to look at the Compiled Sources option available under the Build Phases portion of the project.
The added value with this view is that the path to each file is visible, and you can use this to figure out which (of the duplicate) files you want to remove.

Can CMake recognize CMakeLists.txt with another name (CMakeLists_nightly.txt)?

I am wanting to create CMakeLists.txt files that are more specifically named such as "CMakeLists_nightly.txt", "CMakeLists_weekly.txt" and so forth. The reason I want to do this is to cut down on the folder hierarchy clutter of my project. I could easily put each of these files in their own folder with the postfix I showed above but I do not want to do this.
Can I tell cmake to take a CMakeLists.txt file by another name? I have seen this question asked before on another forum (http://www.cmake.org/pipermail/cmake/2007-August/016036.html) but it was back in 2007 and the answer was no. Does the current version of CMake provide this capability?
Not really, but you can emulate this by putting CMakeLists.txt in separate directories, e.g. continous/CMakeLists.txt and nightly/CMakeLists.txt. Use INCLUDE to include the appropriate scripts for each of the build configs.
Consider if this really is the right approach - completely separating the nightly and continuous script is a really bad idea as that will lead to duplication and a very bug prone build setup.
Answer, which came into my mind, while I was reading an answer from larsmoa and thinking about it little bit longer:
(this is not exactly the answer to the question about different name for CMakeLists.txt, but rather, to "how to have two different CMake configuraiton files in the same directory")
You can avoid creating multiple directories and storing there CMakeLists.txt (it may also be problematic, if you want your script to be the parent of everything). My Idea is, that you can have two "include" cmake files with any names you like. And then in CMakeLists.txt you may have an set(CACHE), which controlls, which include-script should be actually included.
With this setup you can have two build directories: one configured with one value of the option, and another - with another. Depending on that, in which build-directory you do the build, corresponding build definition will be used.
It can look something like this:
CMakeLists.txt:
set(
MY_BUILD_KIND BUILD_A CACHE STRING
"Select build kind: BUILD_A or BUILD_B"
)
if ( MY_BUILD_KIND strequal "BUILD_A" )
include(build_a.cmake)
elseif (MY_BUILD_KIND strequal "BUILD_B")
include(build_b.cmake)
else ()
message ( FATAL_ERROR "Unknown build kind: ${MY_BUILD_KIND}" )
endif ()
Background (why do I need it?): My situation is kind of exotic, I guess. I have a C++ project, different parts of which use two different compilers. And there is a part of it, which needs to be built by each of them. So the directory structure is like this:
Projects
CompilerAProjects
CompilerBProjects
CommonProjects
Here "CommonProjects" are included as Part of "CompilerAProjects" and also as part of "CompilerBProjects". Now we try to integrate cmake and I was thinking, how can we keep the structure, but do the build with CMake. If I put CMakeLists.txt in the root directory, then I don't understand, how to differentiate between two compilers. And if I don't have the root project, then it is not clear, how to refer to "sibling" project. So I came to the idea, that I can included sub-directories basing on the current compiler. And then I decided, that actually it is not necessary, that compiler is the driving factor, we can use set(CACHE) instead. And we are not restricted to select, which sub-directory we select, but can also include ".cmake" files.

include_libraries for a single target only

In project with many multiple targets, I wish to add include libraries for a certain target only. I don't want to slow down compilation by adding many include libraries to all projects, and I do want that if I did not specify a required library as a dependency to the executable, it will fail in compile time, and not only in link time.
Is there any way to do that in CMake? Something like target_link_libraries, but only for include directories?
First of all, I would not bother with a potential increase in compilation time, because you added many include-directories. Of course, you should test if it really is an issue.
You may try to specify the COMPILE_FLAGS property directly on the source files, but this is likely not cross-platform and needs to be done on each source-file.
Alternatively, consider splitting up your project in subdirectories and write a separate CMakeLists.txt for each subdir. In that case, the include_directories() call is limited to the scope of the current project (and its subprojects) and you would have more fine-grained control over each project.
There may be an issue with requiring failure at compilation time: E.g. when using static libraries A, depending on B, depending on C: When someones links an exe/dll to A, the libs B and C are needed, but this is not necessarily detectable at compile-time... and difficult to solve generically with CMake.