如何使cmake自动重新检查依赖项的版本?

时间:2016-05-04 11:45:37

标签: cmake

我有以下CMakeLists.txt

cmake_minimum_required(VERSION 2.8.11)

project(test)

find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED gtk+-2.0>=2.24)
include_directories(SYSTEM ${GTK_INCLUDE_DIRS})

set(test_SOURCES test.c)
add_executable(test ${test_SOURCES})
target_link_libraries(test ${GTK_LIBRARIES})

和源文件test.c

#include <gtk/gtk.h>

int main(int argc, char** argv)
{
    gtk_init(&argc,&argv);
    return 0;
}

然后我做

mkdir build && cd build
cmake ..
make

成功配置并构建测试。现在我做了

sed -i 's@2\.24@2.25@' ../CMakeLists.txt

因此将所需的GTK版本更新为我没有的版本(GTK 2.25不存在)。现在再次运行make我得到:

-- Configuring done
-- Generating done
-- Build files have been written to: /home/ruslan/cmake-test/build
[100%] Built target test

即。 cmake甚至没有检查是否安装了现在需要的版本。

所以我的问题是:如何让它自动重新检查所需的版本?如果无法自动执行,那么如何在不需要提供整个cmake命令行的情况下执行此操作(在实际项目中可以使用很长时间)?

1 个答案:

答案 0 :(得分:2)

将我的评论转化为答案

这似乎是一个众所周知的问题:0015795: pkg_check_modules produces incorrect results depending on contents of CMakeCache.txt。但不幸的是,到目前为止,这一点还没有得到太多支持。

因此,让我们简要了解相关的FindPkgConfig.cmake代码段:

macro(pkg_check_modules _prefix _module0)
  # check cached value
  if (NOT DEFINED __pkg_config_checked_${_prefix} OR 
      __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR 
      NOT ${_prefix}_FOUND)
     ...
    _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
  endif()
endmacro()

正如您所看到的,一旦将包标记为找到了一个名为${_prefix}_FOUND的缓存变量,它就不会再做任何事了。

可能的解决方法

如果您想强制检查每个配置,您可以添加,例如在检查模块之前unset(GTK_FOUND CACHE)。这是在性能和​​更改所需软件包的便利性之间进行权衡,而无需从头开始进行完整的配置/构建。

...
unset(GTK_FOUND CACHE)
pkg_check_modules(GTK REQUIRED gtk+-2.0>=2.24)
...

建议修复

以下代码作为解决此问题的草案而浮现在脑海中。如果有人可以请它审查,我会欢迎任何意见:

编辑:通过将参数合并到pkgconfig版本检查中简化了我的方法。无论如何,我们应该重新检查pkgconfig脚本是否发生了变化。

macro(pkg_check_modules _prefix _module0)
  # check cached value
  if (NOT DEFINED __pkg_config_checked_${_prefix} OR 
      NOT __pkg_config_checked_${_prefix} STREQUAL "${PKG_CONFIG_VERSION},${ARGV}" OR 
      NOT ${_prefix}_FOUND) 
    ...
    # save pkgconfig version and the arguments used
    _pkgconfig_set(__pkg_config_checked_${_prefix} "${PKG_CONFIG_VERSION},${ARGV}")
  endif()
endmacro()

如果这得到了一些积极的反馈,我会将其作为提案添加到上面提到的CMake错误跟踪器中。

编辑:为了更具体地说明我提议的更改,以下是FindPkgConfig.cmake version as of 21th March, 2016的统一diff

--- FindPkgConfig.cmake 
+++ FindPkgConfig.cmake      
@@ -523,11 +523,13 @@
 #]========================================]
 macro(pkg_check_modules _prefix _module0)
   # check cached value
-  if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)
+  if (NOT DEFINED __pkg_config_checked_${_prefix} OR
+      NOT __pkg_config_checked_${_prefix} STREQUAL "${PKG_CONFIG_VERSION},${ARGV}" OR
+      NOT ${_prefix}_FOUND)
     _pkgconfig_parse_options   (_pkg_modules _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path "${_module0}" ${ARGN})
     _pkg_check_modules_internal("${_pkg_is_required}" "${_pkg_is_silent}" ${_no_cmake_path} ${_no_cmake_environment_path} "${_prefix}" ${_pkg_modules})

-    _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
+    _pkgconfig_set(__pkg_config_checked_${_prefix} "${PKG_CONFIG_VERSION},${ARGV}")
   endif()
 endmacro()

@@ -550,7 +552,9 @@
 #]========================================]
 macro(pkg_search_module _prefix _module0)
   # check cached value
-  if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND)
+  if (NOT DEFINED __pkg_config_checked_${_prefix} OR
+      NOT __pkg_config_checked_${_prefix} STREQUAL "${PKG_CONFIG_VERSION},${ARGV}" OR
+      NOT ${_prefix}_FOUND)
     set(_pkg_modules_found 0)
     _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required _pkg_is_silent _no_cmake_path _no_cmake_environment_path "${_module0}" ${ARGN})

@@ -575,7 +579,7 @@
       endif()
     endif()

-    _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
+    _pkgconfig_set(__pkg_config_checked_${_prefix} "${PKG_CONFIG_VERSION},${ARGV}")
   endif()
 endmacro()