diff options
Diffstat (limited to 'cmake/ModulePackage.cmake')
-rw-r--r-- | cmake/ModulePackage.cmake | 98 |
1 files changed, 88 insertions, 10 deletions
diff --git a/cmake/ModulePackage.cmake b/cmake/ModulePackage.cmake index 3a4eb9b9..d51607df 100644 --- a/cmake/ModulePackage.cmake +++ b/cmake/ModulePackage.cmake | |||
@@ -51,45 +51,123 @@ function(pkg_use_module mod pkg) | |||
51 | endif() | 51 | endif() |
52 | endfunction() | 52 | endfunction() |
53 | 53 | ||
54 | macro(add_submodule super lib) | ||
55 | add_module(${lib} ${ARGN}) | ||
56 | set(${super}_SUBLIBS ${${super}_SUBLIBS} ${lib}) | ||
57 | set(${super}_SOURCES ${${super}_SOURCES} ${${lib}_SOURCES}) | ||
58 | endmacro() | ||
59 | |||
54 | function(add_module lib) | 60 | function(add_module lib) |
55 | set_source_language(${ARGN}) | 61 | set_source_language(${ARGN}) |
62 | set(${lib}_SOURCES ${ARGN} PARENT_SCOPE) | ||
56 | 63 | ||
57 | if(ENABLE_SHARED) | 64 | if(ENABLE_SHARED) |
58 | add_library(${lib}_shared SHARED ${ARGN}) | 65 | add_library(${lib}_shared SHARED ${ARGN}) |
66 | set_target_properties(${lib}_shared PROPERTIES OUTPUT_NAME ${lib}) | ||
67 | endif() | ||
68 | if(ENABLE_STATIC) | ||
69 | add_library(${lib}_static STATIC ${ARGN}) | ||
70 | set_target_properties(${lib}_static PROPERTIES OUTPUT_NAME ${lib}) | ||
71 | endif() | ||
72 | |||
73 | # ${lib}_PKGCONFIG_LIBS is what's added to the Libs: line in ${lib}.pc. It | ||
74 | # needs to contain all the libraries a program using ${lib} should link against | ||
75 | # if it's statically linked. If it's dynamically linked, there is no need to | ||
76 | # explicitly link against all the dependencies, but it doesn't harm much(*) | ||
77 | # either. | ||
78 | # | ||
79 | # (*) It allows client code to use symbols from our dependencies without | ||
80 | # explicitly linking against them. | ||
81 | set(${lib}_PKGCONFIG_LIBS PARENT_SCOPE) | ||
82 | # Requires: in pkg-config file. | ||
83 | set(${lib}_PKGCONFIG_REQUIRES PARENT_SCOPE) | ||
84 | endfunction() | ||
85 | |||
86 | function(install_module lib) | ||
87 | if(ENABLE_SHARED) | ||
59 | set_target_properties(${lib}_shared PROPERTIES | 88 | set_target_properties(${lib}_shared PROPERTIES |
60 | OUTPUT_NAME ${lib} | ||
61 | VERSION ${SOVERSION} | 89 | VERSION ${SOVERSION} |
62 | SOVERSION ${SOVERSION_MAJOR} | 90 | SOVERSION ${SOVERSION_MAJOR} |
63 | ) | 91 | ) |
64 | install(TARGETS ${lib}_shared DESTINATION "lib") | 92 | install(TARGETS ${lib}_shared DESTINATION "lib") |
65 | endif() | 93 | endif() |
66 | if(ENABLE_STATIC) | 94 | if(ENABLE_STATIC) |
67 | add_library(${lib}_static STATIC ${ARGN}) | ||
68 | set_target_properties(${lib}_static PROPERTIES OUTPUT_NAME ${lib}) | ||
69 | install(TARGETS ${lib}_static DESTINATION "lib") | 95 | install(TARGETS ${lib}_static DESTINATION "lib") |
70 | endif() | 96 | endif() |
97 | |||
98 | string(REPLACE ";" " " ${lib}_PKGCONFIG_LIBS "${${lib}_PKGCONFIG_LIBS}") | ||
99 | string(REPLACE ";" " " ${lib}_PKGCONFIG_REQUIRES "${${lib}_PKGCONFIG_REQUIRES}") | ||
100 | |||
101 | configure_file( | ||
102 | "${${lib}_SOURCE_DIR}/other/pkgconfig/${lib}.pc.in" | ||
103 | "${CMAKE_BINARY_DIR}/${lib}.pc" | ||
104 | @ONLY | ||
105 | ) | ||
106 | |||
107 | install(FILES | ||
108 | ${CMAKE_BINARY_DIR}/${lib}.pc | ||
109 | DESTINATION "lib/pkgconfig") | ||
110 | |||
111 | foreach(sublib ${${lib}_API_HEADERS}) | ||
112 | string(REPLACE "^" ";" sublib ${sublib}) | ||
113 | list(GET sublib 0 header) | ||
114 | |||
115 | install(FILES ${header} ${ARGN}) | ||
116 | endforeach() | ||
71 | endfunction() | 117 | endfunction() |
72 | 118 | ||
73 | function(target_link_modules target) | 119 | function(target_link_modules target) |
120 | # If the target we're adding dependencies to is a shared library, add it to | ||
121 | # the set of targets. | ||
74 | if(TARGET ${target}_shared) | 122 | if(TARGET ${target}_shared) |
75 | set(_targets ${_targets} ${target}_shared) | 123 | set(_targets ${_targets} ${target}_shared) |
124 | # Shared libraries should first try to link against other shared libraries. | ||
125 | set(${target}_shared_primary shared) | ||
126 | # If that fails (because the shared target doesn't exist), try linking | ||
127 | # against the static library. This requires the static library's objects to | ||
128 | # be PIC. | ||
129 | set(${target}_shared_secondary static) | ||
76 | endif() | 130 | endif() |
131 | # It can also be a static library at the same time. | ||
77 | if(TARGET ${target}_static) | 132 | if(TARGET ${target}_static) |
78 | set(_targets ${_targets} ${target}_static) | 133 | set(_targets ${_targets} ${target}_static) |
134 | # Static libraries aren't actually linked, but their dependencies are | ||
135 | # recorded by "linking" them. If we link an executable to a static library, | ||
136 | # we want to also link statically against its transitive dependencies. | ||
137 | set(${target}_static_primary static) | ||
138 | # If a dependency doesn't exist as static library, we link against the | ||
139 | # shared one. | ||
140 | set(${target}_static_secondary shared) | ||
79 | endif() | 141 | endif() |
142 | # If it's neither, then it's an executable. | ||
80 | if(NOT _targets) | 143 | if(NOT _targets) |
81 | set(_targets ${_targets} ${target}) | 144 | set(_targets ${_targets} ${target}) |
145 | # Executables preferrably link against static libraries, so they are | ||
146 | # standalone and can be shipped without any external dependencies. As a | ||
147 | # frame of reference: nTox becomes an 1.3M binary instead of 139K on x86_64 | ||
148 | # Linux. | ||
149 | set(${target}_primary static) | ||
150 | set(${target}_secondary shared) | ||
82 | endif() | 151 | endif() |
83 | 152 | ||
84 | foreach(target ${_targets}) | 153 | foreach(dep ${ARGN}) |
85 | foreach(dep ${ARGN}) | 154 | foreach(_target ${_targets}) |
86 | if(TARGET ${dep}_shared) | 155 | if(TARGET ${dep}_${${_target}_primary}) |
87 | target_link_libraries(${target} ${dep}_shared) | 156 | target_link_libraries(${_target} ${dep}_${${_target}_primary}) |
88 | elseif(TARGET ${dep}_static) | 157 | elseif(TARGET ${dep}_${${_target}_secondary}) |
89 | target_link_libraries(${target} ${dep}_static) | 158 | target_link_libraries(${_target} ${dep}_${${_target}_secondary}) |
90 | else() | 159 | else() |
91 | target_link_libraries(${target} ${dep}) | 160 | # We record the modules linked to this target, so that we can collect |
161 | # them later when linking a composed module. | ||
162 | list(FIND LINK_MODULES ${dep} _index) | ||
163 | if(_index EQUAL -1) | ||
164 | set(LINK_MODULES ${LINK_MODULES} ${dep}) | ||
165 | endif() | ||
166 | |||
167 | target_link_libraries(${_target} ${dep}) | ||
92 | endif() | 168 | endif() |
93 | endforeach() | 169 | endforeach() |
94 | endforeach() | 170 | endforeach() |
171 | |||
172 | set(${target}_LINK_MODULES ${${target}_LINK_MODULES} ${LINK_MODULES} PARENT_SCOPE) | ||
95 | endfunction() | 173 | endfunction() |