Nested CMakeLists.txt files in CLion - c++

Using CLion, I have a project structure that looks like this:
You'll see that in the root there are an include directory, a src directory, a lib directory, a cmake-build-debug directory, a CMakeLists.txt file (see red arrow), and a tests directory. The project builds a shared object into lib using the root-level CMakeLists.txt file and the various source, header, and external files.
I can successfully run the root-level CMakeList.txt file and build the library. So far, so good.
Here is the issue. In addition to the above, I am now interested -- on an informal, exploratory basis -- in testing some of the code in the project. To that end, as an initial example, I have created a test_nnls directory with its own CMakeLists.txt (see yellow arrow) file and a test_nnls.cpp file. The code in test_nnls.cpp creates some dummy data, calls a function in src/nnls.cpp, and prints the results. The build process here just creates an executable that does this. This approach is not meant to be part of any formal test framework and I do not want the test to run as part of the root-level build. This is just me adding a simple test program in the overall project that I would like to compile and run on an independent basis when I feel the need. I plan to possibly implement a formal test framework later, but at present I don't know how to do this and for now just need to print some simple output to see if the chosen code is working correctly.
The problem is that I cannot seem to execute the CMakeLists.txt file (yellow arrow) to build the test. It does not appear to be possible in CLion to set up a build for the test program using cmake. How do I structure all of this to get what I want? Thanks.

You don't execute a CMakeLists.txt. It is read by cmake (the root CMaksLists.txt file), which is called by CLion. However, CLion only passes the root CMaksLists.txt file to cmake. Even if you call cmake yourself you would only pass this root CMaksLists.txt file.
If you want to define targets (or anything) in other CMaksLists.txt files located in other folders, then you must add add_subdirectory(folder_name_that_contains_another_CMakeLists_file) to your root CMaksLists.txt file. Only then targets in these other CMaksLists.txt files will appear in CLion.
Note that a few things should appear in the root CMaksLists.txt file, but not in the other ones. Particularly, the two lines below should only be in the root file
cmake_minimum_required(VERSION 3.14) # Choose the minimum cmake version
project(name_of_your_project)

Related

How to set a working directory to a cmake target in VSCode?

I have a pure cmake project where I work on it from Linux (makefiles) and Windows (Visual Studio) environments.
And I want to be able to specify a kind of working directory to one of my targets so that I could read input files with relative path.
My project tree is something like:
App/
src/
code.cpp
assets/
image.png
build/
CMakeLists.txt
My App target is build at build directory and my program think that there is the starting directory (obviously).
I want to be able to load my image.png inside my code as:
stbi_load("assets/image.png");
Instead as I am doing now:
stbi_load("../App/assets/image.png");
In CLion, there is setting called "Working directory" that works exactly as I want, but I don't know how to set this directly to my CMake configuration. Or better saying, I don't know how CLion do this.
To be clearer, I develop using VSCode, I worked on CLion for a long time and I remembered this setup.

CMake output to build directory [duplicate]

Is it possible to specify build directory within CMakeLists file? If yes, how.
My aim is to be able to call "cmake" within top level source directory and have cmake figure out the build directory.
Afaik, with CMake the build directory is always the directory from where you invoke the cmake or ccmake command. So if you want to change the build directory, you have to change directories before running CMake.
To control the location where executables, static and shared libraries are placed once finished, you can modifiy CMAKE_RUNTIME_OUTPUT_DIRECTORY, CMAKE_ARCHIVE_OUTPUT_DIRECTORY, and CMAKE_LIBRARY_OUTPUT_DIRECTORY respectively.
By design, there is not a way to specify that in CMakeLists.txt. It is designed for the user to be able to build the project in whatever directory they want. The typical workflow is:
Check out the project source code.
Go to desired build directory, or the source dir if you plan to do an in-source build.
Run cmake or ccmake to configure the project in that build directory.
Build your project.
All of the directories specified within your CMakeLists.txt should be relative to the ${PROJECT_BINARY_DIR} and ${PROJECT_SOURCE_DIR} variables. In this way, your code becomes buildable across different platforms, which is the goal of CMake.

Cmake issue. Copying dll post build

I'm struggling again with cmake.
What I'm trying to achieve is this:
I have a project, say ProjectA, which contains a submodule with a CMakeLists.txt, say ProjectB.
ProjectA adds ProjectB as subdirectory.
ProjectB outputs a shared library (.dll).
ProjectA has a post build script that copies the dll into its output directory in order to use it.
The problem is that when i change a few things inside ProjectB, this one gets built, but since no modifications are made in ProjectA, it wont build nor copy the dll.
The solution would be to move the post build script inside ProjectB, but if i do that my submodule will be incompatible in other scenarios and tied to ProjectA implementation (what I mean is that the Cmakelists file of projectB should copy the dll in a folder outside it's directory, which is something I want to avoid).
I can't really find a way to avoid manually rebuilding the whole project every time.
To make the situation more clear, the project hierarchy is something like
ProjectA/
CMakeLists.txt
src/
vendor/
ProjectB/
CMakeLists.txt
src/
The First CMakeLists.txt adds Project B as subdirectory.
This cmakelists file also apply a post build script to the target in project A that copies content of ProjectB/bin (dll).
I managed to solve this by myself.
For those who has the same issue and want to find a good solution, just do not use a post build script.
Instead you can add a second parameter to add_subdirectory specifying the build folder of the subproject.

What does cmake .. do?

I got the Box2D project source and want to compile the testbed portion of it.
The project folder contains folders like: freeglu glui testbed(a demo) helloword(a demo)
Box2D Build CMakeFiles
There are many CMakeLists.txt in all the different folders.
I was thinking that I should cmake all those files so that make files are created in all places required.
I read this (as instructions to do do want I want) :
wget http://box2d.googlecode.com/files/Box2D_v2.2.1.zip
unzip Box2D_v2.2.1.zip
cd Box2D_v2.2.1/Build
cmake ..
make
What does the cmake .. do?
There is no CMakeLists.txt in the build folder.
cmake is a Makefile generator.
When you call cmake [path], you ask it to generate a Makefile in the current directory following instructions given in [path]/CMakeLists.txt
Usually cmake output some messages while it is working, and after it is done without errors, you can type "make" to execute your newly created Makefile.
CMakeLists.txt files can reference other CMakeLists.txt file in sub-directories, so you are usually only interested by the CMakeLists.txt of the top directory, not the other ones.
Using an empty "build" directory is a technique called "out-of-source build", in which all your generated files (.o, executable, Makefile, .anything) are generated in the separate "build" directory and not mixed with source files. If you want to clean all, you can delete all the content of the build directory.
In fact, you can put your "build" directory in any place, as long as you give cmake the correct path of the top CMakeLists.txt. You can even have several build directories. It is very useful if you need several different builds at the same time (with different options, different versions of gcc, etc.)
In old programs, you generate the Makefile too, but using ./configure (this is called auto-tools. You may have encountered that already). cmake is considered a successor of the auto-tools.
cmake .. generates makefiles in the current directory, using ../CMakeLists.txt file as starting point. make command, executed after this, builds the program, using generated makefile(s) as an input. This is convenient to keep a source code and build results in different folders. General syntax is: cmake source-dir (of course, there are a lot of other switches).
Well, .. is shorthand for the parent folder, so it will presumably act upon whatever it finds in Box2D_v2.2.1.

Working with Multiple Projects in CMake

I am currently working on transitioning over a Visual C++ project (that has multiple subprojects inside of it) over to CMake.
There is one thing that I am not sure about – basically, to include the subprojects from the top level CMakeLists.txt file, I just utilize the add_subdirectory command, and reference the directories that these various subprojects are stored under.
However, I have one project that is in the same directory as my top level CMakeLists.txt file, and so I am wondering if it is still possible to include this file somehow? CMake does not allow me to call add_subdirectory on the existing PROJECT_BINARY_DIR (see below):
add_subdirectory(${PROJECT_BINARY_DIR}) #not allowed in CMake
I cannot think of another way for me to include this subproject into my CMake build. Any ideas?
All add_subdirectory does is add a subdirectory with a CMakeLists.txt file in it, and so it would not make sense to allow you to add the current directory. You can simply add the CMake logic to build that part of your project in the CMakeLists.txt file. If you would like to separate the logic, then you could put it in build_project.cmake, and then use include,
include(build_project.cmake)
You can include as many other CMake files as you like, and that CMake code will be evaluated as if it was pasted inline. So all the normal add_executable and similar commands would work.