12

I need to create the following always-out-of-date file: ${CMAKE_BINARY_DIR}/version.hpp.in
before any target is executed in the make file. The content of file is exactly as the following:

#define RELEASE_VERSION "${RELEASE}"
#define MAJOR_VERSION "${MAJOR}"
#define MINOR_VERSION "${MINOR}"
#define PATCH_VERSION "${PATCH}"
#define REVISION "${REVISION}"
#define SVNPATH "${SVNPATH}"

I've got the following piece of code in my CMake file, but it's executed only after running the cmake command:

FILE(WRITE ${CMAKE_BINARY_DIR}/version.hpp.in
"#define RELEASE_VERSION \"${RELEASE}\"\n"
"#define MAJOR_VERSION \"${MAJOR}\"\n"
"#define MINOR_VERSION \"${MINOR}\"\n"
"#define PATCH_VERSION \"${PATCH}\"\n"
"#define REVISION \"${REVISION}\"\n"
"#define SVNPATH \"${SVNPATH}\"\n"
)

I want to generate the version.hpp.in file each time I run the make command. How can I do that?

B Faley
  • 17,120
  • 43
  • 133
  • 223

2 Answers2

5

You can use configure_file() for this:

configure_file(version.hpp.in ${DESTPATH}/version.hpp)

Where DESTPATH is optional and set to the path you want that file.

If the file is modified the build system will re-run CMake to re-configure the file and generate the build system again.

(Source: Documentation, see below)

File version.hpp:

#define RELEASE_VERSION "${RELEASE}"
#define MAJOR_VERSION "${MAJOR}"
#define MINOR_VERSION "${MINOR}"
#define PATCH_VERSION "${PATCH}"
#define REVISION "${REVISION}"
#define SVNPATH "${SVNPATH}" 

Syntax:

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

Documentation:


# 'example' is the targetname here, eg. using add_executable(example example.cpp)

add_custom_command(TARGET example PRE_BUILD COMMAND <CMAKE COMMAND HERE>)

Minimal Example

Version.h.in

#define VERSION ${VERSION}

Just for testing …

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.12)

set(VERSION 1.10)
set(TEMPLATE_DIR ${CMAKE_CURRENT_SOURCE_DIR})

add_executable(example example.cpp)

add_custom_command(TARGET example PRE_BUILD 
        COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/SetVersion.cmake)

SetVersion.cmake

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../Version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/../Version.h)
message("Version set") # For testing only

Now run cmake and make as usual and check if HELLO is printed on make.

ollo
  • 24,797
  • 14
  • 106
  • 155
  • The point is that I'm already using the `configure_file`! The `version.hpp.in` file that I'm trying to generate is supposed to be the file of the `configure_file` command. The problem is that `configure_file` is executed only after has been modified. That's why I am trying to always generate the file (version.hpp.in) so that `configure_file` is always executed. – B Faley Oct 04 '14 at 13:45
  • I see, so you may test `add_custom_command()`, eg. as stated [here](http://cmake.3232098.n2.nabble.com/configure-file-as-a-build-step-td7518670.html). I hope this helps more. – ollo Oct 04 '14 at 13:53
  • Could you please do me a favor and integrate that in your answer? I can't get a grasp of it... – B Faley Oct 04 '14 at 14:08
  • A question to understand your problem a bit better: If you change a variable, eg. `RELEASE` in your cmake file, running `make` should also re-run cmake. – ollo Oct 04 '14 at 14:17
  • Even if you delete the configured file, it will be created again on `make`. Btw. what version of cmake are you using? *-- 5 min edit time was over :-(* – ollo Oct 04 '14 at 14:22
  • cmake version: 2.8.10.1. No, if I remove the configured file, the `configure_file` command wont be executed because its input has not changed. – B Faley Oct 04 '14 at 14:27
  • Strange, i'm using Cmake 3.0.2 and if i remove the generated file and run make, it's created again. – ollo Oct 04 '14 at 14:32
  • I've added a small example, just have to finally get the correct command to execute. Btw. for testing you can replace `` with `echo HELLO` - if hello is shown on `make`, we are ok so far. – ollo Oct 04 '14 at 14:50
  • 'Hello' is printed, I also just upgraded to 3.0.2. What cmake command should I use instead of `echo HELLO`? – B Faley Oct 04 '14 at 14:57
  • Ok, but the problem isn't fixed with 3.0.2, isn't it? I'll edit the rest into my answer, just give me some minutes. – ollo Oct 04 '14 at 15:08
  • No it wasn't fixed. Thank you very much. – B Faley Oct 04 '14 at 15:11
  • Just a few works: the generation of the config file is done in an extra cmake file. As command `cmake -P ` is used. This means: Cmake runs just that single file (where the configs are set) instead of the full cmakelists. Just *beware of the paths*! – ollo Oct 04 '14 at 15:13
  • Thank you very much for the effort you put on this. I have to leave the office now. I will try to get it working the other that as soon as I can and will update you. – B Faley Oct 04 '14 at 15:30
  • I almost got your solution working. The only problem is that the `VERSION` variable is not known in the `SetVersion.cmake` file, unless I pass this variable to the `SetVersion.cmake` file like this: `COMMAND ${CMAKE_COMMAND} -DVERSION=${VERSION} -P ${CMAKE_CURRENT_SOURCE_DIR}/SetVersion.cmake`. Correct? Please take a look at the followup question I asked: http://stackoverflow.com/q/26216570/69537 – B Faley Oct 06 '14 at 13:36
  • Sorry for my late response. I hope i understand you correct, but you can place the variable in the cache - see documentation of `set()`. Did you test that? – ollo Oct 12 '14 at 20:38
0

You can use add_custom_command (and perhaps add_custom_target) to do this sort of thing.

Since you're asking about building version symbols into your program, I will tell you about a slightly different method that I use. I asked a question related to it here, with some code: Embed Git revision in executable during remote build with NetBeans

The concept I use is to generate actual symbols in an object file directly from a textual file which I write at build (or git pull) time. Then I link this file into the executable.

Community
  • 1
  • 1
John Zwinck
  • 239,568
  • 38
  • 324
  • 436