In the previous post, we learnt how to build a really basic application. For that, we created a CMake target using the add_executable
CMake macro. During this post, I will explain some extra things can we do with targets.
Compiler definitions
Sometimes you will need to build software that is using definitions. Example:
#include <stdio.h>
int main()
{
#ifdef AWESOME
char *message = "YOU ARE AWESOME!\n";
#else
char *message = "Sorry, you are not awesome\n";
#endif
printf("%s", message);
return 0;
}
This code is using the AWESOME
definition. If we provide to the compiler the definition AWESOME
the final application will print "YOU ARE AWESOME!
". Otherwise, it will print "Sorry, you are not awesome
". How can we handle this situation from CMake?
cmake_minimum_required(VERSION 3.5)
project(example)
add_executable(my_app
"${CMAKE_CURRENT_SOURCE_DIR}/myapp.c"
)
target_compile_definitions(my_app
PRIVATE
AWESOME
)
As before, we created one target (that will build an executable) using the source files. Then, we provide the definitions needed by that target using the target_compile_definitions
.
There are other methods to the compiler calls like add_definitions
but they are discouraged. Why? Using target_compile_definitions
we will apply the definitions just to the desired targets and add_definitions
will ad them to all the targets.
The PRIVATE
keyword references to the visibility of the definition. There are 3 visibility modes:
- PRIVATE: used when the definitions will be applied just for the current target.
- INTERFACE: used when the definitions need to be applied to targets that link against the given target.
- PUBLIC: it is the union between the
INTERFACE
andPRIVATE
vibilities. It will use the given definitions to build the current target and also targets that link against the current target.
INTERFACE
and PUBLIC
visibility modes are useful for libraries.
Include directories
Now, let's imagine we need to build a software where the folder structure is this one:
.
├── include
│ └── awesome.h
└── src
└── myapp.c
The file src/myapp.c
contains:
#include "awesome.h"
int main()
{
print_awesome();
return 0;
}
And include/awesome.h
:
#ifndef _awesome_h
#define _awesome_h
#include <stdio.h>
void print_awesome() {
printf("AWESOME MESSAGE\n");
}
#endif
We need to add the include
directory as part of the build of the application. How can this be done? It is really similar to how we add a compiler definition:
cmake_minimum_required(VERSION 3.5)
project(example)
add_executable(my_app
"${CMAKE_CURRENT_SOURCE_DIR}/src/myapp.c"
)
target_include_directories(my_app
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
The visibility parameters has the same meaning than in the case of target_compile_definitions
.
Target properties
The macros shown during the previous sections will modify the target properties. You can access these properties using the get_target_property CMake macro. Also, you can set some of these properties with the set_target_properties CMake macro.
You will find the complete list of properties in this link. Some of then can be modified and others only will apply depending on different situations like the operating system or the generator used to create the build system.
Pay special attention to these properties where the token <CONFIG>
is present: these variables will be used in multiconfiguration generators: depending on the configuration used to build or generate the build system. For instance, the property OUTPUT_NAME_<CONFIG>
is used to the base name for output files created for an executable or library target. It can exists as OUTPUT_NAME_RELEASE
and OUTPUT_NAME_DEBUG
Recap
What did we learn?
- How to work with targets
- The use of
target_compile_definitions
andtarget_include_directories
- How the visibility works for these CMake macros
- How to get and modify the target properties values
Top comments (3)
Hello Israel Blancas
Can you explain more on CMake and also on Make. I think 4 Series on CMake is not enough. Your explanation is simple and clear. Can you add more series in CMake and Make it will good for new developers.
Thanks for the blog.
I have been waiting for a CMake series
and here it is 👌
would you convert it to a DEV Blog Series?
Hi! I am almost new in dev.to and I didn't know about the "series" feature. Yes, I'll convert these posts to a "DEV Blog Series" :)
Thanks for your comment.