当环境变量更改时,让基于 makefile 的 cmake 项目自动运行 makerebuild_cache

发布于 2024-11-09 14:50:37 字数 210 浏览 0 评论 0 原文

在我的 cmake 配置中,几个变量依赖于环境变量才能正确设置。该环境变量可以更改,这意味着应该重建 cmake 的缓存。

我的配置可以检测到重新配置的需要,并在调用另一个“cmake”调用或调用“makerebuild_cache”时更新适当的缓存条目。

但是,我希望每当我运行时都会自动检查更改,并在必要时运行rebuild_cache目标。

这可能吗?

In my cmake configuration several variables depend on an environment variable in order to be set correctly. This environment variable can change and it means that the cache for cmake should be rebuilt.

My configuration can detect the need for this reconfigure and update the appropriate cache entries when either another call to "cmake " is called or "make rebuild_cache" is called.

However, I would like whenever I run make it to be checked automatically for changes and have the rebuild_cache target run if necessary.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

も让我眼熟你 2024-11-16 14:50:37

Make没有记忆。 make 无法“记住”上次运行 make 时给定环境变量的设置。

除非您将环境变量写入文件。

我从未使用过 CMake,所以我不知道如何最好地实现它。但在“原始”make 级别上,总体思路是:

1)编写一条规则(例如,envir_cache),将环境变量写入文件(命名为,并非巧合, envir_cache),如果该文件尚不存在,该文件存在但其内容与环境变量的值不同。 (类似于 if [ -f envir_cache ]read cached_var if [ "${myvar}" != "${cached_var }" ]。)

2)使目标rebuild_cache依赖于envir_cache

这样,rebuild_cache 规则将在第一次运行时以及每次运行之间变量发生更改时执行。

Make does not have a memory. There is no way for make to "remember" what a given environment variable was set to the last time make was run.

Unless you write the environment variable to a file.

I've never used CMake, so I don't know how to best implement it. But on the "raw" make level, the general idea would be to:

1) write a rule (say, envir_cache) which writes the environment variable to file (named, not so coincidentially, envir_cache), if that file does not yet exist, or the file exists but its contents are different from the value of the environment variable. (Something along the lines of if [ -f envir_cache ] and read cached_var < envir_cache and if [ "${myvar}" != "${cached_var}" ].)

2) make the target rebuild_cache depend on envir_cache.

That way, the rebuild_cache rule will be executed on the first run, and whenever the variable changed between runs.

む无字情书 2024-11-16 14:50:37

使用 CMake 不容易完成此操作,但下面显示了如何以 CMake 包含模块的形式执行此操作的示例。该解决方案取决于使用自定义目标,该目标将有问题的变量输出到文件,并调用 cmake Compare_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 Makefile):

mkdir build
cd build

以下示例演示了 Unix Makefile 的初始创建。请注意,在这种情况下,变量使用其默认值。

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 模块创建的 check-variables 目标及其依赖目标。请注意如何不发生重建缓存。

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

This is not easily done with CMake, but an example of how to do this as a CMake include modules is shown below. The solution depends on using a custom target that outputs the variables in question to a file and calls the cmake compare_files option to compare the previous file to the verify file and calls cmake to rebuild the cache in the event they don't match.

The solution involves a carefully crafted CMake include module that will recursively call itself to verify the cached values haven't been changed by an Environment variable. If it has, it will perform the rebuild cache step by calling cmake with appropriate arguments as shown below. It is expected that you will call the add_option macro for every variable you want to be able to override using an Environment variable (see examples below):

# 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()

If the above CMake module was named add_option.cmake you could use it as follows:

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}")

With the above CMakeLists.txt file do the following (using Unix Makefiles):

mkdir build
cd build

The following example demonstrates the initial creation of the Unix Makefiles. Note the variables use their default values in this case.

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

The following example shows how make can invoke the check-variables target and its dependent targets created by the add_option.cmake module above. Notice how no rebuild cache occurs.

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

The following example shows how an environment variable causes one of the check-variables step to fail and triggers a rebuild cache event. Note the change in the MYVAR value during the cache rebuild process.

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

The following example shows how the variable changed temporarily above is reverted back to the defaults and a different variable is triggered to change its value. Note the MYVAR variable revert back to its default value while the MYSTR variable obtains a new value provided.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文