Это нелегко сделать с помощью CMake, но пример того, как сделать это в качестве включаемых модулей CMake, показан ниже. Решение зависит от использования пользовательской цели, которая выводит соответствующие переменные в файл и вызывает параметр cmake compare_files для сравнения предыдущего файла с файлом проверки и вызывает cmake для восстановления кеша в случае, если они не совпадают.
Решение включает тщательно разработанный модуль CMake include, который будет рекурсивно вызывать себя для проверки того, что кэшированные значения не были изменены переменной Environment. Если это так, он выполнит шаг восстановления кеша, вызвав cmake с соответствующими аргументами, как показано ниже. Ожидается, что вы будете вызывать макрос add_option для каждой переменной, которую вы хотите переопределить с помощью переменной Environment (см. Примеры ниже):
# 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 выполните следующие действия (с использованием файлов Makefile Unix):
mkdir build
cd build
Следующий пример демонстрирует первоначальное создание Make-файлов Unix. Обратите внимание, что в этом случае переменные используют свои значения по умолчанию.
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 может вызывать цель check-variable и ее зависимые цели, созданные модулем 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
В следующем примере показано, как переменная окружения вызывает сбой одного из шагов check-variable и вызывает событие восстановления кеша. Обратите внимание на изменение значения 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
В следующем примере показано, как временно измененная выше переменная возвращается к значениям по умолчанию, а другая переменная запускается для изменения ее значения. Обратите внимание, что переменная MYVAR возвращается к своему значению по умолчанию, в то время как переменная MYSTR получает новое предоставленное значение.
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