summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2021-01-08 01:25:32 (GMT)
committerKeith Packard <keithp@keithp.com>2021-01-12 06:48:46 (GMT)
commit43f50793826918f78b79d2e8197da4e58bdf6748 (patch)
tree67950fd574e3bad87675fae1733c396d91e03cea
parent74949b1d3578873af031f9ad67a8fdb571c5f1bc (diff)
gcc: Add support for building libstdc++ with alternate libc
This adds another mode to do_gcc_core_backend that builds libstdc++ against an alternate libc implementation. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--config/cc/gcc.in2
-rw-r--r--packages/gcc/10.2.0/0019-libstdcxx-pure-stdio.patch275
-rw-r--r--scripts/build/cc/gcc.sh84
3 files changed, 353 insertions, 8 deletions
diff --git a/config/cc/gcc.in b/config/cc/gcc.in
index 849b1ad..9d9b692 100644
--- a/config/cc/gcc.in
+++ b/config/cc/gcc.in
@@ -1,6 +1,6 @@
# GCC options
-## select CC_SUPPORT_CXX if !LIBC_NONE
+## select CC_SUPPORT_CXX
## select CC_SUPPORT_FORTRAN
## select CC_SUPPORT_JAVA if !GCC_7_or_later && OBSOLETE
## select CC_SUPPORT_ADA
diff --git a/packages/gcc/10.2.0/0019-libstdcxx-pure-stdio.patch b/packages/gcc/10.2.0/0019-libstdcxx-pure-stdio.patch
new file mode 100644
index 0000000..da92ba3
--- /dev/null
+++ b/packages/gcc/10.2.0/0019-libstdcxx-pure-stdio.patch
@@ -0,0 +1,275 @@
+From ce06ad6901b1d24abb90d6baba5fe01c750ffb4e Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Tue, 15 Dec 2020 17:39:24 +0000
+Subject: [PATCH] libstdc++: Support libc with stdio-only I/O in libstdc++
+
+The current libstdc++ basic_file_stdio.cc code assumes a POSIX API
+underneath the stdio implementation provided by the host libc. This
+means that the host must provide a fairly broad POSIX file API,
+including read, write, open, close, lseek and ioctl.
+
+This patch changes basic_file_stdio.cc to only use basic ANSI-C stdio
+functions, allowing it to be used with libc implementations like
+picolibc which may not have a POSIX operating system underneath.
+
+This is enabled by a new --enable-cstdio=stdio_pure configure option.
+
+Aided-by: Jonathan Wakely <jwakely@redhat.com>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+
+libstdc++-v3/ChangeLog:
+
+ * acinclude.m4 (GLIBCXX_ENABLE_CSTDIO): Allow "stdio_pure"
+ option and define _GLIBCXX_USE_PURE_STDIO when it is used. Also
+ add "stdio_posix" option as an alias for "stdio".
+ * config/io/basic_file_stdio.cc [_GLIBCXX_USE_PURE_STDIO]: Only
+ use defined stdio entry points for all I/O operations, without
+ direct calls to underlying POSIX functions.
+ * config.h.in: Regenerate.
+ * configure: Regenerate.
+---
+ libstdc++-v3/acinclude.m4 | 20 ++++++----
+ libstdc++-v3/config.h.in | 3 ++
+ libstdc++-v3/config/io/basic_file_stdio.cc | 46 +++++++++++++++++++---
+ libstdc++-v3/configure | 17 +++++---
+ 4 files changed, 69 insertions(+), 17 deletions(-)
+
+diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
+index ee5e0336f2c..9604533c306 100644
+--- a/libstdc++-v3/acinclude.m4
++++ b/libstdc++-v3/acinclude.m4
+@@ -2826,24 +2826,30 @@ AC_DEFUN([GLIBCXX_ENABLE_PARALLEL], [
+
+
+ dnl
+-dnl Check for which I/O library to use: stdio, or something specific.
++dnl Check for which I/O library to use: stdio and POSIX, or pure stdio.
+ dnl
+-dnl Default is stdio.
++dnl Default is stdio_posix.
+ dnl
+ AC_DEFUN([GLIBCXX_ENABLE_CSTDIO], [
+ AC_MSG_CHECKING([for underlying I/O to use])
+ GLIBCXX_ENABLE(cstdio,stdio,[[[=PACKAGE]]],
+- [use target-specific I/O package], [permit stdio])
++ [use target-specific I/O package], [permit stdio|stdio_posix|stdio_pure])
+
+- # Now that libio has been removed, you can have any color you want as long
+- # as it's black. This is one big no-op until other packages are added, but
+- # showing the framework never hurts.
++ # The only available I/O model is based on stdio, via basic_file_stdio.
++ # The default "stdio" is actually "stdio + POSIX" because it uses fdopen(3)
++ # to get a file descriptor and then uses read(3) and write(3) with it.
++ # The "stdio_pure" model doesn't use fdopen and only uses FILE* for I/O.
+ case ${enable_cstdio} in
+- stdio)
++ stdio*)
+ CSTDIO_H=config/io/c_io_stdio.h
+ BASIC_FILE_H=config/io/basic_file_stdio.h
+ BASIC_FILE_CC=config/io/basic_file_stdio.cc
+ AC_MSG_RESULT(stdio)
++
++ if test "x$enable_cstdio" = "xstdio_pure" ; then
++ AC_DEFINE(_GLIBCXX_USE_STDIO_PURE, 1,
++ [Define to restrict std::__basic_file<> to stdio APIs.])
++ fi
+ ;;
+ esac
+
+diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
+index 8940e0c7acd..eabcf18b52b 100644
+--- a/libstdc++-v3/config.h.in
++++ b/libstdc++-v3/config.h.in
+@@ -1031,6 +1031,9 @@
+ /* Define if sendfile is available in <sys/sendfile.h>. */
+ #undef _GLIBCXX_USE_SENDFILE
+
++/* Define to restrict std::__basic_file<> to stdio APIs. */
++#undef _GLIBCXX_USE_STDIO_PURE
++
+ /* Define if struct stat has timespec members. */
+ #undef _GLIBCXX_USE_ST_MTIM
+
+diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc b/libstdc++-v3/config/io/basic_file_stdio.cc
+index ba830fb9e97..eedffb017b6 100644
+--- a/libstdc++-v3/config/io/basic_file_stdio.cc
++++ b/libstdc++-v3/config/io/basic_file_stdio.cc
+@@ -111,13 +111,21 @@ namespace
+
+ // Wrapper handling partial write.
+ static std::streamsize
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ xwrite(FILE *__file, const char* __s, std::streamsize __n)
++#else
+ xwrite(int __fd, const char* __s, std::streamsize __n)
++#endif
+ {
+ std::streamsize __nleft = __n;
+
+ for (;;)
+ {
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ const std::streamsize __ret = fwrite(__file, 1, __nleft, __file);
++#else
+ const std::streamsize __ret = write(__fd, __s, __nleft);
++#endif
+ if (__ret == -1L && errno == EINTR)
+ continue;
+ if (__ret == -1L)
+@@ -133,7 +141,7 @@ namespace
+ return __n - __nleft;
+ }
+
+-#ifdef _GLIBCXX_HAVE_WRITEV
++#if defined(_GLIBCXX_HAVE_WRITEV) && !defined(_GLIBCXX_USE_STDIO_PURE)
+ // Wrapper handling partial writev.
+ static std::streamsize
+ xwritev(int __fd, const char* __s1, std::streamsize __n1,
+@@ -286,9 +294,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ __basic_file<char>::is_open() const throw ()
+ { return _M_cfile != 0; }
+
++#ifndef _GLIBCCXX_USE_STDIO_PURE
+ int
+ __basic_file<char>::fd() throw ()
+ { return fileno(_M_cfile); }
++#endif
+
+ __c_file*
+ __basic_file<char>::file() throw ()
+@@ -315,28 +325,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ {
+ streamsize __ret;
+ do
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ __ret = fread(__s, 1, __n, this->file());
++#else
+ __ret = read(this->fd(), __s, __n);
++#endif
+ while (__ret == -1L && errno == EINTR);
+ return __ret;
+ }
+
+ streamsize
+ __basic_file<char>::xsputn(const char* __s, streamsize __n)
+- { return xwrite(this->fd(), __s, __n); }
++ {
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ return xwrite(this->file(), __s, __n);
++#else
++ return xwrite(this->fd(), __s, __n);
++#endif
++ }
+
+ streamsize
+ __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
+ const char* __s2, streamsize __n2)
+ {
+ streamsize __ret = 0;
+-#ifdef _GLIBCXX_HAVE_WRITEV
++#if defined(_GLIBCXX_HAVE_WRITEV) && !defined(_GLIBCXX_USE_STDIO_PURE)
+ __ret = xwritev(this->fd(), __s1, __n1, __s2, __n2);
+ #else
+ if (__n1)
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ __ret = xwrite(this->file(), __s1, __n1);
++#else
+ __ret = xwrite(this->fd(), __s1, __n1);
++#endif
+
+ if (__ret == __n1)
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ __ret += xwrite(this->file(), __s2, __n2);
++#else
+ __ret += xwrite(this->fd(), __s2, __n2);
++#endif
+ #endif
+ return __ret;
+ }
+@@ -350,7 +378,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ if (__off > numeric_limits<off_t>::max()
+ || __off < numeric_limits<off_t>::min())
+ return -1L;
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ return fseek(this->file(), __off, __way);
++#else
+ return lseek(this->fd(), __off, __way);
++#endif
+ #endif
+ }
+
+@@ -361,7 +393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ streamsize
+ __basic_file<char>::showmanyc()
+ {
+-#ifndef _GLIBCXX_NO_IOCTL
++#if !defined(_GLIBCXX_NO_IOCTL) && !defined(_GLIBCXX_USE_STDIO_PURE)
+ #ifdef FIONREAD
+ // Pipes and sockets.
+ int __num = 0;
+@@ -371,7 +403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ #endif
+ #endif
+
+-#ifdef _GLIBCXX_HAVE_POLL
++#if defined(_GLIBCXX_HAVE_POLL) && !defined(_GLIBCXX_USE_STDIO_PURE)
+ // Cheap test.
+ struct pollfd __pfd[1];
+ __pfd[0].fd = this->fd();
+@@ -395,8 +427,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ struct stat __buffer;
+ const int __err = fstat(this->fd(), &__buffer);
+ if (!__err && _GLIBCXX_ISREG(__buffer.st_mode))
++#ifdef _GLIBCXX_USE_STDIO_PURE
++ return __buffer.st_size - fseek(this->file(), 0, ios_base::cur);
++#else
+ return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur);
+ #endif
++#endif
+ #endif
+ return 0;
+ }
+diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
+index 9f9c5a2419a..50c8f00a41c 100755
+--- a/libstdc++-v3/configure
++++ b/libstdc++-v3/configure
+@@ -16299,7 +16299,7 @@ $as_echo_n "checking for underlying I/O to use... " >&6; }
+ if test "${enable_cstdio+set}" = set; then :
+ enableval=$enable_cstdio;
+ case "$enableval" in
+- stdio) ;;
++ stdio|stdio_posix|stdio_pure) ;;
+ *) as_fn_error $? "Unknown argument to enable/disable cstdio" "$LINENO" 5 ;;
+ esac
+
+@@ -16309,16 +16309,23 @@ fi
+
+
+
+- # Now that libio has been removed, you can have any color you want as long
+- # as it's black. This is one big no-op until other packages are added, but
+- # showing the framework never hurts.
++ # The only available I/O model is based on stdio, via basic_file_stdio.
++ # The default "stdio" is actually "stdio + POSIX" because it uses fdopen(3)
++ # to get a file descriptor and then uses read(3) and write(3) with it.
++ # The "stdio_pure" model doesn't use fdopen and only uses FILE* for I/O.
+ case ${enable_cstdio} in
+- stdio)
++ stdio*)
+ CSTDIO_H=config/io/c_io_stdio.h
+ BASIC_FILE_H=config/io/basic_file_stdio.h
+ BASIC_FILE_CC=config/io/basic_file_stdio.cc
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: stdio" >&5
+ $as_echo "stdio" >&6; }
++
++ if test "x$enable_cstdio" = "xstdio_pure" ; then
++
++$as_echo "#define _GLIBCXX_USE_STDIO_PURE 1" >>confdefs.h
++
++ fi
+ ;;
+ esac
+
+--
+2.29.2
+
diff --git a/scripts/build/cc/gcc.sh b/scripts/build/cc/gcc.sh
index 3d4db35..1ad1db5 100644
--- a/scripts/build/cc/gcc.sh
+++ b/scripts/build/cc/gcc.sh
@@ -279,7 +279,8 @@ do_cc_core_pass_2() {
# build_manuals : whether to build manuals or not : bool : no
# cflags : cflags to use : string : (empty)
# ldflags : ldflags to use : string : (empty)
-# build_step : build step 'core1', 'core2', 'gcc_build'
+# build_step : build step 'core1', 'core2', 'gcc_build',
+# 'libstdcxx'
# or 'gcc_host' : string : (none)
# Usage: do_gcc_core_backend mode=[static|shared|baremetal] build_libgcc=[yes|no] build_staticlinked=[yes|no]
do_gcc_core_backend() {
@@ -291,6 +292,7 @@ do_gcc_core_backend() {
local build_manuals=no
local host
local prefix
+ local enable_optspace
local complibs
local lang_list
local cflags cflags_for_build cflags_for_target
@@ -298,6 +300,9 @@ do_gcc_core_backend() {
local build_step
local log_txt
local tmp
+ local exec_prefix
+ local header_dir
+ local libstdcxx_name
local -a host_libstdcxx_flags
local -a extra_config
local -a core_LDFLAGS
@@ -327,11 +332,30 @@ do_gcc_core_backend() {
# to inhibit the libiberty and libgcc tricks later on
build_libgcc=no
;;
+ libstdcxx)
+ CT_DoLog EXTRA "Configuring libstdc++ for ${libstdcxx_name}"
+ if [ "${header_dir}" = "" ]; then
+ header_dir="${CT_PREFIX_DIR}/${libstdcxx_name}/include"
+ fi
+ if [ "${exec_prefix}" = "" ]; then
+ exec_prefix="${CT_PREFIX_DIR}/${libstdcxx_name}"
+ fi
+ extra_config+=( "${CT_CC_SYSROOT_ARG[@]}" )
+ extra_config+=( "--with-headers=${header_dir}" )
+ extra_user_config=( "${CT_CC_GCC_EXTRA_CONFIG_ARRAY[@]}" )
+ log_txt="libstdc++ ${libstdcxx_name} library"
+ # to inhibit the libiberty and libgcc tricks later on
+ build_libgcc=no
+ ;;
*)
- CT_Abort "Internal Error: 'build_step' must be one of: 'core1', 'core2', 'gcc_build' or 'gcc_host', not '${build_step:-(empty)}'"
+ CT_Abort "Internal Error: 'build_step' must be one of: 'core1', 'core2', 'gcc_build', 'gcc_host' or 'libstdcxx', not '${build_step:-(empty)}'"
;;
esac
+ if [ "${exec_prefix}" = "" ]; then
+ exec_prefix="${prefix}"
+ fi
+
case "${mode}" in
static)
extra_config+=("--with-newlib")
@@ -389,6 +413,10 @@ do_gcc_core_backend() {
extra_config+=(--disable-libquadmath-support)
fi
+ if [ "${build_libstdcxx}" = "no" ]; then
+ extra_config+=(--disable-libstdcxx)
+ fi
+
core_LDFLAGS+=("${ldflags}")
# *** WARNING ! ***
@@ -447,7 +475,8 @@ do_gcc_core_backend() {
extra_config+=("--with-host-libstdcxx=${host_libstdcxx_flags[*]}")
fi
- if [ "${CT_CC_GCC_ENABLE_TARGET_OPTSPACE}" = "y" ]; then
+ if [ "${CT_CC_GCC_ENABLE_TARGET_OPTSPACE}" = "y" ] || \
+ [ "${enable_optspace}" = "yes" ]; then
extra_config+=("--enable-target-optspace")
fi
if [ "${CT_CC_GCC_DISABLE_PCH}" = "y" ]; then
@@ -595,6 +624,7 @@ do_gcc_core_backend() {
--host=${host} \
--target=${CT_TARGET} \
--prefix="${prefix}" \
+ --exec_prefix="${exec_prefix}" \
--with-local-prefix="${CT_SYSROOT_DIR}" \
"${extra_config[@]}" \
--enable-languages="${lang_list}" \
@@ -678,6 +708,11 @@ do_gcc_core_backend() {
core_targets_all=all
core_targets_install=install
;;
+ libstdcxx)
+ core_targets=( target-libstdc++-v3 )
+ core_targets_all="${core_targets[@]/#/all-}"
+ core_targets_install="${core_targets[@]/#/install-}"
+ ;;
esac
CT_DoLog EXTRA "Building ${log_txt}"
@@ -754,7 +789,9 @@ do_cc_for_build() {
# lack of such a compiler, but better safe than sorry...
build_final_opts+=( "mode=baremetal" )
build_final_opts+=( "build_libgcc=yes" )
- build_final_opts+=( "build_libstdcxx=yes" )
+ if [ "${CT_LIBC_NONE}" != "y" ]; then
+ build_final_opts+=( "build_libstdcxx=yes" )
+ fi
build_final_opts+=( "build_libgfortran=yes" )
if [ "${CT_STATIC_TOOLCHAIN}" = "y" ]; then
build_final_opts+=( "build_staticlinked=yes" )
@@ -843,7 +880,9 @@ do_cc_for_host() {
if [ "${CT_BARE_METAL}" = "y" ]; then
final_opts+=( "mode=baremetal" )
final_opts+=( "build_libgcc=yes" )
- final_opts+=( "build_libstdcxx=yes" )
+ if [ "${CT_LIBC_NONE}" != "y" ]; then
+ final_opts+=( "build_libstdcxx=yes" )
+ fi
final_opts+=( "build_libgfortran=yes" )
if [ "${CT_STATIC_TOOLCHAIN}" = "y" ]; then
final_opts+=( "build_staticlinked=yes" )
@@ -876,20 +915,27 @@ do_cc_for_host() {
# Parameter : Definition : Type : Default
# host : the host we run onto : tuple : (none)
# prefix : the runtime prefix : dir : (none)
+# exec_prefix : prefix for executables : dir : (none)
# complibs : the companion libraries prefix : dir : (none)
# cflags : cflags to use : string : (empty)
# ldflags : ldflags to use : string : (empty)
# lang_list : the list of languages to build : string : (empty)
# build_manuals : whether to build manuals or not : bool : no
+# build_step : build step 'gcc_build', 'gcc_host'
+# or 'libstdcxx' : string : (none)
do_gcc_backend() {
local host
local prefix
+ local exec_prefix
local complibs
local lang_list
local cflags
local cflags_for_build
local ldflags
local build_manuals
+ local exec_prefix
+ local header_dir
+ local libstdcxx_name
local -a host_libstdcxx_flags
local -a extra_config
local -a final_LDFLAGS
@@ -900,7 +946,24 @@ do_gcc_backend() {
eval "${arg// /\\ }"
done
- CT_DoLog EXTRA "Configuring final gcc compiler"
+ if [ "${exec_prefix}" = "" ]; then
+ exec_prefix="${prefix}"
+ fi
+
+ # This function gets called for final gcc and libstdcxx.
+ case "${build_step}" in
+ gcc_build|gcc_host)
+ log_txt="final gcc compiler"
+ ;;
+ libstdcxx)
+ log_txt="libstdc++ library for ${libstdcxx_name}"
+ ;;
+ *)
+ CT_Abort "Internal Error: 'build_step' must be one of: 'gcc_build', 'gcc_host' or 'libstdcxx', not '${build_step:-(empty)}'"
+ ;;
+ esac
+
+ CT_DoLog EXTRA "Configuring ${log_txt}"
# Enable selected languages
extra_config+=("--enable-languages=${lang_list}")
@@ -974,6 +1037,10 @@ do_gcc_backend() {
fi
fi
+ if [ "${build_libstdcxx}" = "no" ]; then
+ extra_config+=(--disable-libstdcxx)
+ fi
+
final_LDFLAGS+=("${ldflags}")
# *** WARNING ! ***
@@ -1043,9 +1110,11 @@ do_gcc_backend() {
fi
fi
- if [ "${CT_CC_GCC_ENABLE_TARGET_OPTSPACE}" = "y" ]; then
+ if [ "${CT_CC_GCC_ENABLE_TARGET_OPTSPACE}" = "y" ] || \
+ [ "${enable_optspace}" = "yes" ]; then
extra_config+=("--enable-target-optspace")
fi
+
if [ "${CT_CC_GCC_DISABLE_PCH}" = "y" ]; then
extra_config+=("--disable-libstdcxx-pch")
fi
@@ -1161,6 +1230,7 @@ do_gcc_backend() {
--host=${host} \
--target=${CT_TARGET} \
--prefix="${prefix}" \
+ --exec_prefix="${exec_prefix}" \
${CT_CC_SYSROOT_ARG} \
"${extra_config[@]}" \
--with-local-prefix="${CT_SYSROOT_DIR}" \