CMake - Removing an option from the GUI set in another cmake file - c++

I'm creating a project (let's call it myProject) that includes macros and CMakefiles defined in another project (let's call it otherProject). Of course, myProject depends on libraries created and compiled in otherProject.
otherProject has an option to set compilation of the libraries in dynamic or static using the standard option command:
option(USE_STATIC_LIBRARIES "Build static libraries?" OFF )
In myProject, I want to force this option to ON all the time and remove it from the GUI so that users will not be able to change it; WITHOUT having to modify the original CMakefile. What I have done so far is force the value to ON by using the following:
set( USE_STATIC_LIBRARIES ON FORCE )
include( otherProjectCmakefile)
This works as intended, forcing the value to ON, but the option still appears in the GUI (user action however is ignored and internally, the value is always ON).
My question is, how can I remove the option from the GUI completely, not display it at all. I want to avoid any possible confusion.

You can start reading from
cmake --help-command SET
and you will probably be interested in this option for SET
INTERNAL = No GUI entry (used for persistent variables).

Related

CMake: compilation speed when including external makefile

I have a c++ cmake project. In this project I build (among other) one example, where I need to use another project, call it Foo. This Foo project does not offer a cmake build system. Instead, it has a pre-made Makefile.custom.in. In order to build an executable that uses Foo's features, one needs to copy this makefile in his project, and modify it (typically setting the SOURCES variable and a few compiler flags). Basically, this Makefile ends up having the sources for your executable and also all the source files for the Foo project. You will not end up using Foo as a library.
Now, this is a design I don't like, but for the sake of the question, let's say we stick with it.
To create my example inside my cmake build I added a custom target:
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/Makefile.custom.in Makefile.custom)
ADD_CUSTOM_TARGET(my_target COMMAND $(MAKE) -f Makefile.custom
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
This works. I can specify some variables to cmake, which get resolved in the call to CONFIGURE_FILE, and I end up with a working Makefile.custom. Then, invoking make my_target from the build directory, I can build the executable. I can even add it to the all target (to save me the effort of typing make my_target) with
SET_TARGET_PROPERTIES(my_target PROPERTIES EXCLUDE_FROM_ALL FALSE)
Sweet. However, cmake appears to assign a single job to the custom target, slowing down my compilation time (the Foo source folder contains a couple dozens cpp files). On top of that, the make clean target does not forward to the custom makefile. I end up having to add another target:
ADD_CUSTOM_TARGET(really-clean COMMAND "$(MAKE)" clean
COMMAND "$(MAKE)" -f Makefile.custom clean
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
which, unlike my_target with all, I can't include in the clean target (can I?).
Now, I know that a cleaner solution would be to have the Foo project be built as an external project, and then link to it. However, I've been 'recommended' to use their Makefile.custom.in makefile, modifying the few lines I need (adding my sources, specifying compiler flags, and few other minor modifications). So, regardless of how neat and clean this design pattern is, my questions are:
is there a way to tell cmake that make should use more than 1 job when making the target my_target?
is there a cleaner way to include a pre-existing makefile in a cmake project? Note that I don't want (can't?) use Foo as a library (and link against it). I want (need?) to compile it together with my executable using a makefile not generated by cmake (well, cmake can help a bit, through CONFIGURE_FILE, by resolving some variables, but that's it).
Note: I am aware of ExternalProject (as suggested also in this answer), but I think it's not exactly what I need here (since it would build Foo and then use it as a library). Also, both my project and Foo are written exclusively in C++ (not sure this matter at all).
I hope the question makes sense (regardless of how ugly/annoying/unsatisfactory the resulting design would be).
Edit: I am using cmake version 3.5.2
First, since you define your own target, you can assign more cores to the build process for the target my_target, directly inside your CMakeLists.txt.
You can include the Cmake module ProcessCount to determine the number of cores in your machine and then use this for a parallel build.
include(ProcessorCount)
ProcessorCount(N)
if(NOT N EQUAL 0)
# given that cores != 0 you could modify
# math(EXPR N "${N}+1") # modify (increment/decrement) N at your will, in this case, just incrementing N by one
set(JOBS_IN_PARALLEL -j${N})
endif(NOT N EQUAL 0)
and when you define your custom target have something like the following:
ADD_CUSTOM_TARGET(my_target
COMMAND ${CMAKE_MAKE_PROGRAM} ${JOBS_IN_PARALLEL} -f Makefile.custom
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
by the way, I don't think there's the need for you to include also CMAKE_BUILD_TOOL among the COMMANDs in your target.
I believe that instead of modifying the lines as above, you could call
make -j8 my_target
and it might start 8 jobs (just an example) without modifying the CMakeLists.txt, but I cannot guarantee this works having defined the COMMAND the way you have, just try if that's enough.
For the second point, I cannot think right now of a "cleaner" way.

Files exclusion (custom and transient) from build

I have many C++ (Google Test) source files in my Visual Studiosolution and I want to have the possibility to keep only a few for the build (to focus on the problem), but also to come back quick enough (two times by day) to the initial configuration.
We are using, more or less, about three solutions: Visual Studio, CMake and QT (but I could add yet another one). I never used QT, so the other two solutions I see are:
Visual Studio: folders are useless, but I can select files and exclude them from build. But these changes are saved in vcproj so I have to pay attention not to save them on the version control, which is annoying.
CMake: easy change the CMakeLists.txt (comment lines with the sources folders), but I always have the version control problem ... maybe I can configure the excluded files in a custom (user) file. Advantage: I can generate only what I want, more flexible and not so boring like the previous one.
By example, if I do not want the sources in src_2:
file(GLOB_RECURSE SRC_FILES_1
${SOURCE_BASE_DIR}/src_1/*.cpp
${SOURCE_BASE_DIR}/src_1/*.h
)
file(GLOB_RECURSE SRC_FILES_2
${SOURCE_BASE_DIR}/src_2/*.cpp
${SOURCE_BASE_DIR}/src_2/*.h
)
file(GLOB_RECURSE SRC_FILES_3
${SOURCE_BASE_DIR}/src_3/*.cpp
${SOURCE_BASE_DIR}/src_3/*.h
)
add_executable(${PROJECT_TEST_NAME}
${SRC_FILES_1}
# next line is commented
# ${SRC_FILES_2}
${SRC_FILES_3}
)
Is there another solution or a way to improve one of these proposed here?
You can control this with a cmake variable.
option(BUILD_TESTS "builds test cpp files" ON)
This adds an option for your cmake file. It defaults in this case to ON you can change that though. Now lets get on:
if(BUILD_TESTS)
set(TEST_CPP_FILES test1.cpp test2.cpp)
endif(BUILD_TESTS)
add_executabe(foo bar.cpp bar1.cpp $(TEST_CPP_FILES))
Here you define a variable with the source file of your tests (or whatever source files you want to build when the BUILD_TESTS is ON. These then get added to the target. If BUILD_TESTS is off this variable will be empty.
now to change the Value you can run
cmake <...> -DBUILD_TESTS=OFF
Or with ON if you want to turn them back on again. You also can keep the change in version control because it will default to ON and you need to explicitly disable it.
You can also exclude whole subdirectories or targets with this in the if statement if you not just only want to exclude source files.
EDIT:
For your example it could look like this:
if(BUILD_TESTS)
file(GLOB_RECURSE SRC_FILES_2
${SOURCE_BASE_DIR}/src_2/*.cpp
${SOURCE_BASE_DIR}/src_2/*.h
)
endif(BUILD_TESTS)
SRC_FILES_2 should be empty afterwards.

cannot change cmake executable output directory on windows

I have a project that builds on both Linux and Windows.
In that, I have in a subfolder somedir/modules/MyModule a CMakeLists.txt which should add some test executables. cmake wants to put them in some subdirectory binary folder, but I want to place them in the common binary folder under ${CMAKE_BINARY_DIR}/x64
So what I'm doing is this (in the CMakeLists.txt in the somedir/modules/MyModules directory):
ADD_EXECUTABLE(MyTest MyTest.cpp)
set_target_properties(MyTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/x64")
TARGET_LINK_LIBRARIES(MyTest SomeLibraries...)
ADD_TEST(MyTest ${CMAKE_BINARY_DIR}/x64/MyTest)
Under Linux this works nicely, but under Windows I simply cannot get it to build into the ${CMAKE_BINARY_DIR}/x64 folder. I've checked via MESSAGE, the ${CMAKE_BINARY_DIR}/x64 does point to the right folder. I also tried changing the CMAKE_RUNTIME_OUTPUT_DIRECTORY (or even the per-target variables, e.g. CMAKE_MyTest_OUTPUT_DIRECTORY, MyTest_OUTPUT_DIRECTORY_Release, MyTest_OUTPUT_DIRECTORY_Debug, as mentioned here: https://stackoverflow.com/a/25328001/671366). Tested both before or after ADD_EXECUTABLE, doesn't change anything. The output directory stays fixed on somedir/modules/x64/.
I'm out of ideas what I need to do, or even where the output directory it insists on using is coming from. Any ideas? At which point in time is the output directory decided in cmake? How does this relate to subdirectories? The executables specified in the parent folder CMakeLists.txt files get built in the desired directory, but if that is by mere chance I can't really say.
Config-specific property RUNTIME_OUTPUT_DIRECTORY_<CONFIG> has priority over common one RUNTIME_OUTPUT_DIRECTORY. Both types of properties are initialized from corresponded CMAKE_* variable(if it is set) when executable target is created.
So, having e.g CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG config-specific variable being set makes this variable to be used for Debug configuration even if RUNTIME_OUTPUT_DIRECTORY property is explicitely set. The only way to redefine output directory in that case is to set RUNTIME_OUTPUT_DIRECTORY_DEBUG config-specific property.

CMake building targets conditionally based on library existence

I have a large cross-platform project which needs to build in various places; in some places, different UI toolkits, sound APIs, etc. may be available, and I am trying to figure out the best way to automatically configure which targets get configured based on which libraries are present.
The code I am trying for that is, for example:
find_library(PC_EGL EGL)
find_library(PC_GLESv2 GLESv2)
find_library(PC_Xxf86vm Xxf86vm)
if (DEFINED PC_EGL AND DEFINED PC_GLESv2 AND DEFINED PC_Xxf86vm)
add_executable(foo foo.cpp)
target_link_libraries(foo ${PC_EGL} ${PC_GLESv2} ${PC_Xxf86vm})
endif()
However, in the case that I build this on a system which doesn't have libGLESv2 available, I get the error:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
PC_GLESv2
linked by target "foo" in directory /path/to/platform
The find_library documentation implies that the variable PC_EGL_NOTFOUND should be getting set, but it isn't (CMake 2.8.5). So, what is the appropriate way to use find_library to determine whether a target should be made to exist at all? It seems like using
if (NOT PC_EGL MATCH "-NOTFOUND")
is a bit fragile and fiddly, so is there a better mechanism for determining a CMake command path based on wheter a library was found at all?
It's simply
if(PC_EGL AND PC_GLESv2 AND PC_GLESv2)
CMake treats 0, FALSE, OFF, ANYTHING-NOTFOUND as false.

How to have a variable only in one mode with CMake

I Want to create a new mode (Debug, Release and a new one) in my project. After that I will need a variable that is only used in that new mode, so I can create a variable for all and set different value for Debug/Release (i.e. 0) and for the new one (1).
How can I solve this?
What i have:
set (CMAKE_CONFIGURATION_TYPES "Release;Debug;NewConfig" CACHE STRING "Configurations" FORCE)
SET (VARIABLEX 1)
if (VARIABLEX )
add_definitions (-DVARIABLEX )
endif (VARIABLEX )
First of all, adding new configuration types is not yet well supported in CMake.
Despite the CMake FAQ, looks like there is something still a bit unimplemented for this feature request. There is even an open issue for it:
http://www.cmake.org/Bug/view.php?id=5811
Monitor that bug in the CMake bug tracker to be notified as things are updated.
However, given that you would like to have different definitions for different configurations, you should see the help for the CMake target property COMPILE_DEFINITIONS and COMPILE_DEFINITIONS_DEBUG (for example):
http://cmake.org/cmake/help/v2.8.8/cmake.html#prop_tgt:COMPILE_DEFINITIONS
http://cmake.org/cmake/help/v2.8.8/cmake.html#prop_tgt:COMPILE_DEFINITIONS_CONFIG