cmake set value of variable for first run after command "project" - c++

If in my CMakeLists.txt I have (order #1)
...
set (CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON")
project ("my_project")
...
on first run I get in ccmake
CMAKE_VERBOSE_MAKEFILE *ON
But if I invert the order of set (CMAKE_VERBOSE_MAKEFILE ... and project ... (order #2)
...
project ("my_project")
set (CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON")
...
I get on first run
CMAKE_VERBOSE_MAKEFILE *OFF
Since I have many projects largely sharing configuration, I want to have a common CMakeLsts.txt, and a project-specific CMakeLsts.txt with the minimum project-specific contents, and an include
project ("my_project")
set (COMMON_DIR "${CMAKE_SOURCE_DIR}/../common")
include ("${COMMON_DIR}/CMakeLists.txt")
and setting CMAKE_VERBOSE_MAKEFILE=ON in ${COMMON_DIR}/CMakeLists.txt.
So I seem to be forced to work with order #2.
Under these conditions,
Only having the minimum project-specific contents in the project CMakeLsts.txt (so excluding setting CMAKE_VERBOSE_MAKEFILE=ON).
Setting CMAKE_VERBOSE_MAKEFILE=ON for the first run in the common CMakeLsts.txt.
what are (perhaps more than one) possible ways of getting CMAKE_VERBOSE_MAKEFILE=ON on first run, and then using the cache?
From what I tried, using FORCE is not useful, since if I change the value to something different (OFF in this case), it will revert the value to ON with each run.
I wouldn't want to move setting CMAKE_VERBOSE_MAKEFILE=ON to my project-specific CMakeLists.txt.
Related
Overriding a default option(...) value in CMake from a parent CMakeLists.txt

Related

cmake does not override set variable from command line

I am using a variable that I want the user to be able to pass using the command line. However, the variable is not overridden as I was expecting. The reference doc I am using is Cmake Cache
My CMakeLists.txt looks like this
cmake_minimum_required(VERSION 3.23.0)
project(design_principles)
set(PRINCIPLE "solid/single_responsibility" CACHE STRING "Enter the principle to be run" FORCE)
message(${PRINCIPLE})
add_executable(
${PROJECT_NAME}
${PRINCIPLE}.cpp
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)
The command I am passing through the command line is
cmake -S . -B build -DPRINCIPLE=temp
However, it appears that the build is always using the default value from CMakeLists.txt
From the documentation:
Since cache entries are meant to provide user-settable values this does not overwrite existing cache entries by default. Use the FORCE option to overwrite existing entries. [...] If the cache entry does not exist prior to the call or the FORCE option is given then the cache entry will be set to the given value.
The problem is clear: since you have written FORCE, the set() command will always overwrite the cache entry. The solution is to simply get rid of FORCE:
set(PRINCIPLE "solid/single_responsibility"
CACHE STRING "Enter the principle to be run")

cmake + clang_tidy - disable checking in directory

I have large project using CMake. I want to add clang_tidy-8 support with following code:
set(BORG_CLANG_TIDY OFF CACHE STRING "If enabled, clang-tidy will be used. If set to 'fix', fixes will be done on source")
set_property(CACHE BORG_CLANG_TIDY PROPERTY STRINGS ON OFF fix)
if(BORG_CLANG_TIDY)
if (BORG_CLANG_TIDY STREQUAL "fix")
set(maybe_fix -fix)
endif()
set(CMAKE_CXX_CLANG_TIDY clang-tidy-8 -extra-arg=-Wno-unknown-warning-option -format-style=file ${maybe_fix} )
endif()
I put proper .clang-tidy in root directory of project (proper = with desired checks). However, there are directories that I don't want clang tidy to check/fix (3rdparty and legacy code that can't be modified because it is brittle). So I tried putting empty .clang-tidy file in those directories (empty = with -checks=-*). This doesn't work because Error: no checks enabled.
I hoped to find some some fake -checks=-*,hello-world-do-nothing-check but nothing presented itself.
Is there other way to disable checks in selected subdirectories (/subtrees)? Those directories are static and may be hardcoded in CMake if needed.
If you want a dummy check that would do nothing there's at least one that's pretty easy to disable by its options: misc-definitions-in-headers
The HeaderFileExtensions option can be used to make the check work with only certain header file suffixes. If you set it to something non-existent line "x" then you have a hello-world-do-nothing-check alternative. Your clang-tidy file would then look something like this:
Checks: '-*,misc-definitions-in-headers'
CheckOptions:
- { key: HeaderFileExtensions, value: "x" }
You can also check https://stackoverflow.com/a/56319752/9874699 and try to adapt the line-filter to filter out files from certain directories.
Is there other way to disable checks in selected subdirectories (/subtrees)?
In CMakeList.txt files contained in those subdirectories, add the following line:
set(CMAKE_CXX_CLANG_TIDY "")
But this is not a good solution: it creates a binding between the build system and a toolchain-specific tool. CMAKE_CXX_CLANG_TIDY should only ever be set via the configuration command (or possibly via a tool-chain file).
Here's what I used in this scenario:
# Disable most checks as this is third-party code
# Have to enable at least one check, so pick a benign one!
#InheritParentConfig: false
Checks: cppcoreguidelines-avoid-goto
I think we can all agree "Go To Statement Considered Harmful".

Setting CMAKE_CXX_STANDARD to various values

I have a C++ library, that's intended to be usable across several compiler versions and several C++ standards. I have tests for this library - and I need to ensure that these tests pass for this matrix of compilers/versions that I wish to support.
I can provide -DCMAKE_CXX_STANDARD=xx (for 11, 14, 17) on the command line, and this seems to work fine. How do I provide a default value for this field? I would like that, if not provided by the user, that default is 11. It seems that when I do:
$ CXX=/path/to/gcc-7 cmake .. -DCMAKE_CXX_STANDARD=17
# does stuff, CMAKE_CXX_STANDARD is 17
$ CXX=/path/to/gcc-7 cmake ..
# does stuff, CMAKE_CXX_STANDARD is still 17
which is counterintuitive to me. Is there a way to make the latter use the desired default value of 11?
Also, if I just rerun cmake with a different value in the same build directory, would that be enough to trigger a rebuild or would I need a new build directory?
You can use the [option][1] command to let the user choose and give a default value yourself:
option(Barry_CXX_STANDARD "C++ standard" 11)
set(CMAKE_CXX_STANDARD Barry_CXX_STANDARD)
The variable name Barry_CXX_STANDARD indicated that it is specific to your project and should be the same prefix as all project-specific variables are named.
The downside of this approach is, that experienced CMake users would be surprised and set CMAKE_CXX_STANDARD directly.
Another approach is to check whether the variable is set.
if(NOT "${CMAKE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD 11)
endif()
If CMake provides already a variable, I would use the second approach. If it is only your project-specific variable, the first one is better.
In any case, if you want to change the value you have to delete the CMakeCache.txt in your build directory. Otherwise the caching hides the change.
In CMake world, first invocation of cmake differs from later ones (from the view of setting options in command line):
First invocation:
If option's value is given in command line(-DOPTION=VALUE), this value is used.
If option's value is not given in command line, default value is used.
Later invocations:
If option's value is given in command line(-DOPTION=VALUE), this value is used.
If option's value is not given in command line, previous value is used.
If option is unset (-UOPTION), default value is used.
Thus, having one cmake invocation already done, one may:
modify some of options and leave other unchanged
For doing that, pass modified options' values with -D.
reset some of options and leave other unchanged
For doing that, pass reset options' values with -U.
set some options, and reset others to default values
For doing that, make a clean rebuild by removing CMakeCache.txt from build directory or removing all files from build directory.
For assign default value for an option in the project, use common CACHE variables:
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ standard to be used")

Qt Creator, build dir with branch name

Based on several kits I am using, the Qt Creator build directory is derived from
project name
Qt version
compiler
build configuration: debug / release
Example: build-client-Qt_5_3_0_fooProject_MINGW_32bit_qmake_MinGW22-Debug
My problem is, if I switch my git branch, I always have to recompile from scratch (time consuming). I wonder, if it might be possible to include the branch name, so I can keep different builds at the same time
=> Possible build dirs:
build-client-Qt_5_3_0_fooProject_MINGW_32bit_qmake_MinGW22-Debug_master
build-client-Qt_5_3_0_fooProject_MINGW_32bit_qmake_MinGW22-Debug_branchbar
Or is there a chance to add a third build configuration, e.g. Debug_others, resulting in a build directory such as
build-client-Qt_5_3_0_fooProject_MINGW_32bit_qmake_MinGW22-Debug_others
You can manage builds in Project tab on the left. If you want to have build automaticaly switching dirs depending on the branch you are on, on each branch you would have to edit *.pro.user file. Find line:
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">
/home/etc/etc/etc
</value>
And change the directory to the one you want it to be (ex. edit the ending part of the value). On a different branch have it point somewhere else. Thus changing branches will change the shadow build directory.
P.S. If you have several builds (like debug, release) you need to check if the build directory you're editing is the one you want. Check activeBuildConfiguration number and edit it's directory only (the number of build is usually a line above the one I showed), or change activeBuildConfiguration to 0 and the first build directory.
It's a bit knotty but I think manageable.

different set of flags for subprojects in waf

I'm still struggling with waf for setting up different set of flags for subprojects.
I have a structure like this, in which superproject recursed to the subprojects:
superproject/wscript
libproject/wscript
progproject/wscript
The problem is that both subprojects progrproject and libproject use boost tool.
I want that both projects check for boost at configuration time, since I want the projects to be self-contained when they are built independently.
I have to do something like this to not overwrite flags for boost between subprojects:
#In libproject
cfg.check_boost('regex', uselib_store='BOOST_LIBPROJECT')
#In progrpoject
cfg.check_boost('program_options', uselib_store='BOOST_PROGPROJECT')
This has the side-effect of making options --boost-libsand --boost-includesdefaults not to work anymore.
Actually, I would like to use the default BOOST store for both, but one seems to overwrite the other in _cache.py file. If I build the projects alone and separate, this problem does not happen. I think setting another environment is not a solution (right?)
since this makes the command to become ./waf build_libproject or similar, which is not what I want.
I want:
./waf configure build
to run correctly without workarounding with different stores or preventive flag name changing.
What is the correct way to do it?