CMake install dependencies - cmake

I currently want to create an installer with cmake, but don't add all necessary DLLs by myself to CMakeLists.txt. So one solution should be to use fixup_bundle, like here suggested, so hopefully he copy all DLLs, which he can detect with a dependency walker and are on path.
But currently I have no idea how is best way to use it on a target, following code won't work, because he don't resolve TARGET_FILE_DIR like if you are using add_custom_command. Do read location via get_property won't work too, because he don't know the target anymore at time of execution. Any idea?
INSTALL(CODE "
include(BundleUtilities)
fixup_bundle($<TARGET_FILE_DIR:${PROJECT_NAME}> \"\" \"D:\\Qt\")
" COMPONENT Runtime
)

If you are using Qt4, rather than using BundleUtilities directly, you may be better off using the DeployQt4 module. It includes the following three commands which may do what you need:
install_qt4_plugin_path
install_qt4_plugin
install_qt4_executable
If you are using Qt5, it gets a bit trickier. If you are only interested in Windows and/or Mac, then Qt itself provides an appropriate tool for handling/bringing across Qt's dependencies. The relevant tools are called windeployqt and macdeployqt respectively. Sadly, at time of writing, there is no linuxdeployqt tool yet that I'm aware of.
If neither of the above options are open to you or don't do what you need, then at least the DeployQt4 module gives some clues as to how you may be able to use the INSTALL(...) command like you attempted to. The DeployQt4 module uses the following for defining its target (see right near the end of the DeployQt4.cmake file):
FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")"
${component}
)
The stuff in front of ${executable} is probably the bit you were missing. In your case, without seeing your full CMakeLists.txt file, I can only assume that you have a single target and it has the same name as your project (since you used ${PROJECT_NAME} in your attempted generator expression). You could try something like the following (not tested):
INSTALL(CODE "
include(BundleUtilities)
fixup_bundle(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${MyTarget}\" \"\" \"D:\\Qt\")
" COMPONENT Runtime
)
where MyTarget is the name of the executable for your target (I think without any .exe suffix if you are on Windows). The DESTDIR part is needed when making packages, since CMake will redirect the install location by setting the DESTDIR environment variable (at least with some CMake generators). The CMAKE_INSTALL_PREFIX part is the path under which the application would be installed. There is some history behind this, but the above reflects the correct way of how to refer to the installed executable.

Related

How to set RPATH in CMAKE?

I wish to build and install a software locally to the $HOME/.local/ path instead of a system-wide /usr/ folder. The software uses CMAKE for compilation.
After installation, the software binaries and libraries get stored in $HOME/.local/bin/ and $HOME/.local/lib/, respectively. However, when I try to run the program, it throws an error that the required library is not found (which, by the way, is present in $HOME/.local/lib/).
The program works fine if I set the $LD_LIBRARY_PATH to $HOME/.local/lib. But I don't want to do this. Hence, instead of this, I would like to know how to specify the RPATH variable (which would point to $HOME/.local/lib) while compiling the software using CMAKE.
Kindly help.
I am using the following two lines in the CMakefile
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
(the first one is required only if you use MacOSX)
you may also use:
set(CMAKE_BUILD_RPATH "/my/libs/location")
specifying runtime path (RPATH) entries to add to binaries linked in the build tree (for platforms that support it). The entries will not be used for binaries in the install tree. See also the CMAKE_INSTALL_RPATH variable.
CMAKE_INSTALL_RPATH is a predefined list, so I can see scenarios where it would be better to do
list( APPEND CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib )
If you include( GNUInstallDirs ) you could also
list( APPEND CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_LIBDIR} )
I am a CMake novice though, so if someone sees an issue with the above please let me know.

CMAKE_SYSROOT in CMakeTestCCompiler

I have a project which builds for PPC, the Toolchain is working correctly, i can build when the sysroot is installed under /opt/poky/1.5. Now i tried to move that Installation to the Project Directory (it is not a part of the Repository there, it is just installed there so it is not reliant on that fix path, so that everyone can check out the project and build it wothout setting up the sysroot under that fixed folder).
To achieve this I set CMAKE_SYSROOT to "${PROJECT_SOURCE_DIR}/poky" where the poky will be installed upon execution of a custom build script (the project also needs to build a secure image, so it is way simpler to use a build script instead of anything else, also this is convenient for jenkins).
Since the CMAKE_SYSROOT is build from the PROJECT_SOURCE_DIR which is different for the CMakeTestCCompiler Project, the cmake call fails teloling me that the CCompiler is broken of course. So I want to know, how I am supposed to get the CMakeTestCCompiler Project to compile with the same CMAKE_SYSROOT variable, without altering the CMakeTestCCompiler Project itself (of course).
Somehow I cannot find an answer anywhere, it seems that noone ever had this issue (which frankly i cannot understand, this should be a common setup in my opinion). (Or maybe i am just too much of a noob when it comes to CMAKE, which i will gladly admit)
I am not interested in solutions like: "JUST INSTALL IT IN A FIX PATH" or such... please, I need the setup like this, I have reasons for that.
THX for reading/trying/answering/helping
Have a nice day
EDIT1:
In CMakeLists.txt (top level CMakeFile so it should be used by any build):
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
In ToolchainCMake (the one given to the cmake as CMAKE_TOOLCHAIN_FILE):
`SET(CMAKE_SYSTEM_NAME Linux)`
`SET(CMAKE_SYSTEM_VERSION 1)`
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
`SET(COMPILER_ROOT ${PROJECT_SOURCE_DIR}/poky/sysroots/i686-pokysdk-linux/usr/bin/powerpc-poky-linux-gnuspe)`
`SET(CMAKE_C_COMPILER ${COMPILER_ROOT}/powerpc-poky-linux-gnuspe-gcc)`
`SET(CMAKE_CXX_COMPILER ${COMPILER_ROOT}/powerpc-poky-linux-gnuspe-g++)`
`MESSAGE("CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")`
`MESSAGE("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}")`
`MESSAGE("COMPILER_ROOT: ${COMPILER_ROOT}")`
`SET(CMAKE_FIND_ROOT_PATH ${SYS_ROOT}/ppce500v2-poky-linux-gnuspe)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)`
EDIT2:
I used the
`set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")`
`set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")`
settings to simulate the CMakeTestCCompiler build succeeding and realized that I am facing some additional problems: It seem that the packages are looked up on the system instead of the CMAKE_SYSROOT folder. Even tried the
`SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})`
to try to force the search in there, but without luck. In the CMakeError.log I can see, that the compiler itself was configured with the prefix option that points to /opt/poky/1.5, the path that i want to "overwrite", now I am not sure if the compiler could even deal with an alternate path.
I felt the need to add these information, they not really add to the problem at hand.
ERRORS:
I also found some errors in the above cmake:
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
must be
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots/ppce500v2-poky-linux-gnuspe")`
instead and therefor the
`SET(CMAKE_FIND_ROOT_PATH ${SYS_ROOT}/ppce500v2-poky-linux-gnuspe)`
changes to
`SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})`
EDIT: Whole answer changed.
My first suspicion was that the problem is that value of ${PROJECT_SOURCE_DIR} is not known in CMAKE_TOOLCHAIN_FILE as it is processed before CMakeLists.txt. But this isn't true.
I had similar problem (CMake 2.8.12.2), everything worked OK, when I passed cross compiler by CC environment variable with --sysroot option, i.e. CMake was invoked as follows:
CC="arm-linux-gnueabi-gcc --sysroot=/path/to/sysroot" cmake /path/to/sources
When I switched to using toolchain file, CMake started to report that C compiler doesn't work.
To workaround this problem, I use CMakeForceCompiler package. Parts toolchain file (along with comments) I think are relevant:
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# Force compiler - only option that actually works
cmake_force_c_compiler (${TOOLCHAIN_PATH}/bin/arm-linux-gnueabi-gcc GNU)
cmake_force_cxx_compiler(${TOOLCHAIN_PATH}/bin/arm-linux-gnueabi-g++ GNU)
# NOTE: CMAKE_SYSROOT doesn't work as expected
add_definitions("--sysroot=${TOOLCHAIN_SYSROOT}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${TOOLCHAIN_SYSROOT}" CACHE INTERNAL "" FORCE)
Note, that TOOLCHAIN_PATH and TOOLCHAIN_SYSROOT are my local variables set before.

What is the default search path for find_package in windows using cmake?

I am porting some code over to windows and my cmake checks for the package Libavahi using
find_package(Libavahi)
I have the headers, dll, etc. but I'm not sure where to place these such that cmake will find them.
Where can I put these files to be found by cmake? They're in a folder called usr.
I see that the module path is specified using:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
but I'm wondering if there is a default location that will be searched as well
The CMake manual fully specifies the rather complicated search order for the different find_* commands. Unfortunately, since Windows lacks a default directory structure à la /usr/local/lib, it is hard to come up with reasonable defaults here.
One of the most reliable ways of managing directories is through environment variable hints. You simply add an $ENV{MY_VAR} to the HINTS section of the find command and then document that environment variable in your project's readme. Most users that are capable of compiling a C++ program know how to use environment variables, and it is way more convenient than having to give the path on the command line every time (although it never hurts to leave that as an additional option).
For find_package CMake offers a special mechanism on Windows called the package registry. CMake maintains a list of package information in the Windows registry under HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\. Packages build from source can register there using the export command. Other projects build later on the same machine will then be able to find that package without additional configuration. This is quite powerful if you need to build a lot of interdependent projects from source on the same machine.
Update: Starting with version 3.12, CMake now implicitly considers the <PackageName>_Root environment variable a HINT for every find_package call.
In the newer versions of cmake, you can use the --debug-find option to list the directories that cmake is searching through. Somethin like:
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TOOLS=ON --debug-find .

Package & library management & installation, and interface with cmake

I have a specific question which serves as context for a more general question.
There is a scientific package called LAMMPS, and it is usually used as an executable. However, it supports use as a "library". To try to do things right, I put it in /usr/local/lib/lammps. It contains a lammps/src/ directory, which has around 40 source files. Using the instructions provided, I compiled lammps as a .so file in lammps/src/liblammps_serial.so.
I also have separate code in "~/code/ljtube/". This uses cmake to try to find the library. Thus, I wrote a FindLAMMPS.txt so that I could use
FIND_PACKAGE (lammps)
in my CMakeLists. I modified the libtool config file to search in /usr/local/ successfully. I found that it searches in /usr/local/lib/ for a .so file and in /usr/local/include/ for a .h file. So I made a dynamic link to the .so file in /usr/local/lib/, and I copied the .h file from the lammps/src/ to /usr/local/include/.
CMake can now find those two files, but it cannot link to anything else in lammps/src/. It seems absurd to need to make a separate FIND_PACKAGE for each of the .h's I want to include (group.h, fix.h, force.h, pair.h, etc.). It also seems ridiculous to dump the whole package of .h files into the /usr/local/include/ directory. I will be using this code both locally and on a cluster, and possibly distributing it to other group members.
How can I make CMake find what I want to find without hard coding in the location of /usr/local/lib/lammps/src/? Phrased more generically, how should I manage large packages like these to make them easy to link to in the code I write, even if the original developer did not use the best conventions?
(As a side note, I am using a shared library because it seems like the right choice, but I'm not especially married to it. Should I be using a static library? Is there a way for CMake to find an already-compiled library relative to the current source directory, and might that be a better way to implement this? I know that I will be using LAMMPS in multiple projects, so having a local shared copy superficially seems to make the most sense.)
Normally a find_package call yields a variable specifying the path to the "includes" folder of the package. This would then be added in the caller's CMakeLists.txt via include_directories.
For example, to use find_package for boost, you could do:
find_package(Boost) # sets ${Boost_INCLUDE_DIRS} and ${Boost_LIBRARIES}
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(foo foo.cc)
target_link_libraries(foo ${Boost_LIBRARIES})
endif()
Regarding your side note, you could use find_library and/or find_path to find the library and its headers given a known location.
Both these commands can be invoked in such a way as to avoid searching in common locations, e.g. by setting PATHS to the known location and using NO_DEFAULT_PATH in the find commands.
Another alternative is for your projects to make use of the ExternalProject_Add function which is described in more detail in this article. From this article:
The ExternalProject_Add function makes it possible to say “download this project from the internet, run its configure step, build it and install it”
A downside to this approach is that each of your projects would end up with its own copy of the third party sources and lib.

Is there any interactive shell for module development in cmake?

CMake is awesome, especially with lots of modules (FindOOXX). However, when it comes to write a FindXXX module, a library XXX which your project depends, it's not that easy to handle for non-cmake-expert. I sometimes encounter a library without support to CMake, and I like to make one for it. I'm wondering if there is any interactive shell while writing/testing cmake modules?
Are you writing FindXXX for project "XXX" or is "XXX" a dependency of your project that you're trying to find? If the former, you should instead write a file called XXX-config.cmake (or XXXConfig.cmake) and install it into one of the directories mentioned in the docs for find_package. In general, XXX-config.cmake files are for projects which are expected to be found by CMake (and installed by the project itself) and FindXXX.cmake files are for projects which don't support CMake (and usually have to support finding any version of XXX).
That said, for FindXXX.cmake, usually you just need a few find_file (e.g., for headers), some find_library calls, or even just a single pkg_check_module from FindPkgConfig.cmake followed by a find_package_handle_standard_args call (use include(FindPackageHandleStandardArgs) to get it). FPHSA makes writing proper Find modules a breeze.
For XXX-config.cmake files, I have typically used configure_file to generate two versions: one for the install (which includes your install(EXPORT) file) and one for the build tree (generated by export() calls). Using this, other useful variables can be accurately set such as things like "which exact version of Boost was used" or "was Python support compiled in" so that dependent projects can get a better picture of what the dependency looks like.
I have also recently discovered that CMake ships with the CMakePackageConfigHelpers module which is supposed to help with making these files. There looks to be quite a bit of documentation for it.