Using CMake to generate multiple Code Composer build configurations - cmake

My goal is to use a script/CMake to create a "Debug" build configuration and a "Release" build configuration that can be switched between within Code Composer Studio's UI (using the "Build Configuration -> Set Active..." option).
Currently,
A script is ran that runs CMake with desired commands (toolchain, etc). A Code Composer Studio project is generated (as described in CMakeLists.txt)
CCS project is imported into CCS
The problem is this only generates a "Debug" build configuration. Is it possible to add a command to CMakeLists.txt, or to cmake command line, or even ccs command line that allows multiple build configurations to be generated?
The only difference between the two will basically be defining NDEBUG, and possibly changing optimization level.

I had this same question...then realized I am the one who originally asked this ~4 years ago! Anyways, I found a way to do this:
Using Code Composer, create the build configuration(s) as you want them to behave. When done, copy the .cproject file to a cproject.in "template". CMake will use this template to generate an identical .cproject for any future cmake builds. Make sure to replace any hardcoded values (ex: project name) with proper cmake variables.
For me, my CMakeLists.txt called configure_file(path/to/cproject.in ${CMAKE_SOURCE_DIR}/.cproject #ONLY).
Also be sure to delete your CMakeCache and CMakeFiles if they already exist...I believe those were preventing me from seeing the resulting change.

Related

How to build multiple configurations of an ESP-IDF application

I have one ESP-IDF application and two hardware boards. I use a preprocessor definition to control which hardware board version to build. For now, I'm modifying the config in the sdkconfig file via menuconfig. But I would like to build both versions at once from a script, or build only one specific config without the manual process of menuconfig.
I have a header that looks like this, and works when HW_VER is set correctly:
#if HW_VER == 2
#define BTN_GPIO 9
#elif HW_VER == 3
#define BTN_GPIO 10
#endif
And from the a script I would like to build each by selecting a value for HW_VER, for example:
idf.py build -DHW_VER=2
idf.py build -DHW_VER=3
The idf.py build command runs cmake and ninja. I'm new to cmake, so perhaps there is a natural way to do this?
I would also like to build release and debug builds, turn on/off memory debugging etc. from the command line.
I've tried idf.py build -DHW_VER=2 but I've learned that these vars are only sent to cmake and not to the preprocessor. The HW_VER macro remains undefined.
Using add_definitions() in my CMakeLists.txt can set HW_VER, but doesn't help me make different builds from the same files.
Using a config variable like CONFIG_HW_VER in the sdkconfig works to control builds using menuconfig but I don't see a way to automate this.
I've considered modifying the configuration variable, CONFIG_HW_VER in the sdkconfig file programmatically, but this file is under source control, and it is auto generated by menuconfig, so that doesn't seem wise.
Similarly I can modify the CMakeLists.txt file programmatically, but that file is also under source control, and isn't a trivial format.
I use two ways to feed custom configurations into an ESP IDF project.
Firstly, the light weight stuff like preprocessor definitions from the environment are quite simple. You have to configure CMakeLists.txt file (the one in project root) to pass variable values from environment into the build process. For example, to create something equivalent to preprocessor definitions -DMY_NUMBER=123 and -DMY_STRING="abc" add this somewhere before the "project" line:
add_compile_definitions(MY_NUMBER=$ENV{MY_NUMBER})
add_compile_definitions(MY_STRING=\"$ENV{MY_STRING}\")
...
project(myproject)
Assuming you're working in Bash, build with:
$ MY_NUMBER=123 MY_STRING="abc" idf.py build
or (for a slightly more "sticky" enviroment):
$ export MY_NUMBER=123 MY_STRING="abc"
$ idf.py build
You can use cmake to add more advanced logic, e.g. setting default values in case the environment doesn't set anything.
Secondly, the more powerful configuration tool for ESP IDF is the menuconfig target and sdkconfig file. As you've already noticed, playing with sdkconfig directly is not so easy. In my projects I consider this a generated temporary file and I never commit it to git. Instead I delete it. When sdkconfig is missing, idf.py will take file sdkconfig.defaults, copy it into sdkconfig and work with this. That is your best mechanism for supporting different hardware configurations - no sdkconfig and instead different variants of sdkconfig.defaults for each hardware you wish to support.
As an example, assume you have two different HW versions described in sdkconfig.defaults.hw_ver1 and sdkconfig.defaults.hw_ver2 and you wish to build for HW ver2 configuration:
$ rm sdkconfig && cp sdkconfig.defaults.hw_ver2 sdkconfig.defaults
$ idf.py reconfigure
Now you can build for this configuration like you usually would:
$ idf.py build
When you wish to build for the other FW configuration, re-execute the previous commands with sdkconfig.defaults.hw_ver1
All this is rather thoroughly documented in the Build System documentation, so feel free to dig in.

CMake in QtCreator 4.3 shows many automatic targets, how to remove/hide them?

I just switched to the last version of QtCreator (4.3.1) and the project explorer now shows many targets like ContinuousBuild, ContinuousConfigure, NightlyBuild, ExperimentalCoverage etc.
How can I remove all of these (or at least hide them) ?
I don't even know where this is generated in CMake.
Seems to be related to this question Hide automatically generated CTest targets except that I am not using CLion.
You are probably using somewhere:
include(CTest)
According to the documentation:
Configure a project for testing with CTest/CDash
All those targets are pulled in by the combination of the two, CTest and CDash (almost all of them are due to the latter actually).
If you don't know why they are there and for what they can be used, probably you are using the wrong command.
If all what you want is to use only CTest, add tests with add_test and run them with make test, replace the line above with this one:
enable_testing()
The documentation is quite clear indeed:
Enable testing for current directory and below.
Clean up the build directory and run cmake from scratch from within QtCreator. All the targets you mentioned should disappear.
I had exactly the same problem in a project of mine when I updated QtCreator a couple of months ago. You can see in the history of the project the commit that solved the issue. Pretty short indeed.

Why there are two buttons in GUI Configure and Generate when CLI does all in one command

I understand that cmake is build generator. It mean that it can generate appropriate builds (makefiles, Visual Studio project etc.) based on instructions from CMakeLists.txt. But I do not understand two things which I guess are related:
Why there are two buttons "Configure" and "Generate" in cmake-gui? In command line tutorials that I've read (e.g. this one) usual process was done with one cmake command.
What is cache in cmake world? AFAIK it is state when "Configure" button was pressed but "Generate" button was not pressed. But why is this useful? What all those variables that pops-up after pressing "Configure" mean? Why I'm supposed to edit them? Isn't the only allowed configuration done via CMakeLists.txt?
Thanks
There are two stages when CMake is run, as reflected by the two buttons in the CMake GUI. The first stage is the configure step where the CMakeLists.txt file is read in. CMake builds up an internal representation of the project during this stage. After that, the second stage called generation occurs where the project files are written out based on that internal representation.
In CMake GUI, the two stages can be run separately. When you run the configure step, the GUI shows all cache variables (see below) which changed their values since the last time configure was run or since CMake GUI was started if this is the first configure run. Normal practice is to re-run the configure stage until no variables are highlighted red. Once configure leaves no variables in red, you can press the generate button and the build tool's native project files will be created and you are good to go starting your builds, etc.
The command line cmake tool doesn't allow you to separate out running the configure and generate steps individually. Rather, it always runs configure and then generate.
For simple projects, the distinction between configuration and generation is not all that important. Simple tutorials will often just lump the two together since the reader can get away without understanding the distinction for basic project arrangements. There are, however, some CMake features which rely on this distinction. In particular, generator expressions are a generation-time feature where decisions about certain aspects of the build are delayed to generation time rather than being fully handled at configure time. One example of this is configuration-specific content such as compiler flags, source files only compiled in for some configurations, etc. The build configuration isn't always known at CMake's configure step (e.g. Xcode and Visual Studio are multi configuration build tools, so there can be more than one and it is selected by the user at build time). The generation step will process generator expressions for each build type and the result can be different for each configuration. You might also find this answer informative regarding this particular example. For a more advanced example of a technique which takes advantage of the distinction between configure and generation stages, see this post, but be aware it is not a common technique.
Regarding your other question about what is the cache, CMake records information between runs in the variable cache. At the end of the run, it updates a file called CMakeCache.txt in the build directory. When you next run CMake, it reads in that cache to pre-populate various things so it doesn't have to recompute them (like finding libraries and other packages) and so that you don't have to supply custom options you want to override each time. You wouldn't typically edit CMakeCache.txt by hand (although it's okay to do so). Rather, you can modify the variables you want in CMake GUI and then re-run the configure step (don't forget to then also run generate to create updated project files). You can also define or modify cache variables at the cmake command line with the -D option.

How can I configure CMake generated Eclipse project's Build Command and Project Paths?

Our project uses CMake to configure our code. We use Ninja along with a distributed build system. A number of people on our team use Eclipse CDT. We run CMake with the "Eclipse CDT4 - Ninja" generator and the result is generally pretty good.
The issues is that any time a CMake file is changed and you ask Eclipse to build the code it regenerate the eclipse project file overwriting any manual changes you've made to the project.
For example the default build command that it provides the eclipse project is /usr/bin/ninja when in fact I want to take advantage of our distributed build system and set the build command to /usr/bin/ninja -j16. It would be nice if I could have the project file that CMake generates automatically include this setting change.
The other setting I am most interested in preserving is the C/C++ Project Paths->Source. As a general rule we place our CMake build directory as a sibling to the main project directory i.e. ./project ./build. We want to include some files in the build directory in the Eclipse index to make code completion and other tools work better. The default project doesn't include the build directory in source path and thus it does not get indexed.
Is there some way to remedy these issues?
I found a solution to build command issue.
When you run cmake to generate the eclipse project include the additional argument:-DCMAKE_ECLIPSE_NINJA_ARGUMENTS=-j100. I haven't confirmed but I believe a similar command is required for eclipse make projects -DCMAKE_ECLIPSE_MAKE_ARGUMENTS=-j100.
Unfortunately this feature is poorly documented and I have not found a solution to my other issue.

qtcreator can only build all not each single targets for cmake projects

I use cmake to generate qtcreator's project files, For the run part I can have different targets, but the build parts, I can only select all, and could not build each targets separately. Is there anyway I can build only one targets with qtcreator's cmake projects?
Since QtCreator 4.0.0, on Projects pane, go to build steps -> Details and select your target.
You can also use the "--target" command line option with cmake.
Update:
Since QtCreator 4.3.0 with CMake 3.7.2 or greater the list of targets is on the project view, so you can just right click and build.
With QtCreator 4.0+ it is is possible, see rboc's answer below.
Old answer
I believe this is currently essentially impossible. I say "essentially" because if you wanted to, you could make a custom build configuration for each target you want to create, manually specifying the target as an argument in the command for that configuration. Then, to build that target, simply select that configuration and build. This is an extremely hacky workaround, but unfortunately I think it's the only viable option at the moment. A better solution might be to create a separate project for each target.
One can configure QtCreator to build the target that is currently selected for running, which IMHO should be the default.
To do so, navigate to the "Projects" pane, then in your Kit's "Build" tab, locate the "Build Steps" section. Remove all existing build steps by clicking on the cross.
Add one "Custom Process Step". Fill the "command" field with "%{CMake:Executable:FilePath}", the "arguments" field with "--build . --target %{CurrentRun:Executable:FileBaseName}" and the "working directory" field with "%{buildDir}" (all without quotes).
Tada!