Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake: create a new library target which consists of a prebuilt library

Tags:

c++

boost

cmake

I'm trying to create a custom target in cmake which:

  • links a vendor supplied archive
  • adds target_compile_options(... PUBLIC ...)
  • adds target_include_directories(... PUBLIC ...)

In this way consumers can link against my new target and have requisite include directories and compile options set.

In boost-build you can use the <file> feature to "wrap" or "alias" a prebuilt library, and add additional "usage requirements" (compiler flags etc) which will be added to all targets using the library.

lib foo 
: 
: <file>vendor/library.a
:
: <include>vendor
;
  • This aliases vendor/library.a as a new library foo.
  • When another target uses foo it will also have its include paths updated.
  • The code using foo will then be able to #include "foo.h", and the file will be found because vendor has been added to the include paths.

I'm looking for a way to do the same thing in CMake.

The way I would currently do it would be something along these lines:

find_library(LIB_FOO library.a PATHS ${CMAKE_SOURCE_DIR}/path/to/vendor NO_DEFAULT_PATH)

target_link_library       (my_target ${LIB_FOO})
target_include_directories(my_target PRIVATE "${CMAKE_SOURCE_DIR}/path/to/vendor")

However, if there are several targets which need to use foo then these 3 calls would have be repeated for each of them, which becomes quite onerous.

It would be far easier for consumers of foo to have some other target which has

target_link_libraries     (foo ${CMAKE_CURRENT_LIST_DIR}/vendor/library.a)
target_compile_options    (foo PUBLIC ...)
target_include_directories(foo PUBLIC ...)

Question:

  • Can I create a new library target which consists of a prebuilt library which will allow me to do what I've described?

Edit in response to comment:

I have tried to create an IMPORTED library (as described here):

add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/vendor/library.a)

However, when I then try to set include directories I get an error:

target_include_directories(foo SYSTEM PUBLIC "${CMAKE_CURRENT_LIST_DIR}/vendor")

Error:

CMake Error at vendor/CMakeLists.txt:39 (target_include_directories):
  Cannot specify include directories for imported target "foo".
like image 356
Steve Lorimer Avatar asked Apr 22 '16 16:04

Steve Lorimer


1 Answers

  1. You need to import a pre-built library. here is the tutorial how to do it.
  2. To make the resulted target "complete" you need to add certain properties to it. Unfortunately this can't be done using usual techniques, because of this CMake issue. So you have to set these props manually, like described in this SO QA
like image 193
user3159253 Avatar answered Oct 04 '22 02:10

user3159253