In CLion, how do you set CMakeLists.txt option values? - cmake

I'm trying to use CLion (latest version - 2019.3) to work on a source repository of mine, which already uses CMake (i.e. has a CMakeLists.txt). Now, the package has some options regarding which targets to build; by default it builds just a few, but if you set an option to ON, then a bunch of tests are compiled and built.
Unfortunately, I don't quite see where CLion lets you set CMake option values for the build subdirectories it generates. Is it really forcing the defaults on you, or am I missing something in the main UI or the preferences?

CLion 2022.2 and later
CMake now supports setting (cached) option values:
On the Menu, choose File | Settings...
In the navigation tree, locate Build, Execution, Deployment | CMake
In the Profiles pane, choose the CMake profile for which you want to edit options.
You will see an expandable area entitled "Cache Variables".
CMake 2022.1 and earlier
For now, there's no UI for setting option values. You'll need to edit your CMake profiles (on the menu: File | Settings | Build, Execution, Deployment | CMake) and manually add CMake command-line options, e.g. -DBUILD_TESTS:BOOL=ON.
I've filed bug CPP-20268 about this fact.
CLion developers are planning to allow this through a mechanism for editing all of the CMake cache - an approach which I disapprove of, but it'll be better than nothing I suppose. That is issue CPP-423.

Related

What is the one-step process to clone a repo and run a CMake+vcpkg project, not assuming vcpkg exists?

I'm missing something in my understanding of CMake+vcpkg, and I'm also missing proper keywords to search for a solution. (Plus I'm new to both CMake and vcpkg, unfortunately.)
I want to have a public repo for a C++ project that uses CMake as its build system and vcpkg as its package manager.
At my currently level of understanding the user needs to have CMake and vcpkg already installed before he can type cmake and build the repo. I'd like to make it as simple as possible to build the repo and not have a bunch of instructions telling him how to get set up even before he can build.
Is this right?
I'd like a one-step solution: After cloning the repo user types ... something ... and the repo gets built.
I am willing in this day-and-age to assume he's got CMake installed ... plus that it can find the right toolchain. So maybe all he needs to type is 'cmake' ...
Is it a reasonable assumption that the user has CMake installed and configured with his preferred toolchain?
I am not willing to assume he's got vcpkg installed.
Is it a reasonable assumption that the user does not have vcpkg installed and configured?
(TBH, I don't even know if it is CMake or vcpkg that configures the toolchain - I assumed CMake but one of the suggested questions suggests it is vcpkg ...)
What are the reasonable assumptions today, and what is the minimal-step solution?
There's nothing wrong in assuming that the user has certain tools installed.
Let's say you are developing libfoo which depends on libbar and you want to make it as easy as possible for your users to install libfoo.
With a package manager
If libfoo and libbar are available via the same package manager all your users have to do is:
vcpkg install libbar libfoo
You don't have to do anything special in libfoo for this, just instruct the user to install all dependencies in your readme.
It doesn't really matter what package manager is used.
Without a package manager
You will still want to make it easy for people to build and install your project directly. It may seem that invoking a package manager during the build or configuration phase of your project and solving all dependencies is user friendly because the user no longer has to deal with installing those, but it isn't for a number of reasons, including:
you or someone else may want to add your project to another package manager (like conan, spack, etc)
someone may want to consume libfoo with FetchContent, CPM, directly with add_subdirectory, etc
someone may not be a user of vcpkg - there's no need to force them to use it, if possible
you may want to add another dependency, libbaz, which is not available on vcpkg
a user may have the right version of libbar already installed (not necessarily through vcpkg)
This list is not exhaustive. If you're not writing a library some points don't really apply.
This means that someone who has all the dependencies already installed should be able to use libfoo like this:
git clone your-repo
cd your-repo
cmake -Bbuild
cmake --build build
cmake --install build
Resolving dependencies without a package manager
However, it may be desirable to solve dependencies automatically. If your dependencies are using CMake the easiest way of doing this is with FetchContent. For some of the reasons outlined above you should provide an escape hatch so people can still use the already installed dependencies. This can be done with an option. For example, something like FOO_USE_EXTERNAL_BAR. This can be set either to yes or no by default, there's no right answer. As long as the user can control this I don't think it matters that much. You should namespace your options to avoid possible conflicts with options used by other projects.
In this case your build script could do this:
if (FOO_USE_EXTERNAL_BAR)
find_package(bar REQUIRED)
else ()
FetchContent_Declare(
bar
GIT_REPOSITORY bar-repo
GIT_TAG release-tag
)
FetchContent_MakeAvailable(bar)
endif ()
target_link_libraries(foo PRIVATE bar::bar)
Depending on how libbar's CMakeLists.txt is written and organized the if and else branches may get more complicated. See Effective CMake for some details and tips.
Now I can either let libfoo resolve the libbar by setting FOO_USE_EXTERNAL_BAR to ON when I configure your project, or I can set it to OFF to have more control over how it is resolved. I may even use libfoo as a dependency for a project that already depends on libbar. If you always pull it in I can't avoid conflicts in this case.
Using CMake to update dependencies
You may still find it easy for you to be able to update all the project's dependencies using CMake without downloading them via FetchContent. While this will probably raise some eyebrows you could add a custom target for solving dependencies with a package manager. This should also be controllable by an option. Unlike in the above case I strongly believe that if you do this the option should be set to off by default:
if (FOO_AUTO_USE_VCPKG)
add_custom_target(
update_deps
COMMAND vcpkg install libbar
)
add_dependencies(foo update_deps)
endif ()
This will invoke vcpkg every time you build foo so it will make your builds slower. If you remove the add_dependencies call you would have to manually run the update_deps target whenever you need to (which shouldn't be that often anyway).
Notes
Using options is a great way of providing options to your users. It should be noted that they increase the cognitive load, so picking strong defaults can help with that.
FetchContent is a nice way of taking the care away from the user, but at the same time multiple projects that use it will end up re-downloading the same libraries over and over again. It is still more user friendly than invoking a package manager at build time and as long as the users can disable this behavior there's nothing to worry about.
Some parts of this answer may be regarded more as opinion and less as facts. As I said, there is no one right way of doing this, different people will have different ways of solving this problem. Different projects and different environments will have different constraints.
I already recommended the Effective CMake talk above, other useful recourses are available here. If you're a library author you may also want to take a look at Deep CMake for Library Authors.
I had this same question. For my part, I am not willing to assume that the user has either CMake or vcpkg preinstalled.
Here is my solution so far, as a Windows batch file:
#REM Bootstrap...
set VCKPG_PARENT_DIR=C:\Projects
set CMAKE_VERSION="3.20.2"
mkdir "%VCKPG_PARENT_DIR%"
pushd "%VCKPG_PARENT_DIR%"
git clone https://github.com/Microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat -disableMetrics
set PATH=%PATH%;%VCKPG_PARENT_DIR%\vcpkg\downloads\tools\cmake-%CMAKE_VERSION%-windows\cmake-%CMAKE_VERSION%-windows-i386\bin
set VCPKG_DEFAULT_TRIPLET=x64-windows
set PYTHONHOME=%VCKPG_PARENT_DIR%\vcpkg\packages\python3_x64-windows\tools\python3
popd
#REM Build the project...
cmake -B build -S .\engine\ -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%\scripts\buildsystems\vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DUSE_PYTHON_3=ON
cmake --build .\build\ --config Release
mkdir bin
xcopy .\build\Release\*.* .\bin\
xcopy .\build\objconv\Release\*.* .\bin\
xcopy .\build\setup\Release\*.* .\bin\
It could use some improvement, but hopefully this gives you an idea of one route you could take.

CMake workflow?

I am learning CMake and I am having problems in understanding its multi-step workflow. So far, my understanding is that you:
write a CMakeLists.txt
run cmake from a subdirectory to generate a build file (a Makefile, in my case)
run make
However, I don't understand how you should handle different targets (Release vs Debug). By running CMake in two different subdirectories?
Also, I don't understand why you would edit CMakeCache.txt (there is also a GUI tool for that). To emulate what you would accomplish with ./configure by passing different options?
You got it pretty much right. The write CMakeLists.txt > cmake > make sequence is correct.
Regarding different configurations (Debug vs. Release), you have to differentiate between multi-config generators (Visual Studio, XCode), and single-config generators (everything else). With the multi-config generators, you generate one buildsystem (e.g. solution file) which contains all configurations, and choosing between them happens at build time.
With single-config generators, different configurations are obtained by generating different buildsystems, that is, by running CMake multiple times in different directories (and with a different value of the CMAKE_BUILD_TYPE CMake variable).
So you'd do something like this:
> cd my_project/bld/debug
> cmake ../../src -DCMAKE_BUILD_TYPE=Debug
> cd ../release
> cmake ../../src -DCMAKE_BUILD_TYPE=Release
Regarding editing the cache (usually through CMake GUI or ccmake): you're right again, this largely corresponds to passing options to ./configure from AutoMake world. This would be the typical workflow with a freshly downloaded project (using CMake GUI):
Run CMake GUI, point it to the source directory (input) and binary directory (output) you want
Configure. This will fill the cache with project-specified defaults. If CMake cannot find some dependencies of the project automatically, this will end with an error.
Inspect the cache, change any values you don't like (such as compilation options), fill in any missing options (paths to libraries CMake couldn't find etc.)
Repeat steps 2 & 3 until you're satisfied with the project's setup.
Generate the buildsystem.
Exit CMake GUI and build using the appropriate build tool.
What #Angew said. Plus here's an image of the cmake-gui:
Also note that you install it (the CMake GUI) on Ubuntu with sudo apt install cmake-qt-gui, and you run it with cmake-gui.
Source: Where is the CMake GUI for Linux?
Here's my cmake-gui image:

Clion and CMake messages

I just started using the Clion IDE. Maybe this is written somewhere but I haven't seen it in a Google search. If I put a message() call in my CMake script, where in Clion can I see the output? These message calls are the only way that I know how to debug my CMake scripts.
Use message(WARNING ...) instead of message(...). Warnings go to stderr.
Another possible workaround:
disable "cmake auto-reload" if it is enabled
after you changed something in your cmake file, don't trigger "Reload changes"
run/build your project
When clion starts a build, it realizes the cmake files are not up-to-date and reloads them, but like other build output it is displayed inside the Messages tab.
Warning and errors are displayed, but other messages are currently suppressed. However, there is a feature request concerning this issue.
As of CLion 2016.2.2,
Build #CL-162.1967.7, CLion is displaying CMake message(STATUS) output in its Messages tool window (Alt+0) during Build (Ctrl+F9) when a project is first built after changes to CMakeLists.txt. But as noted in the other answers, this output doesn't show in CLion's CMake tool window (as many would prefer).
Update: Above I wrote that CLion "is displaying message(STATUS) output." I now find that this occurs intermittently. #Michael wrote that this happens if you skip cmake reload after modifying your cmake file, but I've found CLion sometimes does not display any CMake output in its Messages tool window even under this condition. So far I haven't discovered the exact circumstances that make CLion show CMake message(STATUS) output, will report back here when/if I do.
Big Update: CLion opens 2016.3 EAP: user-defined literals, CMake output, C11 keywords completion and more. See in particular:CMake output window: a separate I think it fixes this whole problem: CLion 2016.3 EAP adds a new tab that contains CMake command output.
Of course, this is EAP, which comes with JetBrains' caveat:
It is important to distinguish EAP from traditional pre-release
software. Please note that the quality of EAP versions may at times be
way below even usual beta standards.
So use it at your own risk, but you may judge this a risk worth taking if you need the CMake debugging.

CMake for Code::Blocks -- how to NOT get a Makefile

Here is my setup:
Windows 7 x64, MingW, Msys, CMake, Freescale Kinetis SDK, Code::Blocks
I'm trying to get the project settings established by CMake into a proper Code::Blocks project. When I modify the provided build_debug.bat file with -G "CodeBlocks - Unix Makefiles", it indeed produces a .cbp file, as well as the normal Makefile (and it builds the project). However when I open this .cbp file in Code::Blocks, it basically just points to the Makefile, and building the project just runs make on the Makefile.
If I deselect "This is a custom Makefile" from Project Options, and add a source file to the project tree like a normal IDE, it doesn't get built correctly, ie the include files, libraries, linker stuff, compile options, etc., are not imported into the project itself. It seems the project is basically just a holder for the Makefile, so there is not much benefit to this as an IDE.
Of course if I add the source file to the original CMakeLists.txt which is part of the distribution, and rerun cmake (via the build_debug.bat file), then it works fine.
So is there any way to get a "real" IDE configuration out of CMake? I'm guessing the answer is No, since a "real" IDE configuration is a static thing, and a Makefile is a general (Turing complete) program, so there is no way in general to create this automatically, although I suspect for 99% of cases you're just specifying include directories, lib files, and compiler options, so no general programmability is truly needed.
I can probably try to figure out where the deeply obscured gcc calls are getting their include files from, what libs are being linked in, and what compile options are being used, and add all that stuff manually into a native Code::Blocks project, but this seems to defeat the purpose of having this already done for me by the package providers, and gets very tedious when building for a different CPU or development board.
Thanks
"Real configuration" is a CMakeLists.txt, and you need to modify CMakeLists when you editing project configuration. Both makefiles and IDE settings generated by CMake are temporary and you should not edit them.
Some IDEs are able to manage project configuration directly in the CMakeLists.txt

How to configure Eclipse CDT for cmake?

How to configure Eclipse "Helios" with plugin CDT for cmake?
cmake all
CMake Error: The source directory "D:/javaworkspace/workspace/Planner/Debug/all" does not exist.
Eclipse always wants to use 'all' option and I don't know how to stop its to not use it.
I've seen that in "Build behavior" section, in "Preference" there have been 'all' option. I erased this, but it still works wrong (this same error).
In Eclipse-CDT you do not create cmake projects but you import cmake projects.
This is what you should do:
Say the source of your CMake project named "Planner" is located in D:/javaworkspace/src/Planner
Create a folder (the folders NEED to be parallel to each other): D:/javaworkspace/build/Planner
Go to the folder D:/javaworkspace/build/Planner and run CMake using the Eclipse generator:
cmake ../../src/Planner -G"Eclipse CDT4 - Unix Makefiles"
This will generate the make files for your Planner project.
To import this in Eclipse do the following:
File -> Import -> C/C++ -> Existing code as Makefile project
and select D:/javaworkspace/build/Planner (the build output folder with the make files) as the "Existing Code location"
However, looking at your paths it seems to me that you are working on Windows. In windows CMake can generate Visual Studio projects. If you want to use CMake I suggest first creating a "hello world" project using CMake (remember, Eclipse does not create CMake projects, you have to create a CMakeLists.txt file by hand)
What worked best for me is cmake4eclipse. It's a plugin that is available via the marketplace.
Portions from the cmake4eclipse help text:
CMake for CDT requires an existing C/C++ project to work with. It
allows to use cmake as the generator for the makefiles instead of the
generator built-in to CDT. See Enabling CMake buildscript generation
for details.
To set up a new project with existing source code, please follow these
steps:
Check out your source code.
Open the new C/C++ project wizard ("File" => "New" => "C Project" or "File" => "New" => "C++ Project").
Make sure the project location
points to root directory of your checked out files
For the project
type, select Executable. You may also select Shared Library or Static
Library, it does not matter, that information comes from your
CMakeLists.txt, but CDT requires it. Do not select Makefile project
here!
Finish project creation.
Open the "Project Properties" dialog.
Select the "C/C++ Build" node and the "Builder Settings" tab and make sure Generate Makefiles
automatically is checked.
Select the "Tool Chain Editor" node and
set "CMake Make Builder" as the current builder.
If your top level
CMakeLists.txt does not reside in the root directory of your checked
out files, select the "C/C++ General" "Path and Symbols" node and the
"Source Location" tab. Then adjust the source folder to point to the
directory containing your CMakeLists.txt file. This will tell the CDT
indexer to scan the header files in your project.
Pro Tip: Add a CMakeLists.txt file in the root directory of your checked out files, if you miss the Binaries or Archives folder in the
C/C++ Projects View. Build the project. This will invoke cmake to
generate the build scripts, if necessary, and then will invoke make.
Do not try to import an Eclipse project that you created manually
using cmake -G Eclipse CDT4 - Unix Makefiles, as that will put you on
the classic Makefile project route!
The best thing about this plugin is that it can use the cmake exported compiler options to index your project.
Open the "Project Properties" dialog.
Select the "C/C++ General" node and the "Preprocessor Includes Paths, Macros etc." tab. Select "CMAKE_EXPORT_COMPILE_COMMANDS Parser" and move it to the top of the list.
Hit "OK" to close the dialog. Make sure to trigger one build now and recreate the index.
This fixed all the nasty indexer problems that were annoying me when I only used "CDT GCC Build-In Compiler Settings" and added stuff like "-std=c++14" to "Command to get the compiler specs".
Using CMAKE in Eclipse Makefile project(on win):
1) create new "Makefile Project with Existing Code"
2) modify builder settings(Project Properties->C/C++ Build->Builder Settings):
Build command: cmd /c "mkdir ${PWD} & cd /D ${PWD} && ${CMAKE} -G "Unix Makefiles" ${ProjDirPath} && make"
Build directory: ${workspace_loc:/IoT_SDK}/build/${ConfigName}
That's all!
In addition to accepted answer you should specify eclipse version.
Eclipse Luna (4.4):
cmake -G"Eclipse CDT4 - Unix Makefiles" -D_ECLIPSE_VERSION=4.4 ../../src/Planner
Eclipse Kepler (4.3):
cmake -G"Eclipse CDT4 - Unix Makefiles" -D_ECLIPSE_VERSION=4.3 ../../src/Planner
Another completely different method.
Manually create an empty Eclipse project.
Link source directory via Project Properties -> C/C++ General -> Paths and Symbols -> Source Location.
In the Debug and Release build directories create 'Make Targets' (using the 'Make Targets View'). Leave 'Make Target' field empty and set the 'command' field to cmake -G "Unix Makefiles" <path/to/the/sources>.
When you double-click on the 'Make Target' that you've created, it should trigger cmake invocation inside the Debug/Release dirs.
In 'Project Properties -> C/C++ Build' disable built-in makefile generator.
Now normal build should work. It will also pick up any changes in the CMakeLists.txt files (to the extent that CMake can).
Maybe a more detailed description: https://stackoverflow.com/a/38140914/4742108
Whatever method I have used the external includes has not been indexed.
This is because CMAKE used the "response files" which hides all includes inside those files, instead use it directly (-IPATH_TO_SOME_DIR)
To disable the "response file" I have used following commands:
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES NO)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES NO)
To force the CMAKE to show gcc/g++ execution I have modified the make build target to
"all VERBOSE=1". Note that this is not needed when you are using cmake4eclipse.
I have eclipse in version 2018-12 (4.10.0) with CDT in version 9.6.
This is an old question, but deserves some updates.
First is that the person who made cmake4eclipse added the parsing functionality into CDT. The feature/bug was marked as "Resolved-Fixed" on 2020-08-05 (Aug 5, 2020), so it should go into the version of Eclipse due out next month. See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=559674
The other thing to point out is that you can manually trigger parsing on files:
Configuration Options / Index source and header files opened in editor