Skip to content

Toolchain C++ headers can be included when libstdc++ is not selected #36644

@stephanosio

Description

@stephanosio

Status quo
The Zephyr build system does not specify -nostdinc argument when newlib is enabled (CONFIG_NEWLIB_LIBC=y):

if (NOT CONFIG_NEWLIB_LIBC AND
NOT COMPILER STREQUAL "xcc" AND
NOT ZEPHYR_TOOLCHAIN_VARIANT STREQUAL "espressif" AND
NOT CONFIG_NATIVE_APPLICATION)
set_compiler_property(PROPERTY nostdinc -nostdinc)
set_compiler_property(APPEND PROPERTY nostdinc_include ${NOSTDINC})
endif()

This has the effect of making the toolchain-provided standard headers (which includes newlib standard C library headers for the currently supported toolchains) available for inclusion.

When CONFIG_LIB_CPLUSPLUS=y, which semantically enables the use of libstdc++, this also has the intended effect since the toolchain-provided libstdc++ C++ standard library headers are available for inclusion when -nostdinc is not specified.

When CONFIG_NEWLIB_LIBC=y and CONFIG_LIB_CPLUSPLUS=n however, this has an unintended effect of making the libstdc++ headers available for inclusion even when it was never the developer's intention to make use of the toolchain-provided libstdc++ features, as observed in #36612 (comment).

The libstdc++, also known as the GNU C++ library, mainly consists of the standard C++ library header files, which include both definitions and implementations, and the standard C++ library object archive, which provides the implementations for the methods that do not come with implementation in the headers.

The current definition of CONFIG_LIB_CPLUSPLUS is "Link with STD C++ library":

config LIB_CPLUSPLUS
bool "Link with STD C++ library"

One may possibly argue that allowing the use of libstdc++ headers without linking the libstdc++ archive, alongside the minimal C++ runtime implemented by the Zephyr C++ subsystem (one might call this a "hybrid" scheme), is a both valid and intended scheme; but, in reality, this is simply not a correct thing to do for the following reasons and need to be classified as a bug:

  1. In traditional sense, headers are supposed to provide definitions and the object archive (.a file) is supposed to provide the implementations. In terms of C++, this separation often gets blurred and, as with the libstdc++, many small method implementations tend to get put in the header file. This does not mean that you can rely on the headers to provide the full implementation and making use of the headers without linking the relevant object files leaves the build success at the mercy of what gets put in the headers and source files on the libstdc++ side. This is non-deterministic and not a correct behaviour.
  2. libstdc++ headers are provided by the toolchain and its version may vary with the toolchain being used. Mixing libstdc++ headers with the minimal C++ library provided by what is currently known as the Zephyr C++ subsystem can lead to version-dependent compatibility issues as well as unexpected behaviours. We cannot afford to have this.
  3. gcc is currently the toolchain of choice for Zephyr and libstdc++ is shown as an example here for that reason. In the future, we will be adding support for other toolchains (e.g. Clang/LLVM), and this "hybrid" scheme, once again, makes that very non-deterministic and leaves things at the mercy of the toolchain type and version. We cannot afford to maintain such a non-deterministic scheme.

To be
As briefly noted in #36612 (comment):

  1. Disallow using libstdc++ headers when CONFIG_LIB_CPLUSPLUS=n by specifying -nostdinc++.
  2. Refactor C++ subsystem (subsys/cpp) such that the separation between the "minimal C++ runtime library" and the toolchain-specific C++ runtime library integration (glue/shim) is clear.
  3. Possibly downgrade "C++ subsystem" to "C++ library" (lib/cpp) and adopt the same scheme as the C library (lib/libc).
  4. Consider expanding the scope of "minimal C++ runtime library" such that basic standard C++ features are available in a toolchain-agnostic way (similar to the concept of minimal C library -- lib/libc/minimal).
  5. Consider adopting a BSD or Apache licensed C++ runtime library (e.g. Apache C++ Standard Library, LLVM C++ Standard Library, ...).

Metadata

Metadata

Assignees

Labels

area: C++bugThe issue is a bug, or the PR is fixing a bugpriority: mediumMedium impact/importance bug

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions