CMake - using external libraries as APR [duplicate] - build

This question already has an answer here:
Cmake link library target link error
(1 answer)
Closed 2 years ago.
I am quite new to this CMake.
I need to use APR from Apache 2 and I have a problem with this build system. The Apache 2 web server is installed under the C:\Apache24 folder, the APR related include files are located under C:\Apache24\include and the libraries under the C:\Apache24\lib folder.
cmake_minimum_required(VERSION 3.15)
project(json C)
set(CMAKE_C_STANDARD 90)
include_directories(
C:\Apache24\include
)
link_directories(
C:\Apache24\lib
)
target_link_libraries(
json apr-1.lib
)
add_executable(larak larak.h larak.c main.c)
By build I get this error:
Cannot specify link libraries for target "larak" which is not built by this project.
I've already read a lot of similar posts but most all of them are for Linux/Unix systems, not for Windows and not for APR/Apache.

The target_link_libraries() command specifies libraries to link for a specific target. This target name must be provided as the first argument to the command, and must already be defined earlier in your CMake file. Since you only have one target, larak, defined in your CMake file, you probably want to do something like this:
cmake_minimum_required(VERSION 3.15)
project(json C)
set(CMAKE_C_STANDARD 90)
include_directories(
C:/Apache24/include
)
link_directories(
C:/Apache24/lib
)
add_executable(larak larak.h larak.c main.c)
target_link_libraries(larak PRIVATE
apr-1.lib
)
Careful, CMake will probably complain about the backslash usage (\) you have. You should convert these to forward slashes.
Note, you may instead specify the full path to the library in the target_link_libraries() command, to avoid the use of the link_directories() command.
cmake_minimum_required(VERSION 3.15)
project(json C)
set(CMAKE_C_STANDARD 90)
include_directories(
C:/Apache24/include
)
add_executable(larak larak.h larak.c main.c)
target_link_libraries(larak PRIVATE
C:/Apache24/lib/apr-1.lib
)

Related

How do I include the Eigen library in a CMakelist.txt on windows

I am trying to include the Eigen library to my CMakelist.txt. I have followed the CMake instructions on the Eigen Docs but I am using Jetbrain's Clion and not CMake directly. So I do not know how to use the Cmake commands provided. I have researched around but I don't have have a very good understanding of CMake to write Cmakelists, so I haven't been able to get anything to work yet.
this is what I have been using just to test the serup of the library:
cmake_minimum_required(VERSION 3.17)
project(Eigen_Test)
set(CMAKE_CXX_STANDARD 20)
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
add_executable (example example.cpp)
target_link_libraries (example eigen)
add_executable(Eigen_Test main.cpp)
this is the error I have been receiving:
CMake Error at CMakeLists.txt:5 (find_package):
Could not find a package configuration file provided by "Eigen3" (requested
version 3.3) with any of the following names:
Eigen3Config.cmake
eigen3-config.cmake
Add the installation prefix of "Eigen3" to CMAKE_PREFIX_PATH or set
"Eigen3_DIR" to a directory containing one of the above files. If "Eigen3"
provides a separate development package or SDK, be sure it has been installed.
I Have researched many ways to include the library but most methods use command lines which I am unfamiliar with. Also I do not have an Eigen3Config.cmake the only file I have Eigen3Config.cmake.in. I assume there is some install trick that I must not be aware of. If anyone has a way to include clion strictly using a CMakelist.txt, I would be greatly appreciative.
Here a working example with CMake on Windows using the MinGW environment with mingw32-make.exe and g++.exe compiler.
CMakeLists.txt :
# The following lines depends on your project :
cmake_minimum_required(VERSION 3.19)
project(PROJECT_NAME)
set(CMAKE_CXX_STANDARD 17)
# You have to set these variables as Windows environment variables:
# EIGEN3_INCLUDE_DIR <- %EIGEN3_ROOT%
# EIGEN3_DIR <- %EIGEN3_ROOT%\cmake
#
# EIGEN3_INCLUDE_DIR: variable needed for file %EIGEN3_ROOT%/cmake/FindEigen3.cmake
#
# CMAKE_MODULE_PATH: Search path for the module Eigen3 to be loaded by find_package
#
SET( EIGEN3_INCLUDE_DIR "$ENV{EIGEN3_INCLUDE_DIR}" )
SET( CMAKE_MODULE_PATH "$ENV{EIGEN3_DIR}" )
find_package( Eigen3 3.3 REQUIRED )
# include_directories is needed for the compiler to know where looking for Eigen3 header files to be included
include_directories( ${EIGEN3_INCLUDE_DIR} )
add_executable(PROJECT_NAME FILES...)
You can then call the Eigen3 libraries, such as:
#include <Eigen/Core>
Eigen is a header only library, so you don't have to add it to target_link_library, and you don't need a CMake Macro to detect it.
Instead just add the header file into your include path and you should be set.

CMake: Link an executable to multiple libraries (*.so) [duplicate]

This question already has answers here:
CMake link to external library
(6 answers)
Closed 2 years ago.
I'm new to building with CMake. I'm using Ubuntu and I have a .cpp file (say xyz.cpp located somewhere in ~/mydir) which links to three custom shared libraries (libA.so, libB.so & libC.so libraries). These three *.so files are located in /usr/local/lib.
I want to create a CMakeLists.txt to get this compiled. The below script throws errors like:
cmake_minimum_required(VERSION 3.11)
project(xyz VERSION 1.0.0 LANGUAGES C CXX)
# Set C standard to C11
set(CMAKE_C_STANDARD 11)
set(SOURCES src/xyz.cpp)
include_directories(/usr/local/include)
#For the shared library:
target_link_libraries(libA -L/usr/local/lib/)
target_link_libraries(libB -L/usr/local/lib/)
target_link_libraries(libC -L/usr/local/lib/)
target_link_libraries(xyz libA libB libC )
add_executable(xyz src/xyz.cpp)
ERROR:
CMake Error at CMakeLists.txt: (target_link_libraries):
Cannot specify link libraries for target "libA" which is not built
by this project.
-- Configuring incomplete, errors occurred!
A couple important notes:
The first argument to target_link_libraries() should be a valid CMake target, created by add_library() or add_executable(). Therefore, any target_link_libraries() call should be placed after the add_executable() call in your code.
You only need one call to target_link_libraries() to link all of your *.so libraries to the executable. The first three calls are unnecessary (and invalid because libA, libB, and libC are all undefined). You should provide the full path to each of these libraries to ensure that the correct library is used.
It is good practice to include the scoping argument in target_* calls, such as target_link_libraries(). This specifies whether the libraries are linked-to (PRIVATE), added to the link interface (INTERFACE), or both (PUBLIC). This distinction becomes more important as your CMake project grows to include more targets.
With these notes, and a few others commented below, your CMake file could look something like this:
cmake_minimum_required(VERSION 3.11)
# No need to specify C and CXX for LANGUAGES here, these are enabled by default!
project(xyz VERSION 1.0.0)
# Set C standard to C11
set(CMAKE_C_STANDARD 11)
set(SOURCES src/xyz.cpp)
include_directories(/usr/local/include)
# Define your executable target. You can pass in the SOURCES variable defined above.
add_executable(xyz ${SOURCES})
# Link the other libraries to your executable, using their full path.
# Note, the '-L' flag is not necessary.
target_link_libraries(xyz PRIVATE
/usr/local/lib/libA.so
/usr/local/lib/libB.so
/usr/local/lib/libC.so
)

How to build static library with bundled dependencies - CMake

I am currently using CMake to create a static library which utilizes a few of the static libraries from OpenCV 4 ( core imgcodecs video highgui imgproc ). My intention is to be able to bundle all of the required OpenCV static libraries into my own library so that I can distribute it as one library. Additionally, I want for the user of my library to not have to install OpenCV 4 on their system (but do not mind if the user has to do simple installs using apt-get install). I know there are tools for bundling static libraries (such as using ar for linux).
However, where I really am having the issue is with all the dependencies of OpenCV (such as libjpeg, libpng, etc). I don't necessarily mind if these libraries are bundled with mine or linked dynamically as they are relatively easy to install (can be installed with sudo apt-get install, whereas opencv4 needs to be built from source).
What is the best way to go about doing this?
This is my current CMakeLists.txt
It is currently working, but that is because I am using find_package(OpenCV REQUIRED) (which defeats the purpose of what I am trying to do). When I remove that line, the linker complains about not being able to find the OpenCV dependencies.
cmake_minimum_required(VERSION 2.8)
project(myproject)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
list(APPEND LINKER_LIBS opencv_core opencv_highgui opencv_video opencv_imgcodecs libmxnet.so libncnn.a nlohmann_json::nlohmann_json)
file(GLOB SRC${CMAKE_CURRENT_LIST_DIR}/src/*.cpp${CMAKE_CURRENT_LIST_DIR}/main.cpp)
add_library(myproject ${SRC})
target_link_libraries(myproject ${LINKER_LIBS} ${OpenMP_CXX_FLAGS})
To elaborate on my question. I build my project which generates libmyproject.a. I then take this library and will eventually extract the symbols from the OpenCV libs (libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a) and add them to my lib (for the time being, I have not yet done this step, which is why in the below example I am linking libopencv_*). I then use my library in a new project, for which the CMakeLists.txt is shown below:
cmake_minimum_required(VERSION 2.8)
project(myproject-driver)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
link_directories(${CMAKE_CURRENT_LIST_DIR}/lib)
find_package(OpenMP REQUIRED)
add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver myproject libncnn.a ${OpenMP_CXX_FLAGS} libmxnet.so libopencv_core.a libopencv_highgui.a libopencv_imgcodecs.a libopencv_video.a)
Building this generates the following errors:
Linking CXX executable myproject-driver
/usr/bin/ld: /home/nchafni/Cyrus/myproject/lib/libopencv_imgcodecs.a(grfmt_jpeg.cpp.o): undefined reference to symbol 'jpeg_default_qtables##LIBJPEG_8.0'
//usr/lib/x86_64-linux-gnu/libjpeg.so.8: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
How can I fix this. Is there some CMake command which will link all these dependencies for me? Do I need to manually track down each dependency of those libopencv_* libs and link those manually? Once again, this is assuming that the person using libmyproject.a can't use find_package(OpenCV REQUIRED) as it won't be defined as they have not installed OpenCV on their machine.
First of all, don't use the super old and outdated version 2.8 of CMake. CMake 3.x is so much more powerful and pretty straightforward to use.
Some tips for modern CMake.
Don't use file(GLOB), see here why that is.
Don't use directory wide instructions, rather use target instructions, e.g. target_include_directories vs. include_directories.
Don't use string variables like ${<PACKAGE_NAME>_LIBRARIES}, rather use targets, e.g. <Package_NAME>::lib
When using targets instead of string variables, all the properties (including LINK_INTERFACE) of that target will be populated to the library/executable when calling target_link_libraries, so no more include_directories,link_directories, etc.
myproject
cmake_minimum_required(VERSION 3.14)
project(myproject)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenMP REQUIRED)
find_package(OpenCV REQUIRED)
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json)
set(SOURCES ...) # list all the source files here
add_library(myproject ${SOURCES})
target_include_directories(myproject PUBLIC # give it a scope
${CMAKE_CURRENT_LIST_DIR}/include
)
target_link_libraries(myproject PUBLIC # give it a scope
opencv_core # using the target, you will get all LINK_LIBRARIES
opencv_highgui
opencv_video
opencv_imgcodecs
libmxnet.so # where is this coming from?
libncnn.a # where is this coming from?
nlohmann_json::nlohmann_json
OpenMP::OpenMP_CXX ## linking against a target, CXX_FLAGS will be populated automatically
)
myprojec-driver
cmake_minimum_required(VERSION 3.14)
project(myproject-driver)
set(CMAKE_CXX_STANDARD 14)
add_executable(myproject-driver main.cpp)
target_link_libraries(myproject-driver PUBLIC # give it a scope
myproject # gets all dependencies through the LINK_INTERFACE
)

Cmake error: Cannot specify link libraries for target [duplicate]

This question already has an answer here:
Build project with "experimental/filesystem" using cmake
(1 answer)
Closed 3 years ago.
I am trying to build a simple CMake project but I'm having problems understanding CMake or at least the error I get.
The project i made is divided in a couple directories.
The main one has this cmake:
cmake_minimum_required(VERSION 3.7.2)
project(Raytracer)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(src)
set(COMMON_INCLUDES ${PROJECT_SOURCE_DIR}/inc)
From there my project splits in 2 folders src and inc.
and in src i have the following cmake with the idea to global all subfolders:
FILE(GLOB sub-dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
FOREACH(dir ${sub-dirs})
IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
ADD_SUBDIRECTORY(${dir})
ENDIF()
ENDFOREACH()
add_executable(raytracer main.cpp)
I also add the executable there which is in this main src folder.
From there on i want to be able to make sub folders adding with their own Cmake files and linking those files to my executable.
I have the following cmake:
set(OBJECTS
asdf.cpp
)
add_library(obj_files ${OBJECTS} ${COMMON_FILES})
target_link_libraries(raytracer obj_files)
but when I try to build I get the following error:
Cannot specify link libraries for target "raytracer" which is not built by this project.
Basically in Cmake file or toolchain.cmake the order of commands are important!
target_link_libraries() or target_include_directories() have to be always after add_executable()

Add library to Cmake project

Perhaps I simply can't find it, but I want to add some code to a project of mine (libunwind found here http://www.nongnu.org/libunwind/download.html)
This library does not come with a CMakeLists.txt file and when I try to include it cmake complains about this fact. Right now I've simply added the libunwind directory to my external code and added a reference in my main CMakeLists.txt
Any input would be great.
Dealing with libraries there are 2 options for you :
If you've downloaded and was able to build and install it you can try to find it later on inside you CMAKE like this ( in case of Boost ) and link to your target:
find_package( Boost COMPONENTS date_time system serialization thread program_options filesystem unit_test_framework regex chrono REQUIRED )
if( NOT Boost_FOUND )
message( FATAL_ERROR "Cannot find boost!" )
endif( NOT Boost_FOUND )
message(STATUS "boost found")
include_directories( ${Boost_INCLUDE_DIRS} )
link_directories( ${Boost_LIBRARY_DIRS} )
target_link_libraries(YOUR_TARGET_NAME ${Boost_LIBRARIES})
2. You can add external library sources as a stand-alone target and use smth like this for CMake to build it :
set (sources
async_waiter.h
async_waiter_impl.h
async_waiter_impl.cpp
)
add_library( async_waiter ${sources} )
and later on link you target to it with :
target_link_libraries(YOUR_TARGET_NAME async_waiter)
If you want to build it each time along with your project, the easiest way would be to:
Add the source code somewhere into your project tree
Add a custom CMake target which should run before the compilation starts
In that custom target, run whatever is needed to compile the library (in your case it's ./configure -> make -> make install.
However that is rarely needed and most of the times you should just build the library once and link it as any other external library.