Cmake refuses to find dbus-0 during compile - cmake

Hi im trying to get cmake to find dbus-1
I keep getting this error when i try to compile
-- Checking for module 'dbus-1'
-- No package 'dbus-1' found
Ive tried this command
pkg-config --cflags dbus-glib-1
I get the output
-I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include
I edited the CMakeLists.txt and added
include_directories(/usr/include/dbus-1.0/)
What am i doing wrong??

The first thing to know about CMake in this situation is don't use the include_directories to include any system directories with a hard-coded path(which is what you are doing now). What you should do instead is use the CMake FindPkgConfig module which will call pkg-config and get those include directories for you.
To do this, something like the following should work.
include( FindPkgConfig )
pkg_check_modules( dbus REQUIRED dbus-1 )
# Add the include directories to our target executable/shared object.
# In this case, our target is called 'executable' and must have been
# created by a previous call to either 'add_executable' or 'add_library'
target_include_directories( executable PUBLIC ${dbus_INCLUDE_DIRECTORIES} )

Related

Cmake and vcpkg - find the correct library name

I have troubles finding out the right "library target name" to be used in a cmake file, for packages installed using vcpkg.
In example, I installed the gtest package using vcpkg install gtest. My sample cmake file looks like:
#CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(example)
add_executable(main main.cpp)
find_package(gtest REQUIRED)
target_link_libraries(main gtest) # here, "gtest" is not the right name!
Running cmake, a solution for Visual Studio is generated, but after running cmake --build ., I get the error:
../use-cmake-vcpkg\main.cpp(1): fatal error C1083: Cannot open include file: 'gtest/gtest.h': No such file or directory ..
Turns out the line: target_link_libraries(main gtest) isn't correct, and I need to use another "name" to include/link the gtest package.
Is there a way (using cmake or vcpkg) to find out what is the correct target name to be used? (for gtest in this case, but also for any other pacakage?)
When use find_package(XXX), it can work in two modes: MODULE and CONFIG. And resulted variables and targets of this call depend on the mode.
If FindXXX.cmake file exists (and can be found), the MODULE mode is used and given file is processed. Otherwise, if the package is shipped with XXXConfig.cmake file, CONFIG mode is used and given file is processed. If none of this file exists, CMake emits an error (if called with REQUIRED keyword) or a warning (without REQUIRED keyword).
In case of gtest package, CMake is shipped with FindXXX.cmake script, so this script is processed in MODULE mode. You may find description of this script in the documentation, which tells that you need to use GTest::GTest target for link with gtest:
target_link_libraries(main GTest::GTest)
Not all packages provide a CMake library definition. If you're lucky, then vcpkg install will show you the name:
$ ./vcpkg install openssl
The package openssl is compatible with built-in CMake targets:
find_package(OpenSSL REQUIRED)
target_link_libraries(main PRIVATE OpenSSL::SSL OpenSSL::Crypto)
This will work even if you've already installed the package, so you can use it anytime to query the package name.
On the other hand, if vcpkg install <pkg> doesn't say anything about CMake, then you need to include it manually in your CMake file, by finding the include path and the library files.
Here is an example of such a case, here for the live555 library:
# Use one of the headers to locate the include location
find_path(LIVE555_INCLUDE_DIR liveMedia.hh)
# Find the libraries
find_library(LIVE555_LIBRARY1 liveMedia)
find_library(LIVE555_LIBRARY2 groupsock)
find_library(LIVE555_LIBRARY3 BasicUsageEnvironment)
find_library(LIVE555_LIBRARY4 UsageEnvironment)
add_executable(rtsp testRTSPClient.cpp)
target_include_directories(rtsp PRIVATE ${LIVE555_INCLUDE_DIR})
target_link_libraries(rtsp PRIVATE ${LIVE555_LIBRARY1} ${LIVE555_LIBRARY2} ${LIVE555_LIBRARY3} ${LIVE555_LIBRARY4})

How must I use cmake so that the "swig plugin" honors the include path

I am using cmake 3.8.1 with the FindSWIG und UseSWIG "extensions" for using swig as code generator. The "swig .i" file contains an include statement to a file in a different directory. The important part of my CMakeLists.txt looks like this:
...
find_package (TCL REQUIRED)
if (TCL_FOUND)
set (HAVE_TCL_H 1)
endif (TCL_FOUND)
find_package (SWIG )
if (SWIG_FOUND)
include(${SWIG_USE_FILE})
set (SWIG_FILE /home/steve/cmake_games/src/foo/bar/bar_swig.i)
set_property(SOURCE ${SWIG_FILE} PROPERTY CPLUSPLUS ON)
swig_add_library (bar_tclext LANGUAGE tcl SOURCES ${SWIG_FILE})
include_directories (/home/steve/cmake_games/src/foo/bar /home/steve/cmake_games/src/this/that)
set_target_properties(bar_tclext PROPERTIES LINKER_LANGUAGE CXX)
swig_link_libraries(bar_tclext ${TCL_LIBRARY})
endif (SWIG_FOUND)
cmake generates make files without a problem. Executing make however leads to the following error message
/home/steve/cmake_games/src/foo/bar/bar_swig.i:3: Error: Unable to find 'that.iih'
that.iih is located in /home/steve/cmake_games/src/this/that
Looking at the swig call in the generated Makefile I can see that swig is not called with an include path.
You might think that CMakeLists.txt with absolute paths is weird. True! This is the case due to the fact that the CMakeLists.txt are generated by scripts that take advantage of our conventions in directory topology and naming. We want keep enforcing this by generating the CMakeLists.txt as part of the "configure" process.
What do I need to change in the CMakeLists.txt?
you should try to setup CMAKE_SWIG_FLAGS in your case something like:
list(APPEND CMAKE_SWIG_FLAGS
"-I/home/steve/cmake_games/src/foo/bar"
"-I/home/steve/cmake_games/src/this/that")
e.g.: https://github.com/google/or-tools/blob/master/cmake/python.cmake#L57
ps: if you have compile definitions you should also pass them to SWIG by hand since you can't say to swig macro to get all the properties of an associated target.

Making a CMake library accessible by other CMake packages automatically

I have one project that produces a library:
project (myCoolLibrary)
ADD_LIBRARY(my_cool_library SHARED ${mysources_SRC})
And another project that should be using this library:
find_package (myCoolLibrary REQUIRED)
INCLUDE_DIRECTORIES("${myCoolLibrary_INCLUDE_DIRS}" )
add_executable(myCoolExe ${my_sources_SRC} )
TARGET_LINK_LIBRARIES(myCoolExe ${myCoolLibrary_LIBRARIES} )
Is there a way that I can change the first file so that the second file works automatically? That by running CMake on the first file and then running make on the output, then running CMake on the second file, CMake is able to find the package?
An answer where I just give the address of where the first project is built to the second package is also acceptable.
Taking the code found in a blog post by #daniperez - Use CMake-enabled libraries in your CMake project (III) - I've come up with the following minimal solution:
myCoolLibrary/CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(myCoolLibrary)
function(my_export_target _target _include_dir)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
"
include(\"\$\{CMAKE_CURRENT_LIST_DIR\}/${_target}Targets.cmake\")
set_property(
TARGET ${_target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES \"${_include_dir}\"
)
"
)
export(TARGETS ${_target} FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake")
# NOTE: The following call can pollute your PC's CMake package registry
# See comments/alternatives below
export(PACKAGE ${_target})
endfunction(my_export_target)
...
add_library(${PROJECT_NAME} SHARED ${mysources_SRC})
my_export_target(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}")
myCoolExe/CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(myCoolExe)
find_package(myCoolLibrary REQUIRED)
...
add_executable(${PROJECT_NAME} ${my_sources_SRC})
target_link_libraries(${PROJECT_NAME} myCoolLibrary)
To make it reusable I have packed everything into my_export_target(). And I'm friend of self-propagating properties like INTERFACE_INCLUDE_DIRECTORIES.
As commented by #ruslo, using export(PACKAGE ...) can pollute your package registry. So alternatively you can:
Write the target configuration files directly to some dedicated place specific for a certain toolchain
See e.g. How to install your custom CMake-Find module and 0003659: FIND_PACKAGE command improvements.
Set CMAKE_MODULE_PATH via the second project's CMake command line (injecting the search path(s) from the outside). If you are building the two projects anyway with a build script, then this is the most direct way to propagate the module search path(s).
Additional References
export()
CMake/Tutorials/Package Registry
Unable to find Eigen3 with CMake
How to instruct CMake to use the build architecture compiler

cmake try_compile: Using library found in configure

I am building a project with cmake. The project uses the external library plplot; I have configured cmake to the library and headers, and that is cached in variables ${PLPLOT_LIBRARY}, ${PLPLOT_LIB_PATH} and ${PLPLOT_INCLUDE_PATH}. In the plplot library a function has changed name: plwid -> plwidth and I want to detect that. I have written a small try_compile() test:
try_compile(HAVE_PLWID ${CMAKE_BINARY_DIR} cmake/tests/test_plwid.c)
However this test will always fail, because I have to pass header and library information to the try_compile process. Invoking gcc manually like this:
gcc -I${PLPLOT_INCLUDE_PATH} cmake/tests/test_plwid.c -L${PLPLOT_LIB_PATH} -l${PLPLOT_LIBRARY}
works. However I don understand how to pass the necessary flags to the try_compilecommand: I have tried:
try_compile(HAVE_PLWID ${CMAKE_BINARY_DIR} cmake/tests/test_plwid.c
INCLUDE_DIRECTORIES ${PLPLOT_INCLUDE_PATH}
LINK_DIRECTORIES ${PLPLOT_LIB_PATH}
LINK_LIBRARIES ${PLPLOT_LIBRARY})
Then I just get the cmake configure error:
Attempt at a recursive or nested TRY_COMPILE in directory
/path/to/build
I am quite confident the ${PLPLOT_XXX} variables are correct, at least the rest of the build works fine based on these variables.
Update: If I invoke cmakewith the --debug_trycompile command and go to the build/CMakeFiles/CMakeTmp directory and invoke cmakethere manually as:
cmake . -DINCLUDE_DIRECTORIES=/path/plplot/include -DLINK_DIRECTORIES=/path/to/plplot/lib -DLINK_LIBRARIES=plplotd
The test program will build and link correctly; so it seems the challenge is to pass these options correctly to the try_compile() cmake command invocation?
The LINK_DIRECTORIES and INCLUDE_DIRECTORIES cannot be passed as options to try_compile but have to passed as extra flags with the CMAKE_FLAGS option in the following way:
try_compile(HAVE_PLWID "${CMAKE_BINARY_DIR}/temp" "${CMAKE_SOURCE_DIR}/tests/test_plwid.c"
LINK_LIBRARIES ${PLPLOT_LIBRARY}
CMAKE_FLAGS
"-DINCLUDE_DIRECTORIES=${PLPLOT_INCLUDE_PATH}"
"-DLINK_DIRECTORIES=${PLPLOT_LIB_PATH}")

Find package Eigen3 for CMake

CMake cannot find my Eigen3 package. I set an environment variable called
EIGEN3_INCLUDE_DIR
pointing to the path where FindEigen3.cmake is.
Then in the CMakelists.txt I wrote:
find_package( Eigen3 REQUIRED )
include_directories( EIGEN3_INCLUDE_DIR )
I get next message of error:
CMake Error at C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:91 (MESSAGE):
Could NOT find Eigen3 (missing: EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
(Required is at least version "2.91.0")
Call Stack (most recent call first):
C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:252 (_FPHSA_FAILURE_MESSAGE)
C:/Program Files (x86)/CMake 2.8/share/cmake-2.8/Modules/FindEigen3.cmake:76 (find_package_handle_standard_args)
test/test_quaternion/CMakeLists.txt:25 (find_package)
Any idea on what I am missing or doing wrong?
Since Eigen3 is completely header only, all you ever need is the path to the include directory. And this one, you are already defining manually anyway. So there is no real need for a FindEigen3.cmake or FIND_PACKAGE call.
Simply use
INCLUDE_DIRECTORIES ( "$ENV{EIGEN3_INCLUDE_DIR}" )
or
SET( EIGEN3_INCLUDE_DIR "$ENV{EIGEN3_INCLUDE_DIR}" )
IF( NOT EIGEN3_INCLUDE_DIR )
MESSAGE( FATAL_ERROR "Please point the environment variable EIGEN3_INCLUDE_DIR to the include directory of your Eigen3 installation.")
ENDIF()
INCLUDE_DIRECTORIES ( "${EIGEN3_INCLUDE_DIR}" )
A few notes:
If you want to access the content of a CMake variable, make sure to use ${...}
$ENV{....} accesses environment variables.
The second example will stop with an error if the environment variable is not set (and, thus, EIGEN3_INCLUDE_DIR cmake variable is empty)
Be careful to use quotation marks around (evaluated) variables if they could contain whitespace. Otherwise, CMake will interpret it as a list.
If you want to use custom find modules, make sure to either place them in you CMake installation or, as #Fraser pointed out above, make sure to point CMAKE_MODULE_PATH to the directory where it is. Not sure, but it could be that CMake checks the current directory as well automatically (where your CMakeLists.txt resides. Anyhow, setting EIGEN3_INCLUDE_DIR is totally unrelated to the location of FindEigen3.cmake
However, it could be that your FindEigen3 script evaluates this variable to determine the location of your Eigen3 installation.
Alternatively, self-built CMake-based projects often provide a <PackageName>Config.cmake. If you point a variable called <PackageName>_DIR to the directory containing this file, you can use FIND_PACKAGE( <PackageName> ...) as normal. See documentation of FIND_PACKAGE for details.
Eigen >= 3.3 has direct CMake integration, so it seems yours isn't set up correctly.
Assume Eigen has been installed to /opt/eigen/3.3 with default settings. Append or prepend the the location /opt/eigen/3.3 to the environment variable CMAKE_PREFIX_PATH e.g in bash:
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH:/opt/eigen/3.3"
Then CMake should pick it up.
If you are writing your own CMakeLists.txt that uses Eigen I suggest using code like this:
find_package (Eigen3 3.3 REQUIRED)
add_executable (example example.cpp)
target_link_libraries (example Eigen3::Eigen)
You should not use include_directories since CMake 3 was released -- the targets approach should be preferred whenever available.
First, make sure Eigen is properly installed. Refer to the INSTALL file that comes with the tarball.
Second, copy the cmake/FindEigen3.cmake file from the tarball to the directory containing your CMakeLists.txt.
In your CMakeLists.txt add:
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})
Now you should be able to do e.g. #include <Eigen/Core>.
All of this comes (mostly) from this source.
This approach has the advantage over e.g. include_directories("$ENV{EIGEN3_INCLUDE_DIR}") that it the uses CMake's standard mechanism for finding external dependencies, making it easier for someone else (or your future self) to pick up the project, possibly on another platform.
(However, it would be nice if Eigen itself installed an EigenConfig.cmake file, making it accessible through the find_package mechanism without any extra paths.)
I found another solution here (which referred to here) which uses the pkg-config file :
find_package(PkgConfig)
pkg_search_module(Eigen3 REQUIRED eigen3)
As a detailed explanation of the note 7 from the top answer of Johannes. By using the "Config mode" rather than "Module mode" of CMake find_packate(), only writing
find_package( Eigen3 REQUIRED )
include_directories( EIGEN3_INCLUDE_DIR )
in CMakeLists.txt is enough.
Please refer to the INSTALL guidance text file contained in the eigen source code directory (eg. extracted from eigen-3.3.7.tar.gz downloaded from official website), which said:
Method 2. Installing using CMake
********************************
Let's call this directory 'source_dir' (where this INSTALL file is).
Before starting, create another directory which we will call 'build_dir'.
Do:
cd build_dir
cmake source_dir
make install
The "make install" step may require administrator privileges.
You can adjust the installation destination (the "prefix")
by passing the -DCMAKE_INSTALL_PREFIX=myprefix option to cmake, as is
explained in the message that cmake prints at the end.
Just like installing usual CMake projects to your machine.
The difference from directly including the /usr/include/eigne3 or /usr/local/include/eigen3 directory is that, a configuration directory called eigen3/cmake will also be installed to /usr/share or usr/local/share. This configuration directory contains the Eigen3Config.cmake file, which can automatically be found by CMake to locate the eigen3 directory.
If you have not added Eigen Library to environment variable then do the following in CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(ProjectName)
set(CMAKE_CXX_STANDARD 11)
# set EIGEN_DIR variable to Eigen Library Path
set(EIGEN_DIR "C:\\Eigendir\\Eigen")
# include the directory
include_directories(${EIGEN_DIR})
add_executable(ProjectName main.cpp)
target_link_libraries(ProjectName ${EIGEN_DIR})
Another simple way that doesn't require adding an environment variable is to simply find eigen with the cmake find_path function https://cmake.org/cmake/help/v3.6/command/find_path.html. The example code finds the directory "Eigen" in paths "/usr/include/" and "/usr/local/include" with an additional search in subdirectory "eigen3".
find_path(EIGEN3_INCLUDE_DIRS "Eigen" paths "/usr/include" "/usr/local/include" path_suffixes "eigen3")
message(${EIGEN3_INCLUDE_DIRS})
if ( NOT EIGEN3_INCLUDE_DIRS )
message(FATAL_ERROR "CMake variable EIGEN3_INCLUDE_DIRS not found.")
endif()
include_directories ( "${EIGEN3_INCLUDE_DIRS}" )
You could try setting the CMAKE_MODULE_PATH to the location of Eigen subdirectory named "cmake":
cmake . -DCMAKE_MODULE_PATH=<Eigen root dir>/cmake/
I had a similar problem when run cmake .. && make on Google Colab on a project clone from github. I fixed it by editing CMakeLists.txt file and adding this line to it:
set(EIGEN3_INCLUDE_DIR "/usr/include/eigen3")
As you can see, my eigen3 was in /usr/include/eigen3 path (and I had installed it using !sudo apt-get install build-essential cmake libeigen3-dev)
When installing on Kubuntu 20.04 following steps from INSTALL:
Do:
cd build_dir
cmake source_dir
make install
using -DCMAKE_INSTALL_PREFIX=/usr/local/eigen-3.4.0 and sudo
FindEigen3.cmake is not installed. However, using
set(Eigen3_DIR "/usr/local/eigen/share/eigen3/cmake")
seem to work. FindEigen3.cmake is in the build directory
but it is not copied to the installation directory tree.
This worked:
Changed c++11 to c++14
Changed find_package(Eigen3 QUIET) to find_package(Eigen3 CONFIG)
Another simple way is:
if the Eigen library is in /opt/eigen/3.3/Eigen
include_directories(/opt/eigen/3.3)
which is equivalent to what Jai suggested
set(EIGEN_DIR "/opt/eigen/3.3")
include_directories(${EIGEN_DIR})
You need to read official documentation:
Click here
After install Eigen from tar and compile it correctly.
CMakeLists.txt will looks like this:
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
add_executable(${PROJECT_NAME} something.cpp)
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen)
It will be fine work.