summaryrefslogtreecommitdiffstats
path: root/src/ceph/cmake/modules/MergeStaticLibraries.cmake
blob: 92d41567b8c82f4746452d4fdeeee3923d67c72a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# This function is a helper that will merge static libraries.
# For example,
#
#    merge_static_libraries(mylib staticlibX staticlibY)
#
# mylib.a will generate a new static library mylib that is
# a combination of staticlibX and staticlibY
#
function(merge_static_libraries target)

    set(dummy_source ${CMAKE_CURRENT_BINARY_DIR}/${target}_dummy.c)
    add_library(${target} STATIC ${dummy_source})

    # remove duplicates
    set(libs ${ARGN})
    list(REMOVE_DUPLICATES libs)

    # validate that all libs are static
    foreach(lib ${libs})
        if (NOT TARGET ${lib})
            message(FATAL_ERROR "${lib} not a valid target")
        endif()

        get_target_property(libtype ${lib} TYPE)
        if(NOT libtype STREQUAL "STATIC_LIBRARY")
            message(FATAL_ERROR "${lib} not a static library")
        endif()

        # add a dependency on the lib
        add_dependencies(${target} ${lib})
    endforeach()

    # Force the merged Make the generated dummy source file depended on all static input
    # libs. If input lib changes,the source file is touched
    # which causes the desired effect (relink).
    add_custom_command(
        OUTPUT  ${dummy_source}
        COMMAND ${CMAKE_COMMAND} -E touch ${dummy_source}
        DEPENDS ${libs})

    # only LINUX is currently supported. OSX's libtool and windows lib.exe
    # have native support for merging static libraries, and support for them
    # can be easily added if required.
    if(LINUX)
        # generate a script to merge the static libraries in to the target
        # library. see https://sourceware.org/binutils/docs/binutils/ar-scripts.html
        set(mri_script "open $<TARGET_FILE:${target}>=")
        foreach(lib ${libs})
            # we use the generator expression TARGET_FILE to get the location
            # of the library. this will not be expanded until the script file
            # is written below
            set(mri_script "${mri_script} addlib $<TARGET_FILE:${lib}>=")
        endforeach()
        set(mri_script "${mri_script} save=end")

        add_custom_command(
            TARGET ${target} POST_BUILD
            COMMAND echo ${mri_script} | tr = \\\\n | ${CMAKE_AR} -M)
    endif(LINUX)

    message("-- MergeStaticLibraries: ${target}: merged ${libs}")

    # we want to set the target_link_libraries correctly for the new merged
    # static library. First we get the list of link libraries for each
    # of the libs we are merging
    set(link_libs)
    foreach(lib ${libs})
      get_property(trans TARGET ${lib} PROPERTY LINK_LIBRARIES)
      list(APPEND link_libs ${trans})
    endforeach()

    if (link_libs)
        # now remove the duplicates and any of the libraries we already merged
        list(REMOVE_DUPLICATES link_libs)
        foreach(lib ${libs})
            list(REMOVE_ITEM link_libs ${lib})
        endforeach()

        # set the target link libraries
        target_link_libraries(${target} ${link_libs})

        message("-- MergeStaticLibraries: ${target}: remaining ${link_libs}")
    endif()

endfunction()