CMake add system-wide prefix path [duplicate] - cmake

This question already has an answer here:
Hinting Find<name>.cmake Files with a custom directory
(1 answer)
Closed 2 years ago.
I want every CMake project that uses boost (or any other lib) to find it in custom directory, for example /home/someuser/mylibs or C:/mylibs.
To achieve this I may add in CMakeLists.txt following command:
list(APPEND CMAKE_PREFIX_PATH "/home/someuser/mylibs")
This is not very comfortable when I cooperate with different people on different projects. The question is: can I use some environment variable to set it or there's another way to do this?

The usual way is to add -DCMAKE_PREFIX_PATH=/path/to/boost/ when calling CMake to configure your project. But, of course, you can also set an environment variable, e.g. BOOST_DIR and then read it out using CMake:
list(APPEND CMAKE_PREFIX_PATH $ENV{BOOST_DIR})

Related

How to determine whether cmake project included via add_subdirectory? [duplicate]

This question already has answers here:
How to detect if current scope has a parent in CMake?
(3 answers)
How can I tell, within a CMakeLists.txt, whether it's used with add_subdirectory()? [duplicate]
(1 answer)
Closed 4 months ago.
I have a small CMake project that encapsulate a small C++ library. For this library, I want to enable almost all available warnings by default while developing it. However, if someone wants to make use of my library and therefore uses add_subdirectory to include my project, I would like to disable warnings for my library.
I know how to disable warnings, but I would like to know how one would go about detecting whether the CMake project is currently processed stand-alone or embedded in another CMake project.
CMake >= v3.21
There's a boolean flag PROJECT_IS_TOP_LEVEL, which seems to indicate exactly this.
For more general querying (not only the current project), there's also <PROJECT-NAME>_IS_TOP_LEVEL.
CMake pre < v3.21
Disclaimer: This answer assumes that project calls always happen in the first processed CMakeLists.txt file that is processed for every project.
The best way to check for this (to my knowledge) would be to test whether the variables CMAKE_SOURCE_DIR and PROJECT_SOURCE_DIR (note: no CMAKE_ prefix) refer to the same path.
From the docs 1, 2:
CMAKE_SOURCE_DIR
The path to the top level of the source tree.
This is the full path to the top level of the current CMake source tree.
PROJECT_SOURCE_DIR
This is the source directory of the last call to the project() command made in the current directory scope or one of its parents. Note, it is not affected by calls to project() made within a child directory scope (i.e. from within a call to add_subdirectory() from the current scope).
So the gist of it is that if the project is built stand-alone, top-level source directory, is the one that contains your own CMakeLists.txt file, which (as is normally the case) contains the project call of your own project. Assuming you don't have multiple project calls in your project (again: as is usually the case), that means that the directory in which the last project call happened (and which does not lie in a sun directory of your current directory, which according to the docs don't count) is the same as the top-level source directory. Therefore, the mentioned variables will refer to the same path.
If, however, your project is embedded in someone else's CMake project, their CMakeLists.txt location will define the top-level source directory. At some point, they will include your project, which starts by its own project call, updating PROJECT_SOURCE_DIR to the path to the directory in which your CMakeLists.txt file lies. Therefore, CMAKE_SOURCE_DIR != PROJECT_SOURCE_DIR.
TL;DR: This is the necessary check
if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
message(STATUS "Your project is standalone")
else()
message(STATUS "Your project is embedded")
endif()

Is it possible to refer to an additional .txt-file inside the CMakeLists.txt? [duplicate]

I use some libraries that I don't want built as part of every project that uses them. A very understandable example is LLVM, which has 78 static libraries. Even having the cmake code to find and import these in every cmakefile is excessive.
The obvious solution seems to be to use the "include" command, and to factor out relevant chunks of cmake script into *.cmake files, and set up a CMAKE_MODULE_PATH environment variable.
Except it just plain doesn't work. Cmake doesn't find the file I specify in the include command.
On the off-chance, I even tried specifying the path in the environment variable several ways - once with backslashes, once with forward slashes... - and I restarted the command prompt each time and checked that the environment variable was present and correct.
In the cmake manual, it kind of implies that a "file" is different from a "module" - only a module gets the automatic add-the-extension-and-search-the-path treatment. But there is no explanation of what the difference is. I guessed that the missing extension might be enough (as with standard modules) but clearly it isn't.
Searching the manual for "module" isn't much help as the word seems to be overloaded. For example, a module is also a dynamic library loaded using LoadLibrary/dl_open.
Can anyone explain what the difference is between a file and a module in this context, and how I create my own module so that the cmake include command can find and use it?
I'm using cmake 2.8.1 on Windows.
EDIT
I'm pretty confident that the problem here is not understanding how cmake is supposed to work. I think what I should be doing is writing something that find_package can work with.
As things stand though, I'm still some way from being able to answer my own question.
I believe that a CMake 'module' is simply a file that can be used with the find_package directive. That is, when you run find_package(Module), it searches for a file in the MODULE_PATH that is named FindModule.cmake.
That said, if you include a file without the extension, it too will search through your MODULE_PATH for that file.cmake. In a CMake project I'm working on, I have a very similar directory structure as to what you propose.
+ root/
+ CMakeLists.txt
+ cmake/
| + FindMatlab.cmake
| + TestInline.cmake
| + stdint.cmake
+ src/
+ include/
In CMakeLists.txt I have:
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package (Matlab) # runs FindMatlab.cmake
include(TestInline) # defines a macro:
test_inline (CONFIG_C_INLINE)
include(stdint) # simply executes flat CMake code
Perhaps your issue is that you are trying to define the Module path from the environment. Instead, try to simply append to it within the very CMakeList you try to access the modules/files.
I had this same question after reading the CMake include() command documentation. It states:
Load and run CMake code from the file given. [...snip for brevity...] If a module is specified instead of a file, the file with name .cmake is searched first in CMAKE_MODULE_PATH, then in the CMake module directory.
This leaves a lot of interpretation as to what CMake considers a module vs. a file, because a CMake module is a file on the file system after all. So what's the difference?
The CMake source code is the only place I could find the answer. Basically CMake considers the argument to include() to be a file if it looks like an absolute path. This means:
On Linux/Unix
The argument starts with either '/' or '~'
On Windows
The argument's second character is ':' (as in C:)
The argument starts with '\'
CMake assumes anything else that doesn't meet the above criteria is a Module. In which case it appends '.cmake' to the argument and searches the CMAKE_MODULE_PATH for it.
File is CMake listfile, example is CMakeLists.txt. Use following command to get the list of command used in
cmake --help-command-list
Module is a cmake file (*.cmake) which contain cmake commands.
As Matt B. put, the CMAKE_MODULE_PATH is not environment variable of your shell, but cmake variable.
To append your module path to CMAKE_MODULE_PATH
LIST(APPEND CMAKE_MODULE_PATH ${YourPath})
Or if you perfer your modules to be used first
LIST(INSERT CMAKE_MODULE_PATH 0 ${Yourpath})

How to navigate in cmakelists.txt? [duplicate]

This question already has an answer here:
How do I specify relative paths in CMAKE?
(1 answer)
Closed 1 year ago.
I have project dependency packages in the directory
C:/Users/king/my/mytest/dds
mytest contains folders dds, Source, testapp
I use the following in my cmakelists.txt
find_package(Idlpp-cxx REQUIRED PATHS C:/Users/king/my/mytest/dds/Idlpp-cxx)
find_package(CycloneDDS REQUIRED PATHS C:/Users/king/my/mytest/dds/CycloneDDS)
find_package(CycloneDDS-CXX REQUIRED PATHS C:/Users/king/my/mytest/dds/CycloneDDS-CXX)
how can I set them to pick up automatically without hardcoding C:/Users/king/my/mytest/? which will differ from pc to pc....
I do cmake build in this folder
C:/Users/king/my/mytest/testapp
cmaklists.txt file is in
C:/Users/king/my/mytest/Source
New in version 3.12: Search paths specified in the <PackageName>_ROOT CMake variable and the <PackageName>_ROOT environment variable, where <PackageName> is the package to be found.
ref: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
CMAKE_CURRENT_SOURCE_DIR can be used to pick any forward directory from the current directory
Idlpp-cxx PATHS ${CMAKE_CURRENT_SOURCE_DIR}/my/mytest/dds/idlpp-cxx)
worked for me

Compile .o files with Clion [duplicate]

This question already has answers here:
how to add prebuilt object files to executable in cmake
(4 answers)
Closed 3 years ago.
We have been given a C++ group project, and we've been given the completed project in .o format too, so as we work over the break we can test the individual parts we are working on.
I'm using CLion and I'd like to firstl compile the whole project from the object files to see how it works and from there I should be able to remove the .o files I am working on and include my own .h/.cpp versions.
Can someone tell me how to write the CMakeLists.txt, or at least tell me what to read? I couldn't find any specific documentation, and I don't know where to start.
**edit
I had a look at the other solution mentioned in the duplicate, but implementing that didn't work, I still needed to set the target properties. Possibly down to the object files being created with a different piece of software?
Thanks to Some programmer dude I got it working. I'll write it out here for clarity.
First I added all the .o files in the add_executable.
After that I added the language in the project command but it didn't work, still had the
CMake Error: CMake can not determine linker language for target: myProject
CMake Error: Cannot determine link language for target "myProject"
so I added set_target_properties. First the project name, then PROPERTIES then the thing I wanted to set: LINKER_LANGUAGE, then the language.
My file ended up looking like this:
cmake_minimum_required(VERSION 3.12)
project(myProject)
set(CMAKE_CXX_STANDARD 14)
add_executable(myProject
first.o
second.o
third.o
fourth.o)
set_target_properties(myProject PROPERTIES LINKER_LANGUAGE CXX )

Is it possible to alter CMAKE_MODULE_PATH from CMake commandline?

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.