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