Selected for *-picolibc-* targets or when --with-picolibc is
passed to configure.

Add custom options for use with picolibc:

 * '--oslib='. Allows targets to insert an OS library after the C
   library in the LIB_PATH spec file fragment. This library maps a few
   POSIX APIs used by picolibc to underlying system capabilities.

 * '--crt0='. Allows targets to use an alternate crt0 in place of the
   usual one as provided by Picolibc. Picolibc provides a range of
   crt0 versions which this can be used to select among.

 * '--printf=' and '--scanf='. Allows targets to customize the version
   of printf and scanf linked from the C library.

Adds some new preprocessor variables allowing the C library to adjust
the specfile generation process without affecting target changes:

 * LIBC_CPP_SPEC. A specfile fragment appended to cpp_spec. Picolibc
   uses this to add preprocessor definitions when the --printf and
   --scanf options are provided so that applications can detect the
   available printf and scanf versions.

 * LIBC_LINK_SPEC. A specfile fragment appended to link_spec. Picolibc
   uses this to implement the --printf and --scanf options, passing
   suitable --defsym options to the linker.

Documents the new driver options and target macros.

Signed-off-by: Keith Packard <[email protected]>
---
 gcc/config.gcc               | 18 ++++++++++
 gcc/config/picolibc-spec.h   | 57 +++++++++++++++++++++++++++++
 gcc/config/picolibc.opt      | 47 ++++++++++++++++++++++++
 gcc/config/picolibc.opt.urls |  2 ++
 gcc/configure.ac             |  3 ++
 gcc/doc/invoke.texi          | 69 ++++++++++++++++++++++++++++++++++++
 gcc/doc/tm.texi              | 16 +++++++++
 gcc/doc/tm.texi.in           | 16 +++++++++
 gcc/gcc.cc                   | 17 +++++++--
 9 files changed, 243 insertions(+), 2 deletions(-)
 create mode 100644 gcc/config/picolibc-spec.h
 create mode 100644 gcc/config/picolibc.opt
 create mode 100644 gcc/config/picolibc.opt.urls

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 6c8545883fd..cb61b2ee99a 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -3697,6 +3697,24 @@ case ${target} in
        ;;
 esac
 
+# picolibc systems
+case "${target}_${with_picolibc}" in
+*-picolibc-*|*_yes)
+       default_use_cxa_atexit=yes
+       use_gcc_stdint=none
+       # add newlib-stdint.h if not already present
+       case "${tm_file}" in
+       *newlib-stdint.h*)
+               ;;
+       *)
+               tm_file="${tm_file} newlib-stdint.h"
+               ;;
+       esac
+       tm_file="${tm_file} picolibc-spec.h"
+       extra_options="${extra_options} picolibc.opt"
+       ;;
+esac
+
 # Assume the existence of indirect function support and allow the use of the
 # resolver attribute.
 case ${target} in
diff --git a/gcc/config/picolibc-spec.h b/gcc/config/picolibc-spec.h
new file mode 100644
index 00000000000..d1024ced3e7
--- /dev/null
+++ b/gcc/config/picolibc-spec.h
@@ -0,0 +1,57 @@
+/* Configuration common to all targets running Picolibc.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define PICOLIBC_LD "picolibc.ld"
+
+/* Default to local-exec TLS model.  */
+#undef OS_CC1_SPEC
+#define OS_CC1_SPEC " %{!ftls-model=*:-ftls-model=local-exec}"
+
+/* Pass along preprocessor definitions when --printf or --scanf are specified 
*/
+#define LIBC_CPP_SPEC                          \
+  " %{-printf=*: -D_PICOLIBC_PRINTF='%*'}"     \
+  " %{-scanf=*: -D_PICOLIBC_SCANF='%*'}"
+
+/*
+ * Add picolibc.ld if not using -shared, -r or -T and we can find it.
+ * Define vfprintf if --printf is set
+ * Define vfscanf if --scanf is set
+ */
+#define LIBC_LINK_SPEC                                                 \
+  " %{!shared:%{!r:%{!T*: %:if-exists-then-else(%:find-file(" PICOLIBC_LD ") 
-T" PICOLIBC_LD ")}}}" \
+  " %{-printf=*:--defsym=" USER_LABEL_PREFIX "vfprintf=" USER_LABEL_PREFIX 
"__%*_vfprintf}" \
+  " %{-scanf=*:--defsym=" USER_LABEL_PREFIX "vfscanf=" USER_LABEL_PREFIX 
"__%*_vfscanf}"
+
+/*
+ * Place the C library, libgcc and any oslib in a link group to resolve
+ * interdependencies
+ */
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -lc %{-oslib=*:-l%*} %(libgcc) --end-group"
+
+/* Select alternate crt0 version if --crt0 is specified */
+#undef  STARTFILE_SPEC
+#define STARTFILE_SPEC "%{-crt0=*:crt0-%*%O%s; :crt0%O%s}"
+
+#define EH_TABLES_CAN_BE_READ_ONLY 1
diff --git a/gcc/config/picolibc.opt b/gcc/config/picolibc.opt
new file mode 100644
index 00000000000..e68e5d00016
--- /dev/null
+++ b/gcc/config/picolibc.opt
@@ -0,0 +1,47 @@
+; Processor-independent options for picolibc.
+;
+; Copyright (C) 2026 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+-oslib
+Driver Separate Alias(-oslib=)
+
+-oslib=
+Driver Joined
+Specify an OS support library to load after libc.
+
+-crt0
+Driver Separate Alias(-crt0=)
+
+-crt0=
+Driver Joined
+Specify an alternate startup file.
+
+-printf
+Driver Separate Alias(-printf=)
+
+-printf=
+Driver Joined
+Specify the printf version linked from libc.
+
+-scanf
+Driver Separate Alias(-scanf=)
+
+-scanf=
+Driver Joined
+Specify the scanf version linked from libc.
diff --git a/gcc/config/picolibc.opt.urls b/gcc/config/picolibc.opt.urls
new file mode 100644
index 00000000000..b3a57d15a39
--- /dev/null
+++ b/gcc/config/picolibc.opt.urls
@@ -0,0 +1,2 @@
+; Autogenerated by regenerate-opt-urls.py from gcc/config/picolibc.opt and 
generated HTML
+
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 6777200dc93..d1aba1ea561 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1221,6 +1221,9 @@ AC_ARG_WITH(multilib-generator,
 :,
 with_multilib_generator=default)
 
+AC_ARG_WITH(picolibc,
+[AS_HELP_STRING([--with-picolibc], [Support for picolibc, including command 
line options and spec rules])])
+
 # -------------------------
 # Checks for other programs
 # -------------------------
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index fe94d4d3cb7..16065d0f740 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -164,6 +164,7 @@ listing and explanation of the binary and decimal byte size 
prefixes.
 * Link Options::        Specifying libraries and so on.
 * Directory Options::   Where to find header files and libraries.
                         Where to find the compiler executable files.
+* Picolibc Options::    Select compile and link options when using picolibc.
 * Code Gen Options::    Specifying conventions for function calls, data layout
                         and register usage.
 * Developer Options::   Printing GCC configuration info, statistics, and
@@ -803,6 +804,11 @@ Objective-C and Objective-C++ Dialects}.
 --no-canonical-prefixes  --no-standard-includes
 --prefix=@var{prefix}  --sysroot=@var{dir}}
 
+@item Picolibc Options
+@xref{Picolibc Options,,Options for use with Picolibc}.
+@gccoptlist{--oslib=@var{library} 
--crt0=@r{[}none@r{|}minimal@r{|}hosted@r{|}semihost@r{]}
+--printf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]} 
--scanf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]}}
+
 @item Code Generation Options
 @xref{Code Gen Options,,Options for Code Generation Conventions}.
 @gccoptlist{-fcall-saved-@var{reg}  -fcall-used-@var{reg}
@@ -20264,6 +20270,69 @@ such a suffix.
 
 @end table
 
+@node Picolibc Options
+@section Options for use with Picolibc
+@cindex picolibc options
+@cindex options, picolibc
+
+These options control compilation and linking when using picolibc:
+
+@table @gcctabopt
+@opindex oslib
+@item --oslib=@var{library}
+Search the library named @var{library} after the C library, permitting
+symbols undefined by the C library to be defined by this library. The
+C library, libgcc and this library are placed between
+@option{--start-group} and @option{--end-group} flags so that each can
+refer to symbols in the others. For many targets, picolibc provides a
+@samp{semihost} variant (specified with @option{--oslib=semihost})
+which provides enough basic OS functionality to support console and
+file I/O when run in an emulator or when using an in-circuit debugger.
+
+@opindex crt0
+@item --crt0=@r{[}none@r{|}minimal@r{|}hosted@r{|}semihost@r{]}
+Replace the default @file{crt0.o} name with
+@file{crt0-@var{variant}.o}. The @samp{none} variant provides no
+startup code at all, allowing the user to supply their
+own. @samp{minimal} performs basic memory setup but does not invoke
+any constructors. When no @option{-crt0} option is provided, the
+default initialization code adds calls to all
+constructors. @samp{hosted} adds a call to @code{exit} when
+@code{main} returns. @samp{semihost} accesses a command line parameter
+supplied via the semihosting interface and splits that into arguments
+at whitespace boundaries, passing the resulting array of strings to
+main in @code{argc} and @code{argv}. On some targets, including
+aarch64, arc, arm, loongarch, m68k, riscv, super-h and x86,
+@samp{semihost} also traps hardware exceptions and prints information
+to the console. Note that @option{--crt0=semihost} depends upon APIs
+provided by @option{--oslib=semihost}.
+
+@opindex printf
+@item --printf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]}
+Select the printf variant. Picolibc provides five different printf
+variants which offer decreasing levels of functionality along with
+decreasing code size. @samp{d} is the default level, offering full C17
+and POSIX.1-2024 conformance. @samp{f} provides the same feature set,
+but supports @code{float} values instead of @code{double} which are
+passed using the @code{printf_float} macro. @samp{l} elides all
+floating point and POSIX positional parameter support. @samp{i} limits
+integers to those no larger than @code{long}. @samp{m} removes support
+for most formatting options including width and precision. The formats
+and arguments are still parsed correctly, but output does not respect
+those parameters.
+
+@opindex scanf
+@item --scanf=@r{[}d@r{|}f@r{|}l@r{|}i@r{|}m@r{]}
+Select the scanf variant. Picolibc provides five different scanf
+variants which offer decreasing levels of functionality along with
+decreasing code size. @samp{d} is the default level, offering full C17
+and POSIX.1-2024 conformance. @samp{f} removes support for
+@code{double} values. @samp{l} elides all floating point
+support. @samp{i} limits integers to those no larger than
+@code{long}. @samp{m} removes support for @code{%[} conversion specifiers.
+
+@end table
+
 @node Code Gen Options
 @section Options for Code Generation Conventions
 @cindex code generation conventions
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 2ddb11846ee..feedf1c42b6 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -188,6 +188,14 @@ give to GCC into options for GCC to pass to the CPP@.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_CPP_SPEC
+A C string constant which is appended to the value of
+@code{CPP_SPEC}. @code{LIBC_CPP_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac CPLUSPLUS_CPP_SPEC
 This macro is just like @code{CPP_SPEC}, but is used for C++, rather
 than C@.  If you do not define this macro, then the value of
@@ -254,6 +262,14 @@ give to GCC into options for GCC to pass to the linker.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_LINK_SPEC
+A C string constant which is appended to the value of
+@code{LINK_SPEC}. @code{LIBC_LINK_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac LIB_SPEC
 Another C string constant used much like @code{LINK_SPEC}.  The difference
 between the two is that @code{LIB_SPEC} is used at the end of the
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 253965bdafc..66d014d8f12 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -188,6 +188,14 @@ give to GCC into options for GCC to pass to the CPP@.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_CPP_SPEC
+A C string constant which is appended to the value of
+@code{CPP_SPEC}. @code{LIBC_CPP_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac CPLUSPLUS_CPP_SPEC
 This macro is just like @code{CPP_SPEC}, but is used for C++, rather
 than C@.  If you do not define this macro, then the value of
@@ -254,6 +262,14 @@ give to GCC into options for GCC to pass to the linker.
 Do not define this macro if it does not need to do anything.
 @end defmac
 
+@defmac LIBC_LINK_SPEC
+A C string constant which is appended to the value of
+@code{LINK_SPEC}. @code{LIBC_LINK_SPEC} is intended to depend upon the
+C library in use.
+
+Do not define this macro if it does not need to do anything.
+@end defmac
+
 @defmac LIB_SPEC
 Another C string constant used much like @code{LINK_SPEC}.  The difference
 between the two is that @code{LIB_SPEC} is used at the end of the
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 3a6cc5a639b..d93a25c573b 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -727,6 +727,13 @@ proper position among the other output files.  */
 #define CPP_SPEC ""
 #endif
 
+/* libc can define LIBC_CPP_SPEC to provide extra args to the C preprocessor
+   or extra switch-translations. */
+
+#ifndef LIBC_CPP_SPEC
+#define LIBC_CPP_SPEC ""
+#endif
+
 /* Operating systems can define OS_CC1_SPEC to provide extra args to cc1 and
    cc1plus or extra switch-translations.  The OS_CC1_SPEC is appended
    to CC1_SPEC in the initialization of cc1_spec.  */
@@ -752,6 +759,12 @@ proper position among the other output files.  */
 #define LINK_SPEC ""
 #endif
 
+/* libc can define LIBC_LINK_SPEC to provide extra args to the linker
+   or extra switch-translations.  */
+#ifndef LIBC_LINK_SPEC
+#define LIBC_LINK_SPEC ""
+#endif
+
 /* config.h can define LIB_SPEC to override the default libraries.  */
 #ifndef LIB_SPEC
 #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
@@ -1212,14 +1225,14 @@ proper position among the other output files.  */
 
 static const char *asm_debug = ASM_DEBUG_SPEC;
 static const char *asm_debug_option = ASM_DEBUG_OPTION_SPEC;
-static const char *cpp_spec = CPP_SPEC;
+static const char *cpp_spec = CPP_SPEC LIBC_CPP_SPEC;
 static const char *cc1_spec = CC1_SPEC OS_CC1_SPEC;
 static const char *cc1plus_spec = CC1PLUS_SPEC;
 static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
 static const char *link_ssp_spec = LINK_SSP_SPEC;
 static const char *asm_spec = ASM_SPEC;
 static const char *asm_final_spec = ASM_FINAL_SPEC;
-static const char *link_spec = LINK_SPEC;
+static const char *link_spec = LINK_SPEC LIBC_LINK_SPEC;
 static const char *lib_spec = LIB_SPEC;
 static const char *link_gomp_spec = "";
 static const char *libgcc_spec = LIBGCC_SPEC;
-- 
2.51.0

Reply via email to