1#
2# SPDX-License-Identifier: BSD-3-Clause
3#
4# Copyright © 2019-2021 Keith Packard
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12#
13# 2. Redistributions in binary form must reproduce the above
14#    copyright notice, this list of conditions and the following
15#    disclaimer in the documentation and/or other materials provided
16#    with the distribution.
17#
18# 3. Neither the name of the copyright holder nor the names of its
19#    contributors may be used to endorse or promote products derived
20#    from this software without specific prior written permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33# OF THE POSSIBILITY OF SUCH DAMAGE.
34#
35project('picolibc', 'c',
36	default_options: [
37	  'buildtype=minsize',
38	  'debug=true',
39	  'c_std=c18',
40	  'b_staticpic=false',
41          'warning_level=2',
42	],
43	license : 'BSD',
44	meson_version : '>= 0.53',
45	version: '1.8.6'
46       )
47
48targets = []
49
50fs = import('fs')
51
52cc = meson.get_compiler('c')
53
54# Find the compiler installation directory by parsing the output of
55# cc -print-search-dirs
56
57cc_install_dir = ''
58foreach _line : run_command(cc.cmd_array() + ['-print-search-dirs'], check : false).stdout().split('\n')
59  if _line.startswith('install: ')
60    if meson.version().version_compare('>=0.56')
61      # trim off the leading 'install: '
62      cc_install_dir = _line.substring(9)
63    else
64      cc_install_dir = run_command(['expr', _line, ':', 'install: *\(.*\)'], check : false).stdout().split('\n')[0]
65    endif
66  endif
67endforeach
68
69# these options are required for all C compiler operations, including
70# detecting many C compiler features, as we cannot expect there
71# to be a working C library on the system.
72
73core_c_args = []
74if not get_option('use-stdlib')
75  core_c_args += cc.get_supported_arguments(['-nostdlib'])
76endif
77
78# Find the picolibc name for the host cpu. Provide
79# for some common aliases
80
81cpu_family_aliases = {
82		       # aarch64
83		       'arm64' : 'aarch64',
84		       # arc
85		       'arc64' : 'arc',
86		       # cris
87		       'crisv32' : 'cris',
88		       # m68hc11
89		       'm6811' : 'm68hc11',
90		       'm6812' : 'm68hc11',
91		       'm68hc12' : 'm68hc11',
92		       # m68k
93		       'fido' : 'm68k',
94		       # m88k
95		       'm88110' : 'm88k',
96		       # Microblaze
97		       'microblazeel' : 'microblaze',
98		       # or1k
99		       'or1knd': 'or1k',
100		       # powerpc
101		       'powerpc64' : 'powerpc',
102		       'ppc64' : 'powerpc',
103		       'ppc64le' : 'powerpc',
104		       # riscv
105		       'riscv32' : 'riscv',
106		       'riscv64' : 'riscv',
107		       # sparc
108		       'sparc64' : 'sparc',
109		       # x86
110		       'amd64' : 'x86',
111		       'i486' : 'x86',
112		       'i586' : 'x86',
113		       'i686' : 'x86',
114		       'x86_64' : 'x86',
115		     }
116
117# Check for an alias, default to provided name
118host_cpu_family = cpu_family_aliases.get(host_machine.cpu_family(), host_machine.cpu_family())
119
120# Make sure we have meson build support for the machine-specific files
121if not fs.is_file('newlib/libc/machine' / host_cpu_family / 'meson.build')
122  message = '''
123
124Unsupported architecture: "@0@"
125
126    Read the Supported Architectures section in README.md
127    to learn how to add a new architecture.
128'''
129  error(message.format(host_cpu_family))
130endif
131
132# Find out about float types
133
134long_double_code = '''
135#include <float.h>
136#ifndef __LDBL_MANT_DIG__
137#error No long double support in float.h
138#endif
139long double test(void)
140{
141	long double ld = 0.0L;
142	return ld;
143}
144'''
145
146have_long_double = cc.compiles(long_double_code, name : 'long double check', args: core_c_args)
147
148enable_multilib = get_option('multilib')
149multilib_list = get_option('multilib-list')
150multilib_exclude = get_option('multilib-exclude')
151enable_picolib = get_option('picolib')
152enable_picocrt = get_option('picocrt')
153enable_picocrt_lib = get_option('picocrt-lib')
154enable_semihost = get_option('semihost')
155enable_tests = get_option('tests')
156enable_native_tests = get_option('native-tests')
157tests_enable_stack_protector = get_option('tests-enable-stack-protector')
158tests_enable_full_malloc_stress = get_option('tests-enable-full-malloc-stress')
159tests_enable_posix_io = get_option('tests-enable-posix-io')
160have_alias_attribute_option = get_option('have-alias-attribute')
161have_format_attribute_option = get_option('have-format-attribute')
162have_weak_attribute_option = get_option('have-weak-attribute')
163
164newlib_iconv_encodings = get_option('newlib-iconv-encodings')
165newlib_iconv_encodings_exclude = get_option('newlib-iconv-encodings-exclude')
166newlib_iconv_from_encodings = get_option('newlib-iconv-from-encodings')
167newlib_iconv_to_encodings = get_option('newlib-iconv-to-encodings')
168newlib_iconv_external_ccs = get_option('newlib-iconv-external-ccs')
169
170newlib_atexit_dynamic_alloc = get_option('newlib-atexit-dynamic-alloc')
171newlib_nano_malloc = get_option('newlib-nano-malloc')
172lite_exit = get_option('lite-exit')
173
174newlib_elix_level = get_option('newlib-elix-level')
175c_args = ['-include', '@0@/@1@'.format(meson.current_build_dir(), 'picolibc.h')] + core_c_args
176native_c_args = ['-DNO_NEWLIB']
177
178if get_option('profile')
179  c_args += ['-pg', '-no-pie']
180endif
181
182if get_option('freestanding')
183  c_args += ['-ffreestanding']
184endif
185
186# Disable ssp and fortify source while building picolibc (it's enabled
187# by default by the ubuntu native compiler)
188c_flags = cc.get_supported_arguments(['-fno-common', '-frounding-math', '-fsignaling-nans',
189				      '-Wno-unsupported-floating-point-opt', '-fno-stack-protector',
190				      '-fno-builtin-copysignl'])
191
192c_sanitize_bounds_flags = cc.get_supported_arguments(['-fsanitize=bounds'])
193c_sanitize_trap_flags = cc.get_supported_arguments(['-fsanitize-undefined-trap-on-error'])
194c_sanitize_no_trap_flags = cc.get_supported_arguments(['-fno-sanitize-undefined-trap-on-error', '-static-libubsan'])
195have_ubsan = c_sanitize_bounds_flags != []
196c_args += c_flags
197native_c_args += c_flags
198
199sanitize_bounds = get_option('sanitize-bounds')
200sanitize_trap_on_error = get_option('sanitize-trap-on-error')
201
202if sanitize_bounds
203  if not have_ubsan
204    error('sanitize-bounds option selected but -fsanitize=bounds is not supported')
205  endif
206  c_args += c_sanitize_bounds_flags
207  native_c_args += c_sanitize_bounds_flags
208  if sanitize_trap_on_error
209    c_args += c_sanitize_trap_flags
210  else
211    c_args += c_sanitize_no_trap_flags
212  endif
213endif
214
215if cc.symbols_have_underscore_prefix()
216  global_prefix = '_'
217else
218  global_prefix = ''
219endif
220fast_strcmp = get_option('fast-strcmp')
221
222newlib_mb = get_option('newlib-mb')
223newlib_locale_info = get_option('newlib-locale-info')
224
225newlib_obsolete_math = get_option('newlib-obsolete-math')
226newlib_obsolete_math_float = get_option('newlib-obsolete-math-float')
227newlib_obsolete_math_double = get_option('newlib-obsolete-math-double')
228
229sysroot_install = get_option('sysroot-install')
230system_libc = get_option('system-libc')
231prefix = get_option('prefix')
232
233nm = find_program('nm', required : false)
234
235check_duplicate_names = nm.found()
236
237if nm.found()
238  duplicate_names = find_program('scripts/duplicate-names', required : true)
239endif
240
241# Select exit code
242picoexit = get_option('picoexit')
243
244# Shared stdio options
245io_long_long = get_option('io-long-long')
246newlib_io_long_long = get_option('newlib-io-long-long')
247if newlib_io_long_long != 'auto'
248  io_long_long = newlib_io_long_long == 'true'
249endif
250
251io_c99_formats = get_option('io-c99-formats')
252newlib_io_c99_formats = get_option('newlib-io-c99-formats')
253if newlib_io_c99_formats != 'auto'
254  io_c99_formats = newlib_io_c99_formats == 'true'
255endif
256
257io_pos_args = get_option('io-pos-args')
258newlib_io_pos_args = get_option('newlib-io-pos-args')
259if newlib_io_pos_args != 'auto'
260  io_pos_args = newlib_io_pos_args == 'true'
261endif
262
263# Select stdio implementation
264tinystdio = get_option('tinystdio')
265
266has_link_defsym = meson.get_cross_property('has_link_defsym',
267                                           cc.has_link_argument('-Wl,--defsym=' + 'start=0') or
268                                           cc.has_link_argument('-Wl,--defsym=' + '_start=0') or
269                                           cc.has_link_argument('-Wl,--defsym=' + '__start=0') or
270                                           cc.has_link_argument('-Wl,--defsym=' + '___start=0') )
271has_link_alias = meson.get_cross_property('has_link_alias', cc.has_link_argument('-Wl,-alias,' + global_prefix + 'main,testalias'))
272lib_gcc = meson.get_cross_property('libgcc', '-lgcc')
273
274# tinystdio options
275posix_console = tinystdio and get_option('posix-console')
276posix_io = tinystdio and (get_option('posix-io') or posix_console)
277io_float_exact = not tinystdio or get_option('io-float-exact')
278atomic_ungetc = tinystdio and get_option('atomic-ungetc')
279format_default = get_option('format-default')
280printf_aliases = get_option('printf-aliases')
281io_percent_b = tinystdio and get_option('io-percent-b')
282io_long_double = get_option('io-long-double') or get_option('newlib-io-long-double')
283printf_small_ultoa = tinystdio and get_option('printf-small-ultoa')
284minimal_io_long_long = tinystdio and get_option('minimal-io-long-long')
285fast_bufio = tinystdio and get_option('fast-bufio')
286
287if printf_aliases
288  double_printf_compile_args=['-DPICOLIBC_DOUBLE_PRINTF_SCANF']
289  float_printf_compile_args=['-DPICOLIBC_FLOAT_PRINTF_SCANF']
290  llong_printf_compile_args=['-DPICOLIBC_LONG_LONG_PRINTF_SCANF']
291  int_printf_compile_args=['-DPICOLIBC_INTEGER_PRINTF_SCANF']
292  min_printf_compile_args=['-DPICOLIBC_MINIMAL_PRINTF_SCANF']
293else
294  double_printf_compile_args=[]
295  float_printf_compile_args=[]
296  llong_printf_compile_args=[]
297  int_printf_compile_args=[]
298  min_printf_compile_args=[]
299endif
300double_printf_link_args=double_printf_compile_args
301float_printf_link_args=float_printf_compile_args
302llong_printf_link_args=llong_printf_compile_args
303int_printf_link_args=int_printf_compile_args
304min_printf_link_args=min_printf_compile_args
305
306if tinystdio and printf_aliases
307  vfprintf_symbol = global_prefix + 'vfprintf'
308  __d_vfprintf_symbol = global_prefix + '__d_vfprintf'
309  __f_vfprintf_symbol = global_prefix + '__f_vfprintf'
310  __l_vfprintf_symbol = global_prefix + '__l_vfprintf'
311  __i_vfprintf_symbol = global_prefix + '__i_vfprintf'
312  __m_vfprintf_symbol = global_prefix + '__m_vfprintf'
313  vfscanf_symbol = global_prefix + 'vfscanf'
314  __d_vfscanf_symbol = global_prefix + '__d_vfscanf'
315  __f_vfscanf_symbol = global_prefix + '__f_vfscanf'
316  __l_vfscanf_symbol = global_prefix + '__l_vfscanf'
317  __i_vfscanf_symbol = global_prefix + '__i_vfscanf'
318  __m_vfscanf_symbol = global_prefix + '__m_vfscanf'
319
320  if has_link_defsym
321    if format_default != 'double'
322      double_printf_link_args += '-Wl,--defsym=' + vfprintf_symbol +  '=' + __d_vfprintf_symbol
323      double_printf_link_args += '-Wl,--defsym=' + vfscanf_symbol + '=' + __d_vfscanf_symbol
324    endif
325    if format_default != 'float'
326      float_printf_link_args += '-Wl,--defsym=' + vfprintf_symbol +  '=' + __f_vfprintf_symbol
327      float_printf_link_args += '-Wl,--defsym=' + vfscanf_symbol + '=' + __f_vfscanf_symbol
328    endif
329    if format_default != 'long-long'
330      llong_printf_link_args += '-Wl,--defsym=' + vfprintf_symbol +  '=' + __l_vfprintf_symbol
331      llong_printf_link_args += '-Wl,--defsym=' + vfscanf_symbol + '=' + __l_vfscanf_symbol
332    endif
333    if format_default != 'integer'
334      int_printf_link_args += '-Wl,--defsym=' + vfprintf_symbol +  '=' + __i_vfprintf_symbol
335      int_printf_link_args += '-Wl,--defsym=' + vfscanf_symbol + '=' + __i_vfscanf_symbol
336    endif
337    if format_default != 'minimal'
338      min_printf_link_args += '-Wl,--defsym=' + vfprintf_symbol +  '=' + __m_vfprintf_symbol
339      min_printf_link_args += '-Wl,--defsym=' + vfscanf_symbol + '=' + __m_vfscanf_symbol
340    endif
341  elif has_link_alias
342    if format_default == 'double'
343      float_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __d_vfprintf_symbol
344      float_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __d_vfscanf_symbol
345      llong_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __d_vfprintf_symbol
346      llong_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __d_vfscanf_symbol
347      int_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __d_vfprintf_symbol
348      int_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __d_vfscanf_symbol
349      min_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __d_vfprintf_symbol
350      min_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __d_vfscanf_symbol
351    endif
352    if format_default == 'float'
353      double_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __f_vfprintf_symbol
354      double_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __f_vfscanf_symbol
355      llong_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __f_vfprintf_symbol
356      llong_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __f_vfscanf_symbol
357      int_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __f_vfprintf_symbol
358      int_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __f_vfscanf_symbol
359      min_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __f_vfprintf_symbol
360      min_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __f_vfscanf_symbol
361    endif
362    if format_default == 'long-long'
363      double_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __l_vfprintf_symbol
364      double_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __l_vfscanf_symbol
365      float_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __l_vfprintf_symbol
366      float_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __l_vfscanf_symbol
367      int_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __l_vfprintf_symbol
368      int_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __l_vfscanf_symbol
369      min_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __l_vfprintf_symbol
370      min_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __l_vfscanf_symbol
371    endif
372    if format_default == 'integer'
373      double_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __i_vfprintf_symbol
374      double_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __i_vfscanf_symbol
375      float_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __i_vfprintf_symbol
376      float_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __i_vfscanf_symbol
377      llong_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __i_vfprintf_symbol
378      llong_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __i_vfscanf_symbol
379      min_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __i_vfprintf_symbol
380      min_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __i_vfscanf_symbol
381    endif
382    if format_default == 'minimal'
383      double_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __m_vfprintf_symbol
384      double_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __m_vfscanf_symbol
385      float_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __m_vfprintf_symbol
386      float_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __m_vfscanf_symbol
387      llong_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __m_vfprintf_symbol
388      llong_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __m_vfscanf_symbol
389      int_printf_link_args += '-Wl,-alias,' + vfprintf_symbol +  ',' + __m_vfprintf_symbol
390      int_printf_link_args += '-Wl,-alias,' + vfscanf_symbol + ',' + __m_vfscanf_symbol
391    endif
392    if format_default != 'double'
393      double_printf_link_args += '-Wl,-alias,' + __d_vfprintf_symbol +  ',' + vfprintf_symbol
394      double_printf_link_args += '-Wl,-alias,' + __d_vfscanf_symbol + ',' + vfscanf_symbol
395    endif
396    if format_default != 'float'
397      float_printf_link_args += '-Wl,-alias,' + __f_vfprintf_symbol +  ',' + vfprintf_symbol
398      float_printf_link_args += '-Wl,-alias,' + __f_vfscanf_symbol + ',' + vfscanf_symbol
399    endif
400    if format_default != 'long-long'
401      llong_printf_link_args += '-Wl,-alias,' + __l_vfprintf_symbol +  ',' + vfprintf_symbol
402      llong_printf_link_args += '-Wl,-alias,' + __l_vfscanf_symbol + ',' + vfscanf_symbol
403    endif
404    if format_default != 'integer'
405      int_printf_link_args += '-Wl,-alias,' + __i_vfprintf_symbol +  ',' + vfprintf_symbol
406      int_printf_link_args += '-Wl,-alias,' + __i_vfscanf_symbol + ',' + vfscanf_symbol
407    endif
408    if format_default != 'minimal'
409      min_printf_link_args += '-Wl,-alias,' + __m_vfprintf_symbol +  ',' + vfprintf_symbol
410      min_printf_link_args += '-Wl,-alias,' + __m_vfscanf_symbol + ',' + vfscanf_symbol
411    endif
412  else
413    if enable_tests
414      # If the alias flag is not supported and we are building tests, emit an
415      # error here to avoid surprising test failures.
416      error('Symbol alias linker flag not supported - printf tests will fail!')
417    endif
418  endif
419endif
420
421# A bunch of newlib-stdio only options
422newlib_global_stdio_streams = get_option('newlib-global-stdio-streams')
423newlib_fvwrite_in_streamio = get_option('newlib-fvwrite-in-streamio')
424newlib_fseek_optimization = get_option('newlib-fseek-optimization')
425newlib_nano_formatted_io = get_option('newlib-nano-formatted-io')
426newlib_io_float = get_option('newlib-io-float')
427newlib_stdio64 = get_option('newlib-stdio64')
428newlib_wide_orient = get_option('newlib-wide-orient')
429newlib_have_fcntl = get_option('newlib-have-fcntl')
430
431# Check for a bunch of newlib-stdio only options and complain
432# if they are selected while using tinystdio
433
434if tinystdio
435  if newlib_io_float
436    error('tinystdio uses a run-time mechanism to select floating point io (newlib-io-float)')
437  endif
438  if newlib_global_stdio_streams
439    error('tinystdio always has (reentrant) global stdio streams (newlib-global-stdio-streams)')
440  endif
441  if newlib_fvwrite_in_streamio
442    error('tinystdio has no fvwrite support (newlib-fvwrite-in-streamio)')
443  endif
444  if newlib_fseek_optimization
445    error('tinystdio has no fseek support (newlib-fseek-optimization)')
446  endif
447  if newlib_nano_formatted_io
448    error('tinystdio uses a run-time mechanism to select smaller printf code (newlib-nano-formatted-io)')
449  endif
450  if newlib_wide_orient
451    error('tinystdio does not support the wide-orient option (newlib-wide-orient)')
452  endif
453else
454  if posix_console
455    error('newlib stdio does not support the posix-console option (posix-console)')
456  endif
457  if io_pos_args
458    error('newlib stdio has bugs with positional arguments (io-pos-args)')
459  endif
460endif
461
462if host_cpu_family == ''
463  host_cc_machine=run_command(cc.cmd_array() + ['-dumpmachine'], check : true).stdout().strip().split('-')
464  host_cpu_family=host_cc_machine[0]
465  message('Computed host_cpu_family as ' + host_cpu_family)
466endif
467
468if have_alias_attribute_option == 'auto'
469  have_alias_attribute = cc.has_function_attribute('alias')
470else
471  have_alias_attribute = have_alias_attribute_option == 'true'
472endif
473
474if have_format_attribute_option == 'auto'
475  have_format_attribute = cc.has_function_attribute('format')
476else
477  have_format_attribute = have_format_attribute_option == 'true'
478endif
479
480if have_weak_attribute_option == 'auto'
481  have_weak_attribute = cc.has_function_attribute('weak')
482else
483  have_weak_attribute = have_weak_attribute_option == 'true'
484endif
485
486tls_model_spec = ''
487thread_local_storage = false
488thread_local_storage_option = get_option('thread-local-storage')
489have_picolibc_tls_api = fs.is_file('newlib/libc/picolib/machine' / host_cpu_family / 'tls.c')
490if thread_local_storage_option == 'auto' or thread_local_storage_option == 'picolibc'
491  # We assume that _set_tls() is defined in the arch specific tls.c
492  if thread_local_storage_option == 'auto' or have_picolibc_tls_api
493    thread_local_storage = not cc.has_function('__emutls_get_address', args: core_c_args + [lib_gcc])
494  endif
495else
496  thread_local_storage = get_option('thread-local-storage') == 'true'
497endif
498if thread_local_storage
499  tls_model_spec = '%{!ftls-model:-ftls-model=' + get_option('tls-model') + '}'
500endif
501
502if sysroot_install
503  sysroot = run_command(cc.cmd_array() + ['-print-sysroot'], check : true).stdout().split('\n')[0]
504  if sysroot != ''
505    specs_prefix_format = '%R/@0@'
506  else
507    sysroot = cc_install_dir + '../../../..'
508    specs_prefix_format = '%:getenv(GCC_EXEC_PREFIX ../../@0@)'
509  endif
510  if not get_option('sysroot-install-skip-checks')
511    if sysroot == ''
512      error('sysroot install requested, but compiler has no sysroot')
513    endif
514    if not fs.is_samepath(sysroot, prefix)
515      error('sysroot install requires --prefix=' + sysroot)
516    endif
517  endif
518else
519  specs_prefix_format = prefix + '/@0@'
520endif
521
522build_type_subdir = get_option('build-type-subdir')
523
524lib_dir = prefix / get_option('libdir') / build_type_subdir
525
526include_dir = prefix / get_option('includedir') / build_type_subdir
527
528newlib_iconv_dir = get_option('newlib-iconv-dir')
529if newlib_iconv_dir == ''
530  newlib_iconv_dir = join_paths(lib_dir, 'locale')
531endif
532
533newlib_iconv_runtime_dir = get_option('newlib-iconv-runtime-dir')
534if newlib_iconv_runtime_dir == ''
535  newlib_iconv_runtime_dir = newlib_iconv_dir
536endif
537
538specs_dir_option = get_option('specsdir')
539if build_type_subdir != ''
540  specs_dir = ''
541  specs_install = false
542elif specs_dir_option == ''
543  specs_dir = cc_install_dir
544  specs_install = specs_dir != ''
545elif specs_dir_option == 'none'
546  specs_dir = ''
547  specs_install = false
548else
549  specs_dir = join_paths(prefix, specs_dir_option)
550  specs_install = true
551endif
552
553# Let targets add more support libraries
554additional_libs_list = meson.get_cross_property('additional_libs', [])
555
556compiler_id = cc.get_id()
557if compiler_id == 'ccomp'
558  # When passing the specs file to CompCert, the libcompcert needs to be included there as well
559  additional_libs_list += '-lcompcert'
560endif
561
562additional_libs = ' '.join(additional_libs_list)
563
564if compiler_id == 'gcc' and target_machine.cpu_family() == 'msp430'
565  # Extract -mhwmult-selection-snippet from GCC.
566  dumped_specs = run_command(cc.cmd_array() + '-dumpspecs').stdout()
567  hwmult_start = dumped_specs.split('%{mhwmult=auto')[1]
568  hwmult_snippet = '%{mhwmult=auto' + hwmult_start.split('-lc')[0]
569  additional_libs += hwmult_snippet
570endif
571
572specs_extra = ''
573specs_extra_list = meson.get_cross_property('specs_extra', [])
574if specs_extra_list != []
575  specs_extra = '\n' + '\n'.join(specs_extra_list)
576endif
577
578specs_printf = ''
579if tinystdio and printf_aliases
580  specs_printf=('%{DPICOLIBC_DOUBLE_PRINTF_SCANF:--defsym=vfprintf=' + __d_vfprintf_symbol + '}' +
581		' %{DPICOLIBC_DOUBLE_PRINTF_SCANF:--defsym=vfscanf=' + __d_vfscanf_symbol + '}' +
582                ' %{DPICOLIBC_FLOAT_PRINTF_SCANF:--defsym=vfprintf=' + __f_vfprintf_symbol + '}' +
583		' %{DPICOLIBC_FLOAT_PRINTF_SCANF:--defsym=vfscanf=' + __f_vfscanf_symbol + '}' +
584		' %{DPICOLIBC_LONG_LONG_PRINTF_SCANF:--defsym=vfprintf=' + __l_vfprintf_symbol + '}' +
585		' %{DPICOLIBC_LONG_LONG_PRINTF_SCANF:--defsym=vfscanf=' + __l_vfscanf_symbol + '}' +
586		' %{DPICOLIBC_INTEGER_PRINTF_SCANF:--defsym=vfprintf=' + __i_vfprintf_symbol + '}' +
587		' %{DPICOLIBC_INTEGER_PRINTF_SCANF:--defsym=vfscanf=' + __i_vfscanf_symbol + '}' +
588		' %{DPICOLIBC_MINIMAL_PRINTF_SCANF:--defsym=vfprintf=' + __m_vfprintf_symbol + '}' +
589		' %{DPICOLIBC_MINIMAL_PRINTF_SCANF:--defsym=vfscanf=' + __m_vfscanf_symbol + '}')
590endif
591
592crt0_expr = '%{-crt0=*:crt0-%*%O%s; :crt0%O%s}'
593
594if system_libc
595  specs_isystem = ''
596  specs_libpath = ''
597  specs_startfile = crt0_expr
598else
599
600#
601# Construct path values for specs file
602#
603# Each of these needs to handle --picolibc-prefix and
604# --picolibc-buildtype options, system-root vs absolute paths and
605# multilib stuff. That makes this all unreasonably complicated.
606#
607# Each option is computed in three parts, the 'prefix' value
608# (corresponding to --picolibc-prefix), the 'buildtype' value
609# (corresponding to --picolibc-buildtype) and the 'gen' value (for
610# when neither of these options is specifed).
611#
612# Because 'getenv' appends a space afterwards in GCC spec files, the
613# entire final path elements must be specified inside the parens;
614# e.g. %:getenv(FOO a/b/c) instead of %:getenv(FOO)/a/b/c. That means
615# we use the specs_prefix_format value computed above to build paths
616# instead of simple concatenation
617#
618
619#
620# How to format each of the three option-selected
621# values
622#
623picolibc_prefix_format = '-picolibc-prefix=*:@0@'
624picolibc_buildtype_format = '-picolibc-buildtype=*:@0@'
625gen_format = '@0@'
626
627#
628# How to glue the three options together
629#
630specs_option_format = '%{@0@; @1@; :@2@}'
631
632#
633# Build the -isystem value
634#
635
636prefix_include_dir = '%*/@0@/'.format(get_option('includedir'))
637isystem_prefix = picolibc_prefix_format.format(prefix_include_dir)
638
639buildtype_include_dir = specs_prefix_format.format(get_option('includedir') / '%*')
640isystem_buildtype = picolibc_buildtype_format.format(buildtype_include_dir)
641
642gen_include_dir = specs_prefix_format.format(get_option('includedir'))
643isystem_gen = gen_format.format(gen_include_dir)
644
645specs_isystem = '-isystem ' + specs_option_format.format(isystem_prefix, isystem_buildtype, isystem_gen)
646
647#
648# Build the non-multilib -L value
649#
650
651prefix_lib_dir = '%*/@0@'.format(get_option('libdir'))
652lib_prefix = picolibc_prefix_format.format(prefix_lib_dir)
653
654buildtype_lib_dir = specs_prefix_format.format(get_option('libdir') / '%*')
655lib_buildtype = picolibc_buildtype_format.format(buildtype_lib_dir)
656
657gen_lib_dir = specs_prefix_format.format(get_option('libdir'))
658lib_gen = gen_format.format(gen_lib_dir)
659
660specs_libpath = '-L' + specs_option_format.format(lib_prefix, lib_buildtype, lib_gen)
661
662#
663# Build the non-multilib *startfile options
664#
665
666prefix_crt0_path = '%*/@0@'.format(get_option('libdir')) / crt0_expr
667crt0_prefix = picolibc_prefix_format.format(prefix_crt0_path)
668
669buildtype_crt0_path = specs_prefix_format.format(get_option('libdir') / '%*' / crt0_expr)
670crt0_buildtype = picolibc_buildtype_format.format(buildtype_crt0_path)
671
672gen_crt0_path = specs_prefix_format.format(get_option('libdir') / crt0_expr)
673crt0_gen = gen_format.format(gen_crt0_path)
674
675#
676# Now build multilib versions of the -L and *startfile values
677#
678if enable_multilib
679
680  #
681  # Build the multilib -L value
682  #
683  prefix_multilib_dir = '%*/@0@'.format(get_option('libdir') / '%M')
684  multilib_prefix = picolibc_prefix_format.format(prefix_multilib_dir)
685
686  buildtype_multilib_dir = specs_prefix_format.format(get_option('libdir') / '%*/%M')
687  multilib_buildtype = picolibc_buildtype_format.format(buildtype_multilib_dir)
688
689  gen_multilib_dir = specs_prefix_format.format(get_option('libdir') / '%M')
690  multilib_gen = gen_format.format(gen_multilib_dir)
691
692  specs_multilibpath = '-L' + specs_option_format.format(multilib_prefix, multilib_buildtype, multilib_gen)
693
694  #
695  # Prepend the multilib -L option to the non-multilib option
696  #
697  specs_libpath = specs_multilibpath + ' ' + specs_libpath
698
699  #
700  # Build the multilib *startfile options
701  #
702  prefix_multilib_crt0_path = '%*/@0@'.format(get_option('libdir')) / '%M' / crt0_expr
703  crt0_prefix = picolibc_prefix_format.format(prefix_multilib_crt0_path)
704
705  buildtype_multilib_crt0_path = specs_prefix_format.format(get_option('libdir') / '%*/%M' / crt0_expr)
706  crt0_buildtype = picolibc_buildtype_format.format(buildtype_multilib_crt0_path)
707
708  gen_multilib_crt0_path = specs_prefix_format.format(get_option('libdir') / '%M' / crt0_expr)
709  crt0_gen = gen_format.format(gen_multilib_crt0_path)
710endif
711
712#
713# Construct the *startfile value from the options computed
714# above. As there's only one value, it's either the
715# multilib path or the non-multilib path
716#
717specs_startfile = specs_option_format.format(crt0_prefix, crt0_buildtype, crt0_gen)
718endif
719
720specs_data = configuration_data()
721specs_data.set('SPECS_ISYSTEM', specs_isystem)
722specs_data.set('SPECS_LIBPATH', specs_libpath)
723specs_data.set('SPECS_STARTFILE', specs_startfile)
724specs_data.set('TLSMODEL', tls_model_spec)
725specs_data.set('LINK_SPEC', meson.get_cross_property('link_spec', ''))
726specs_data.set('CC1_SPEC', meson.get_cross_property('cc1_spec', ''))
727specs_data.set('CC1PLUS_SPEC', meson.get_cross_property('cc1plus_spec', ''))
728specs_data.set('ADDITIONAL_LIBS', additional_libs)
729specs_data.set('SPECS_EXTRA', specs_extra)
730specs_data.set('SPECS_PRINTF', specs_printf)
731
732# Create C and C++ specific specs data,
733# that includes setting the correct linker script
734# and adding the C++ startup/shutdown files
735
736specs_c_data = specs_data
737
738specs_c_data.set('PICOLIBC_LD', 'picolibc.ld')
739specs_c_data.set('CRTBEGIN', '')
740specs_c_data.set('CRTEND', '')
741
742specs_cpp_data = specs_data
743
744specs_cpp_data.set('PICOLIBC_LD', 'picolibcpp.ld')
745specs_cpp_data.set('CRTBEGIN', 'crtbegin%O%s')
746specs_cpp_data.set('CRTEND', 'crtend%O%s')
747
748picolibc_specs = configure_file(input: 'picolibc.specs.in',
749				output: 'picolibc.specs',
750				configuration: specs_c_data,
751				install_dir: specs_dir,
752				install: specs_install)
753
754picolibc_specs_name = 'picolibc.specs'
755
756picolibcpp_specs = configure_file(input: 'picolibc.specs.in',
757				  output: 'picolibcpp.specs',
758				  configuration: specs_cpp_data,
759				  install_dir: specs_dir,
760				  install: specs_install)
761
762# Not all compilers necessarily support all warnings; only use these which are:
763c_warnings = [
764  '-Werror=implicit-function-declaration',
765  '-Werror=vla',
766  '-Warray-bounds',
767  '-Wold-style-definition',
768  '-Werror=double-promotion',
769]
770if get_option('analyzer')
771  c_warnings += [
772    '-fanalyzer',
773    ]
774endif
775disabled_warnings = [
776  '-Wno-missing-braces',
777  '-Wno-implicit-int',
778  '-Wno-return-type',
779  '-Wno-unused-command-line-argument',
780]
781c_flags = cc.get_supported_arguments(c_warnings, disabled_warnings)
782c_args += c_flags
783native_c_args += c_flags
784
785# Make sure _LIBC is not defined when building tests
786test_c_args = c_args
787c_args += ['-D_LIBC', '-U_FORTIFY_SOURCE']
788
789# Select a fortify source option
790fortify_source = get_option('fortify-source')
791if fortify_source == 'none'
792  test_c_args += '-U_FORTIFY_SOURCE'
793else
794  test_c_args += '-D_FORTIFY_SOURCE=' + fortify_source
795endif
796
797# CompCert does not support bitfields in packed structs, so avoid using this optimization
798bitfields_in_packed_structs_code = '''
799struct test { int part: 24; } __attribute__((packed));
800unsigned int foobar (const struct test *p) { return p->part; }
801'''
802have_bitfields_in_packed_structs = cc.compiles(bitfields_in_packed_structs_code, name : 'packed structs may contain bitfields', args: core_c_args)
803
804# CompCert does not have __builtin_mul_overflow
805builtin_mul_overflow_code = '''
806#include <stddef.h>
807int overflows (size_t a, size_t b) { size_t x; return __builtin_mul_overflow(a, b, &x); }
808volatile size_t aa = 42;
809int main (void) { return overflows(aa, aa); }
810'''
811have_builtin_mul_overflow = cc.links(builtin_mul_overflow_code, name : 'has __builtin_mul_overflow', args: core_c_args)
812
813# CompCert does not have __builtin_add_overflow
814builtin_add_overflow_code = '''
815#include <stddef.h>
816int overflows (size_t a, size_t b) { size_t x; return __builtin_add_overflow(a, b, &x); }
817volatile size_t aa = 42;
818int main (void) { return overflows(aa, aa); }
819'''
820have_builtin_add_overflow = cc.links(builtin_add_overflow_code, name : 'has __builtin_add_overflow', args: core_c_args)
821
822# CompCert does not support _Complex
823complex_code = '''
824float _Complex test(float _Complex z) { return z; }
825'''
826have_complex = cc.compiles(complex_code, name : 'supports _Complex', args: core_c_args)
827
828builtin_complex_code = '''
829#include <stddef.h>
830double _Complex test(double r, double i) { return __builtin_complex(r, i); }
831'''
832
833have_builtin_complex = have_complex and cc.compiles(builtin_complex_code, name : 'supports __builtin_complex', args: core_c_args)
834
835# CompCert does not have __builtin_expect
836builtin_expect_code = '''
837volatile int a = 42;
838int main (void) {
839  return __builtin_expect(a, 1);
840}
841'''
842have_builtin_expect = cc.links(builtin_expect_code, name : 'has __builtin_expect', args: core_c_args)
843
844werror_c_args = core_c_args + cc.get_supported_arguments('-Werror')
845
846# CompCert uses the GCC preprocessor, which causes to
847#  > #if __has_attribute(__alloc_size__)
848# produce a wrong result. So test if the compiler has that attribute
849alloc_size_code = '''
850void *foobar(int) __attribute__((__alloc_size__(1)));
851void *foobar2(int, int) __attribute__((__alloc_size__(1, 2)));
852'''
853have_alloc_size = cc.compiles(alloc_size_code, name : 'attribute __alloc_size__', args : werror_c_args)
854
855# attributes constructor/destructor are a GNU extension - if the compiler doesn't have them, don't test them.
856attr_ctor_dtor_code = '''
857void __attribute__((constructor(101))) ctor (void) {}
858void __attribute__((destructor(101))) dtor (void) {}
859'''
860have_attr_ctor_dtor = cc.compiles(attr_ctor_dtor_code, name : 'attributes constructor/destructor', args : werror_c_args)
861
862if enable_multilib
863  used_libs = []
864
865  # Ask the compiler for the set of available multilib configurations,
866  # set up the build system to compile for all desired ones
867
868  target_list = run_command(cc.cmd_array() + get_option('c_args') + ['--print-multi-lib'], check : true).stdout().strip().split('\n')
869
870  has_mcmodel = false
871  foreach target : target_list
872    if target.contains('mcmodel=')
873      has_mcmodel = true
874    endif
875  endforeach
876
877  foreach target : target_list
878    message('target ' + target)
879    tmp = target.split(';')
880    matches_exclude = false
881    foreach exclude : multilib_exclude
882      if tmp[0].contains(exclude)
883        matches_exclude = true
884        message('skipping target ' + tmp[0])
885        break
886      endif
887    endforeach
888    if matches_exclude
889      continue
890    endif
891    flags = []
892
893    # Let the user specify a subset of the possible multilib
894    # configurations to build for
895    if multilib_list == [] or tmp[0] in multilib_list
896      used_libs += tmp[0]
897      if tmp.length() > 1
898	foreach flag : tmp[1].strip('@').split('@')
899	  if flag != ''
900	    if host_cpu_family == 'nios2'
901	      # Hacks for NIOS II to get rid of -fsingle-precision-constant
902	      # mode (which breaks libm). We don't need fph2 as that
903	      # doesn't set the single precision constant flag
904	      if flag == 'mcustom-fpu-cfg=60-1'
905		flags += ['-mcustom-fmuls=252', '-mcustom-fadds=253',
906			  '-mcustom-fsubs=254']
907	      elif flag == 'mcustom-fpu-cfg=60-2'
908		flags += ['-mcustom-fmuls=252', '-mcustom-fadds=253',
909			  '-mcustom-fsubs=254', '-mcustom-fdivs=255']
910	      elif flag == 'mcustom-fpu-cfg=72-3'
911		flags += ['-mcustom-floatus=243', '-mcustom-fixsi=244',
912			  '-mcustom-floatis=245','-mcustom-fcmpgts=246',
913			  '-mcustom-fcmples=249', '-mcustom-fcmpeqs=250',
914			  '-mcustom-fcmpnes=251', '-mcustom-fmuls=252',
915			  '-mcustom-fadds=253', '-mcustom-fsubs=254',
916			  '-mcustom-fdivs=255']
917	      else
918		flags += '-' + flag
919	      endif
920	    else
921	      flags += '-' + flag
922	    endif
923	  endif
924	endforeach
925	if tmp[0] == '.'
926	  name = ''
927	else
928	  name = tmp[0].underscorify()
929	endif
930      else
931	name = ''
932      endif
933      targets += name
934
935      # rv64 needs to use a non-default mcmodel so that variables can
936      # live in a broader range of memory addresses
937      if not has_mcmodel and name.startswith('rv64')
938	flags += [ '-mcmodel=medany' ]
939      endif
940
941      # Add any extra flags for this target from the cross file
942      flags += meson.get_cross_property('c_args_' + name, [])
943
944      value = [tmp[0], flags]
945      set_variable('target_' + name, value)
946    endif
947  endforeach
948
949  # Make sure all requested multilib configurations
950  # are actually available
951  if multilib_list != []
952    foreach lib : multilib_list
953      if lib not in used_libs
954	error('Unavailable multilib: ' + lib)
955      endif
956    endforeach
957  endif
958else
959  targets = ['']
960  target_ = ['.', []]
961endif
962
963foreach target : ['default-target'] + targets
964
965  message('generate linker script target ' + target)
966
967  custom_mem_config = meson.get_cross_property('custom_mem_config_' + target, '')
968
969  if target == 'default-target' or custom_mem_config != ''
970
971    picolibc_linker_type_data = configuration_data()
972    # We need to use different alignment flags for .tdata/.tbss for ld.bfd
973    # (ALIGN_WITH_INPUT, which is not supported by ld.lld) and ld.lld
974    # (ALIGN(__tls_align), which is rejected as non-constant by ld.bfd), so we use
975    # the {BFD,LLD}_{START,END} templates to comment out the incompatible flag.
976    if cc.get_linker_id() == 'ld.lld'
977      picolibc_linker_type_data.set('BFD_START', '/* For ld.bfd: ')
978      picolibc_linker_type_data.set('BFD_END', '*/')
979      picolibc_linker_type_data.set('LLD_START', '')
980      picolibc_linker_type_data.set('LLD_END', '')
981      if host_cpu_family == 'riscv'
982        # ld.lld before version 15 did not support linker relaxations, disable
983        # them if we are using an older version.
984        # There is no `cc.get_linker_version()` function, so we detect ld.lld
985        # version 15 by checking for a newly added linker flag.
986        if not cc.has_link_argument('--package-metadata=1')
987          message('Linking for RISCV with ld.lld < 15, forcing -mno-relax')
988          c_args += ['-mno-relax']
989        endif
990      endif
991    else
992      picolibc_linker_type_data.set('BFD_START', '')
993      picolibc_linker_type_data.set('BFD_END', '')
994      picolibc_linker_type_data.set('LLD_START', '/* For ld.lld: ')
995      picolibc_linker_type_data.set('LLD_END', '*/')
996    endif
997
998    init_memory_template = '''
999	@0@ (rx!w) :
1000		ORIGIN = DEFINED(__@0@) ? __@0@ : @1@,
1001		LENGTH = DEFINED(__@0@_size) ? __@0@_size : @2@'''
1002    init_phdr_template = '''
1003	text_@0@ PT_LOAD;'''
1004    init_section_template = '''
1005	.@0@ : {@1@
1006	} >@2@ AT>@2@ :@3@
1007'''
1008    default_init_section_template = init_section_template.format('@0@', '''
1009		KEEP (*(.text.init.enter))
1010		KEEP (*(.data.init.enter))
1011		KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*)))''',
1012                                                                 '@1@',
1013                                                                 '@2@')
1014
1015    additional_sections = []
1016
1017    fallback_flash_addr = '0x10000000'
1018    fallback_flash_size = '0x00010000'
1019
1020    if meson.get_cross_property('separate_boot_flash_' + custom_mem_config,
1021                                meson.get_cross_property('separate_boot_flash', false))
1022      boot_flash_addr = meson.get_cross_property(
1023        'default_boot_flash_addr_' + custom_mem_config,
1024        meson.get_cross_property(
1025          'default_boot_flash_addr',
1026          '0x10000000'))
1027      boot_flash_size = meson.get_cross_property(
1028        'default_boot_flash_size_' + custom_mem_config,
1029        meson.get_cross_property(
1030          'default_boot_flash_size',
1031          '0x00000400'))
1032      additional_sections = [
1033        {
1034          'name' : 'boot_flash',
1035          'addr' : boot_flash_addr,
1036          'size' : boot_flash_size,
1037          'contents' : default_init_section_template.format('boot_flash', 'boot_flash', 'text_boot_flash')
1038        }]
1039      fallback_flash_addr = '0x10000400'
1040      fallback_flash_size = '0x0000fc00'
1041    else
1042      additional_section_names = meson.get_cross_property('additional_sections_' + custom_mem_config,
1043                                                     meson.get_cross_property('additional_sections', []))
1044      if additional_section_names != []
1045        foreach section_name : additional_section_names
1046          default_content_list =  ['*.(.' + section_name + ')', '*.(.' + section_name + '.*)']
1047          content_list = meson.get_cross_property('default_' + section_name + '_contents', default_content_list)
1048          contents = ''
1049          foreach content : content_list
1050            contents += '''
1051		@0@'''.format(content)
1052          endforeach
1053          additional_sections += [
1054            {
1055              'name' : section_name,
1056              'addr' : meson.get_cross_property('default_' + section_name + '_addr'),
1057              'size' : meson.get_cross_property('default_' + section_name + '_size'),
1058              'contents' : init_section_template.format(section_name, contents, section_name, 'text_' + section_name)
1059            }]
1060        endforeach
1061      endif
1062    endif
1063
1064    init_memory = ''
1065    init_phdrs = ''
1066    init_sections = ''
1067
1068    if additional_sections != []
1069      foreach section : additional_sections
1070        section_name = section['name']
1071        init_memory += init_memory_template.format(section_name, section['addr'], section['size'])
1072        init_phdrs += init_phdr_template.format(section_name)
1073        init_sections += section['contents']
1074      endforeach
1075    else
1076      init_memory = ''
1077      init_sections = default_init_section_template.format('init', 'flash', 'text')
1078    endif
1079
1080    picolibc_linker_type_data.set('INIT_MEMORY', init_memory)
1081    picolibc_linker_type_data.set('INIT_PHDRS', init_phdrs)
1082    picolibc_linker_type_data.set('INIT_SECTIONS', init_sections)
1083
1084    picolibc_linker_type_data.set(
1085      'DEFAULT_FLASH_ADDR', meson.get_cross_property(
1086        'default_flash_addr_' + custom_mem_config,
1087        meson.get_cross_property(
1088          'default_flash_addr',
1089          fallback_flash_addr)))
1090
1091    picolibc_linker_type_data.set(
1092      'DEFAULT_FLASH_SIZE', meson.get_cross_property(
1093        'default_flash_size_' + custom_mem_config,
1094        meson.get_cross_property(
1095          'default_flash_size',
1096          fallback_flash_size)))
1097
1098    picolibc_linker_type_data.set(
1099      'DEFAULT_RAM_ADDR',
1100      meson.get_cross_property('default_ram_addr_' + custom_mem_config,
1101                               meson.get_cross_property('default_ram_addr',
1102                                                        '0x20000000')))
1103
1104    picolibc_linker_type_data.set(
1105      'DEFAULT_RAM_SIZE',
1106      meson.get_cross_property('default_ram_size_' + custom_mem_config,
1107                               meson.get_cross_property('default_ram_size',
1108                                                        '0x00008000')))
1109
1110    picolibc_linker_type_data.set(
1111      'DEFAULT_STACK_SIZE',
1112      meson.get_cross_property('default_stack_size_' + custom_mem_config,
1113                               meson.get_cross_property('default_stack_size',
1114                                                        '0x00001000')))
1115
1116    picolibc_linker_type_data.set(
1117      'DEFAULT_ALIGNMENT',
1118      meson.get_cross_property('default_alignment_' + custom_mem_config,
1119                               meson.get_cross_property('default_alignment',
1120                                                        '8')))
1121
1122    picolibc_ld_data = configuration_data()
1123    picolibc_ld_data.merge_from(picolibc_linker_type_data)
1124    picolibc_ld_data.set('CPP_START', '/*')
1125    picolibc_ld_data.set('CPP_END', '*/')
1126    picolibc_ld_data.set('C_START', '')
1127    picolibc_ld_data.set('C_END', '')
1128    picolibc_ld_data.set('PREFIX', global_prefix)
1129
1130    if target == 'default-target'
1131      picolibc_ld_file = 'picolibc.ld'
1132      picolibc_ld_variable = 'picolibc_ld'
1133      picolibc_ld_config_variable = 'picolibc_ld_config'
1134      picolibcpp_ld_file = 'picolibcpp.ld'
1135      picolibcpp_ld_variable = 'picolibcpp_ld'
1136      picolibcpp_ld_config_variable = 'picolibcpp_ld_config'
1137      picolibc_ld_install = true
1138    else
1139      picolibc_ld_file = 'picolibc_' + custom_mem_config + '.ld'
1140      picolibc_ld_variable = 'picolibc_' + target + '_ld'
1141      picolibc_ld_config_variable = 'picolibc_' + target + 'ld_config'
1142      picolibcpp_ld_file = 'picolibcpp_' + custom_mem_config + '.ld'
1143      picolibcpp_ld_variable = 'picolibcpp_' + target + '_ld'
1144      picolibcpp_ld_config_variable = 'picolibcpp_' + target + 'ld_config'
1145      picolibc_ld_install = false
1146    endif
1147
1148    if not is_variable(picolibc_ld_config_variable)
1149      set_variable(picolibc_ld_config_variable,
1150                   configure_file(input: 'picolibc.ld.in',
1151                                  output: picolibc_ld_file,
1152                                  configuration: picolibc_ld_data,
1153                                  install: picolibc_ld_install,
1154                                  install_dir: lib_dir))
1155    endif
1156
1157    set_variable(picolibc_ld_variable, get_variable(picolibc_ld_config_variable))
1158
1159    picolibcpp_ld_data = configuration_data()
1160    picolibcpp_ld_data.merge_from(picolibc_linker_type_data)
1161    picolibcpp_ld_data.set('CPP_START', '')
1162    picolibcpp_ld_data.set('CPP_END', '')
1163    picolibcpp_ld_data.set('C_START', '/*')
1164    picolibcpp_ld_data.set('C_END', '*/')
1165    picolibcpp_ld_data.set('PREFIX', global_prefix)
1166
1167    if not is_variable(picolibcpp_ld_config_variable)
1168      set_variable(picolibcpp_ld_config_variable,
1169                 configure_file(input: 'picolibc.ld.in',
1170                                output: picolibcpp_ld_file,
1171                                configuration: picolibcpp_ld_data,
1172                                install: picolibc_ld_install,
1173                                install_dir: lib_dir))
1174    endif
1175
1176    set_variable(picolibcpp_ld_variable, get_variable(picolibcpp_ld_config_variable))
1177
1178  endif
1179endforeach
1180
1181conf_data = configuration_data()
1182
1183# The supported builtins vary depending on compiler and target.
1184# If you want to check for a given builtin, add an array
1185#   ['some_builtin_name', '__call_to_builtin(1,2,3);']
1186# The below loop will then add the define HAVE_SOME_BUILTIN_NAME if the code snippet
1187#   > int main (void) { __call_to_builtin(1,2,3); return 0; }
1188# can be compiled + linked.
1189# The name should match the builtin, but technically it's not necessary
1190builtins = [
1191  ['builtin_alloca', '__builtin_alloca(1)', 'void *'],
1192  ['builtin_ffs', '__builtin_ffs(42)', 'int'],
1193  ['builtin_ffsl', '__builtin_ffsl((long)42)', 'long'],
1194  ['builtin_ffsll', '__builtin_ffsll((long long)42)', 'long long'],
1195  ['builtin_ctz', '__builtin_ctz((unsigned int)42)', 'int'],
1196  ['builtin_ctzl', '__builtin_ctzl((unsigned long)42)', 'int'],
1197  ['builtin_ctzll', '__builtin_ctzll((unsigned long long)42)', 'int'],
1198  ['builtin_copysignl', '__builtin_copysignl((long double)42, (long double) 42)', 'long double'],
1199  ['builtin_copysign', '__builtin_copysign(42, 42)', 'double'],
1200  ['builtin_isinfl', '__builtin_isinfl((long double)42)', 'int'],
1201  ['builtin_isinf', '__builtin_isinf((long double)42)', 'int'],
1202  ['builtin_isnanl', '__builtin_isnanl((long double)42)', 'int'],
1203  ['builtin_isnan', '__builtin_isnan((long double)42)', 'int'],
1204  ['builtin_finitel', '__builtin_finitel((long double)42)', 'int'],
1205  ['builtin_isfinite', '__builtin_isfinite((long double)42)', 'int'],
1206  ['builtin_issignalingl', '__builtin_issignalingl((long double)42)', 'int'],
1207]
1208foreach builtin : builtins
1209  builtin_template='''
1210static int foo(@1@ i __attribute__((unused))) { return 0; }
1211int main(void) { return foo(@0@); }
1212'''
1213  builtin_code = builtin_template.format(builtin[1], builtin[2])
1214  have_current_builtin = cc.links(builtin_code, name : 'test for __' + builtin[0], args: core_c_args)
1215  conf_data.set('_HAVE_' + builtin[0].to_upper(), have_current_builtin, description: 'The compiler supports __' + builtin[0])
1216endforeach
1217
1218NEWLIB_VERSION='4.1.0'
1219NEWLIB_MAJOR_VERSION=4
1220NEWLIB_MINOR_VERSION=1
1221NEWLIB_PATCHLEVEL_VERSION=0
1222
1223if get_option('newlib-retargetable-locking') != get_option('newlib-multithread')
1224  error('newlib-retargetable-locking and newlib-multithread must be set to the same value')
1225endif
1226
1227conf_data.set('_HAVE_CC_INHIBIT_LOOP_TO_LIBCALL',
1228	      cc.has_argument('-fno-tree-loop-distribute-patterns'),
1229	      description: 'Compiler flag to prevent detecting memcpy/memset patterns')
1230
1231conf_data.set('_HAVE_NO_BUILTIN_ATTRIBUTE',
1232	      cc.compiles('int __attribute__((no_builtin)) foo(int x) { return x + 1; }',
1233			  name : 'no_builtin attribute',
1234			  args : werror_c_args),
1235	      description: 'Compiler attribute to prevent the optimizer from adding new builtin calls')
1236
1237conf_data.set('_HAVE_LONG_DOUBLE', have_long_double,
1238	      description: 'Compiler has long double type')
1239conf_data.set('_HAVE_ALIAS_ATTRIBUTE', have_alias_attribute)
1240conf_data.set('_HAVE_FORMAT_ATTRIBUTE', have_format_attribute)
1241conf_data.set('_HAVE_WEAK_ATTRIBUTE', have_weak_attribute)
1242conf_data.set('_WANT_REGISTER_FINI', get_option('newlib-register-fini'))
1243conf_data.set('_WANT_IO_LONG_LONG', io_long_long)
1244conf_data.set('_WANT_MINIMAL_IO_LONG_LONG', minimal_io_long_long)
1245conf_data.set('_WANT_FAST_BUFIO', fast_bufio)
1246conf_data.set('_WANT_IO_POS_ARGS', io_pos_args)
1247conf_data.set('_WANT_IO_C99_FORMATS', io_c99_formats)
1248conf_data.set('_IO_FLOAT_EXACT', io_float_exact)
1249conf_data.set('_WANT_IO_PERCENT_B', io_percent_b)
1250conf_data.set('_WANT_IO_LONG_DOUBLE', io_long_double)
1251conf_data.set('_ASSERT_VERBOSE', get_option('assert-verbose'))
1252
1253if not tinystdio
1254  conf_data.set('NO_FLOATING_POINT', not newlib_io_float)
1255  conf_data.set('FLOATING_POINT', newlib_io_float)
1256  conf_data.set('_WANT_REENT_GLOBAL_STDIO_STREAMS', newlib_global_stdio_streams)
1257  conf_data.set('__LARGE64_FILES', newlib_stdio64)
1258endif
1259conf_data.set('_WANT_REENT_SMALL', get_option('newlib-reent-small'))
1260conf_data.set('_MB_CAPABLE', newlib_mb)
1261conf_data.set('_MB_LEN_MAX', newlib_mb ? '8' : '1')
1262conf_data.set('__SINGLE_THREAD__', get_option('newlib-multithread') == false)
1263conf_data.set('_ICONV_ENABLE_EXTERNAL_CCS', newlib_iconv_external_ccs)
1264conf_data.set('_ELIX_LEVEL', newlib_elix_level)
1265if newlib_iconv_external_ccs
1266  conf_data.set_quoted('ICONV_DEFAULT_NLSPATH', newlib_iconv_runtime_dir)
1267endif
1268conf_data.set('_ATEXIT_DYNAMIC_ALLOC', newlib_atexit_dynamic_alloc)
1269conf_data.set('_REENT_GLOBAL_ATEXIT', get_option('newlib-global-atexit'))
1270conf_data.set('_FVWRITE_IN_STREAMIO', newlib_fvwrite_in_streamio)
1271conf_data.set('_FSEEK_OPTIMIZATION', newlib_fseek_optimization)
1272conf_data.set('_WIDE_ORIENT', newlib_wide_orient)
1273conf_data.set('_HAVE_FCNTL', newlib_have_fcntl)
1274conf_data.set('_NANO_MALLOC', newlib_nano_malloc)
1275conf_data.set('_UNBUF_STREAM_OPT', get_option('newlib-unbuf-stream-opt'))
1276conf_data.set('_LITE_EXIT', lite_exit)
1277conf_data.set('_PICO_EXIT', picoexit)
1278conf_data.set('_NANO_FORMATTED_IO', newlib_nano_formatted_io)
1279conf_data.set('_RETARGETABLE_LOCKING', get_option('newlib-retargetable-locking'))
1280conf_data.set('TINY_STDIO', tinystdio, description: 'Use tiny stdio from gcc avr')
1281conf_data.set('_IEEE_LIBM', not get_option('want-math-errno'), description: 'math library does not set errno (offering only ieee semantics)')
1282conf_data.set('_WANT_MATH_ERRNO', get_option('want-math-errno'), description: 'math library sets errno')
1283conf_data.set('PREFER_SIZE_OVER_SPEED', get_option('optimization') == 's', description: 'Optimize for space over speed')
1284conf_data.set('FAST_STRCMP', fast_strcmp, description: 'Always optimize strcmp for performance')
1285conf_data.set('__HAVE_LOCALE_INFO__', newlib_locale_info, description: 'locale support')
1286conf_data.set('__HAVE_LOCALE_INFO_EXTENDED__', get_option('newlib-locale-info-extended'), description: 'extended locale support')
1287conf_data.set('NEWLIB_GLOBAL_ERRNO', get_option('newlib-global-errno'), description: 'use global errno variable')
1288conf_data.set('_HAVE_INITFINI_ARRAY', get_option('newlib-initfini-array'), description: 'compiler supports INIT_ARRAY sections')
1289conf_data.set('_HAVE_INIT_FINI', get_option('newlib-initfini'), description: 'Support _init() and _fini() functions')
1290conf_data.set('NEWLIB_TLS', thread_local_storage, description: 'use thread local storage')
1291conf_data.set('PICOLIBC_TLS', thread_local_storage, description: 'use thread local storage')
1292conf_data.set('_HAVE_PICOLIBC_TLS_API', thread_local_storage and have_picolibc_tls_api, description: '_set_tls and _init_tls functions available')
1293conf_data.set('POSIX_IO', posix_io, description: 'Use open/close/read/write in tinystdio')
1294conf_data.set('_PRINTF_SMALL_ULTOA', printf_small_ultoa, description: 'avoid software division in decimal conversion')
1295conf_data.set('ATOMIC_UNGETC', atomic_ungetc, description: 'Use atomics for fgetc/ungetc for re-entrancy')
1296conf_data.set('_PICOLIBC_ATOMIC_SIGNAL', get_option('atomic-signal'), description: 'Use atomics for signal/raise for re-entrancy')
1297conf_data.set('_HAVE_BITFIELDS_IN_PACKED_STRUCTS', have_bitfields_in_packed_structs, description: 'Use bitfields in packed structs')
1298conf_data.set('_HAVE_BUILTIN_MUL_OVERFLOW', have_builtin_mul_overflow, description: 'Compiler has __builtin_mul_overflow')
1299conf_data.set('_HAVE_BUILTIN_ADD_OVERFLOW', have_builtin_add_overflow, description: 'Compiler has __builtin_add_overflow')
1300conf_data.set('_HAVE_COMPLEX', have_complex, description: 'Compiler supports _Complex')
1301conf_data.set('_HAVE_BUILTIN_COMPLEX', have_builtin_complex, description: 'Compiler has __builtin_complex')
1302conf_data.set('_HAVE_BUILTIN_EXPECT', have_builtin_expect, description: 'Compiler has __builtin_expect')
1303conf_data.set('_HAVE_ALLOC_SIZE', have_alloc_size, description: 'The compiler REALLY has the attribute __alloc_size__')
1304conf_data.set('_HAVE_ATTRIBUTE_ALWAYS_INLINE',
1305	      cc.has_function_attribute('always_inline'),
1306	      description: 'The compiler supports the always_inline function attribute')
1307conf_data.set('_HAVE_ATTRIBUTE_GNU_INLINE',
1308	      cc.has_function_attribute('gnu_inline'),
1309	      description: 'The compiler supports the gnu_inline function attribute')
1310conf_data.set('__PICOLIBC_CRT_RUNTIME_SIZE',
1311	      get_option('crt-runtime-size'),
1312	      description: 'Compute static memory area sizes at runtime instead of link time')
1313if tinystdio
1314  conf_data.set('_FORMAT_DEFAULT_DOUBLE',
1315                format_default == 'double',
1316                description: 'The default printf functions is the double variant')
1317  conf_data.set('_FORMAT_DEFAULT_FLOAT',
1318                format_default == 'float',
1319                description: 'The default printf functions is the float variant')
1320  conf_data.set('_FORMAT_DEFAULT_INTEGER',
1321                format_default == 'integer',
1322                description: 'The default printf functions is the integer variant')
1323  conf_data.set('_FORMAT_DEFAULT_MINIMAL',
1324                format_default == 'minimal',
1325                description: 'The default printf functions is the minimal variant')
1326endif
1327errno_function=get_option('errno-function')
1328if errno_function == 'auto'
1329  errno_function = 'false'
1330  # these symbols are from the glibc and os x system C libraries,
1331  # it's useful to access them when doing testing
1332  foreach e : ['__errno_location', '__error']
1333    code = '''extern int @0@();
1334int main(void) {
1335	return @0@();
1336}
1337'''.format(e)
1338    if cc.links(code, name : 'detect errno function')
1339      errno_function = e
1340      break
1341    endif
1342  endforeach
1343elif errno_function == 'zephyr'
1344  if thread_local_storage
1345    errno_function = 'false'
1346  else
1347    errno_function = 'z_errno_wrap'
1348  endif
1349endif
1350
1351if errno_function != 'false'
1352  conf_data.set('__PICOLIBC_ERRNO_FUNCTION', errno_function)
1353endif
1354
1355# Obsolete newlib options
1356conf_data.set('_WANT_USE_LONG_TIME_T', get_option('newlib-long-time_t'), description: 'Obsoleted. Define time_t to long instead of using a 64-bit type')
1357conf_data.set('REENTRANT_SYSCALLS_PROVIDED', get_option('newlib-reentrant-syscalls-provided'), description: 'Obsoleted. Reentrant syscalls provided for us')
1358conf_data.set('MISSING_SYSCALL_NAMES', get_option('newlib-missing-syscall-names'), description: 'Obsoleted. Use regular syscalls')
1359
1360if newlib_obsolete_math == 'auto'
1361  obsolete_math_value = false
1362elif newlib_obsolete_math == 'true'
1363  obsolete_math_value = 1
1364elif newlib_obsolete_math == 'false'
1365  obsolete_math_value = 0
1366endif
1367
1368if newlib_obsolete_math_float == 'auto'
1369  obsolete_math_float_value = false
1370elif newlib_obsolete_math_float == 'true'
1371  obsolete_math_float_value = 1
1372elif newlib_obsolete_math_float == 'false'
1373  obsolete_math_float_value = 0
1374endif
1375
1376if newlib_obsolete_math_double == 'auto'
1377  obsolete_math_double_value = false
1378elif newlib_obsolete_math_double == 'true'
1379  obsolete_math_double_value = 1
1380elif newlib_obsolete_math_double == 'false'
1381  obsolete_math_double_value = 0
1382endif
1383
1384conf_data.set('__OBSOLETE_MATH', obsolete_math_value, description: 'Use old math code (undef auto, 0 no, 1 yes)')
1385conf_data.set('__OBSOLETE_MATH_FLOAT', obsolete_math_float_value, description: 'Use old math code for float funcs (undef auto, 0 no, 1 yes)')
1386conf_data.set('__OBSOLETE_MATH_DOUBLE', obsolete_math_double_value, description: 'Use old math code for double funcs (undef auto, 0 no, 1 yes)')
1387
1388# Check if compiler has -fno-builtin
1389
1390arg_fnobuiltin = []
1391if cc.has_argument('-fno-builtin')
1392  arg_fnobuiltin = ['-fno-builtin']
1393endif
1394
1395# Compute iconv encodings to support in the library
1396
1397# Dig out the list of available encodings from the encoding.aliases file. Only
1398# accept the first entry from each line
1399
1400available_encodings = []
1401# fs.read was added in meson version 0.57.0. The sed invocation can be
1402# removed once picolibc requires a version of meson newer than that.
1403if meson.version().version_compare('>=0.57')
1404  foreach line : fs.read('newlib/libc/iconv/encoding.aliases').split('\n')
1405    if line != '' and not line.startswith('#')
1406      available_encodings += [line.split()[0]]
1407    endif
1408  endforeach
1409else
1410  _available_encodings = run_command(['sed', '-e', '/^#/d', '-e', '/^$/d', '-e', 's/ .*$//', files('newlib/libc/iconv/encoding.aliases')[0]], check : true).stdout().split('\n')
1411  foreach _encoding : _available_encodings
1412    if _encoding != ''
1413      available_encodings += _encoding
1414    endif
1415  endforeach
1416endif
1417
1418# Include all available encodings if none were specified on the command line
1419
1420if newlib_iconv_encodings.length() == 0
1421  newlib_iconv_encodings = available_encodings
1422elif newlib_iconv_encodings.length() == 1 and newlib_iconv_encodings[0] == 'none'
1423  newlib_iconv_encodings = []
1424endif
1425
1426# Use newlib_iconv_encodings for from/to by default
1427
1428if newlib_iconv_from_encodings.length() == 0
1429  newlib_iconv_from_encodings = newlib_iconv_encodings
1430endif
1431if newlib_iconv_to_encodings.length() == 0
1432  newlib_iconv_to_encodings = newlib_iconv_encodings
1433endif
1434
1435# Set config variables for each requested 'from' encoding
1436
1437foreach from : newlib_iconv_from_encodings
1438  message('from ' + from)
1439  if not available_encodings.contains(from)
1440    error('Requested from encoding ' + from + ' is not available. Look in newlib/libc/iconv/encoding.aliases')
1441  endif
1442  encoding_include = true
1443  if from not in newlib_iconv_encodings_exclude
1444    conf_data.set('_ICONV_FROM_ENCODING_' + from.to_upper(), true)
1445  endif
1446endforeach
1447
1448# Set config variables for each requested 'to' encoding
1449
1450foreach to : newlib_iconv_to_encodings
1451  if not available_encodings.contains(to)
1452    error('Requested to encoding ' + to + ' is not available. Look in newlib/libc/iconv/encoding.aliases')
1453  endif
1454  if to not in newlib_iconv_encodings_exclude
1455    conf_data.set('_ICONV_TO_ENCODING_' + to.to_upper(), true)
1456  endif
1457endforeach
1458
1459version_array = meson.project_version().split('.')
1460
1461if version_array.length() > 2
1462  picolibc_patch_level = version_array[2]
1463else
1464  picolibc_patch_level = 0
1465endif
1466
1467conf_data.set('__PICOLIBC_VERSION__', '"@0@"'.format(meson.project_version()), description: 'The Picolibc version in string format.')
1468conf_data.set('__PICOLIBC__', version_array[0], description: 'The Picolibc major version number.')
1469conf_data.set('__PICOLIBC_MINOR__', version_array[1], description: 'The Picolibc minor version number.')
1470conf_data.set('__PICOLIBC_PATCHLEVEL__', picolibc_patch_level, description: 'The Picolibc patch level.')
1471
1472# Old version macros. These have just a single leading underscore,
1473# which isn't consistent with the newlib macros; they were created
1474# by mistake.
1475conf_data.set('_PICOLIBC_VERSION', '"@0@"'.format(meson.project_version()), description: 'The Picolibc version in string format.')
1476conf_data.set('_PICOLIBC__', version_array[0], description: 'The Picolibc major version number.')
1477conf_data.set('_PICOLIBC_MINOR__', version_array[1], description: 'The Picolibc minor version number.')
1478
1479conf_data.set('_NEWLIB_VERSION', '"@0@"'.format(NEWLIB_VERSION), description: 'The newlib version in string format.')
1480conf_data.set('__NEWLIB__', NEWLIB_MAJOR_VERSION, description: 'The newlib major version number.')
1481conf_data.set('__NEWLIB_MINOR__', NEWLIB_MINOR_VERSION, description: 'The newlib minor version number.')
1482conf_data.set('__NEWLIB_PATCHLEVEL__', NEWLIB_PATCHLEVEL_VERSION, description: 'The newlib patch level.')
1483
1484if tinystdio
1485  stdio_inc_dir = 'newlib/libc/tinystdio'
1486else
1487  stdio_inc_dir = 'newlib/libc/stdio'
1488endif
1489
1490inc_dirs = [stdio_inc_dir, '.', 'newlib/libc/include']
1491
1492inc = include_directories(inc_dirs)
1493
1494# We don't need '-fdata-sections' currently as there aren't any
1495# files with data used in separate code paths. This works around
1496# versions of gcc for RISC-V which have a bug that mis-names
1497# initialized read-only data segments when -fdata-sections
1498# is defined
1499arguments = []
1500if cc.has_argument('-ffunction-sections')
1501  arguments += ['-ffunction-sections']
1502endif
1503
1504if thread_local_storage
1505  tls_arg = '-ftls-model=' + get_option('tls-model')
1506  assert(cc.has_argument(tls_arg), 'Compiler does not support \'-ftls-model\'!')
1507  arguments += [tls_arg]
1508endif
1509
1510add_project_arguments(arguments, language: 'c')
1511
1512# libc will adjust this if supported
1513has_ieeefp_funcs = false
1514
1515# semihost will adjust these if supported
1516
1517# any kind of semihosting support, enough to run general
1518has_semihost = false
1519
1520# arm compatible semihosting, enough to run arm semihost tests
1521has_arm_semihost = false
1522
1523# some semihost needs bios to run the tests with qemu
1524bios_bin = []
1525
1526# make sure to include semihost BEFORE picocrt!
1527if enable_semihost
1528  subdir('semihost')
1529endif
1530if tinystdio
1531  subdir('dummyhost')
1532endif
1533
1534conf_data.set('_HAVE_SEMIHOST', has_semihost, description: 'Semihost APIs supported')
1535
1536# By default, tests don't require any special arguments
1537
1538# disable compiler built-ins so we don't use native equivalents
1539native_c_args += arg_fnobuiltin
1540if tests_enable_stack_protector
1541  if cc.has_argument('-fstack-protector-all') and cc.has_argument('-fstack-protector-strong')
1542    test_c_args += ['-fstack-protector-all', '-fstack-protector-strong', '-DTESTS_ENABLE_STACK_PROTECTOR']
1543  else
1544    tests_enable_stack_protector = false
1545  endif
1546endif
1547
1548if have_long_double and get_option('test-long-double')
1549  test_c_args += ['-D_TEST_LONG_DOUBLE']
1550  native_c_args += ['-D_TEST_LONG_DOUBLE']
1551endif
1552
1553# Meson version 0.53.2 doesn't check for the skip_sanity_check value
1554# before attempting to run test fragments during configuration. That
1555# means the exe_wrapper value needs to handle being run at that
1556# point. To support this, the exe_wrapper becomes a script which
1557# checks for a environment variable (PICOLIBC_TEST) and exits
1558# indicating success if that is not present.
1559#
1560# This was fixed in meson version 0.54.2, so this can be removed from
1561# here and the sample cross scripts once picolibc requires a version
1562# of meson newer than that.
1563
1564test_env = environment({'PICOLIBC_TEST' : '1'})
1565test_env.prepend('PATH', meson.current_source_dir() / 'scripts')
1566
1567# CompCert needs the '-WUl,' prefix to correctly pass the --spec parameters to the linker
1568specs_prefix = ''
1569if cc.get_id() == 'ccomp'
1570  specs_prefix = '-WUl,'
1571endif
1572
1573if has_semihost
1574  specs = picolibc_specs
1575  specs_name = picolibc_specs_name
1576else
1577  specs = configure_file(input: 'test.specs.in',
1578			 output: '@BASENAME@',
1579			 configuration: specs_data,
1580			 install: false)
1581  specs_name = 'test.specs'
1582endif
1583
1584# Clang does not support spec files
1585specs_line = []
1586if cc.get_id() != 'clang'
1587  specs_line += [specs_prefix + '--specs', specs_prefix + meson.current_build_dir() / specs_name]
1588endif
1589test_c_args += specs_line
1590
1591if has_semihost
1592  foreach target : ['default-target'] + targets
1593    if target == 'default-target'
1594      test_link_args_variable = 'test_link_args'
1595      test_linker_files_variable = 'test_linker_files'
1596      test_link_depends_variable = 'test_link_depends'
1597      picolibc_ld_value = picolibc_ld
1598    else
1599      test_link_args_variable = 'test_link_args_' + target
1600      test_linker_files_variable = 'test_linker_files_' + target
1601      test_link_depends_variable = 'test_link_depends_' + target
1602      picolibc_ld_value = get_variable('picolibc_' + target + '_ld', picolibc_ld)
1603    endif
1604
1605    if meson.version().version_compare('>=1.4.0')
1606      picolibc_ld_string = picolibc_ld_value.full_path()
1607    else
1608      picolibc_ld_string = '@0@'.format(picolibc_ld_value)
1609    endif
1610
1611    set_variable(test_link_args_variable,
1612		 ['-nostartfiles', '-T', picolibc_ld_string,
1613		  lib_gcc] + additional_libs_list + specs_line)
1614
1615    set_variable(test_linker_files_variable, [picolibc_ld_value])
1616
1617    # Make sure all of the tests get re-linked if the linker scripts change.
1618    set_variable(test_link_depends_variable, [picolibc_ld_value, specs])
1619  endforeach
1620else
1621  test_link_args = specs_line
1622  test_linker_files = [specs]
1623  test_link_depends = [specs]
1624endif
1625
1626# make sure to include semihost BEFORE picocrt!
1627if enable_picocrt
1628  subdir('picocrt')
1629endif
1630subdir('newlib')
1631
1632if enable_tests
1633  subdir('test')
1634endif
1635
1636conf_data.set('_HAVE_IEEEFP_FUNCS', has_ieeefp_funcs, description: 'IEEE fp funcs available')
1637
1638configure_file(output : 'picolibc.h',
1639	       configuration: conf_data,
1640	       install_dir: include_dir)
1641
1642# Usage as an embedded subproject:
1643# If picolibc is embedded into the source as a subproject,
1644# provide a dependency to be used by the main project:
1645#   dependency('libc', fallback: ['picolibc', 'libc_dep'])
1646if not enable_multilib and meson.is_subproject()
1647  picolibc_dep = declare_dependency(include_directories: inc, link_with: [lib_c])
1648endif
1649