Add export-dev target to export all libraries
[helenos.git] / uspace / lib / meson.build
blob06d16bf42e7c8b74997723f3bdcd0d4b1cb72dc3
2 # Copyright (c) 2019 Jiří Zárevúcky
3 # All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
9 # - Redistributions of source code must retain the above copyright
10 #   notice, this list of conditions and the following disclaimer.
11 # - Redistributions in binary form must reproduce the above copyright
12 #   notice, this list of conditions and the following disclaimer in the
13 #   documentation and/or other materials provided with the distribution.
14 # - The name of the author may not be used to endorse or promote products
15 #   derived from this software without specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 always_static = not CONFIG_BUILD_SHARED_LIBS
31 # Which libraries are installed when CONFIG_DEVEL_FILES is enabled
32 installed_libs = [
33         'c',
34         'math',
35         'display',
36         'pixconv',
37         'posix',
38         'clui',
39         'pcm',
40         'hound',
41         'gfx',
42         'gfximage',
43         'ipcgfx',
44         'congfx',
45         'display',
46         'ui',
49 # IMPORTANT: Dependencies must be listed before libs that depend on them.
50 libs = [
51         'c',
53         'inet',
55         'input',
56         'output',
57         'console',
58         'device',
60         'block',
61         'clipboard',
62         'clui',
63         'codepage',
64         'compress',
65         'corecfg',
66         'cpp',
67         'crypto',
68         'dltest',
69         'fbfont',
70         'fdisk',
71         'fmtutil',
72         'fs',
73         'gfx',
74         'http',
75         'ipctest',
76         'label',
77         'math',
78         'minix',
79         'nettl',
80         'ofw',
81         'pcm',
82         'pcut',
83         'pixconv',
84         'posix',
85         'riff',
86         'scsi',
87         'sif',
88         'tbarcfg',
89         'trackmod',
90         'untar',
91         'uri',
93         'bithenge',
94         'congfx',
95         'drv',
96         'ext4',
97         'gfxfont',
98         'gfximage',
99         'hound',
100         'ipcgfx',
101         'memgfx',
102         'nic',
103         'usb',
104         'usbdev',
105         'usbhid',
106         'usbhost',
107         'usbvirt',
108         'virtio',
110         'ieee80211',
111         'ddev',
112         'dispcfg',
113         'display',
114         'wndmgt',
116         'ui',
119 # Generated list of include directory paths
120 include_paths = []
122 # Generated list of test sources
123 testfiles = []
125 # Text of the install script.
126 uspace_lib_devel_install_script_text = []
128 foreach l : libs
129         # Variables that might be defined in library meson files:
131         # List of source files.
132         # To set it correctly, use files('list.c', 'of.c', 'files.c')
133         # Often this is the only variable that needs to be set.
134         src = files()
136         # Public include directories. These are used by everyone who depends
137         # on this library.
138         # Use include_directories('include_dir1', 'include_dir2') to set this.
139         # If the variable is omitted, it defaults to 'include' subdirectory
140         # if it exists, or the source directory otherwise.
141         # If the library has no headers, you can use
142         # includes += include_directories()
143         includes = []
145         # Private include directories.
146         # Unnecessary if you always include private headers using relative
147         # paths, but may be useful if you need to override system headers.
148         private_includes = []
150         # List of dependency names.
151         # E.g. to use libnic and libuntar use
152         # `deps = [ 'nic', 'untar' ]`
153         deps = []
155         # Extra arguments for the C compiler.
156         # Don't use for arguments involving file paths.
157         c_args = []
159         # Shared object version of the library.
160         version = '0.0'
162         # Sources of unit tests.
163         # Automatically get compiled into a test binary,
164         # but not into the library itself.
165         test_src = []
167         # Language of the library.
168         # Currently supported options are 'c' and 'cpp', with 'c' being default.
169         language = 'c'
171         # Whether the library can be dynamically linked.
172         # Eventually, all libraries will be shared by default and this will go away.
173         allow_shared = false
175         subdir(l)
177         # Add `include` or `.` subdirectory to include dirs if needed.
178         if includes.length() == 0
179                 incdir = join_paths(l, 'include')
180                 if run_command('[', '-d', incdir, ']').returncode() == 0
181                         includes += include_directories(incdir)
182                         _sdir = meson.current_source_dir() / l / 'include'
184                         if installed_libs.contains(l)
185                                 uspace_lib_devel_install_script_text += 'cp -R -L -T "@0@" "${DESTDIR}include/lib@1@"'.format(_sdir, l)
186                         endif
188                         exported_devel_files += ['include', _sdir, 'lib' + l]
189                 else
190                         includes += include_directories(l)
192                         if installed_libs.contains(l)
193                                 _sdir = meson.current_source_dir() / l
194                                 uspace_lib_devel_install_script_text += 'mkdir -p "${DESTDIR}include/lib@0@"'.format(l)
195                                 uspace_lib_devel_install_script_text += 'cp -L -t "${DESTDIR}include/lib@0@" "@1@"/*.h || true'.format(l, _sdir)
196                         endif
197                 endif
198         endif
200         # Pretty much everything depends on libc.
201         if l != 'c'
202                 deps += 'c'
203         endif
205         if language == 'cpp' and l != 'cpp'
206                 deps += 'cpp'
207         endif
209         mapfile = meson.current_build_dir() / 'lib' + l + '.map'
211         link_args = [ '-Wl,--no-undefined,--no-allow-shlib-undefined' ]
212         # We want linker to generate link map for debugging.
213         link_args += [ '-Wl,-Map,' + mapfile ]
215         # Convert strings to dependency objects
216         # TODO: this dependency business is way too convoluted due to issues in current Meson
217         _any_deps = []
218         _static_deps = []
219         _shared_deps = []
220         _include_deps = []
221         foreach s : deps
222                 _any_deps += get_variable('lib' + s).get('any')
223                 _static_deps += get_variable('lib' + s).get('static')
224                 if not always_static
225                         _shared_deps += get_variable('lib' + s).get('shared')
226                 endif
227                 _include_deps += get_variable('lib' + s).get('include')
228         endforeach
230         install_static_lib = CONFIG_DEVEL_FILES and installed_libs.contains(l)
231         install_shared_lib = allow_shared
233         _shared_dep = disabler()
235         if src.length() > 0
236                 if not always_static
237                         _libname = 'lib' + l + '.so.' + version.split('.')[0]
239                         _shared_lib = shared_library(l, src,
240                                 # TODO: Include private headers using #include "quoted",
241                                 #       and get rid of private_includes.
242                                 include_directories: [ private_includes, includes ],
243                                 dependencies: _shared_deps,
244                                 c_args: arch_uspace_c_args + c_args,
245                                 cpp_args: arch_uspace_c_args + c_args,
246                                 link_args: arch_uspace_c_args + arch_uspace_link_args + link_args,
247                                 version: version,
248                                 build_by_default: true,
249                         )
251                         if install_shared_lib
252                                 install_files += [[ 'lib', _shared_lib.full_path(), _libname ]]
253                                 install_deps += [ _shared_lib ]
254                         endif
256                         if install_shared_lib and install_debug_files
257                                 install_files += [[ 'debug/lib', mapfile, _libname + '.map' ]]
258                         endif
260                         if disassemble
261                                 _disasm = custom_target('lib' + l + '.disasm',
262                                         command: [ objdump, '-S', '@INPUT@' ],
263                                         input: _shared_lib,
264                                         output: 'lib' + l + '.disasm',
265                                         capture: true,
266                                         build_by_default: true,
267                                 )
269                                 if install_shared_lib and install_debug_files
270                                         install_files += [[ 'debug/lib', _disasm.full_path(), _libname + '.disasm' ]]
271                                         install_deps += [ _disasm ]
272                                 endif
273                         endif
275                         _shared_dep = declare_dependency(
276                                 link_with: _shared_lib,
277                                 # TODO: Always use `include` subdirectory for public headers,
278                                 #       and ditch the variable.
279                                 include_directories: includes,
280                                 dependencies: _shared_deps,
281                         )
282                 endif
284                 _static_lib = static_library(l, src,
285                         # TODO: Include private headers using #include "quoted",
286                         #       and get rid of private_includes.
287                         include_directories: [ private_includes, includes ],
288                         dependencies: _include_deps,
289                         c_args: arch_uspace_c_args + c_args,
290                         cpp_args: arch_uspace_c_args + c_args,
291                 )
293                 if install_static_lib
294                         install_files += [[ 'lib', _static_lib.full_path(), 'lib' + l + '.a' ]]
295                         install_deps += [ _static_lib ]
296                 endif
298                 exported_devel_files += ['staticlib', _static_lib, 'lib' + l + '.a']
300                 _static_dep = declare_dependency(
301                         link_with: _static_lib,
302                         # TODO: Always use `include` subdirectory for public headers,
303                         #       and ditch the variable.
304                         include_directories: includes,
305                         dependencies: _static_deps,
306                 )
308                 if always_static or not allow_shared
309                         _any_dep = declare_dependency(
310                                 link_with: _static_lib,
311                                 # TODO: Always use `include` subdirectory for public headers,
312                                 #       and ditch the variable.
313                                 include_directories: includes,
314                                 dependencies: _any_deps,
315                         )
316                 else
317                         _any_dep = declare_dependency(
318                                 link_with: _shared_lib,
319                                 # TODO: Always use `include` subdirectory for public headers,
320                                 #       and ditch the variable.
321                                 include_directories: includes,
322                                 dependencies: _any_deps,
323                         )
324                 endif
326                 _include_dep = declare_dependency(
327                         # TODO: Always use `include` subdirectory for public headers,
328                         #       and ditch the variable.
329                         include_directories: includes,
330                         dependencies: _include_deps,
331                 )
332         else
333                 # Header-only library.
334                 _any_dep = declare_dependency(
335                         include_directories: includes,
336                         dependencies: _any_deps,
337                 )
338                 _static_dep = declare_dependency(
339                         include_directories: includes,
340                         dependencies: _static_deps,
341                 )
342         endif
344         if test_src.length() > 0
345                 testfiles += [ {
346                         'name': l,
347                         'src': test_src,
348                         'includes': [ private_includes, includes ],
349                 } ]
350         endif
352         set_variable('lib' + l, {
353                 'any': _any_dep,
354                 'static': _static_dep,
355                 'shared': _shared_dep,
356                 'include': _include_dep,
357         })
358 endforeach
360 if not CONFIG_PCUT_TESTS
361         subdir_done()
362 endif
364 # Test binaries
365 foreach test : testfiles
366         _testname = test['name']
367         _libname = _testname.split('-')[0]
368         _ldargs = []
369         _test_binname = 'test-lib' + _testname
371         if link_map
372                 # We want linker to generate link map for debugging.
373                 _ldargs += [ '-Wl,-Map,' + meson.current_build_dir() / _test_binname + '.map' ]
374         endif
376         _bin = executable(_test_binname, test.get('src'),
377                 include_directories: test.get('includes'),
378                 dependencies: [ get_variable('lib' + _libname).get('any'), libpcut.get('any') ],
379                 link_whole: libstartfiles,
380                 c_args: arch_uspace_c_args,
381                 cpp_args: arch_uspace_c_args,
382                 link_args: arch_uspace_c_args + arch_uspace_link_args + _ldargs,
383                 build_by_default: true,
384         )
386         install_files += [[ 'test', _bin.full_path(), _test_binname ]]
387         install_deps += [ _bin ]
389         if disassemble
390                 _disasm = custom_target(_test_binname + '.disasm',
391                         command: [ objdump, '-S', '@INPUT@' ],
392                         input: _bin,
393                         output: _test_binname + '.disasm',
394                         capture: true,
395                         build_by_default: true,
396                 )
398                 if install_debug_files
399                         install_files += [[ 'debug/test', _disasm.full_path(), _test_binname + '.disasm' ]]
400                         install_deps += [ _disasm ]
401                 endif
402         endif
403 endforeach