CMake can't link external libraries - c++

I have a C++ project that contains source files. For an external project, there are some folders I need to search for included libraries:
/home/data/lib/wisenet
/home/data/lib/wise_log
/home/data/lib/wise_rs_device
/home/data/lib/json
/home/data/lib/wise_versioning
What must I write to include these external libraries in CMake? These folders contain only interface resources (h files and .a libraries).
I tried to include these directories like this:
include_directories(
/home/data/lib/wisenet
/home/data/lib/wise_log
... etc
)
And I don't understand how to correctly add the lib files such as libwise_rs_device.a.

Include directories only are for... well, include paths for your code. It won't link libraries.
The correct way to use external library is using imported libraries:
add_library(wise_rs_device STATIC IMPORTED GLOBAL)
set_target_properties(wise_rs_device PROPERTIES
IMPORTED_LOCATION "path/to/static/library"
INTERFACE_INCLUDE_DIRECTORIES "path/to/headers/of/wise_rs_device"
)
Then, you can simply link the imported target to yours:
# will link to the static library and add include directories.
target_link_libraries(your_executable PRIVATE wise_rs_device)

Related

Why linking with imported executable target results in LNK1181: cannot open include file 'xsd.lib'

I'm writing my own find module for a third-party application (xsd from codesynthesis, but I think it's not relevant) and my project needs to use this target in two ways:
include its headers to build my project
execute the xsd executable to generate sources.
Initially I made the xsd target an interface imported library and linking to it with simple target_link_libraries was working as expected (my project built fine). Then I went to add the generate sources option, so I changed the xsd target to an executable, precisely this way:
FindXSD.cmake
if(NOT TARGET xsd)
add_executable(xsd IMPORTED)
target_include_directories(xsd INTERFACE ${_XSD_INCLUDE_DIR})
set_target_properties(xsd PROPERTIES IMPORTED_LOCATION ${_XSD_EXECUTABLE}
add_executable(xsd::xsd ALIAS xsd)
endif()
Then I referenced the target this way in one of the libraries (well, it was already like this before I switched from library to executable):
find_package(XSD EXACT ${XSD_PACKAGE_VERSION} REQUIRED)
target_link_libraries(my_target PUBLIC xsd::xsd)
and the compilation failed as xsd headers were not found. I tried to add this to see if it helps:
get_target_property(XSD_INCLUDES xsd::xsd INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(my_target PUBLIC ${XSD_INCLUDES})
and now the headers are found correctly, but it fails with
LINK : fatal error LNK1181: cannot open include file 'xsd.lib'
Why does it try to include .lib?
Why doesn't target_link_libraries automatically populate the correct include directories?
What is the proper way of handling such dependency?
My motivation to go with an imported executable instead of an imported interface library was so I can use CMake's substitution of xsd's executable path instead of using XSD_EXECUTABLE variable outside of the FindXSD.cmake.

How to build a static library from two directories?

I have two folders with two different libraries.
LibBase
LibPublic
LibB includes some LibBase's headers.
I'd like to have LibPublic as a static library including "LibBase" in its .a file.
Each CMakeLists.txt is:
set(SRCLIB file.cpp)
add_library(${PROJECT_NAME} ${SRCLIB})
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_include_directories(...)
The top level CMakeLists.txt:
add_subdirectory(LibBase)
add_subdirectory(LibPublic)
How can I force CMake to include LibBase inside LibPublic so that I can only share libLibPublic.a?
LibBase is a proprietary library and LibPublic is the "public" library we share.
LibBase and LibPublic, both may be added using add_subdirectory() by other libraries or apps so that a single app executable or a single .a file can be provided. Each "library" should be compiled as just objects, static library or even dynamic library. I'd like them to be generic, and an upper CMakeLists.txt will decide what to do.
I tried with add_library(${PROJECT_NAME}-obj OBJECT ${SRCLIB}) but I get errors:
CMakeLists.txt:22 (target_include_directories):
Cannot specify include directories for target "LibPublic" which is not
built by this project.
Given the following file and some dummy cpp files:
cmake_minimum_required(VERSION 3.10)
project(foo)
add_library(Base STATIC base.cpp)
add_library(Public STATIC public.cpp)
target_sources(Public PRIVATE $<TARGET_OBJECTS:Base>)
I end up with a libPublic.a that contains functions from both libraries.
Note that this is a solution to your question, but maybe not a solution to your underlying requirement: static libraries are simple collections of functions and the functions in "Base" are plainly visible.

CMake imported library include_directories before other ones

I have a cmake project with an IMPORTED library which has a include directory which must be used before the include directories of the executable.
I tried the following:
cmake_minimum_required(VERSION 3.20)
project(test_cmake)
set(CMAKE_CXX_STANDARD 98)
#Librarry
add_library(lib SHARED IMPORTED)
target_include_directories(lib SYSTEM BEFORE INTERFACE ./lib_inc/)
set_target_properties(lib PROPERTIES IMPORTED_IMPLIB "lib.lib")
add_executable(test_cmake main.cpp)
target_include_directories(test_cmake AFTER PRIVATE include)
target_link_libraries(test_cmake PRIVATE lib)
But at least with the generator "Visual Studio 9 2008" the directory "include" in used before "lib_inc". Does anybody know a way to modify the imported lib so that there include will be the first?
Does anybody know a way to modify the imported lib so that there include will be the first?
The answer is no. Compiler command lines are computed by walking the DAG of linked libraries and placing the merged interface properties in (de-duplicated) pre-order starting with the "top" target. So there is no interface property that can do exactly what you want.
I have a [...] library which has a include directory which must be used before the include directories of the executable.
Frankly, this is a really dubious requirement. The library cannot know to which executables it will be linked so it cannot be a requirement to override its linkers' (as in "linker" and "linkee", not ld) include paths. Similarly, if this library L were a dependency of a static library S, and an executable E linked to S, what should happen with the "before" include dirs of L? Should they override E's? If so, that would be a truly confusing behavior, whereby no target can ever trust its own headers to be used, ever.
So this is not only not available, it's pretty dubious that it ever should be available. This just isn't a coherent semantics for property propagation.

cmake/cpack distribute a library and its dependencies

Let's say I have to distribute a C++ library libA which depends on other libraries libB and libC.
The final user will have to include just the header files of libA but needs to link also the others two.
What's the preferable way to distribute all together the libraries?
Is it possible to use cpack to take care of it?
If you have to hide the source code, then you could precompile the libraries yourselves and just distribute the static .a files and the header files seperately for each distribution.
However, If you want the code to be transparent to the end users and let the users compile the libraries on their own. Then you could try cmake.
The common folder structure for a library will look like this
MainFolder
src ( To have all the required Src files )
include ( all the necessary files to be included )
test ( to run test cases upon installation to validate a successfull installation -- optional )
Then you could create a CMakeLists.txt file in the root folder which would look like this,
cmake_minimum_required(VERSION 3.2)
project(MyAwesomeLibrary)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")// Sets up the compiler and flags
include_directories("${CMAKE_SOURCE_DIR}/include") // This includes the .h files in include directory
// Set the Codes to be compiled for Different Libraries
set (LIB_A ${CMAKE_SOURCE_DIR}/lib_a.c);
set (LIB_B ${CMAKE_SOURCE_DIR}/lib_b.c);
set (LIB_C ${CMAKE_SOURCE_DIR}/lib_c.c);
add_library(MyAwesomeStaticLib STATIC ${LIB_A} ${LIB_B} ${LIB_C}) // Generates the static library
If you have multiple files to be compiled for each of the libraries then you can refer this link.
how would I compile multiple files in a folder?
Then the end user can use the library by linking the generated MyAwesomeStaticLib.a file and also use the -I flag to include the include directories.

How to link cmake build libs to external code?

I want to use this library c++ library in my code on external directory, which I have build with cmake (I'm new with it), as the compiling tutorial explain. After this, what files (or makefiles) do I'm suppose to add to my directory to do things like this is my code
#include "rpc/server.h"
I saw something about importing static libraries that would have to add a CMakeLists.txt to my directory and compile my main code with something as
g++ -static main.cc -L<librpc.a directory> -lrpc -o main
But getting this:
fatal error: rpc/server.h: No such file or directory compilation terminated.
I have searched the web about these procedures but I'm not having sucess on this. Could someone help
First you need to add the rpc library to the project as an imported library, and subsequently you must specify target properties such as the imported location and the include directories.
add_library(rpc SHARED IMPORTED)
set_target_properties(rcp
PROPERTIES
IMPORTED_LOCATION "${rpc_LIBRARIES}"
INCLUDE_DIRECTORIES "${rpc_INCLUDES}"
)
After you've successfully added the rpc library to the project, just add rpc as a target to your executable.
add_executable(your_test_program main.cpp)
target_link_libraries(your_test_program PRIVATE rpc )