When google-ing export CMAKE_PREFIX_PATH, you will often find the suggestion to cure the problem that CMake doesn't find this or that package by setting an environment variable:
export CMAKE_PREFIX_PATH=/path/to/package
I've convinced myself that setting this environment variable has the effect of appending /path/to/package to the list of paths specified in the CMake call using
cmake -DCMAKE_PREFIX_PATH="/path/to/package1;..." .
(I've tried this on macOS Catalina and Ubuntu 18.04 using CMake 3.15.5 and 3.16.0, respectively.)
The documentation doesn't mention any of this. In fact, it simply states:
By default this [CMAKE_PREFIX_PATH] is empty. It is intended to be set by the project.
(see CMake documentation). There's no mention of the effect of setting the environment variable.
This raises two questions:
Is this effect of setting the environment variable intended? Where is it documented? Is this the canonical way of adding prefix paths to all projects build in the environment?
As the documentation says, "It [CMAKE_PREFIX_PATH] is intended to be set by the project". Is there any reason why there shouldn't be a way to set a default CMAKE_PREFIX_PATH?
The effect of setting it as an environment variable is, by default, no effect. CMake defines it's own variables (those set with the set() command, or the -D command line argument) in a file called CMakeCache.txt in the root of your CMake project. Those are the variables which will affect your cmake script.
In order to access and environment variable in CMake, you need to specify the ENV Syntax
$ENV{VAR}
Hence, even if you set a CMAKE_PREFIX_PATH environment variable, it will have no effect unless you explicitly use it in you CMakeLists.txt.
(Edit: I have only verified this behavior on Windows 10 with CMake 3.16.3)
Setting the CMAKE_PREFIX_PATH environment variable works in finding things with function find_file, find_path, etc.
Just because by default these functions use the CMAKE_PREFIX_PATH environment variable as a path hint as well as the CMAKE_PREFIX_PATH variable set via -DCMAKE_PREFIX_PATH=xx or set function.
Related
I am trying to move from an own written tool to cmake for Windows to simplify our build environment.
We have a tool in the build process that requires to have set environment variables. I would like to set them with cmake but don't know how. What I have tried:
set(ENV{MYENVVAR} "My-Content")
I would expect that I can read this environment variable again with
message($ENV{MYENVVAR})
But this does not work. Even setting a variable before invoking cmake (instead of setting it in cmake) does not help, I cant read the variable in cmake.
What do I do wrong?
Edit:
I do invoke cmake again after changing CMakeLists.exe.
I do set environment variables with set MYENVVAR=My-Content in Windows cmd.exe and then invoke cmake from exactly this console.
cmake is version 3.20.0 for Windows.
You're going to need to produce a minimal, reproducible example. Here's my best attempt based on your question and unfortunately, the best I can say is "works for me":
alex#alex-ubuntu:~$ export MYENVVAR=FooBarBaz
alex#alex-ubuntu:~$ cat test.cmake
cmake_minimum_required(VERSION 3.20)
message($ENV{MYENVVAR})
set(ENV{MYENVVAR} "My-Content")
message($ENV{MYENVVAR})
alex#alex-ubuntu:~$ cmake -P test.cmake
FooBarBaz
My-Content
alex#alex-ubuntu:~$ echo $MYENVVAR
FooBarBaz
So CMake can both read the environment variable and write to it in-process, but it does not affect the controlling process's (in this case bash; in your case cmd.exe) environment.
I want to pass an additional parameter to cmake relative to where it is.
My libraries are in:
C:/bla/imgui
C:/bla/imgui-integration
From
C:/bla/imgui-integration/build folder I want to refer to C:/bla/imgui in a parameter named IMGUI_DIR :
cmake .. -DIMGUI_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../imgui"
The problem is that I tried every combination of :
-DIMGUI_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../imgui"
-DIMGUI_DIR="${CMAKE_CURRENT_SOURCE_DIR}/imgui"
And none of them works.
Only works if I directly use:
-DIMGUI_DIR="C:/bla/imgui"
What am I doing wrong exactly?
As Tsyvarev said in a comment:
CMAKE_CURRENT_SOURCE_DIR is a CMake variable, which is set by CMake
when it interprets your project. But when running cmake <..> you use
shell scripting. You need to use abilities of the shell for prepare
needed parameters
I can't use cmake variables in the shell that will be interpreted inside cmake.
Edit: The accepted answer actually shows that it is pretty normally possible to set CMAKE_MODULE_PATH as any other CMake variable e.g. via the -DCMAKE_MODULE_PATH path CLI parameter. It seems that in my case there is some included CMake script that calls set(CMAKE_MODULE_PATH /library_path), which erases all previous paths set to the variable. That's why I couldn't get the variable to do what I wanted it to do. I'll leave the question here in case anybody else faces this kind of situation.
I'm building a (3rd party) project that uses the Protobuf library (but this question is general). My system has a system-wide install of a newer version of Protobuf than the project is compatible with. So I've downloaded and compiled from source an older version of Protobuf.
The project uses CMake, and in its CMakeLists.txt, there is:
find_package(Protobuf REQUIRED)
Which, however, finds the (incompatible) system install. Of course, CMake doesn't know about my custom build of Protobuf. But how do I tell it?
I've created a FindProtobuf.cmake file in, say, ~/usr/share/cmake-3.0/Modules/ and want the build process to use this one for finding Protobuf. But I haven't succeeded forcing CMake to pick up this one and not the system one. I think the reason is quite obvious from the CMake docs of find_package:
The command has two modes by which it searches for packages: “Module” mode and “Config” mode. Module mode is available when the command is invoked with the above reduced signature. CMake searches for a file called Find<package>.cmake in the CMAKE_MODULE_PATH followed by the CMake installation. If the file is found, it is read and processed by CMake. ... If no module is found and the MODULE option is not given the command proceeds to Config mode.
So until I succeed to change CMAKE_MODULE_PATH, CMake will just pick up the FindProtobuf.cmake installed to the default system path and won't ever proceed to the "Config" mode where I could probably make use of CMAKE_PREFIX_PATH.
It's important for me to not edit the CMakeLists.txt since it belongs to a 3rd party project I don't maintain.
What I've tried (all without success):
calling CMAKE_MODULE_PATH=~/usr/share/cmake-3.0/Modules cmake ... (the env. variable is not "transferred" to the CMake variable with the same name)
calling cmake -DCMAKE_MODULE_PATH=~/usr/share/cmake-3.0/Modules ... (doesn't work, probably by design?)
calling Protobuf_DIR=path/to/my/protobuf cmake ... (the project doesn't support this kind of override for Protobuf)
It seems to me that, unfortunately, the only way to alter the CMAKE_MODULE_PATH used by find_package is to alter it from within CMakeLists.txt, which is exactly what I want to avoid.
Do you have any ideas/workarounds on how not to touch the CMakeLists.txt and still convince find_package to find my custom Protobuf?
For reference, the CMake part of this project is on github .
As a direct answer to your question, yes, you can set CMAKE_MODULE_PATH at the command line by running cmake -DCMAKE_MODULE_PATH=/some/path -S /path/to/src -B /path/to/build.
But that probably doesn't do what you want it to do; see below.
The Bitbucket link you supplied is dead, but here are a few suggestions that might help.
Avoid writing your own find modules, especially when the upstream supplies CMake config modules.
You can direct CMake to your custom Protobuf installation by setting one of CMAKE_PREFIX_PATH or Protobuf_ROOT (v3.12+) to the Protobuf install root.
You can tell find_package to try CONFIG mode first by setting CMAKE_FIND_PACKAGE_PREFER_CONFIG to true (v3.15+). Then set Protobuf_DIR to the directory containing ProtobufConfig.cmake.
Failing all else, you can manually set the variables documented in CMake's own FindProtobuf module, here: https://cmake.org/cmake/help/latest/module/FindProtobuf.html
All these variables can be set at the configure command line with the -D flag.
There are very few environment variables that populate CMake variables to start and I would avoid relying on them. There is an exhaustive list here: https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html. CMAKE_MODULE_PATH is not among them.
I want to set a particular MPI compiler (mpiifort) with CMake. Well, not the compiler, but get the libraries and include directories from it. But there is also mpif90 in the path, which uses gfortran under the hood, and has a different set of include dirs and libraries. It seems the FindMPI module in CMake insists on locating mpif90 first and therefore sets the wrong paths.
I've tried setting MPI_Fortran_COMPILER=mpiifort in the command line, or setting FC=mpiifort, but none works. So far the only workaround I've found is creating a symlink mpif90 -> mpiifort in the current directory and adding _MPI_PREFIX_PATH=.. Any other ideas?
EDIT: I had tried the environment variable MPI_Fortran_COMPILER, but I had to set the CMake variable instead. So this worked:
FC=ifort CC=icc cmake -D MPI_Fortran_COMPILER=mpiifort ...
According to the source here, if setting MPI_Fortran_COMPILER does not work, then you could simply set MPI_Fortran_LIBRARIES and MPI_Fortran_INCLUDE_PATH.
I'm trying to test a project on a cluster where I can't install some libraries in the default locations, so I'm trying to override the default CMake search path with the CMAKE_INCLUDE_PATH environment variable.
Unfortunately it doesn't seem to be picked up. I'm having to set the path explicitly with
include_directories("." $ENV{CMAKE_INCLUDE_PATH})
but this seems like a bit of a hack. So I have two questions:
Is this expected behavior?
Is there some cleaner way to add a directory to CMake's include path via an environment variable?
First of all, there is a predefined cmake variable CMAKE_INCLUDE_PATH variable that is a ";-list of directories specifying a search path for the find_file() and find_path() commands." This is not meant to specify the compiler include path.
Secondly, good use of cmake should not involve environment variables. To the extent you can, you should use the conventional cmake find_package to configure your build paths. When you need to explicitly add a path to the compiler include search path, then, yes, include_directories is what you need. But you should a cmake cache variable rather than environment variable. For details on setting a cache variable, see this page, which says
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
For your example this becomes:
set(MYINCLUDE /usr/local/foo/include CACHE PATH "path to the foo include directory")
include_directories(${MYINCLUDE})
Then if you need to override the default /usr/local/foo/include, you may specify it with the command line used when invoking cmake; e.g., cmake -DMYINCLUDE=/home/foo/include .