[CMake] Creating custom file before building/compiling with cmake

Michael Wild themiwi at gmail.com
Sat Aug 21 11:43:52 EDT 2010


On 21. Aug, 2010, at 16:48 , Roman Wüger @mac.com wrote:

> OK,
> 
> I added "CONFIGURE_FILE(xml/ApplicationVersion.xml.in xml/ApplicationVersion.xml)" to the CMakeLists.txt file which builds the main.cpp
> The file "xml/ApplicationVersion.xml.in" looks like the following:
> <?xml version="1.0" encoding="UTF-8"?>
> 
> <ApplicationVersion>
> <Date>${BUILD_DATE}</Date>
> <Time>${BUILD_TIME}</Time>
> <Architecture>${BUILD_ARCHITECTURE}</Architecture>
> <Version>
>   <Major>${BUILD_VERSION_MAJOR}</Major>
>   <Minor>${BUILD_VERSION_MINOR}</Minor>
>   <Patch>${BUILD_VERSION_PATCH}</Patch>
>   <Build>${BUILD_VERSION_BUILD}</Build>
>   <Revision>${BUILD_VERSION_REVISION}</Revision>
> </Version>
> </ApplicationVersion>
> 
> But when I run mingw32-make, then no "xml/ApplicationVersion.xml" file is created.
> 
> Is there something else I must do to get it working? How can I get right that the "xml/ApplicationVersion.xml" file is UTF-8 encoded?
> 
> Best Regards
> NoRulez

That won't work, you're missing all the parts I was telling you about in my original instructions. You need a script (call it e.g. createApplicationVersion.cmake.in) containing something like this:


createApplicationVersion.cmake.in:
--------------<8------------------

# configured variables
set(WIN32 @WIN32@)
set(UNIX @UNIX@)
set(SVN_EXECUTABLE "@Subversion_SVN_EXECUTABLE@")
set(CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@")
set(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")

# make sure we don't get translated messages
set(ENV{LC_ALL} C)

# determine date
if(WIN32)
  execute_process(COMMAND cmd /c "date /T"
    RESULT_VARIABLE getdate_result
    OUTPUT_VARIABLE DATE
    ERROR_VARIABLE DATE
    OUTPUT_STRIP_TRAILING_WHITESPACE)
  string(REGEX REPLACE ".*(..)/(..)/(....)"
    "\\3-\\1-\\2" DATE ${DATE})
elseif(UNIX)
  execute_process(COMMAND date "+%Y-%m-%d"
    RESULT_VARIABLE getdate_result
    OUTPUT_VARIABLE DATE
    ERROR_VARIABLE DATE
    OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
  message(FATAL_ERROR "Can't determine date on this system.")
endif()
if(getdate_result)
  message(FATAL_ERROR "Failed to determine date:\n${DATE})
endif()

# determine SVN revision
execute_process(COMMAND ${SVN_EXECUTABLE} info "${CMAKE_SOURCE_DIR}"
  RESULT_VARIABLE svn_info_result
  OUTPUT_VARIABLE SVN_REVISION
  ERROR_VARIABLE SVN_REVISION
  OUTPUT_STRIP_TRAILING_WHITESPACE)
if(svn_info_result)
  message(FATAL_ERROR "Failed to determine SVN revision:\n${SVN_REVISION}")
endif()
string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*"
        "\\2" SVN_REVISION "${SVN_REVISION}")

# create the ApplicationVersion.xml file
configure_file("${CMAKE_SOURCE_DIR}/ApplicationVersion.xml.in"
  "${CMAKE_BINARY_DIR}/ApplicationVersion.xml"  @ONLY)

--------------<8------------------

And in your CMakeLists.txt you do the following:

CMakeLists.txt:
-------<8------

# ...

find_package(Subversion REQUIRED)

configure_file(createApplicationVersion.cmake.in
  "${CMAKE_BINARY_DIR}/createApplicationVersion.cmake"
  @ONLY)

add_custom_target(create_ApplicationVersion
  COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_BINARY_DIR}/createApplicationVersion.cmake"
  COMMENT "Creating ${CMAKE_BINARY_DIR}/ApplicationVersion.xml")

add_executable(super_duper main.cpp "${CMAKE_BINARY_DIR}/ApplicationVersion.xml")
add_dependencies(super_duper create_ApplicationVersion)

set_source_files_properties(main.cpp PROPERTIES
  OBJECT_DEPENDS "${CMAKE_BINARY_DIR}/ApplicationVersion.xml")
set_source_files_properties("${CMAKE_BINARY_DIR}/ApplicationVersion.xml" PROPERTIES
  GENERATED TRUE)

# ...

-------<8------


Note that I haven't tested this code, but I hope it gets you started.

Michael

> 
> Am 21. Aug 2010 um 13:04 schrieb Michael Wild <themiwi at gmail.com>:
> 
>> The .in suffix is merely a convention. Refer to the documentation of the configure_file command for more info.
>> 
>> 
>> Michael
>> 
>> 
>> On 21.08.2010, at 11:04, "Roman Wüger" <norulez at me.com>@mac.com wrote:
>> 
>> 
>>> So, how must the file "ApplicationVersion.xml.in" looks like? I didn't find the documentation for the *.in file extensions.
>>> 
>>> Thanks in advance
>>> 
>>> Best Regards
>>> NoRulez
>>> 
>>> Am 21. Aug 2010 um 02:08 schrieb Michael Hertling <mhertling at online.de>:
>>> 
>>>> On 08/20/2010 12:42 PM, Michael Wild wrote:
>>>> >
>>>> > On 19. Aug, 2010, at 23:36 , Michael Hertling wrote:
>>>> >
>>>> >> On 08/19/2010 09:42 PM, Michael Wild wrote:
>>>> >>>
>>>> >>> In that case I recommend creating a CMake script (e.g. create_application_version.cmake) which creates the ApplicationVersion.xml file. It queries the current revision (have a look at FindSVN.cmake on how to do this), determines the date and time (this is a problem, refer to this thread for more info: http://www.mail-archive.com/cmake@cmake.org/msg30662.html) and then either does a configure_file() or a file(WRITE) to create ApplicationVersion.xml. Ideally the create_application_version.cmake is also a configured file (with the path to the build and source tree and the path to the svn executable etc.).
>>>> >>>
>>>> >>> This script is then invoked by a custom command:
>>>> >>>
>>>> >>> # dummy_file is never created...
>>>> >>> add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/ApplicationVersion.xml ${CMAKE_BINARY_DIR}/dummy_file
>>>> >>> COMMAND ${CMAKE_EXECUTABLE} -P ${CMAKE_BINARY_DIR}/create_application_version.cmake
>>>> >>> COMMENT "Creating ApplicationVersion.xml"
>>>> >>> VERBATIM
>>>> >>> )
>>>> >>>
>>>> >>> # this intentionally depends on dummy_file, which is never created
>>>> >>> add_custom_target(create_appplication_version ALL
>>>> >>> DEPENDS ${CMAKE_BINARY_DIR}/ApplicationVersion.xml ${CMAKE_BINARY_DIR}/dummy_file)
>>>> >>>
>>>> >>> add_executable(super_duper main.cpp ${CMAKE_BINARY_DIR}/ApplicationVersion.xml)
>>>> >>> add_dependencies(super_duper create_appplication_version)
>>>> >>>
>>>> >>>
>>>> >>> The trick I'm trying to pull off, is that super_duper depends on create_appplication_version, which is always out of date and depends on the non-existing file dummy_file, thus always updating ApplicationVersion.xml Not that I haven't tested this.
>>>> >>
>>>> >> Possibly, this may be simplified: The COMMAND can be transferred from
>>>> >> the custom command to the custom target, so the former goes away and
>>>> >> one doesn't need a dummy file for triggering. Furthermore, the custom
>>>> >> target doesn't need to be declared ALL, and the ApplicationVersion.xml
>>>> >> doesn't need to appear in ADD_EXECUTABLE(), but as it's no header and,
>>>> >> thus, not subject to CMake's dependency scanning, one has to imply an
>>>> >> explicit dependency through the OBJECT_DEPENDS source file property on
>>>> >> main.cpp to ensure the executable's rebuild when ApplicationVersionxml
>>>> >> changes.
>>>> >
>>>> > Ahh, I forgot about the OBJECT_DEPENDS. And you also need to set the GENERATED property to TRUE on the ApplicationVersion.xml file if you leave away the custom command, otherwise CMake will complain at configure time But all-in-all probably simpler, and you don't need the despicable dummy_file.
>>>> 
>>>> Yes, the GENERATED property should be set, but if there's a template
>>>> named ApplicationVersion.xml.in CMake won't complain about a missing
>>>> ApplicationVersion.xml not marked as GENERATED since it checks for a
>>>> ".in" extension automatically.
>>>> 
>>>> >> The create_application_version.cmake should use CONFIGURE_FILE() to
>>>> >> generate the ApplicationVersion.xml since this function doesn't write
>>>> >> a new output file if it wouldn't differ from the previous one, so the
>>>> >> ApplicationVersion.xml doesn't trigger rebuilds if it doesn't actually
>>>> >> change. At <http://www.cmake.org/pipermail/cmake/2010-July/037958.html&gt;
>>>> >> and <http://www.cmake.org/pipermail/cmake/2010-July/038015.html&gt;, you'll
>>>> >> find a similar discussion.
>>>> >
>>>> > If he's going to encode the time that probably won't matter, since the file will most likely always differ...
>>>> 
>>>> Yes, and I assume it's not the OP's desire to trigger a rebuild because
>>>> of a hand's leap. ;) Hence, what should be done is to generate one file
>>>> with the version and another file with the timestamp, preferably by the
>>>> same custom target, but to impose a dependency on the version file only.
>>>> So, the version and the timestamp are regenerated each time a concerned
>>>> target is checked for being up to date, but solely a new version will
>>>> trigger a rebuild.
>>>> 
>>>> Regards,
>>>> 
>>>> Michael
>>>> _______________________________________________
>>>> Powered by www.kitware.com
>>>> 
>>>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>>> 
>>>> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>>>> 
>>>> Follow this link to subscribe/unsubscribe:
>>>> http://www.cmake.org/mailman/listinfo/cmake
>>> _______________________________________________
>>> Powered by www.kitware.com
>>> 
>>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>> 
>>> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>>> 
>>> Follow this link to subscribe/unsubscribe:
>>> http://www.cmake.org/mailman/listinfo/cmake
> _______________________________________________
> Powered by www.kitware.com
> 
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
> 
> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
> 
> Follow this link to subscribe/unsubscribe:
> http://www.cmake.org/mailman/listinfo/cmake



More information about the CMake mailing list