diff options
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/ModulePackage.cmake | 98 | ||||
-rw-r--r-- | cmake/StrictAbi.cmake | 46 |
2 files changed, 119 insertions, 25 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() |
diff --git a/cmake/StrictAbi.cmake b/cmake/StrictAbi.cmake index fdf3664b..5a646d77 100644 --- a/cmake/StrictAbi.cmake +++ b/cmake/StrictAbi.cmake | |||
@@ -9,26 +9,42 @@ | |||
9 | # | 9 | # |
10 | ################################################################################ | 10 | ################################################################################ |
11 | 11 | ||
12 | function(make_version_script header ns lib) | 12 | find_program(SHELL NAMES sh dash bash zsh fish) |
13 | execute_process( | ||
14 | COMMAND ${SHELL} -c "egrep '^\\w' ${header} | grep '${ns}_[a-z0-9_]*(' | grep -v '^typedef' | grep -o '${ns}_[a-z0-9_]*(' | egrep -o '\\w+' | sort -u" | ||
15 | OUTPUT_VARIABLE ${lib}_SYMS | ||
16 | OUTPUT_STRIP_TRAILING_WHITESPACE) | ||
17 | string(REPLACE "\n" ";" ${lib}_SYMS ${${lib}_SYMS}) | ||
18 | 13 | ||
19 | set(${lib}_VERSION_SCRIPT "${CMAKE_BINARY_DIR}/${lib}.ld") | 14 | macro(make_version_script) |
15 | if(STRICT_ABI AND SHELL AND ENABLE_SHARED) | ||
16 | _make_version_script(${ARGN}) | ||
17 | endif() | ||
18 | endmacro() | ||
20 | 19 | ||
21 | file(WRITE ${${lib}_VERSION_SCRIPT} | 20 | function(_make_version_script target) |
21 | set(${target}_VERSION_SCRIPT "${CMAKE_BINARY_DIR}/${target}.ld") | ||
22 | |||
23 | file(WRITE ${${target}_VERSION_SCRIPT} | ||
22 | "{ global:\n") | 24 | "{ global:\n") |
23 | foreach(sym ${${lib}_SYMS}) | 25 | |
24 | file(APPEND ${${lib}_VERSION_SCRIPT} | 26 | foreach(sublib ${ARGN}) |
25 | "${sym};\n") | 27 | string(REPLACE "^" ";" sublib ${sublib}) |
26 | endforeach(sym) | 28 | list(GET sublib 0 header) |
27 | file(APPEND ${${lib}_VERSION_SCRIPT} | 29 | list(GET sublib 1 ns) |
30 | |||
31 | execute_process( | ||
32 | COMMAND ${SHELL} -c "egrep '^\\w' ${header} | grep '${ns}_[a-z0-9_]*(' | grep -v '^typedef' | grep -o '${ns}_[a-z0-9_]*(' | egrep -o '\\w+' | sort -u" | ||
33 | OUTPUT_VARIABLE sublib_SYMS | ||
34 | OUTPUT_STRIP_TRAILING_WHITESPACE) | ||
35 | string(REPLACE "\n" ";" sublib_SYMS ${sublib_SYMS}) | ||
36 | |||
37 | foreach(sym ${sublib_SYMS}) | ||
38 | file(APPEND ${${target}_VERSION_SCRIPT} | ||
39 | "${sym};\n") | ||
40 | endforeach(sym) | ||
41 | endforeach(sublib) | ||
42 | |||
43 | file(APPEND ${${target}_VERSION_SCRIPT} | ||
28 | "local: *; };\n") | 44 | "local: *; };\n") |
29 | 45 | ||
30 | set_target_properties(${lib}_shared PROPERTIES | 46 | set_target_properties(${target}_shared PROPERTIES |
31 | LINK_FLAGS -Wl,--version-script,${${lib}_VERSION_SCRIPT}) | 47 | LINK_FLAGS -Wl,--version-script,${${target}_VERSION_SCRIPT}) |
32 | endfunction() | 48 | endfunction() |
33 | 49 | ||
34 | option(STRICT_ABI "Enforce strict ABI export in dynamic libraries" OFF) | 50 | option(STRICT_ABI "Enforce strict ABI export in dynamic libraries" OFF) |