I issue the following commands:
find_file(MATLAB_ROOT matlab $ENV{ProgramW6432})
set(MATLAB_LIBS_DIRECTORY ${MATLAB_ROOT}/extern/lib/win64/microsoft)
find_library(MATLAB_MEX_LIB mex
${MATLAB_LIBS_DIRECTORY}
)
But it fails with MATLAB_MEX_LIB-NOTFOUND. My path seems correct I can easily retrieve the library file with the following command:
find_file(LIB_FILE libmex.lib ${MATLAB_LIBS_DIRECTORY})
I'm working in Windows 7 with cmake version 2.8.9
I found the problem. I used --trace option in cmake and saw that there are missing suffixes for the find_library command:
SET(CMAKE_FIND_LIBRARY_PREFIXES lib )
SET(CMAKE_FIND_LIBRARY_SUFFIXES .dll.a .a )
So I changed the path to:
set(MATLAB_LIBS_DIRECTORY ${MATLAB_ROOT}/bin/win64)
And invoked the following commands:
set(CMAKE_FIND_LIBRARY_SUFFIXES .dll .dll.a .a)
find_library(MATLAB_MEX_LIB mex
PATHS ${MATLAB_LIBS_DIRECTORY}
NO_DEFAULT_PATH
)
This time all went fine. Thanks for the support Fraser!
When you do find_library, the search prepends ${CMAKE_STATIC_LIBRARY_PREFIX} to each of the provided names (and also appends ${CMAKE_STATIC_LIBRARY_SUFFIX}).
On Windows, ${CMAKE_STATIC_LIBRARY_PREFIX} is empty; on Unix it is "lib", so you'll need to prepend the "lib" to your search name for Windows only. You can cover both cases by using the long-hand version of find_library:
find_library(MATLAB_MEX_LIB
NAMES mex libmex
PATHS ${MATLAB_LIBS_DIRECTORY}
NO_DEFAULT_PATH # Avoid searching outside MATLAB_LIBS_DIRECTORY
)
Related
I'm trying to build a c++ project with Meson.
The thing is, I have some libraries under /opt/conda
but can't figure out how to link the project when running meson build.
It seems to be only searching through /usr/lib directory.
As far as I understood, meson uses cmake and pkg-config to look for libraries.
Then would setting something like CMAKE_PREFIX_PATH be a feasible solution? and if so, how can I do that?
Thanks in advance.
I see two possible approaches to solve your problem.
the first solution uses LIBRARY_PATH, which is different from LD_LIBRARY_PATH as explained later.
the second solution uses a modified meson file to directly pass options to the linker. Optionally, it also uses rpath that eliminates the need to modify LD_LIBRARY_PATH afterward.
First solution
When building your project the linker use LIBRARY_PATH (and not LD_LIBRARY_PATH)
LIBRARY_PATH is used by gcc before compilation to search directories
containing static and shared libraries that need to be linked to your
program.
LD_LIBRARY_PATH is used by your program to search directories
containing shared libraries after it has been successfully compiled
and linked.
further details: LD_LIBRARY_PATH vs LIBRARY_PATH
Maybe you can try
export LIBRARY_PATH=/opt/conda/:$LIBRARY_PATH
before running meson to build your project.
Second solution
Modifying your meson file and use rpath (optional)
An alternative to the previous first solution is to directly modify your Meson file to pass some options to the linker.
Here is something I used in the past you can easily adapt to your problem:
#
# blaspp
#
blaspp_lib = 'blaspp'
blaspp_lib_dir = '/opt/slate/lib'
blaspp_header_dir = '/opt/slate/include'
blaspp_dep = declare_dependency(
link_args : ['-L' + blaspp_lib_dir, '-l' + blaspp_lib],
include_directories : include_directories(blaspp_header_dir))
executable('test_blaspp',
'test_blaspp.cpp',
build_rpath : blaspp_lib_dir,
install_rpath : blaspp_lib_dir,
dependencies : [blaspp_dep])
declare_dependency(...) defines options to pass to the linker (this replaces the need to define LIBRARY_PATH in the first solution)
executable(...) defines rpath. This is an optional step that embeds the extra library path information directly into the executable. If you use this, you will not have to modify the LD_LIBRARY_PATH when running your executable.
Further details: https://amir.rachum.com/blog/2016/09/17/shared-libraries/ (have a look at the "rpath and runpath" section) and see wikipedia: https://en.wikipedia.org/wiki/Rpath
If I understand the documentation correctly, you could use different / others build system as subproject, and it doesn't seem basing on cmake.
You should be able to define CMAKE_PREFIX_PATH in a CMakeList.txt of a cmake project, and access the generated library within meson context:
in your cmake subproject:
add_library(cm_lib SHARED ${SOURCES})
in your meson:
cmake = import('cmake')
# Configure the CMake project
sub_proj = cmake.subproject('libsimple_cmake')
# Fetch the dependency object
cm_lib = sub_proj.dependency('cm_lib')
executable(exe1, ['sources'], dependencies: [cm_lib])
if you only want to propagate any specific library to meson, than it looks like you'll need to bundle those third party library, or using built-in options.
But first of all: Have you check, either /opt/conda is in your LD_LIBRARY_PATH ?
Surprised no one mentioned it but this is how it is done from within meson.
CXX = meson.get_compiler('cpp')
libs_you_need_to_link = ['lib_a', 'lib_b', 'lib_c']
deps = []
foreach lib_name : libs_you_need_to_link
deps += CXX.find_library(lib_name, dirs : ['/opt/conda', '/other/path'])
endforeach
I am wondering how is cmake finding my llvm cmake configuration if I haven't given it any variable telling it where to find it.
I am an LLVM newcomer. I am building a Hello World LLVM pass. I am on Ubuntu 16.04. My version of LLVM is 8.0.0. My version of CMake is 3.5.1.
This is my /CMakeLists.txt file:
cmake_minimum_required(VERSION 3.1)
project(FunctionDebugger)
find_package(LLVM REQUIRED CONFIG)
include_directories(${LLVM_INCLUDE_DIRS})
add_subdirectory(FunctionDebugger)
set(CMAKE_VERBOSE_MAKEFILE on)
This is the FunctionDebugger/CMakeLists.txt file:
add_library(LLVMFunctionDebugger MODULE
FunctionDebugger.cpp
)
set_target_properties(LLVMFunctionDebugger PROPERTIES
COMPILE_FLAGS "-fno-rtti -std=c++11"
)
I configure and compile like this:
mkdir build && cd build
cmake ..
make
It correctly compiles and links a shared library called libLLVMFunctionDebugger.so. What I don't understand is how cmake could find the package requested in:
# <project-root>/CMakeLists.txt
find_package(LLVM REQUIRED CONFIG)
I am not giving it any path nor I have anything defined in the environment but the path to the LLVM binaries.
I read the CMake documentation, but it says that the find_package looks in folders under CMAKE_PREFIX_PATH. I print that variable with message(STATUS ${CMAKE_PREFIX_PATH}) and the output is empty.
Your set-up looks correct and clearly CMake is finding LLVMConfig.cmake script (i.e. the script that find_package consumes to propagate the necessary CMake variables with LLVM 8 set-up).
On the Ubuntu 16.04 machine that I have access to, LLVMConfig.cmake is located in /usr/lib/llvm-8/lib/cmake/llvm/LLVMConfig.cmake, but there's also a symlink in /usr/lib/llvm-8/cmake/. So the natural questions is: does CMake know that it should look there? The answer is yes. In CMake docs you can see that one of the search paths is:
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)
You can verify that usr is on the list of prefixes by printing CMAKE_SYSTEM_PREFIX_PATH. On my machine that's set-up to:
/usr/local;/usr;/;/usr;/usr/local
Finally, you can print LLVM_DIR in your CMake script to check which version/installation of LLVM was picked by find_package. The variable will be empty on the first execution of CMake, but then find_package finds LLVM-8, the variable is set and saved in CMakeCache.txt.
Hope this helps.
EDIT
This answer was tested on Ubuntu 16.04 on which LLVM 8 was installed in the default, system-wide location through apt-get. If you install LLVM 8 elsewhere, then there are various ways of pointing CMake to the right location, see the docs for find_package. Editing the PATH variable is one of them:
Search the standard system environment variables. This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is passed. Path entries ending in /bin or /sbin are automatically converted to their parent directories:
PATH
Since cmake 3.17, you can use cmake --debug-find <cmake-options> to ask cmake to output a bunch of debugging information on find_* functions. On my machine, it outputs
Standard system environment variables [CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].
/home/jiaqi/Documents/LLVM/llvm-project/build
/home/jiaqi/.local
/home/jiaqi/.yarn
/home/jiaqi/anaconda3
/home/jiaqi/anaconda3/condabin
/usr/local
/usr
/
/usr/games
/usr/local/games
/snap
... outputs omitted...
find_package considered the following locations for LLVM's Config module:
/home/jiaqi/Documents/LLVM/Test/build/CMakeFiles/pkgRedirects/LLVMConfig.cmake
/home/jiaqi/Documents/LLVM/Test/build/CMakeFiles/pkgRedirects/llvm-config.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/LLVMConfig.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/llvm-config.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/cmake/LLVMConfig.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/cmake/llvm-config.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/lib/cmake/llvm/LLVMConfig.cmake
The file was found at
/home/jiaqi/Documents/LLVM/llvm-project/build/lib/cmake/llvm/LLVMConfig.cmake
So, the cmake is using Config mode here and the file is located at /home/jiaqi/Documents/LLVM/llvm-project/build/lib/cmake/llvm/LLVMConfig.cmake
To figure out how cmake finds the LLVMConfig.cmake, take a look at https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure
For step 5, it says the cmake will search the environment variable $PAT, and note that
Path entries ending in /bin or /sbin are automatically converted to their parent directories.
Since I have put the path to llvm executables in $PATH:
$ echo $PATH
/home/jiaqi/Documents/LLVM/llvm-project/build/bin:/home/jiaqi/.local/bin:/home/jiaqi/.yarn/bin:/home/jiaqi/anaconda3/bin:/home/jiaqi/anaconda3/condabin:/home/jiaqi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
The folder /home/jiaqi/Documents/LLVM/llvm-project/build will be used as prefix. According to https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure, the folder <prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/ will be searched.
I have built opencv locally and installed it to a local directory (not the system default ). opencv.pc is present under a folder pkgconfig in this local folder. How can I find this opencv.pc from cmake, because I want to link and include opencv files from my program.
pkg_search_module(<PREFIX> [REQUIRED] [QUIET] <MODULE> [<MODULE>]*)
does not have any parameter in which I can force the command to use a specific path (similar to HINTS with find_package()) and not the system default.
So basically .cmake works:
find_package(OpenCV REQUIRED HINTS "my/path/to/share/OpenCVConfig.cmake")
but I would like to use a opencv.pc located under my/path/to/pkgconfig/opencv.pc.
After doing some research and a hint from the #OlivierM, I found the answer.
Here are the steps:
Method I :
CMAKE_PREFIX_PATH can be set to find the .pc files
set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/libs/opencv-install")
Method II
A second method is to use the PKG_CONFIG_PATH, which is a system environment variable to look for .pc files.
set(ENV{PKG_CONFIG_PATH} "${CMAKE_SOURCE_DIR}/libs/opencv-install/lib/pkgconfig")
Irrespective of which method you use,
For old (traditional) CMake:
find_package(PkgConfig REQUIRED)
pkg_search_module(PKG_OPENCV REQUIRED opencv) # this looks for opencv.pc file
Please note that the PKG_OPENCV variable can be named anything. Whatever it is is named, its used as a prefix. For example if you name ABCD, then include directories will be ABCD_INCLUDE_DIRS
The variable PKG_OPENCV_INCLUDE_DIRS and PKG_OPENCV_LIBRARIES contains the header files (compile stage) and libraries (link stage) respectively.
One very important thing I noticed was that the variable PKG_OPENCV_LIBRARIES just provides the libraries and not the library path during the link stage. In order to use the library path as well in one command, one has to use
PKG_OPENCV_LDFLAGS
This variable contains the library path as well as all the libraries listed in the package config file.
for examaple:
include_directories(${PKG_OPENCV_INCLUDE_DIRS})
target_link_libraries (FINAL_BINARY ${PKG_OPENCV_LDFLAGS})
For modern CMake:
In modern CMake we don't want variables, we want targets.
find_package(PkgConfig REQUIRED)
# this looks for opencv.pc file and creates a new target
# IMPORTED_TARGET requires CMake >= 3.6.3
pkg_search_module(PKG_OPENCV REQUIRED IMPORTED_TARGET opencv)
All variables will still be created for backwards compatibility, but IMPORTED_TARGET will create a target you can use in your project which will automatically propagate all of its build and usage requirements:
target_link_libraries(my_proj PRIVATE PkgConfig::PKG_OPENCV)
You could set PKG_CONFIG_PATH with the CMake line:
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/my/path/to/pkgconfig")
I did this workaround in this file
Interestingly, it seems CMake 3.1 extends PKG_CONFIG_PATH with some CMake variable see: https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3df51470
I would propose you to call cmake with custom PKG_CONFIG_PATH variable, like below:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:my/path/to/pkgconfig cmake <some args>
Or can make PKG_CONFIG_PATH update to be permanent for whole bash session:
$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:my/path/to/pkgconfig
$ cmake <some args>
For external libraries the user can specify a non-standard location by adding the path to the CMAKE_FLAGS or by adding -DMYLIB_ROOT. Within the CMake script I want to find the library's pkg-config pc file. Because the pc file is not in the standard folder, it is not found by pkg-config with FindPkgConfig's pkg_search_module.
I tried to add the user-given path to the PKG_CONFIG_PATH but it seemed to be ignored:
include(FindPkgConfig)
set(PKG_CONFIG_PATH "${PKG_CONFIG_PATH}:${MYLIB_ROOT}/lib/pkgconfig")
pkg_search_module(PKG_MYLIB mylib)
if(${PKG_MYLIB_FOUND})
...
When I call pkg-config from the terminal with the modified PKG_CONFIG_PATH set, it find the pc file. What am I doing wrong? How can I get pkg_search_module working? I'd like to avoid calling pkg-config directly from CMake.
Maybe the following will do the job
set( ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${MYLIB_ROOT}/lib/pkgconfig" )
This is a known issue and a ticket exists in CMake's bugtracker, but it is backlocked due to lack of developer interest. I guess one has to provide a patch first...
Edit: According to the bugtracker the feature has been implemented and is part of CMake 3.1.
I'm using CMake 2.8 in order to build an application based on MQX OS (using CodeWarrior).
The CMake project basically builds a set of static libraries (let's say LIB1 and LIB2).
I then reference these libraries in the final executable cmake rule:
target_add_executable(X ${some_sources})
target_link_libraries(X LIB1 LIB2)
My problem is that some symbols are defined in more that one library.
Thus, a link command like:
mwldarm <args> -o <output> <objects> /path/to1/libLIB1.a /path/to2/libLIB2.a
would lead to multiple definition of symbols error.
Instead, I would like CMake to generate a link command like:
mwldarm <args> -o <output> <objects> -L/path/to1 -L/path/to2 -lLIB -lLIB2
Question: How to get the following variables from CMAKE?
Libraries directories flags (ex: -L/path/to1 -L/path/to2)
Libraries link flags (ex: -lLIB -lLIB2)
I've read stuff concerning RPATH but it seems to concern shared libraries only. Am I right?
Thanks for advance.
I do appreciate.
It seems that policy CMP0003 may be what you need.
To use it add the following line near the beginning of your CMakeLists.txt:
CMAKE_POLICY( SET CMP0003 OLD )
Another possibility is to directly set the dependencies and search path, however it's not the cleanest way. Assuming you libraries are called liba.a and libb.a, then:
LINK_DIRECTORIES( ${paths_to_search_for} )
TARGET_ADD_EXECUTABLE(X ${some_sources} )
ADD_DEPENDENCIES(X LIB1 LIB2)
TARGET_LINK_LIBRARIES(X a b )
Note that in this case a and b are not cmake targets, therefore a little machinery is needed to correctly set the dependencies.
Part of the design of CMake is that it links with full paths. Why is that a problem?
Toggling the behavior with the policy is not the correct approach.
http://www.cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cd4fa896b
I think CMP0003 is used to switch on/off the function of adding searching path automatically as described in the official document
Libraries linked via full path no longer produce linker search paths.
rather than about replacing the path name with -l.
When linking a library, if the library is a target CMake known, CMake always replaces related -L and -l options with the library's path name. This may not be a problem for linking static libraries. But for a executable to link a shared library, it's may be a problem. Then I found a hacking method, code like below, to solve the problem linking a shread library using -L and `-l' rather than absolute path.
# Find out the link.txt
set(LINK_TXT "${CMAKE_BINARY_DIR}/${ToLinkLib}/CMakeFiles/${ToLinkLIb}.dir/link.txt")
# Add the searching path into link command
add_custom_command(TARGET ${YourTarget} PRE_BUILD
COMMAND sed ARGS -ie "\"s;[[:blank:]]-l; -L${LIBRARY_OUTPUT_PATH} -l;\"" ${LINK_TXT}
DEPENDS ${LINK_TXT}
COMMENT "Hacking CMake: edit __link.txt__ to use -l instead of path to link internal library ...")
# NOTE: Dont't missing the `-l'.
target_link_libraries(${YourTarget} -l${ToLinkLib})
Of course, this is just a hacking so may not be working well with all versions of CMake.
UPDATED: why linking a shared library may be a problem?
When I run a executable cross compiled for android, which linking a shared library built by the same CMake scripts, I've encounter a problem of linking failed. After I used the above hacking method to get a new version, I can run my executable with a command like below
$ LD_LIBRARY_PATH=. ./the_exe opts