diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37d5271b..f992215f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -331,6 +331,26 @@ jobs: file "$RUNNER_TEMP/cross/openkal-same-source.exe" | grep -q 'PE32+ executable' file "$RUNNER_TEMP/cross/openkal-same-source" | grep -q 'Mach-O 64-bit arm64' + # ⭐ AND A TRANSLATION UNIT THAT INCLUDES A STANDARD HEADER, FOR THE SAME TWO. + # + # `same-source` imports std, and the std module is compiled with this + # package's own flags, so it cannot see what a consumer's translation unit + # sees. `examples/cxx` includes the way every module wrapper + # of a header library does, and that path reaches libc++'s musl locale + # support, which calls strtof_l and vasprintf. musl declares those only + # under _GNU_SOURCE, and Clang predefines _GNU_SOURCE for C++ on Linux + # targets alone -- so this example ran on Linux and did not compile for + # either of these targets until __config_site stated it. + - name: A standard header, built here for Windows and for macOS + if: matrix.toolchain == 'llvm@22.1.8' + run: | + set -euo pipefail + cd examples/cxx + for t in x86_64-windows-gnu aarch64-macos; do + rm -rf target + mcpp build --target "$t" + done + - uses: actions/upload-artifact@v4 if: matrix.toolchain == 'llvm@22.1.8' with: diff --git a/README.md b/README.md index 7d852ab2..07112b0b 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,18 @@ position in it is a **claim about the environment beneath**: #define _LIBCPP_HAS_RANDOM_DEVICE 1 /* openkal.random reaches a source */ #define _LIBCPP_HAS_FILESYSTEM 1 /* openkal.fs, and its sources built */ #define _LIBCPP_HAS_TERMINAL 1 /* isatty answers, rather than lying */ +#define _GNU_SOURCE 1 /* musl's GNU interfaces, on every target */ ``` +The last line is not a libc++ switch, and it is here for the same reason as the +others. This configuration's locale support calls `strtof_l`, `strtod_l`, +`strtold_l` and `vasprintf`, which musl declares only under `_GNU_SOURCE`. +Clang predefines `_GNU_SOURCE` for C++ on Linux targets and on no other, so a +translation unit that includes a standard header — which is what every module +wrapper of a header library does — built for Linux and failed for macOS and +Windows with `no member named 'strtof_l' in the global namespace`. Stating it +in the configuration gives every target what the Linux target already had. + The first was measured rather than assumed. With it at `0` — the value a toolchain configured for glibc ships — a translation unit that includes `` fails with twenty errors, of which the first names the cause: diff --git a/llvm-generated/generic/__config_site b/llvm-generated/generic/__config_site index 7ee73e58..0589797c 100644 --- a/llvm-generated/generic/__config_site +++ b/llvm-generated/generic/__config_site @@ -9,6 +9,18 @@ #ifndef _LIBCPP___CONFIG_SITE #define _LIBCPP___CONFIG_SITE +// openkal: the C library beneath is musl, and this configuration's locale +// support (__locale_dir/support/linux.h) calls strtof_l, strtod_l, strtold_l and +// vasprintf, which musl declares only under _GNU_SOURCE. Clang predefines +// _GNU_SOURCE for C++ on Linux targets and on no other, so a translation unit +// that includes a standard header -- as every module wrapper of a header +// library does -- compiled for the Linux target and failed for the macOS and +// Windows targets. Stating it here gives every target the environment the +// Linux target already had; this header is included before any C header. +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + #define _LIBCPP_ABI_VERSION 1 #define _LIBCPP_ABI_NAMESPACE __1 #define _LIBCPP_ABI_FORCE_ITANIUM 0 diff --git a/mcpp.toml b/mcpp.toml index b3f3b6a1..0f1b172f 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-llvm-runtime" -version = "0.9.1" +version = "0.9.2" description = "LLVM's C++ runtime libraries — libc++, libc++abi and libunwind — configured for openkal-musl rather than for a host C library." license = "Apache-2.0" authors = ["mcpplibs"]