当环境变量发生变化时,让基于makefile的cmake项目自动运行make-rebuild_cache
Have makefile based cmake projects automatically run make rebuild_cache when an environment variable changes
在我的cmake配置中,为了正确设置,几个变量取决于一个环境变量。这个环境变量可能会更改,这意味着应该重建cmake的缓存。
我的配置可以检测到这种重新配置的必要性,并在调用另一个对"cmake"的调用或调用"make-rebuild_cache"时更新适当的缓存条目。
但是,我希望无论何时运行,都能自动检查是否有更改,并在必要时运行rebuild_cache目标。
这可能吗?
Make没有内存。make无法"记住"上次运行make时给定环境变量的设置。
除非将环境变量写入文件。
我从未使用过CMake,所以我不知道如何最好地实现它。但在"原始"制造级别上,一般的想法是:
1) 编写一个规则(比如envir_cache
),将环境变量写入文件(命名为envir_cache
,但并非巧合),如果该文件还不存在,则或文件存在,但其内容与环境变量的值不同。(类似于if [ -f envir_cache ]
、read cached_var < envir_cache
和if [ "${myvar}" != "${cached_var}" ]
的东西。)
2) 使得目标CCD_ 6依赖于CCD_。
这样,rebuild_cache
规则将在第一次运行时执行,并且每当变量在两次运行之间发生变化时执行。
使用CMake不容易做到这一点,但下面显示了如何作为CMake包含模块做到这一步的示例。该解决方案取决于使用一个自定义目标,该目标将有问题的变量输出到一个文件,并调用cmakecompare_files选项将前一个文件与验证文件进行比较,并在它们不匹配的情况下调用cmake重建缓存。
该解决方案涉及一个精心编制的CMake-include模块,该模块将递归地调用自己,以验证缓存的值是否已被环境变量更改。如果有,它将通过使用适当的参数调用cmake来执行重建缓存步骤,如下所示。预计您将为每个想要使用环境变量覆盖的变量调用add_option宏(请参阅下面的示例):
# Capture the full path to this CMake module file
if(NOT _option_cmake_file)
set(_option_cmake_file ${CMAKE_CURRENT_LIST_FILE})
endif()
# When this CMake module is called as a script include the option file
if(_option_verify)
include(${_option_file})
endif()
# add_option macro for adding cached values you want to be able to
# override with an environment variable of the same name
# _name - variable name to use for the cached value
# _type - type of cached variable
# _description - description of cached variable for CMake GUI
# _default - default value if no variable with same name is defined
macro(add_option _name _type _description _default)
# Define _option_file to be created if not in verify mode
if(NOT _option_verify)
set(_option_file ${CMAKE_BINARY_DIR}/${_name}.cmake)
endif()
# Determine the source for the alue of the cached variable
set(_option_output "set(_name ${_name})")
list(APPEND _option_output "nset(_type ${_type})")
list(APPEND _option_output "nset(_description "${_description}")")
if(DEFINED ENV{${_name}})
set(${_name} $ENV{${_name}} CACHE ${_type} "${_description}" FORCE)
list(APPEND _option_output "nset(${_name} $ENV{${_name}})")
elseif(${_name})
set(${_name} ${${_name}} CACHE ${_type} "${_description}" FORCE)
set(ENV{${_name}} ${${_name}}) # needed to pass from verify back to rebuild_cache
list(APPEND _option_output "nset(${_name} ${${_name}})")
else()
set(${_name} ${_default} CACHE ${_type} "${_description}" FORCE)
list(APPEND _option_output "nset(${_name} ${_default})")
endif()
# Create the _option_file (or verify file) containing the values
# defined above
execute_process(
COMMAND ${CMAKE_COMMAND} -E echo ${_option_output}
OUTPUT_FILE ${_option_output}${_option_verify})
# If not in verify mode create check target to verify value
if(NOT _option_verify)
# Only create parent check-variables target once
if(NOT TARGET check-variables)
add_custom_target(check-variables ALL)
endif()
# Use this file as custom CMake target to verify variable value
add_custom_target(check-${_name}
COMMAND ${CMAKE_COMMAND}
-D_option_verify:String=-verify
-D_option_file:Filepath=${_option_file}
-D_option_sdir:Path=${CMAKE_SOURCE_DIR}
-D_option_bdir:Path=${CMAKE_BINARY_DIR}
-P ${_option_cmake_file}
COMMENT "Checking variable '${_name}' for changes"
VERBATIM)
# Add custom target as dependency for parent check-variables target
add_dependencies(check-variables check-${_name})
else()
# Use cmake to compare options file and verify file created above
execute_process(
COMMAND ${CMAKE_COMMAND} -E compare_files
${_option_file} ${_option_file}${_option_verify}
OUTPUT_VARIABLE COMPARE_OUTPUT
ERROR_VARIABLE COMPARE_ERROR
RESULT_VARIABLE COMPARE_RESULT)
# Remove verify file
file(REMOVE ${_option_file}${_option_verify})
# If compare failed, then call CMAKE to rebuild_cache
if(NOT COMPARE_RESULT EQUAL 0)
# Perform the rebuild_cache step
execute_process(
COMMAND ${CMAKE_COMMAND} -H${_option_sdir} -B${_option_bdir})
endif()
endif()
endmacro()
# In verify mode? then call add_option macro to initiate the process
if(_option_verify)
# The values below come from the include(_option_file) above
add_option(${_name} ${_type} "${_description}" ${${_name}})
endif()
如果上面的CMake模块名为add_option.CMake,您可以按如下方式使用它:
cmake_minimum_required(VERSION 2.8)
project(Example)
include(${PROJECT_SOURCE_DIR}/add_option.cmake)
add_option(MYVAR
BOOL
"A boolean cached value that can be overridden by Environment variable"
ON)
add_option(MYSTR
STRING
"A string cached value that can be overridden by Environment variable"
"some string")
message(STATUS "MYVAR=${MYVAR}")
message(STATUS "MYSTR=${MYSTR}")
使用上面的CMakeLists.txt文件执行以下操作(使用Unix Makefiles):
mkdir build
cd build
以下示例演示了Unix Makefiles的初始创建过程。请注意,在这种情况下,变量使用它们的默认值。
cmake .. -G "Unix Makefiles"
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- MYVAR=ON
-- MYSTR=some string
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/example/build
以下示例显示了make如何调用由上面的add_option.cmake模块创建的检查变量目标及其依赖目标。请注意,没有发生重建缓存。
make
Scanning dependencies of target check-MYVAR
[ 50%] Checking variable 'MYVAR' for changes
[ 50%] Built target check-MYVAR
Scanning dependencies of target check-MYSTR
[100%] Checking variable 'MYSTR' for changes
[100%] Built target check-MYSTR
Scanning dependencies of target check-variables
[100%] Built target check-variables
以下示例显示了环境变量如何导致其中一个检查变量步骤失败并触发重建缓存事件。请注意在缓存重建过程中MYVAR值的变化。
make MYVAR=off
[ 50%] Checking variable 'MYVAR' for changes
-- MYVAR=off
-- MYSTR=some string
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/example/build
[ 50%] Built target check-MYVAR
[100%] Checking variable 'MYSTR' for changes
[100%] Built target check-MYSTR
[100%] Built target check-variables
以下示例显示了如何将上面临时更改的变量恢复为默认值,并触发另一个变量来更改其值。请注意,当MYSTR变量获得所提供的新值时,MYVAR变量将恢复到其默认值。
make MYSTR="hi mom"
[ 50%] Checking variable 'MYSTR' for changes
-- MYVAR=ON
-- MYSTR=hi mom
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/example/build
[ 50%] Built target check-MYSTR
[100%] Checking variable 'MYVAR' for changes
[100%] Built target check-MYVAR
[100%] Built target check-variables
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- CMake-按正确顺序将项目与C运行时对象文件链接
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- cmake在我的项目中所需的所有静态库都不成功
- 使外部项目可用于find_package CMake
- 在 Mac 上使用 CMAKE 将 FFTW 和 FFTWPP 链接到项目中时未定义的符号
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- CMake WxWidgets项目成功地在Linux上构建,但没有在Windows上构建
- Visual Studio 中的 CMake 项目:如何添加其他包含和库目录?
- 尝试将 boost::stacktrace 添加到 CMake 项目时出现构建错误
- 当我尝试通过 mingw 使用 CMake 和 SFML 库编译项目时出错
- 如何将我的 CMake 项目配置为运行所有单元测试?
- CMake 生成的 MSVC 项目找不到符号,即使为其相关 dll 正确生成了 lib 文件也是如此
- 智能感知不适用于Visual Studio 2017中的cmake项目
- 如何在我的项目中从 CMAKE 中的同一项目获取多个库
- 在现有的C++可执行项目CMAKE中构建Apache Arrow
- 编译/添加 cuda 代码到现有项目 (CMake)
- 将 GLEW 添加到项目 (CMake)
- SDL项目CMake构建失败
- 如何在目标项目 (cmake) 中添加不用于创建目标的文件