custom target as a target library in cmake
Asked Answered
S

2

39

I have a custom target that is in fact an externally generated library that I want to integrate in my build.

add_custom_command(
       OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/liblib2.a
       COMMAND make -f ${CMAKE_CURRENT_SOURCE_DIR}/makefile liblib2.a)

add_custom_target(lib2  
       DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/liblib2.a)

How can I tell cmake that this target is in fact a library, where it can be found and where are the headers ?

To be clear : I don't want the upper CMakeList using this library having to manually specify include folders and the library location folder It must be done automatically (from the target properties).

On a standard cmake library I would just have to add the INTERFACE_INCLUDE_DIRECTORIES property in the library CMakeLists to make cmake link my app with the relevant -I and -L gcc parameters :

set_target_properties(lib1
  PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES
  ${CMAKE_CURRENT_SOURCE_DIR})

But in the case of a custom target I don't know how to to it.

Any clue ?

Thanks for your help.


Thanks to zaufi it works!

For others who may be interested in embedded externally build target inside cmake here is what I did :

cmake_minimum_required(VERSION 2.8)

SET(LIB_FILE ${CMAKE_CURRENT_SOURCE_DIR}/bin/liblib2.a)
SET(LIB_HEADER_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/include)

# how to build the result of the library
add_custom_command(OUTPUT  ${LIB_FILE}
                   COMMAND make 
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

# create a target out of the library compilation result
add_custom_target(lib2_target DEPENDS ${LIB_FILE})

# create an library target out of the library compilation result
add_library(lib2 STATIC IMPORTED GLOBAL)
add_dependencies(lib2 lib2_target)

# specify where the library is and where to find the headers
set_target_properties(lib2
    PROPERTIES
    IMPORTED_LOCATION ${LIB_FILE}
    INTERFACE_INCLUDE_DIRECTORIES ${LIB_HEADER_FOLDER})

Now in a CMakeLists.txt I can do somthing like

add_subdirectory(${ROOT_DIR}/lib1 bin/lib1)
add_subdirectory(${ROOT_DIR}/lib2 bin/lib2)
add_executable(app app.c )
target_link_libraries(app lib1 lib2)

No need to specify where the .a and the .h are.

Symphysis answered 7/7, 2015 at 16:41 Comment(4)
Thanks very much for this nlko and zaufi, after hours trying to figure out how to get a library from nuget via cmake, your technique was the solutionLemuellemuela
On my cmake installation set_target_properties did not work. After 3 days I figured that with a static library (linux .a file) I had to use set_property instead for IMPORTED_LOCATION.Parathyroid
This is awesome, but I have one minor issue. I have copied you CMakeLists.txt, but every time I build application, liblib2.a is being rebuild. I have added DEPENDS to the add_custom_command and let the command depend upon the makefile of the lib2, but it did not work as expected. Any ideas how to solve this?Dyer
I got it. My problem was that the OUTPUT was pointing at something with CMAKE_CURRENT_BINARY_DIR but I did never copy the output from the make to that location. I have added a second command to add_ccustom_command, looking something like: COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_PATH}/liblib2.a ${CMAKE_CURRENT_BINARY_DIR} Dyer
S
23

You can use add_library() and tell that it actually imported. Then, using set_target_properties() you can set required INTERFACE_XXX properties for it. After that, you can use it as an ordinal target like every other built by your project.

Stepfather answered 7/7, 2015 at 16:56 Comment(2)
Awesome, it works, Thanks! I added the complete implementation at the end of my question.Symphysis
It's not possible to "install" such a library target because CMake thinks, it's imported.Amberjack
R
10

Thank you for posting the solution. I have wrapped your snippet in a function:

function(add_external_library)
    set(options)
    set(oneValueArgs TARGET WORKING_DIRECTORY OUTPUT COMMENT)
    set(multiValueArgs COMMAND INCLUDE_DIRS)
    cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" ${multiValueArgs}" ${ARGN})

    # Specify how to build the result of the library
    add_custom_command(OUTPUT "${ARGS_OUTPUT}"
        COMMAND ${ARGS_COMMAND}
        WORKING_DIRECTORY "${ARGS_WORKING_DIRECTORY}"
        COMMENT "${ARGS_COMMENT}")

    # Create a target out of the library compilation result
    add_custom_target(${ARGS_TARGET}_target DEPENDS ${ARGS_OUTPUT})

    # Create an library target out of the library compilation result
    add_library(${ARGS_TARGET} STATIC IMPORTED GLOBAL)
    add_dependencies(${ARGS_TARGET} ${ARGS_TARGET}_target)

    # Specify where the library is and where to find the headers
    set_target_properties(${ARGS_TARGET}
        PROPERTIES
        IMPORTED_LOCATION "${ARGS_OUTPUT}"
        INTERFACE_INCLUDE_DIRECTORIES "${ARGS_INCLUDE_DIRS}")
endfunction()

# Example
add_external_library(TARGET YourLib
    COMMAND           /bin/bash compile_your_lib.sh
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
    OUTPUT            "output/yourlib.a"
    INCLUDE_DIRS      "include/a" "include/b"
    COMMENT           "Building YourLib")

add_executable(YourExe)
target_link_libraries(YourExe YourLib)
Rompish answered 5/2, 2020 at 10:21 Comment(1)
Does this actually work? The CMake docs for add_dependencies() sayGoodall

© 2022 - 2024 — McMap. All rights reserved.