How to run a command at compile time within Makefile generated by CMake?

后端 未结 4 1471
面向向阳花
面向向阳花 2020-12-07 20:50

I would like to pass some options to a compiler. The option would have to be calculated at compile time - everytime when \'make\' is invoked, not when \'cmake\', so execute_

4条回答
  •  天命终不由人
    2020-12-07 21:24

    The solution above (using a separate CMake script file to generate a header file) seems very flexible but a bit complicated for what is being done in the example.

    An alternative is to set a COMPILE_DEFINITIONS property on either an individual source file and or target, in which case the defined pre-processor variables will only be set for the source file or files in the target are compiled.

    The COMPILE_DEFINITIONS properties have a different format from that used in the add_definitions command, and have the advantage that you don't need to worry about "-D" or "\D" syntax and they work cross-platform.

    Example code

    -- CMakeLists.txt --

    execute_process(COMMAND svnversion
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
        OUTPUT_VARIABLE SVN_REV)
    string(STRIP ${SVN_REV} SVN_REV)
    
    execute_process(COMMAND date "+%Y-%m-%d-%H:%M"
        OUTPUT_VARIABLE BUILD_TIME)
    string(STRIP ${BUILD_TIME} BUILD_TIME)
    
    set_source_files_properties(./VersionInfo.cpp
        PROPERTIES COMPILE_DEFINITIONS SVN_REV=\"${SVN_REV}\";BUILD_TIME=\"${BUILD_TIME}\"")
    

    The first line runs a shell command svnversion and puts the result in the variable SVN_REV. The string(STRIP ...) command is needed to remove trailing newline characters from the output.

    Note this is assuming that the command being run is cross-platform. If not you may need to have alternatives for different platforms. For example I use the cygwin implementation of the Unix date command, and have:

    if(WIN32)
     execute_process(COMMAND cmd /C win_date.bat
        OUTPUT_VARIABLE BUILD_TIME)
    else(WIN32)
      execute_process(COMMAND date "+%Y-%m-%d-%H:%M"
        OUTPUT_VARIABLE BUILD_TIME)
    endif(WIN32)
    string(STRIP ${BUILD_TIME} BUILD_TIME)
    

    for the date commands, where win_date.bat is a bat file that outputs the date in the desired format.

    The two pre-processor variables are not available in the file ./VersionInfo.cpp but not set in any other files. You could then have

    -- VersionInfo.cpp --

    std::string version_build_time=BUILD_TIME;
    std::string version_svn_rev=SVN_REV;
    

    This seems to work nicely across platforms and minimizes the amount of platform-specific code.

提交回复
热议问题