changing the project name on every build - cmake

I have a custom makefile used for versioning.
It basically sets the version according to some predefined rules and fetching info from git repo
I want to intergrate it with the esp32 cmake project.
Till now i managed to run the makefile from the cmakelist.txt file using
add_custom_target(versioning ALL
COMMAND ${CMAKE_COMMAND} -P "sometext.cmake"
)
and in the sometext.cmake i am calling the makefile which sets a FirmwareVersion variable.
I use this variable in the root cmakelist.txt to set the project(${FirmwareVersion})
But i want the project name to be changed every time firmwareVersion is changed.
But project command is only if there is some changes in cmakelist.txt
Any help to accomplish it is highly apreciated.
Thanks

The project() command also has VERSION named keyword. That is what you actually want. You can store the actual version in some extra CMake file (like version.cmake)
set(VERSION_FROM_GIT "1.2.3+9a6b075")
and use like
include("${CMAKE_CURRENT_SOURCE_DIR}/version.cmake")
project(MyProject VERSION ${VERSION_FROM_GIT} ...)
...
It's up to you how you going to update this file... There are plenty of ways to do that.

You can tell cmake to do a reconfiguration if a file changes. Since the .git directory contains a HEAD file either denoting the commit hash of the detached head or a reference to the file containing the commit hash, you could these files as configuration dependencies.
# assume the .git directory is in the same directory as this CMakeLists.txt
set(GIT_HEAD_FILE "${CMAKE_CURRENT_SOURCE_DIR}/.git/HEAD")
# add dependency to the head itself
set_property(DIRECTORY . APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${GIT_HEAD_FILE}")
file(READ "${GIT_HEAD_FILE}" GIT_HEAD_CONTENT)
if (GIT_HEAD_CONTENT MATCHES "ref: +([^ ]+)")
# add file referenced in HEAD for non detached head state
set_property(DIRECTORY . APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/.git/${CMAKE_MATCH_1}")
endif()
... your logic depending on the git version goes here ...
This gets a bit more complicated if you intend on using your repository as submodule of another repo, since the .git directory is not necessarily located in the submodule.

Related

Getting environment variable during runtime from file in cmake [duplicate]

I have a project under CMake with some files generated with python generator from XML files. I cannot specify all files generated by this generator in CMakeLists.txt so I use file globbing for this.
The problem is that when I update my XML files or generator sources (which are in the same repository) I would like to have my build system reconfigured so changed files are taken into account when rebuilding the code (via make for example).
Is it possible to make CMake treat some files like it treats CMakeLists.txt files and to make it regenerate build system when those file are changed?
It doesn't require any kind of workarounds. The standard way is to use CMAKE_CONFIGURE_DEPENDS property:
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS <filename>)
Yes, you should be able to do that by (ab)using configure_file(). Configuring a file makes the source a dependency of the CMake run, so that any changes in it cause a reconfiguration. Simply like this:
configure_file(MyInputFile.xml DummyOutput.xml)
Since it has been a while I will add to #roolebo's answer.
There's actually a better command to add a dependency on a file:
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS <relative_or_full_path_to_file>)
What might be confusing is that this command adds a property to the current directory. Well, it does not matter since you can set a full path to a file that resides outside of the current directory's scope, for instance: ../../config.json

Cmake - how include paths with only read access? [duplicate]

Is it possible to specify an include directory when running cmake. For example
cmake . -INCLUDE=/foo/bar
The header files are in a separate directory from the sources that I would like to compile, and I would like to remedy this without tinkering with the Makefile generated by cmake.
Update
The project does have a CMakeLists.txt. Excerpt:
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
Can ${EO_SOURCE_DIR} be set from the command line?
If the path to your headers is fixed in relation to your sources, then you should be able to avoid having to pass this info via the command line.
Say your project's directory structure is:
/CMakeLists.txt
/my_sources/main.cpp
/my_sources/foo.cpp
/my_includes/foo.hpp
and in your CMakeLists.txt, you currently have something like:
add_executable(MyExe my_sources/main.cpp my_sources/foo.cpp)
then to add the /my_includes folder to the the list of include search paths, you only need to add the following:
include_directories(my_includes)
For further info about include_directories, run
cmake --help-command include_directories
Answer to update in question:
Yes, using the -D command line option just do
cmake . -DEO_SOURCE_DIR:PATH=<Path to required dir>
The variable ${EO_SOURCE_DIR} gets cached as a result of this, so you only need this -D argument once (unless the required path changes or you delete your CMakeCache file, etc.)
Proper way to do this is to define a variable in CMakeLists.txt and ask user to set it:
set(YOURLIB_INCLUDE_DIR "" CACHE FILEPATH "Path to yourlib includes")
if(NOT EXISTS ${YOURLIB_INCLUDE_DIR}/header.h)
message(SEND_ERROR "Can't find header.h in ${YOURLIB_INCLUDE_DIR})
endif()
include_directories(${YOURLIB_INCLUDE_DIR})
Now you can set it from the command line: cmake -D YOURLIB_INCLUDE_DIR=/path/to/yourlib/include .

CLion: issue with Cmake configuration types

I understand that by default, Clion creates the binary files for a project loaded in Clion in all the four configurations:
(Debug;Release;MinSizeRel;RelWithDebInfo)
as well as one called: __default__.
I am using a third party cmake module which downloads an external project in a way that add_subdirectory() can be run on it so it would be included in the root project.
add_subdirectory(${downloaded_proj_src_dir} ${downloaded_proj_bin_dir} EXCLUDE_FROM_ALL)
In this setup, if I decide to place the child project outside the binary directory of the root project, I get:
Error:Binary directories outside of CMake build directory are not supported. Most likely this error is caused by an add_subdirectory command with an explicitly specified binary_dir argument.
which is an understandable restriction by CMake.
now if I instead decide to set the binary directory of the downloaded project in a subdirectory of the binary directory of the parent project, ie:
set(downloaded_proj_bin_dir "${CMAKE_BINARY_DIR}/${downloaded_proj}-build")
...
add_subdirectory(${downloaded_proj_src_dir} ${downloaded_proj_bin_dir} EXCLUDE_FROM_ALL)
I will get the file created in the parent binary directory of all the build configurations because ${CMAKE_BINARY_DIR} is different for each configuration. To avoid seeing all these directories listed on the project view sidebar, I have set the CMAKE_CONFIGURATION_TYPES to be Debug. But even then, I get:
Error:Configuration Debug
The current CMakeCache.txt directory /path/Debug/downloaded_proj_bin/CMakeCache.txt is different than the directory /path/__default__/downloaded_proj_bin/CMakeCache.txt where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
Clearly something is going on with this __default__ configuration which I don't understand. So the question is, what is the significance of this default configuration and why should there be a conflict here?
P.s. Setting the configuration to __default__ does not solve the problem as I will have a __default__0 configuration created instead and get the same error.
Update: some further observations
My enviornment variables set in IDE don't have any effect on the cmake builds.
Cmake "options" however which presumably will be passed as arguments to cmake do seem to work.
-D CMAKE_CONFIGURATION_TYPES=Debug.
When I specify the command line option, I get
Warning:Manually-specified variables were not used by the project:
CMAKE_CONFIGURATION_TYPES
But it clearly does have the effect of no longer creating the other build configurations. My guess is that this message relates to the __default__ build which is ignoring the argument.
Even in the case of specifying CMAKE_CONFIGURATION_TYPES in the IDE, I still get the additional __default__ build which is apparently unaffected by the CMAKE_CONFIGURATION_TYPES assignment.
Logging: message("Build type: ${CMAKE_BUILD_TYPE} ) does not return any build_type.
Outputting message(and generator: ${CMAKE_GENERATOR} ") returns "Unix-make files" for both, so both are being generated with the same generator.
Taking a diff from the CMakeCache.txt files, I can see that they are identical.
Do you have in DownloadProject.cmake the right setting? for:
set(_DownloadProjectDir "${CMAKE_CURRENT_LIST_DIR}")
I had the same problem trying to set google test(with the help of https://github.com/Crascit/DownloadProject) and my _DownloadProjectDir was setted as "test". Maybe when I moved this cmake file in my project Clion changed that automatically.
So, it turns out that you can sort this out quite easily by adding the following line above line 145 in DownloadProject.cmake:
file(REMOVE "${DL_ARGS_DOWNLOAD_DIR}/CMakeCache.txt")
This seems to be because CLion copies the default across to the other configurations and doesn't clear the cache. This is a problem only because DownloadProject creates a project within the project (I think...). Anyway, deleting this file before configuring the CMakeLists.txt by-passes this issue. I'll submit a pull request to the DownloadProject repository as this doesn't seem to have any adverse effects when not using CLion.

How to pass variable to cpack?

I have a cmake project which one of the install targets is a collection of files. This files change depending on the configuration (Release, Debug...).
I would like to be able to install the files like so:
install(DIRECTORY $<TARGET_FILE_DIR:tgt>
DESTINATION bin
COMPONENT files)
But cmake does not support that. Generator variables do not apply to DIRECTORY. So I was wondering if there is a way to either save the directory somewhere. Either the cache or a file and then load it into cpack.
So I guess the question is how to pass a variable from cmake to cpack?
This is a rather late answer, but I happened upon this question trying to solve a somewhat different problem that could also be summarized as: "How do I pass a variable to CPack?" In my case, I was making this call from a customized version of CPackDeb.cmake copied to my workspace:
find_program(OPKG_CMD NAMES opkg-build HINTS "${OPKG_HINT}")
# ^^^^^^^^^^^^
# This is what I wanted to pass to CPack
I was setting OPKG_HINT in a file included from my top-level CMakeLists.txt, but it was not getting passed through to cpack; the above find_program() invocation was seeing an empty string for OPKG_HINT.
The solution turned out to be stupid simple: just prepend CPACK_ to the variable name!
If I do this in CMakeLists.txt:
set(CPACK_OPKG_HINT "${_sysroot_top}/aarch64-poky-linux/usr/bin")
then I can put this in my CPackDeb.cmake file and it works fine:
find_program(OPKG_CMD NAMES opkg-build HINTS "${CPACK_OPKG_HINT}")
Anyway, this wound up being a bit of an X-Y problem for the OP, but... if you really need to set a variable at CMake time in such a way that it's accessible to cpack, prefixing the variable name with CPACK_ seems to do the trick nicely...
The following setup work if you use a "single-configuration generators (such as make and Ninja)" and call CMake with
cmake -DCMAKE_BUILD_TYPE=Release <source_dir>
https://cmake.org/cmake/help/v3.0/variable/CMAKE_BUILD_TYPE.html
You can define the ${dir} variable in another way if you like.
IF (CMAKE_BUILD_TYPE STREQUAL "Release")
SET(dir release_dir)
ELSE()
SET(dir debug_dir)
ENDIF()
INSTALL(DIRECTORY ${dir} DESTINATION bin COMPONENT files)
Until now this seems to be the best answer (from someone on the cmake mail list)
install(DIRECTORY path/to/Debug/dir
DESTINATION bin
CONFIGURATIONS Debug
COMPONENT files
)
install(DIRECTORY path/to/Release/dir
DESTINATION bin
CONFIGURATIONS Release
COMPONENT files
)
CMake 3.5 supports generator expressions for the DIRECTORY arguments. See installing directories.

How to best handle data files with CMake?

I've got a CMake project that contains code and a few data files (images to be precise).
My directory structure is like this:
src
data
src contains the source code, data the data files. CMake suggests out of source builds, so when I invoke make, I have the executable program, but not the data files, thus I cannot execute the program.
Of course, make install would copy my data files to the required location and make it work, therefore I develop like this right now:
cmake -DCMAKE_INSTALL_DIR=dist
<edit source code>
make install
dist/myprogram.exe
That's okay if I'm working with the command line and an editor, but I recently decided to move to Eclipse CDT. Generating an Eclipse project from CMake works great, but manually executing the install target from Eclipse is not so nice.
How do you people tackle this problem? Does your program have some clever algorithms to try and find its data directory even if it's not where the binary is? Or do you not use out of source builds?
configure_file should solve that problem.
I have a CMakeLists.txt file in my data directory which contains the following:
configure_file(data_file ${CMAKE_CURRENT_BINARY_DIR}/data_file COPYONLY)
This copies the specified file into the build directory when cmake is invoked, so it is available in the same location even in out of source builds.
configure_file does not support directories however while the file command does:
file(COPY assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
And if copying the files takes too much time (they are images...) you could make it even better by creating a "custom" data_header.h with configure_file which contains the paths to the data still in your source-directory.
This is what I do: I have a file "global_build_config.h.in" in my source, containing the following:
const char* const global_testdatapath = "#Test_Data_Path#";
and then use configure_file in CMake:
# Assume CMake knows a variable Test_Data_Path, it will be filled in automatically
# in the generated config/Global_Build_Config.h
configure_file( Global_Build_Config.h.in ${CMAKE_BINARY_DIR}/config/Global_Build_Config.h )
# The config directory should be added as a include-searchpath
include_directories( ${CMAKE_BINARY_DIR}/config/ )
I can then #include "Global_Build_Config.h" in my cpp files and refer to the fixed path.
Your question is a bit old, but in case you're still interested (or someone else), I have a similar scenario where I copy testdata for a unit-test target:
add_custom_command( TARGET ${UTEST_EXE_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Copying unit test data.."
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_HOME_DIRECTORY}/utest/testdata ${CMAKE_BINARY_DIR}
)
So the main idea is to use a post-build target, and it is executed after each build. For me, it's not much data, and the filesystem caches it, so I don't feel the copy process at all. You could probably enhance this by copying with copy_if_different. In that case, however, you have to create a list of your image files and write a loop, because the command is file based. With the GLOB command, this shouldn't be hard to do if you need to.