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