Reputation: 5201
In my CMake project, I provide a default path to Boost editable by the user.
set(PATH_BOOST_DEFAULT "/softs/boost/${BOOST_VER}/${ARCH}/gcc/${GCCVER}")
set(PATH_BOOST "${PATH_BOOST_DEFAULT}" CACHE PATH "Default path to Boost")
After that, I try to find the libs with:
set(BOOST_ROOT "${PATH_BOOST}")
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.53.0 REQUIRED COMPONENTS thread system)
This works fine and a lot of cache variables like Boost_INCLUDE_DIR
, Boost_LIBRARY_DIRS
or Boost_THREAD_LIBRARY_DEBUG
are generated.
My problem comes when I try to modify the cache variable PATH_BOOST
: the cache variables generated by FindBoost.cmake
aren't updated. The script FindBoost.cmake
seems to be called again (it print messages about found components). I think the variables like Boost_INCLUDE_DIR
are not updated because they are in cache.
Is there a way to say to CMake "if the path is modified by the user, re-find the package by forcing the cache variables"?
Also, is there a nicer way to detect a cache variable was just modified than the following ugly idea?
set(MY_VAR ${MY_VAR_DEFAULT} CACHE TYPE "")
if(NOT DEFINED MY_VAR_copy)
set(MY_VAR_copy ${MY_VAR} CACHE INTERNAL "")
mark_as_advanced(FORCE MY_VAR_copy)
endif()
if(NOT "${MY_VAR}" STREQUAL "${MY_VAR_copy}")
# my_var is modified : do something
set(MY_VAR_copy ${MY_VAR} CACHE INTERNAL "")
endif()
Upvotes: 16
Views: 4899
Reputation: 31
I've got the same problem as you.My project is a cross-compiled project that develops debugging on x86 machines and deploys and runs on aarch64 machines, depending on the x86 and aarch64 versions of the same package, but cmake doesn't seem to re-search for packages when switching architectures.
I noticed that cmake's documentation mentions:
Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again.
By default the value stored in the result variable will be the path at which the file is found. So I find the cached value in CMakeCache.txt, value is just link
packageName_DIR
. Solution is:
unset(packageName_DIR CACHE)
find_package(packageName)
if(packageName_FOUND)
#do something
endif()
then each time you reload the CMakeLists, it will re-find the package.
Or you can set a flag in cache, if the flag changed, unset packageName_DIR
.
Note that if some cache variables are set in the package, you also need to add unset, You may need to look at the package's FindpackageName.cmake or CmakeCache.txt to see if there are extra cache variables. For example,
packageName_LIBRARIES contain LIB1,LIB2,LIB3, you need
unset(LIB1_LIBRARY CACHE)
unset(LIB2_LIBRARY CACHE)
unset(LIB3_LIBRARY CACHE)
unset(LIB1_INCLUDE_DIR CACHE)
unset(LIB2_INCLUDE_DIR CACHE)
unset(LIB3_INCLUDE_DIR CACHE)
If none of the above works, there's a simplest and crudest way is to delete the CMakeCache.txt file (which is usually in the cmake build root directory) and reload CMakeLists.txt.
Upvotes: 1
Reputation: 4430
I think I've got the same problem as you. My setup tries to find a specific version of a package:
set (MYPACK_REQUIRED_VERSION 1.2.3)
find_package (mypack ${MYPACK_REQUIRED_VERSION} EXACT)
The package config script sets the cached variable MYPACK_LIBRARIES
which then is used at a later stage. However when I change the MYPACK_REQUIRED_VERSION
variable cmake still use the old MYPACK_LIBRARIES
instead of trying to look for the new version.
I think I've solved the problem now by unsetting this cache variable:
set (MYPACK_REQUIRED_VERSION 1.2.3)
unset (MYPACK_LIBRARIES CACHE)
find_package (mypack ${MYPACK_REQUIRED_VERSION} EXACT)
This seems to trigger the find_package procedure again in my case. There are some finer details of the find_package
procedure that I don't completely understand so this might not work in your case, but it might be worth a try.
Upvotes: 1