Reputation: 908
I've been building a lot of projects with CMake recently, and overall, I think it's great. However, anytime I need to build a project with dependencies, it quickly becomes a pain.
System installed dependencies are fine, because CMake's find_package system is usually pretty good about finding system installed packages. However, any time I build a dependency from source, I find that it's almost impossible to tell CMake where to find the packages.
I keep ending up searching through the FindFoo.cmake
module, figuring out what special hint variable it's looking at, then setting that variable to where my library is. The real problem is that because these hint variables are always CMake variables, I end up having to either set them in my own CMakeLists.txt
, which is really dirty, or wrapping cmake in a script file to make sure it's passed all the proper hint variables it needs to find packages.
I would just set environment variables, but most of the FindFoo.cmake
modules don't actually check any environment variables.
I looked into using the Package Registry to help solve my problem, but if CMake finds a FindFoo.cmake
module, it doesn't even bother looking in the registry, and CMake just gives up when the FindFoo.cmake
module fails.
What I'm looking for is some way to set variables at "user scope" or "system scope" in CMake, so I can just specify my hint variables in one place instead of across a bunch of project and script files. Unfortunately, I don't seem to be able to find any such functionality.
I'm on Windows, but I'm looking for as general of a solution as possible, because I may not be in the future.
Upvotes: 3
Views: 3280
Reputation: 908
@wasthehelpful's answer mentions creating a my-paths.cmake
file, then importing that into my projects. This is almost a perfect solution, except that it still requires modifying the project. However, after reading the cmake manual some more, I've realized that it has an option to pre-load an "initial-cache" .cmake
file.
So I've created a local.cmake
file in an easily accessible location, filled with entries like this:
set(ZLIB_ROOT "`~/builds/zlib-1.2.8" CACHE PATH "")
set(PNG_ROOT "~/builds/libpng-1.6.27" CACHE PATH "")
set(OSG_DIR "~/builds/OpenSceneGraph_3.4.0" CACHE PATH "")
Then, to configure my project, I invoke cmake
like this:
cmake -C "~/local.cmake" ..
This solution still requires specifying a command line argument, but it's a single argument, and should be easy to remember.
(I'm going to leave this question unanswered for a bit, in case someone comes up with a better solution.)
Upvotes: 0
Reputation: 15976
This is achieved through cmake-gui
: you set the paths and it will remain in the cache of your project unless the cache is deleted.
If you are using CMake in command line, you can give the paths as arguments:
cmake -DCMAKE_PREFIX_PATH=/some/path -DFOO_ROOT=/some/path/to/foo
An other option would be to set the paths in a separate file to be included in your CMakeLists.txt
. You may check if the file exists and generate some template file with a warning message if it isn't available. Something like this:
set(MY_CMAKE_PATHS "${PROJECT_BINARY_DIR}/my-cmake.paths")
if(EXISTS "${MY_CMAKE_PATHS}")
include("${MY_CMAKE_PATHS}")
else()
file(COPY "${PROJECT_SOURCE_DIR}/my-cmake.paths" DESTINATION "${PROJECT_SOURCE_DIR}"
message(FATAL_ERROR
"CMake paths are not available. "
"Please edit the file \"${MY_CMAKE_PATHS}\" with the appropriate values."
)
endif()
With ${PROJECT_SOURCE_DIR}/my-cmake.paths
being something like that:
set(CMAKE_PREFIX_PATH ) # some comment to explain what is expected here
set(FOO_ROOT ) # some comment...
It is up to you to maintain the file with all the variables you want to be filled, and with the appropriate comments to help user to use it.
The paths file is here copied in PROJECT_BINARY_DIR
, but you may as well copy and use it in a "common" path for all your projects.
Upvotes: 1