I'm compiling libdwarf on Windows. In its root CMakeLists.txt, it attempts to find LibElf via:
find_package(LibElf REQUIRED)
LibElf doesn't use CMAKE and I haven't configured it to register itself in any way, so of course the find_package fails. I'd like CMake to print out all the paths under which it is searching for LibElf at runtime. How do I tell CMake to output this? I've tried --trace but that just show me the execution flow through my CMakeLists.txt files--not the locations where CMake itself is presently looking for packages.
I know the documentation for find_package describes where CMake searches, but I can modify that behavior with all sorts of variables, environment variables, and registry settings. I'd like to see where exactly CMake is looking given all my modifications to those items I just mentioned.
I should note that libdwarf includes a cmake/FindLibElf.cmake module. Perhaps what I'm asking for isn't possible if FindLibElf.cmake is free to do whatever it pleases?
Since version 3.17 CMake provides the option --debug-find, which results in output of a ton of debug information about search process of find_package and other find_* commands:
cmake --debug-find <...>
The similar effect could be achieved by setting the variable CMAKE_FIND_DEBUG_MODE.
One may set the variable either in the command line:
cmake -DCMAKE_FIND_DEBUG_MODE=1 <...>
or in the CMakeLists.txt:
set(CMAKE_FIND_DEBUG_MODE 1)
Related
When linking a binary I can use CMAKE_EXE_LINKER_FLAGS to add a flag (let's say -Wl,-as-needed). However, if I link a library this extra flag will not be taken into account. I would need something like CMAKE_LIB_LINKER_FLAGS but I can't find it.
How should I do this?
Note: modern CMake has a better solution than mentioned below (see updates for details).
You can use CMAKE_SHARED_LINKER_FLAGS like:
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
This question looks like related.
UPD
Thanks to #Bruce Adams who points out that since v3.13 CMake has special command for such purpose: add_link_options.
UPD 2
Thanks to #Alex Reinking who points out that modern CMake doesn't recommend using global settings. It is suggested to give the preference to the property settings before the global ones, so instead of add_link_options that has a global scope, the target_link_options should be used. See Alex's answer for details.
This is how you add linker flags to a target in modern CMake (3.13+):
# my_tgt can be an executable, library, or module.
target_link_options(my_tgt PRIVATE "LINKER:-as-needed")
Note that CMake always passes flags to the configured compiler. Thus, to forward your intended link flags to the linker, you must use the LINKER: prefix. CMake will take care of expanding it to -Wl,-as-needed on GCC, and to -Xlinker -as-needed on Clang.
See the documentation here: https://cmake.org/cmake/help/latest/command/target_link_options.html
It looks like this problem is related to the one I had in CLION. I solved it by adding
{set(CMAKE_CXX_STANDARD_LIBRARIES -ljpeg)}
to CMakeLists.txt.
In CMake 3.10.2, the suggested answer of
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
did not work for me. The workaround I employed was to use set_target_properties instead.
My CMakeLists.txt file had a line of this sort:
add_library(libraryname MODULE a.cc b.cc c.cc)
After that line, I added this:
set_target_properties(libraryname PROPERTIES LINK_FLAGS "-Wl,-znodelete")
Check out the ucm_add_linker_flags macro of ucm - it deals with appending linker flags to the appropriate CMake variables.
Note that you need to add your linker option without the "-Wl,", namely:
Good:
-DCMAKE_SHARED_LINKER_FLAGS="-fstack-protector"
Wrong:
-DCMAKE_SHARED_LINKER_FLAGS="-Wl,-fstack-protector"
target_link_libraries(target-name PRIVATE -lexpat)
i used this for linking the XML dependencies in my project. replace -lexpat with -l(library name)
We have an HPC environment with multiple versions of most packages, causing us to have designed a home-rolled way to install packages in unique locations and use environment modules for programmers/researchers to be able to identify which library versions they are using when they build a program, run a program, or both. Is there a relatively painless way to be able to perform builds in this environment. In my case, we're using OpenBLAS, ARPACK, LAPACK and SuperLU when building armadillo. In my case, I'm shooting for armadillo-0.3.7. It would be real nice if the use of switches as was done in the ./configure and make days would work. But all I've found so far is CMake builds, and it appears to be pretty much non-trivial to do a build.
Oh yeah. And, by the way, there's a need for the output Armadillo library to be static.
Thanks in advance for your help. The initial question may be a little vague, but I can get as specific as you like. I just didn't want to write a novel for the initial question on this issue.
Tools exist nowadays to handle the complexity of the build of these scientific software. I would suggest you look at either Spack or EasyBuild. Such tool will help you to save a lot of time by automatically building all the required dependencies and also generating the modulefiles for your users to use the software built.
The CMakeList.txt file and other CMake-related files can be modified to meet your needs. The flags are defined on line 48+, for instance set(ARMA_USE_LAPACK false)
The variables related to the LAPACK library are then defined in the include(ARMA_FindLAPACK) on line 250. The flag in toggled on on line 347 if lapack is found.
The customized path where LAPACK is located can be specified in the file cmake_aux/ARMA_FindLAPACK.cmake. If your customized path is stored as an environment variable as export PATHLAPACKLIB=/usr/lib/openblas-base, you can use it in the ARMA_FindLAPACK.cmake file by modifying line 11 ( see How to retrieve a user environment variable in CMake (Windows) and FIND_LIBRARY()):
message("Searching Lapack in $ENV{PATHLAPACKLIB}")
FIND_LIBRARY(LAPACK_LIBRARY
NAMES ${LAPACK_NAMES}
HINTS $ENV{PATHLAPACKLIB}
NO_DEFAULT_PATH
)
It is not a beautiful modification of the CMakefile, because it makes it not portable as its outcome depends on an environment variable. But, it you intend to to build and install Armadillo once for all, it works. Remember to delete the CMakeCache.txt file every time you modify a CMakeFile.txt, otherwise it keeps some trace of previous runs of cmake . and it looks as though the modification is consequenceless.
To make the library static, add the keyword static to the command add_library() on line 514 of CMakeFile.txt, as shown in CMake - Creating a static library :
add_library( armadillo STATIC ...)
Running cmake . and then make creates a small armadillo.a file, since most of the source consists in cpp headers.
Finally, the exemple1 is compiled as :
g++ -O2 -std=c++11 example1.cpp -o example1 -larmadillo -L/home/...../softs/armadillo-9.800.3/armadillo-9.800.3 -I/home/...../softs/armadillo-9.800.3/armadillo-9.800.3/include -lopenblas
I have a cmake project that is building, but at runtime (for ex, when running my unit tests executable) it is not able to link one of my dylib dependencies. Looking at the output of "otool -L" I see a long list of deps prefixed with #rpath except for one offending set of libs (which all came from same package) that do not have that. Here is a representative example, where the offenders are the libicu* libs:
#rpath/libboost_date_time.dylib ...
libicui18n.44.dylib ...
libicuio.44.dylib ...
#rpath/libQt5DBus_debug.5.dylib ...
Is there anything I can do at build time to get that #rpath prefix on those deps? Looking at the cmake RPATH docs it sounds to me like the RPATH can be set, but by default it will be correct, including all linked lib paths... it isn't clear to me how to make sure the libs themselves use the rpath. Is there anything I can do at build time to make sure that the #rpath prefix is on the dep name?
CMake has some special magic since version 2.8.12 which got additional settings later on and quickliy established as a default.
The proprty MACOSX_RPATH is used on targets to initialize rpath correctly on OSX.
The Policy CMP0042 controls if this is defautl behavior or not.
https://cmake.org/cmake/help/v3.0/prop_tgt/MACOSX_RPATH.html#prop_tgt:MACOSX_RPATH
https://cmake.org/cmake/help/v3.0/policy/CMP0042.html
I try to build a CMake-based software under OS X (Yosemite) which can be built successfully under Fedora 21. It uses a bunch of libraries. Both, big open ones like Boost and some self-written ones lying in /installation_folder/lib. I use CMake version 3.3.0.
After executing
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=/usr/local/Cellar/gcc/5.2.0/bin/gcc-5 -DCMAKE_CXX_COMPILER=/usr/local/Cellar/gcc/5.2.0/bin/g++-5 -DCMAKE_MODULE_PATH=${PWD}/../external/install/share/llvm/cmake
I get the following warnings:
CMake Warning (dev):
Policy CMP0042 is not set: MACOSX_RPATH is enabled by default. Run "cmake
--help-policy CMP0042" for policy details. Use the cmake_policy command to
set the policy and suppress this warning.
MACOSX_RPATH is not specified for the following targets:
ClangWrapper
Structure
WCETXML
This warning is for project developers. Use -Wno-dev to suppress it.
The CMakeLists.txt contains the following lines regarding RPATH:
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
ENDIF("${isSystemDir}" STREQUAL "-1")
All I can say is that ${CMAKE_INSTALL_PREFIX}/lib is indeed the correct path, and that other libraries like Boost are found correctly.
Ignoring the warnings and continuing with "make" in the build directory results in a linking error.
I read the CMake Wiki RPATH handling article, but I am still not able to distinguish between these path variables and their correct use on OS X.
Adding set(CMAKE_MACOSX_RPATH 1) into CMakeLists.txt, before the above written statements, lets the warnings disappear. The linking problem after executing make stays. This brings me to the assumption that my RPATH setup has nothing to do with my linking problem.
Nevertheless, this thread's problem is solved. An explanation about the correct use of the RPATH options inside CMakeLists.txt is still very welcome!
Well, I'll just go one step forward from #fotinsky's answer. (Feel free to incorporate this into your answer.)
The output of the warning's suggestion to run cmake-policy --help-policy CMP0042 is:
CMake 2.8.12 and newer has support for using ``#rpath`` in a target's install
name. This was enabled by setting the target property
``MACOSX_RPATH``. The ``#rpath`` in an install name is a more
flexible and powerful mechanism than ``#executable_path`` or ``#loader_path``
for locating shared libraries.
CMake 3.0 and later prefer this property to be ON by default. Projects
wanting ``#rpath`` in a target's install name may remove any setting of
the ``INSTALL_NAME_DIR`` and ``CMAKE_INSTALL_NAME_DIR``
variables.
This policy was introduced in CMake version 3.0. CMake version
3.1.3 warns when the policy is not set and uses OLD behavior. Use
the cmake_policy command to set it to OLD or NEW explicitly.
This simply means that in later cmake versions, the user is required to explicitly enable or disable CMAKE_MACOSX_RPATH.
There's also more background info on the introduction of this variable in this CMake blog entry.
As mentioned in a comment above, if you don't need to target older versions of cmake, you can simply set:
cmake_minimum_required (VERSION 3.0)
This removes the ambiguity of default values between major versions and simply enables runtime path behaviors by default.
I'm trying to configure a project using CMake, but it fails to find Boost libraries even though they are in the specified folder. I have specified Boost_INCLUDE_DIR, Boost_LIBRARYDIR and BOOST_ROOT , but I still get an error saying that CMake is not able to find Boost. What could be the reason of such error?
Are you sure you are doing it the correct way? The idea is that CMake sets BOOST_INCLUDE_DIR, BOOST_LIBRARYDIR and BOOST_ROOT automatically. Do something like this in CMakeLists.txt:
FIND_PACKAGE(Boost)
IF (Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
ADD_DEFINITIONS( "-DHAS_BOOST" )
ENDIF()
If boost is not installed in a default location and can, thus, not be found by CMake, you can tell CMake where to look for boost like this:
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "C:/win32libs/boost")
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "C:/win32libs/boost/lib")
Of course, those two lines have to be before the FIND_PACKAGE(Boost) in CMakeLists.txt.
There is more help available by reading the FindBoost.cmake file itself. It is located in your 'Modules' directory.
A good start is to set(Boost_DEBUG 1) - this will spit out a good deal of information about where boost is looking, what it's looking for, and may help explain why it can't find it.
It can also help you to figure out if it is picking up on your BOOST_ROOT properly.
FindBoost.cmake also sometimes has problems if the exact version of boost is not listed in the Available Versions variables. You can find more about this by reading FindBoost.cmake.
Lastly, FindBoost.cmake has had some bugs in the past. One thing you might try is to take a newer version of FindBoost.cmake out of the latest version of CMake, and stick it into your project folder alongside CMakeLists.txt - then even if you have an old version of boost, it will use the new version of FindBoost.cmake that is in your project's folder.
Good luck.
For me this error was simply because boost wasn't installed so on ubuntu:
sudo apt install build-essential libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev
I struggled with this problem for a while myself. It turned out that cmake was looking for Boost library files using Boost's naming convention, in which the library name is a function of the compiler version used to build it. Our Boost libraries were built using GCC 4.9.1, and that compiler version was in fact present on our system; however, GCC 4.4.7 also happened to be installed. As it happens, cmake's FindBoost.cmake script was auto-detecting the GCC 4.4.7 installation instead of the GCC 4.9.1 one, and thus was looking for Boost library files with "gcc44" in the file names, rather than "gcc49".
The simple fix was to force cmake to assume that GCC 4.9 was present, by setting Boost_COMPILER to "-gcc49" in CMakeLists.txt. With this change, FindBoost.cmake looked for, and found, my Boost library files.
You can also specify the version of Boost that you would like CMake to use by passing -DBOOST_INCLUDEDIR or -DBOOST_ROOT pointing to the location of correct version boost headers
Example:
cmake -DBOOST_ROOT=/opt/latestboost
This will also be useful when multiple boost versions are on the same system.
I also had a similar problem and discovered that the BOOST_INCLUDE_DIR, BOOST_LIBRARYDIR and BOOST_ROOT env variables must hold absolute paths.
HTH!
In my case Boost was not installed. I used below command on Mac and then cmake find_package(Boost) works like a charm
brew install Boost
Please note upper case 'B' in Boost!
If you are building your own boost do not forget to use the --layout=versioned otherwise the search for a particular version of library will fail
For cmake version 3.1.0-rc2 to pick up boost 1.57 specify -D_boost_TEST_VERSIONS=1.57
cmake version 3.1.0-rc2 defaults to boost<=1.56.0 as is seen using -DBoost_DEBUG=ON
cmake -D_boost_TEST_VERSIONS=1.57 -DBoost_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
One more bit of advice for anyone trying to build CGAL in particular, with statically linked Boost. It is not enough to define Boost_USE_STATIC_LIBS; it gets overridden by the time Boost_DEBUG outputs its value. The thing to do here is to check the "Advanced" checkbox and to enable CGAL_Boost_USE_STATIC_LIBS.
I had the same problem while trying to run make for a project after installing Boost version 1.66.0 on Ubuntu Trusty64. The error message was similar to (not exactly like) this one:
CMake Error at
/usr/local/Cellar/cmake/3.3.2/share/cmake/Modules/FindBoost.cmake:1245 (message):
Unable to find the requested Boost libraries.
Boost version: 0.0.0
Boost include path: /usr/include
Detected version of Boost is too old. Requested version was 1.36 (or newer).
Call Stack (most recent call first):
CMakeLists.txt:10 (FIND_PACKAGE)
Boost was definitely installed, but CMake couldn't detect it. After spending plenty of time tinkering with paths and environmental variables, I eventually ended up checking cmake itself for options and found the following:
--check-system-vars = Find problems with variable usage in system files
So I ran the following in the directory at issue:
sudo cmake --check-system-vars
which returned:
Also check system files when warning about unused and uninitialized variables.
-- Boost version: 1.66.0
-- Found the following Boost libraries:
-- system
-- filesystem
-- thread
-- date_time
-- chrono
-- regex
-- serialization
-- program_options
-- Found Git: /usr/bin/git
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/myproject
and resolved the issue.
See FindBoost.cmake first. The variables you set are the correct ones but they should be all uppercase.
Make sure the library architecture matches with CMake configuration.
cmake -A x64 ..
I suggest creating a minimal executable which only includes a Boost library to see if it compiles.
#include <iostream>
#include <boost/date_time.hpp>
int main() {
using namespace std;
using namespace boost::gregorian;
date today = day_clock::local_day();
cout << today << endl;
}
find_package(Boost REQUIRED COMPONENTS
date_time
)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIRS})
add_executable(test_boost "test_boost.cpp")
target_link_libraries(test_boost Boost::date_time)
Start debugging by checking Boost_FOUND first.
message(STATUS "Boost_FOUND: ${Boost_FOUND}")
The version should be found even if no libraries are found. (Boost_VERSION)
If Boost_LIBRARY_DIRS becomes non-empty, it should compile.
I had the same problem, and none of the above solutions worked. Actually, the file include/boost/version.hpp could not be read (by the cmake script launched by jenkins).
I had to manually change the permission of the (boost) library (even though jenkins belongs to the group, but that is another problem linked to jenkins that I could not figure out):
chmod o+wx ${BOOST_ROOT} -R # allow reading/execution on the whole library
#chmod g+wx ${BOOST_ROOT} -R # this did not suffice, strangely, but it is another story I guess
This can also happen if CMAKE_FIND_ROOT_PATH is set as different from BOOST_ROOT.
I faced the same issue that in spite of setting BOOST_ROOT, I was getting the error.
But for cross compiling for ARM I was using Toolchain-android.cmake in which I had (for some reason):
set(BOOST_ROOT "/home/.../boost")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${SYSROOT}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --sysroot=${SYSROOT} -I${SYSROOT}/include/libcxx")
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
set(CMAKE_FIND_ROOT_PATH "${SYSROOT}")
CMAKE_FIND_ROOT_PATH seems to be overriding BOOST_ROOT which was causing the issue.
For those using python3.7 docker image, this solved:
apt install libboost-system-dev libboost-thread-dev
Maybe
brew install boost
will help you.