diff --git a/.github/workflows/openkal-compat.yml b/.github/workflows/openkal-compat.yml index f028bd6f..9f091a0a 100644 --- a/.github/workflows/openkal-compat.yml +++ b/.github/workflows/openkal-compat.yml @@ -37,7 +37,7 @@ env: # run if this drifts from pins.toml. See the comment beside `mcpp` in # pins.toml for why this pin, not just validate.yml's, is gated by the # index floor. - MCPP_VERSION: "2026.9.21.2" + MCPP_VERSION: "2026.9.21.3" # CROSS-VALIDATION BEFORE A RELEASE, NOT AFTER IT. # # Empty in an ordinary run, so this measurement keeps using the RELEASED diff --git a/.gitignore b/.gitignore index 126226e1..772af0bf 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ tests/examples/*/imgui.ini # plugin bytecode .xpkgindex/plugins/__pycache__/ +__pycache__/ +*.pyc tests/openkal-work/ diff --git a/docs/openkal-compat.md b/docs/openkal-compat.md index 691a179d..2fe7f00f 100644 --- a/docs/openkal-compat.md +++ b/docs/openkal-compat.md @@ -33,10 +33,19 @@ recorded per target: | Result | Meaning | | --- | --- | | `runs` | the member's tests passed; on a target other than the host they ran through the pinned runner (Wine for Windows) | -| `builds` | the member built, and its tests were not run or did not pass; the first diagnostic is kept | +| `builds` | the member's own tests compiled and linked for the target, and were not run or did not pass; the first diagnostic is kept | | `fails` | the member did not build; the first diagnostic is kept | | `refused` | the member asked this graph for a capability it does not supply, and was told so before anything was compiled | +**A target with no runner is measured with `mcpp test --no-run`, and until it +was, `builds` was a statement about the dependencies.** Every member here keeps +its sources under `tests/`, and `mcpp build` builds the PACKAGE: for a target +this host cannot execute it compiled the member's dependencies, exited 0, and +that exit code was recorded as `builds`. Measured on `archive` for +`aarch64-macos`: 1990 objects, none of them from `tests/compression.cpp` or +`tests/versions.cpp`. `mcpp test --no-run` compiles and links the member's own +tests for the target and does not execute them, which is what this row claims. + **A refusal is not a failure, and the difference is not a matter of degree.** A member that declares `[kernel-abi] requires-interfaces` naming something the resolved implementation does not provide has been answered correctly. Counting @@ -158,6 +167,67 @@ lower. The comparison becomes a required check for pull requests once the repository variable `OPENKAL_RATCHET` is `on`; it is enabled after the weekly measurement has been stable for two consecutive weeks. +### The 2026-09-21 measurement, on mcpp 2026.9.21.3 + +Thirty members, two targets, sixty cells, measured by this repository's own CI: + +| | before | after | +| --- | --- | --- | +| `runs` | 50 | **56** | +| `builds` | 0 | 1 | +| `fails` | 10 | **3, all declared** | + +`compat.py check` against the published baseline: no published label +regressed, and no declaration was contradicted. + +The one `builds` is `mimalloc` on `x86_64-windows-gnu`. Its build was repaired +in this round — `MI_USE_BUILTIN_THREAD_POINTER=0`, see the recipe — and its +`alloc` test then exits 1 under the Wine CI installs while passing under +another. A repaired build is not a passing test, and the label says which one +this is. + +### Why `aarch64-macos` is not a pinned target yet + +`pins.toml` names linux and windows. macOS is measurable — `mcpp test --no-run` +compiles and links each member's own tests for a target this host cannot run — +and it was measured once, on 2026-09-21, against mcpp 2026.9.21.3 and +openkal-llvm-runtime 0.15.0: **20 members build and 10 do not.** + +Nine of the ten are one cause, and it is not ten packaging defects: + +| diagnostic | members | +| --- | --- | +| `TargetConditionals.h` not found | catch2, curl, mimalloc, re2, sqlite3 | +| `sys/cdefs.h`, through Apple's `dnsinfo.h` | c-ares | +| `sys/event.h`, the kqueue reactor | cmp-module | +| `xlocale.h` | fmtlib.fmt | +| `pthread_threadid_np` undeclared | spdlog | +| `library not found for -lm` | brotli | + +Every one of those is reached under `#ifdef __APPLE__`, and on this target +`__APPLE__` is **correct**: it is an Apple platform — Mach-O, arm64, macOS. +What it does not say is which C library is underneath, and upstream code uses +it to mean both because on a real macOS the two coincide. + +**This is the macOS mirror of the Windows problem this document's `c-ares` +entry describes, with one difference: there the engine has a lever.** A C +library presenting POSIX on Windows is realised as `--target=…-pc-cygwin`, +which suppresses `_WIN32`, so `#ifdef _WIN32` stops selecting the Win32 +branch. On macOS the realisation adds `-D__unix__` and leaves `__APPLE__` and +`__MACH__` standing, because they are true. Measured, the whole identity a +source file sees there is + +``` +__APPLE__ __MACH__ __MCPP_TARGET_MACOS__ __OPENKAL__ __unix__ +``` + +and nothing in it answers "which C library". musl defines no identifying macro +by design, so there is no portable question to ask either. + +Pinning the target today would add ten red cells whose repair is one design +question, not ten. The measurement is recorded here so the question is asked +with a number attached. + ## 4. Adapting a package A package that fails in an openkal graph has met one of the layers. The rules diff --git a/pkgs/c/compat.c-ares.lua b/pkgs/c/compat.c-ares.lua index 4a9559c8..1505603f 100644 --- a/pkgs/c/compat.c-ares.lua +++ b/pkgs/c/compat.c-ares.lua @@ -76,14 +76,40 @@ package = { -- fail with implicit-declaration errors. cflags = { "-DCARES_STATICLIB", "-DHAVE_CONFIG_H", "-D_GNU_SOURCE", "-D_HAS_EXCEPTIONS=0" }, - linux = { - -- Frozen configure snapshot, taken verbatim from gRPC 1.83.0's - -- third_party/cares/config_linux/ares_config.h. gRPC pins c-ares at this - -- exact release (submodule d3a507e == tag v1.34.5) and ships these files - -- precisely so the library can be built without running c-ares' - -- configure/CMake, which is the same thing this package needs. - generated_files = { - ["mcpp_generated/ares_config.h"] = [==[ + -- ONE SNAPSHOT PER C ENVIRONMENT, AND THE PREPROCESSOR PICKS. + -- + -- These are gRPC 1.83.0's three frozen `ares_config.h` files, verbatim, + -- from third_party/cares/config_{windows,darwin,linux}. gRPC pins c-ares + -- at this exact release (submodule d3a507e == tag v1.34.5) and ships + -- them precisely so the library can be built without running configure + -- or CMake, which is what this package needs too. + -- + -- THEY USED TO BE SELECTED BY THE OPERATING SYSTEM, and a configure + -- snapshot describes a C ENVIRONMENT. Those were the same question + -- until a C library began presenting POSIX on Windows: over openkal the + -- target is still PE and still Win64, and `config_windows` then + -- describes nothing that is there. Of the sixteen headers it declares + -- absent, fifteen are present in that graph, and the first three + -- diagnostics a build produced -- `windows.h` not found, then + -- `gettimeofday` undeclared, then `struct hostent` incomplete -- were + -- each one macro of the sixteen, with thirteen more behind them. + -- + -- `_WIN32` AND `__APPLE__` ARE THE ENGINE'S ANSWER TO EXACTLY THIS + -- QUESTION, so the selection needs no new key in this descriptor and no + -- new axis in the engine. mcpp defines `_WIN32` for a Win32 environment + -- and suppresses it for a POSIX-presenting one; the file asks the + -- preprocessor which environment it is being compiled in, which is the + -- question it was always answering. + -- + -- Measured: x86_64-windows-gnu over openkal goes from `fails` to `runs`. + -- Linux and macOS select the same snapshot they selected before, byte + -- for byte, so neither reading moves. + -- + -- `cflags`/`ldflags` stay per-OS below: a real Windows target still + -- needs ws2_32, and a POSIX-presenting one asks for nothing in it. + generated_files = { + ["mcpp_generated/ares_config.h"] = [==[ +#if defined(_WIN32) /* Generated from ares_config.h.cmake*/ /* Define if building universal (internal helper macro) */ @@ -111,7 +137,7 @@ package = { #undef ETC_INET /* Define to the type of arg 2 for gethostname. */ -#define GETHOSTNAME_TYPE_ARG2 size_t +#define GETHOSTNAME_TYPE_ARG2 int /* Define to the type qualifier of arg 1 for getnameinfo. */ #define GETNAMEINFO_QUAL_ARG1 @@ -129,19 +155,19 @@ package = { #define GETNAMEINFO_TYPE_ARG7 int /* Specifies the number of arguments to getservbyport_r */ -#define GETSERVBYPORT_R_ARGS 6 +#define GETSERVBYPORT_R_ARGS /* Define to 1 if you have AF_INET6. */ #define HAVE_AF_INET6 /* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H +/* #undef HAVE_ARPA_INET_H */ /* Define to 1 if you have the header file. */ -#define HAVE_ARPA_NAMESER_COMPAT_H +/* #undef HAVE_ARPA_NAMESER_COMPAT_H */ /* Define to 1 if you have the header file. */ -#define HAVE_ARPA_NAMESER_H +/* #undef HAVE_ARPA_NAMESER_H */ /* Define to 1 if you have the header file. */ #define HAVE_ASSERT_H @@ -153,10 +179,12 @@ package = { #define HAVE_BOOL_T /* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#if __has_include() && !defined(_WIN32) #define HAVE_CLOCK_GETTIME_MONOTONIC 1 +#endif /* Define to 1 if you have the closesocket function. */ -/* #undef HAVE_CLOSESOCKET */ +#define HAVE_CLOSESOCKET /* Define to 1 if you have the CloseSocket camel case function. */ /* #undef HAVE_CLOSESOCKET_CAMEL */ @@ -168,19 +196,19 @@ package = { /* #undef HAVE_CXX11 */ /* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H +/* #undef HAVE_DLFCN_H */ /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H /* Define to 1 if you have the fcntl function. */ -#define HAVE_FCNTL +/* #undef HAVE_FCNTL */ /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ -#define HAVE_FCNTL_O_NONBLOCK +/* #undef HAVE_FCNTL_O_NONBLOCK */ /* Define to 1 if you have the freeaddrinfo function. */ #define HAVE_FREEADDRINFO @@ -189,7 +217,7 @@ package = { #define HAVE_GETADDRINFO /* Define to 1 if the getaddrinfo function is threadsafe. */ -/* #undef HAVE_GETADDRINFO_THREADSAFE */ +#define HAVE_GETADDRINFO_THREADSAFE /* Define to 1 if you have the getenv function. */ #define HAVE_GETENV @@ -207,31 +235,36 @@ package = { #define HAVE_GETNAMEINFO /* Define to 1 if you have the getservbyport_r function. */ -#define HAVE_GETSERVBYPORT_R +/* #undef HAVE_GETSERVBYPORT_R */ /* Define to 1 if you have the `gettimeofday' function. */ -#define HAVE_GETTIMEOFDAY +/* SUB-SECOND TIME. `ares_timeval.c:93` refuses a configuration that names no + * source of it, and the Win32 one (`GetTickCount64`) needs `windows.h`. A + * POSIX-presenting target has `clock_gettime`, which `time.h` declares. */ +#if __has_include() && !defined(_WIN32) +#define HAVE_GETTIMEOFDAY 1 +#endif /* Define to 1 if you have the `if_indextoname' function. */ -#define HAVE_IF_INDEXTONAME +/* #undef HAVE_IF_INDEXTONAME */ /* Define to 1 if you have a IPv6 capable working inet_net_pton function. */ /* #undef HAVE_INET_NET_PTON */ /* Define to 1 if you have a IPv6 capable working inet_ntop function. */ -#define HAVE_INET_NTOP +/* #undef HAVE_INET_NTOP */ /* Define to 1 if you have a IPv6 capable working inet_pton function. */ -#define HAVE_INET_PTON +/* #undef HAVE_INET_PTON */ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H /* Define to 1 if you have the ioctl function. */ -#define HAVE_IOCTL +/* #undef HAVE_IOCTL */ /* Define to 1 if you have the ioctlsocket function. */ -/* #undef HAVE_IOCTLSOCKET */ +#define HAVE_IOCTLSOCKET /* Define to 1 if you have the IoctlSocket camel case function. */ /* #undef HAVE_IOCTLSOCKET_CAMEL */ @@ -241,13 +274,13 @@ package = { /* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ /* Define to 1 if you have a working ioctlsocket FIONBIO function. */ -/* #undef HAVE_IOCTLSOCKET_FIONBIO */ +#define HAVE_IOCTLSOCKET_FIONBIO /* Define to 1 if you have a working ioctl FIONBIO function. */ -#define HAVE_IOCTL_FIONBIO +/* #undef HAVE_IOCTL_FIONBIO */ /* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ -#define HAVE_IOCTL_SIOCGIFADDR +/* #undef HAVE_IOCTL_SIOCGIFADDR */ /* Define to 1 if you have the `resolve' library (-lresolve). */ /* #undef HAVE_LIBRESOLV */ @@ -268,19 +301,19 @@ package = { #define HAVE_MEMORY_H /* Define to 1 if you have the MSG_NOSIGNAL flag. */ -#define HAVE_MSG_NOSIGNAL +/* #undef HAVE_MSG_NOSIGNAL */ /* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H +/* #undef HAVE_NETDB_H */ /* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H +/* #undef HAVE_NETINET_IN_H */ /* Define to 1 if you have the header file. */ -#define HAVE_NETINET_TCP_H +/* #undef HAVE_NETINET_TCP_H */ /* Define to 1 if you have the header file. */ -#define HAVE_NET_IF_H +/* #undef HAVE_NET_IF_H */ /* Define to 1 if you have PF_INET6. */ #define HAVE_PF_INET6 @@ -328,34 +361,48 @@ package = { #define HAVE_STDLIB_H /* Define to 1 if you have the strcasecmp function. */ -#define HAVE_STRCASECMP +/* WIN32 CRT NAMES vs POSIX NAMES, decided by what the C environment + * presents rather than by the platform. This block is the Windows branch of a + * recipe that branches on the PLATFORM; over openkal the target is PE and the + * C environment is POSIX, so the CRT spellings are the ones that are absent. + * `__has_builtin` cannot answer for library functions, so these ask the same + * question the headers do: `strings.h` carries the POSIX pair. */ +#if __has_include() +#define HAVE_STRCASECMP 1 +#define HAVE_STRNCASECMP 1 +#endif +/* #undef HAVE_STRCASECMP_ORIGINAL */ /* Define to 1 if you have the strcmpi function. */ -/* #undef HAVE_STRCMPI */ +#if !__has_include() +#define HAVE_STRCMPI +#endif /* Define to 1 if you have the strdup function. */ #define HAVE_STRDUP /* Define to 1 if you have the stricmp function. */ -/* #undef HAVE_STRICMP */ +#define HAVE_STRICMP /* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H +/* #undef HAVE_STRINGS_H */ /* Define to 1 if you have the header file. */ #define HAVE_STRING_H /* Define to 1 if you have the strncasecmp function. */ -#define HAVE_STRNCASECMP +/* #undef HAVE_STRNCASECMP */ /* Define to 1 if you have the strncmpi function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the strnicmp function. */ -/* #undef HAVE_STRNICMP */ +#if !__has_include() +#define HAVE_STRNICMP +#endif /* Define to 1 if you have the header file. */ -#define HAVE_STROPTS_H +/* #undef HAVE_STROPTS_H */ /* Define to 1 if you have struct addrinfo. */ #define HAVE_STRUCT_ADDRINFO @@ -373,49 +420,82 @@ package = { #define HAVE_STRUCT_TIMEVAL /* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_H +/* #undef HAVE_SYS_IOCTL_H */ /* Define to 1 if you have the header file. */ -#define HAVE_SYS_PARAM_H +/* #undef HAVE_SYS_PARAM_H */ /* Define to 1 if you have the header file. */ -#define HAVE_SYS_SELECT_H +/* #undef HAVE_SYS_SELECT_H */ /* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H +/* #undef HAVE_SYS_SOCKET_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H -/* Define to 1 if you have the header file. */ +/* THE HEADER THAT DECLARES THE FALLBACK THIS BRANCH ALREADY TAKES. + * + * `HAVE_GETTIMEOFDAY` and `HAVE_CLOCK_GETTIME_MONOTONIC` are defined above + * for a target whose C library supplies them, and `ares_timeval.c` then + * compiles the `clock_gettime` branch --- whose failure path calls + * `gettimeofday` with no guard of its own, because upstream takes one to + * imply the other. Leaving this `#undef` while those two are defined states + * that the function exists and its header does not: + * + * ares_timeval.c:70:11: error: call to undeclared function + * 'gettimeofday' + * + * Asked rather than assumed, for the same reason as the four below. */ +#if __has_include() #define HAVE_SYS_TIME_H +#endif /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ -#define HAVE_SYS_UIO_H +/* #undef HAVE_SYS_UIO_H */ /* Define to 1 if you have the header file. */ #define HAVE_TIME_H -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H - -/* Define to 1 if you have the windows.h header file. */ -/* #undef HAVE_WINDOWS_H */ +/* THESE ASK WHETHER A HEADER IS THERE, SO THEY ASK THE COMPILER. + * + * This block is the Windows branch of a recipe that branches on the PLATFORM, + * and it used to define all four unconditionally. That was true of every + * Windows target this index had until a C library began presenting POSIX on + * one: over openkal the target is still PE, still Win64, and there is no + * `windows.h` --- `ares_setup.h:81` then reached for it and this repository's + * own compatibility measurement recorded + * + * ares_setup.h:81:12: fatal error: 'windows.h' file not found + * + * `__has_include` is standard C and asks the question actually being asked. + * `HAVE_UNISTD_H` gets the same treatment for the same reason, from the other + * side: a POSIX-presenting Windows target HAS it. */ +#if __has_include() +#define HAVE_UNISTD_H 1 +#endif + +#if __has_include() +#define HAVE_WINDOWS_H +#endif -/* Define to 1 if you have the winsock2.h header file. */ -/* #undef HAVE_WINSOCK2_H */ +#if __has_include() +#define HAVE_WINSOCK2_H +#endif -/* Define to 1 if you have the winsock.h header file. */ -/* #undef HAVE_WINSOCK_H */ +#if __has_include() +#define HAVE_WINSOCK_H +#endif /* Define to 1 if you have the writev function. */ -#define HAVE_WRITEV +/* #undef HAVE_WRITEV */ -/* Define to 1 if you have the ws2tcpip.h header file. */ -/* #undef HAVE_WS2TCPIP_H */ +#if __has_include() +#define HAVE_WS2TCPIP_H +#endif /* Define if __system_property_get exists. */ /* #undef HAVE___SYSTEM_PROPERTY_GET */ @@ -433,7 +513,7 @@ package = { #define RECVFROM_QUAL_ARG5 /* Define to the type of arg 1 for recvfrom. */ -#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG1 SOCKET /* Define to the type pointed by arg 2 for recvfrom. */ #define RECVFROM_TYPE_ARG2 void * @@ -442,7 +522,7 @@ package = { #define RECVFROM_TYPE_ARG2_IS_VOID 0 /* Define to the type of arg 3 for recvfrom. */ -#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG3 int /* Define to the type of arg 4 for recvfrom. */ #define RECVFROM_TYPE_ARG4 int @@ -460,22 +540,22 @@ package = { #define RECVFROM_TYPE_ARG6_IS_VOID 0 /* Define to the function return type for recvfrom. */ -#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_RETV int /* Define to the type of arg 1 for recv. */ -#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG1 SOCKET /* Define to the type of arg 2 for recv. */ #define RECV_TYPE_ARG2 void * /* Define to the type of arg 3 for recv. */ -#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG3 int /* Define to the type of arg 4 for recv. */ #define RECV_TYPE_ARG4 int /* Define to the function return type for recv. */ -#define RECV_TYPE_RETV ssize_t +#define RECV_TYPE_RETV int /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE @@ -484,22 +564,22 @@ package = { #define SEND_QUAL_ARG2 /* Define to the type of arg 1 for send. */ -#define SEND_TYPE_ARG1 int +#define SEND_TYPE_ARG1 SOCKET /* Define to the type of arg 2 for send. */ #define SEND_TYPE_ARG2 void * /* Define to the type of arg 3 for send. */ -#define SEND_TYPE_ARG3 size_t +#define SEND_TYPE_ARG3 int /* Define to the type of arg 4 for send. */ #define SEND_TYPE_ARG4 int /* Define to the function return type for send. */ -#define SEND_TYPE_RETV ssize_t +#define SEND_TYPE_RETV int /* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME +/* #undef TIME_WITH_SYS_TIME */ /* Define to disable non-blocking sockets. */ #undef USE_BLOCKING_SOCKETS @@ -509,18 +589,11 @@ package = { /* Type to use in place of in_addr_t when system does not provide it. */ #undef in_addr_t -]==], - }, - ldflags = { "-lpthread" }, - }, - macosx = { - -- Frozen configure snapshot, taken verbatim from gRPC 1.83.0's - -- third_party/cares/config_darwin/ares_config.h. gRPC pins c-ares at this - -- exact release (submodule d3a507e == tag v1.34.5) and ships these files - -- precisely so the library can be built without running c-ares' - -- configure/CMake, which is the same thing this package needs. - generated_files = { - ["mcpp_generated/ares_config.h"] = [==[ + +/* gRPC manual edits here! */ +#define HAVE_IPHLPAPI_H +#define HAVE_NETIOAPI_H +#elif defined(__APPLE__) /* Generated from ares_config.h.cmake*/ /* Define if building universal (internal helper macro) */ @@ -948,19 +1021,7 @@ package = { /* Type to use in place of in_addr_t when system does not provide it. */ #undef in_addr_t -]==], - }, - -- config_darwin defines HAVE_LIBRESOLV, so res_* comes from libresolv. - ldflags = { "-lresolv" }, - }, - windows = { - -- Frozen configure snapshot, taken verbatim from gRPC 1.83.0's - -- third_party/cares/config_windows/ares_config.h. gRPC pins c-ares at this - -- exact release (submodule d3a507e == tag v1.34.5) and ships these files - -- precisely so the library can be built without running c-ares' - -- configure/CMake, which is the same thing this package needs. - generated_files = { - ["mcpp_generated/ares_config.h"] = [==[ +#else /* Generated from ares_config.h.cmake*/ /* Define if building universal (internal helper macro) */ @@ -988,7 +1049,7 @@ package = { #undef ETC_INET /* Define to the type of arg 2 for gethostname. */ -#define GETHOSTNAME_TYPE_ARG2 int +#define GETHOSTNAME_TYPE_ARG2 size_t /* Define to the type qualifier of arg 1 for getnameinfo. */ #define GETNAMEINFO_QUAL_ARG1 @@ -1006,19 +1067,19 @@ package = { #define GETNAMEINFO_TYPE_ARG7 int /* Specifies the number of arguments to getservbyport_r */ -#define GETSERVBYPORT_R_ARGS +#define GETSERVBYPORT_R_ARGS 6 /* Define to 1 if you have AF_INET6. */ #define HAVE_AF_INET6 /* Define to 1 if you have the header file. */ -/* #undef HAVE_ARPA_INET_H */ +#define HAVE_ARPA_INET_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_ARPA_NAMESER_COMPAT_H */ +#define HAVE_ARPA_NAMESER_COMPAT_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_ARPA_NAMESER_H */ +#define HAVE_ARPA_NAMESER_H /* Define to 1 if you have the header file. */ #define HAVE_ASSERT_H @@ -1030,10 +1091,10 @@ package = { #define HAVE_BOOL_T /* Define to 1 if you have the clock_gettime function and monotonic timer. */ -/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 /* Define to 1 if you have the closesocket function. */ -#define HAVE_CLOSESOCKET +/* #undef HAVE_CLOSESOCKET */ /* Define to 1 if you have the CloseSocket camel case function. */ /* #undef HAVE_CLOSESOCKET_CAMEL */ @@ -1045,19 +1106,19 @@ package = { /* #undef HAVE_CXX11 */ /* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ +#define HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H /* Define to 1 if you have the fcntl function. */ -/* #undef HAVE_FCNTL */ +#define HAVE_FCNTL /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H /* Define to 1 if you have a working fcntl O_NONBLOCK function. */ -/* #undef HAVE_FCNTL_O_NONBLOCK */ +#define HAVE_FCNTL_O_NONBLOCK /* Define to 1 if you have the freeaddrinfo function. */ #define HAVE_FREEADDRINFO @@ -1066,7 +1127,7 @@ package = { #define HAVE_GETADDRINFO /* Define to 1 if the getaddrinfo function is threadsafe. */ -#define HAVE_GETADDRINFO_THREADSAFE +/* #undef HAVE_GETADDRINFO_THREADSAFE */ /* Define to 1 if you have the getenv function. */ #define HAVE_GETENV @@ -1084,31 +1145,31 @@ package = { #define HAVE_GETNAMEINFO /* Define to 1 if you have the getservbyport_r function. */ -/* #undef HAVE_GETSERVBYPORT_R */ +#define HAVE_GETSERVBYPORT_R /* Define to 1 if you have the `gettimeofday' function. */ -/* #undef HAVE_GETTIMEOFDAY */ +#define HAVE_GETTIMEOFDAY /* Define to 1 if you have the `if_indextoname' function. */ -/* #undef HAVE_IF_INDEXTONAME */ +#define HAVE_IF_INDEXTONAME /* Define to 1 if you have a IPv6 capable working inet_net_pton function. */ /* #undef HAVE_INET_NET_PTON */ /* Define to 1 if you have a IPv6 capable working inet_ntop function. */ -/* #undef HAVE_INET_NTOP */ +#define HAVE_INET_NTOP /* Define to 1 if you have a IPv6 capable working inet_pton function. */ -/* #undef HAVE_INET_PTON */ +#define HAVE_INET_PTON /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H /* Define to 1 if you have the ioctl function. */ -/* #undef HAVE_IOCTL */ +#define HAVE_IOCTL /* Define to 1 if you have the ioctlsocket function. */ -#define HAVE_IOCTLSOCKET +/* #undef HAVE_IOCTLSOCKET */ /* Define to 1 if you have the IoctlSocket camel case function. */ /* #undef HAVE_IOCTLSOCKET_CAMEL */ @@ -1118,13 +1179,13 @@ package = { /* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ /* Define to 1 if you have a working ioctlsocket FIONBIO function. */ -#define HAVE_IOCTLSOCKET_FIONBIO +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ /* Define to 1 if you have a working ioctl FIONBIO function. */ -/* #undef HAVE_IOCTL_FIONBIO */ +#define HAVE_IOCTL_FIONBIO /* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ -/* #undef HAVE_IOCTL_SIOCGIFADDR */ +#define HAVE_IOCTL_SIOCGIFADDR /* Define to 1 if you have the `resolve' library (-lresolve). */ /* #undef HAVE_LIBRESOLV */ @@ -1145,19 +1206,19 @@ package = { #define HAVE_MEMORY_H /* Define to 1 if you have the MSG_NOSIGNAL flag. */ -/* #undef HAVE_MSG_NOSIGNAL */ +#define HAVE_MSG_NOSIGNAL /* Define to 1 if you have the header file. */ -/* #undef HAVE_NETDB_H */ +#define HAVE_NETDB_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_IN_H */ +#define HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_TCP_H */ +#define HAVE_NETINET_TCP_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_NET_IF_H */ +#define HAVE_NET_IF_H /* Define to 1 if you have PF_INET6. */ #define HAVE_PF_INET6 @@ -1205,34 +1266,34 @@ package = { #define HAVE_STDLIB_H /* Define to 1 if you have the strcasecmp function. */ -/* #undef HAVE_STRCASECMP */ +#define HAVE_STRCASECMP /* Define to 1 if you have the strcmpi function. */ -#define HAVE_STRCMPI +/* #undef HAVE_STRCMPI */ /* Define to 1 if you have the strdup function. */ #define HAVE_STRDUP /* Define to 1 if you have the stricmp function. */ -#define HAVE_STRICMP +/* #undef HAVE_STRICMP */ /* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H */ +#define HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #define HAVE_STRING_H /* Define to 1 if you have the strncasecmp function. */ -/* #undef HAVE_STRNCASECMP */ +#define HAVE_STRNCASECMP /* Define to 1 if you have the strncmpi function. */ /* #undef HAVE_STRNCMPI */ /* Define to 1 if you have the strnicmp function. */ -#define HAVE_STRNICMP +/* #undef HAVE_STRNICMP */ /* Define to 1 if you have the header file. */ -/* #undef HAVE_STROPTS_H */ +#define HAVE_STROPTS_H /* Define to 1 if you have struct addrinfo. */ #define HAVE_STRUCT_ADDRINFO @@ -1250,49 +1311,49 @@ package = { #define HAVE_STRUCT_TIMEVAL /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IOCTL_H */ +#define HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_PARAM_H */ +#define HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SELECT_H */ +#define HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ +#define HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TIME_H */ +#define HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UIO_H */ +#define HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #define HAVE_TIME_H /* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ +#define HAVE_UNISTD_H /* Define to 1 if you have the windows.h header file. */ -#define HAVE_WINDOWS_H +/* #undef HAVE_WINDOWS_H */ /* Define to 1 if you have the winsock2.h header file. */ -#define HAVE_WINSOCK2_H +/* #undef HAVE_WINSOCK2_H */ /* Define to 1 if you have the winsock.h header file. */ -#define HAVE_WINSOCK_H +/* #undef HAVE_WINSOCK_H */ /* Define to 1 if you have the writev function. */ -/* #undef HAVE_WRITEV */ +#define HAVE_WRITEV /* Define to 1 if you have the ws2tcpip.h header file. */ -#define HAVE_WS2TCPIP_H +/* #undef HAVE_WS2TCPIP_H */ /* Define if __system_property_get exists. */ /* #undef HAVE___SYSTEM_PROPERTY_GET */ @@ -1310,7 +1371,7 @@ package = { #define RECVFROM_QUAL_ARG5 /* Define to the type of arg 1 for recvfrom. */ -#define RECVFROM_TYPE_ARG1 SOCKET +#define RECVFROM_TYPE_ARG1 int /* Define to the type pointed by arg 2 for recvfrom. */ #define RECVFROM_TYPE_ARG2 void * @@ -1319,7 +1380,7 @@ package = { #define RECVFROM_TYPE_ARG2_IS_VOID 0 /* Define to the type of arg 3 for recvfrom. */ -#define RECVFROM_TYPE_ARG3 int +#define RECVFROM_TYPE_ARG3 size_t /* Define to the type of arg 4 for recvfrom. */ #define RECVFROM_TYPE_ARG4 int @@ -1337,22 +1398,22 @@ package = { #define RECVFROM_TYPE_ARG6_IS_VOID 0 /* Define to the function return type for recvfrom. */ -#define RECVFROM_TYPE_RETV int +#define RECVFROM_TYPE_RETV ssize_t /* Define to the type of arg 1 for recv. */ -#define RECV_TYPE_ARG1 SOCKET +#define RECV_TYPE_ARG1 int /* Define to the type of arg 2 for recv. */ #define RECV_TYPE_ARG2 void * /* Define to the type of arg 3 for recv. */ -#define RECV_TYPE_ARG3 int +#define RECV_TYPE_ARG3 size_t /* Define to the type of arg 4 for recv. */ #define RECV_TYPE_ARG4 int /* Define to the function return type for recv. */ -#define RECV_TYPE_RETV int +#define RECV_TYPE_RETV ssize_t /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE @@ -1361,22 +1422,22 @@ package = { #define SEND_QUAL_ARG2 /* Define to the type of arg 1 for send. */ -#define SEND_TYPE_ARG1 SOCKET +#define SEND_TYPE_ARG1 int /* Define to the type of arg 2 for send. */ #define SEND_TYPE_ARG2 void * /* Define to the type of arg 3 for send. */ -#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG3 size_t /* Define to the type of arg 4 for send. */ #define SEND_TYPE_ARG4 int /* Define to the function return type for send. */ -#define SEND_TYPE_RETV int +#define SEND_TYPE_RETV ssize_t /* Define to 1 if you can safely include both and . */ -/* #undef TIME_WITH_SYS_TIME */ +#define TIME_WITH_SYS_TIME /* Define to disable non-blocking sockets. */ #undef USE_BLOCKING_SOCKETS @@ -1386,12 +1447,33 @@ package = { /* Type to use in place of in_addr_t when system does not provide it. */ #undef in_addr_t - -/* gRPC manual edits here! */ -#define HAVE_IPHLPAPI_H -#define HAVE_NETIOAPI_H +#endif ]==], - }, + }, + + linux = { + -- Frozen configure snapshot, taken verbatim from gRPC 1.83.0's + -- third_party/cares/config_linux/ares_config.h. gRPC pins c-ares at this + -- exact release (submodule d3a507e == tag v1.34.5) and ships these files + -- precisely so the library can be built without running c-ares' + -- configure/CMake, which is the same thing this package needs. + ldflags = { "-lpthread" }, + }, + macosx = { + -- Frozen configure snapshot, taken verbatim from gRPC 1.83.0's + -- third_party/cares/config_darwin/ares_config.h. gRPC pins c-ares at this + -- exact release (submodule d3a507e == tag v1.34.5) and ships these files + -- precisely so the library can be built without running c-ares' + -- configure/CMake, which is the same thing this package needs. + -- config_darwin defines HAVE_LIBRESOLV, so res_* comes from libresolv. + ldflags = { "-lresolv" }, + }, + windows = { + -- Frozen configure snapshot, taken verbatim from gRPC 1.83.0's + -- third_party/cares/config_windows/ares_config.h. gRPC pins c-ares at this + -- exact release (submodule d3a507e == tag v1.34.5) and ships these files + -- precisely so the library can be built without running c-ares' + -- configure/CMake, which is the same thing this package needs. cflags = { "-DNOMINMAX", "-D_CRT_SECURE_NO_DEPRECATE", "-D_CRT_NONSTDC_NO_DEPRECATE", "-D_WIN32_WINNT=0x0600" }, ldflags = { "-lws2_32", "-liphlpapi" }, }, diff --git a/pkgs/c/compat.curl.lua b/pkgs/c/compat.curl.lua index 1b818cfa..3c2a63e0 100644 --- a/pkgs/c/compat.curl.lua +++ b/pkgs/c/compat.curl.lua @@ -248,20 +248,56 @@ package = { #if defined(__linux__) #define CURL_OS "Linux" -/* glibc's strerror_r returns char*, not int — curl needs to know which */ + +/* `__linux__` ANSWERS "WHICH KERNEL", NOT "WHICH USERSPACE IS INSTALLED", and + * this block used to read it as the second. Every entry below that names a + * HEADER now asks whether that header is reachable, which is the question + * being asked and is standard C; every entry that names a GLIBC extension + * asks for glibc. + * + * Measured: over openkal-musl on x86_64-linux-gnu the kernel is Linux, so + * `__linux__` is correct, and `#define HAVE_LINUX_TCP_H 1` then sent + * `lib/setopt.c:31` to a uapi header that C library does not carry --- + * `fatal error: 'linux/tcp.h' file not found`, one of the failures in this + * repository's own compatibility measurement. */ +#if __has_include() +#define HAVE_LINUX_TCP_H 1 +#endif +/* `__has_include` ANSWERS ABOUT THE HEADER, NOT ABOUT THE FUNCTION, and those + * two come apart here. openkal-musl CARRIES `sys/eventfd.h` and declares + * `eventfd` absent in its `[c-abi-absent]` table, so defining `HAVE_EVENTFD` + * from the header's presence produced a link that mcpp explained by name: + * + * the C library in this graph (musl) declares that it does not supply + * the following, and the link has just asked for it: + * eventfd as timerfd_create + * + * Neither is declared: curl has a poll-based path and takes it. A header + * test cannot stand in for a symbol test. */ +#if __has_include() +#define HAVE_TERMIO_H 1 +#endif +#if __has_include() +#define HAVE_FSETXATTR 1 +#define HAVE_FSETXATTR_5 1 +#endif + +/* WHICH `strerror_r`, AND EXACTLY ONE OF THEM. glibc's returns `char*`, + * POSIX's returns `int`, and `strerr.c:30` refuses a configuration that names + * neither or both. Asking `__linux__` answered "glibc" for musl, which is the + * wrong one; leaving it out answered "neither", which is also refused. */ +#if defined(__GLIBC__) #define HAVE_GLIBC_STRERROR_R 1 +#else +#define HAVE_POSIX_STRERROR_R 1 +#endif + #define HAVE_GETHOSTBYNAME_R 1 #define HAVE_GETHOSTBYNAME_R_6 1 #define HAVE_ACCEPT4 1 #define HAVE_PIPE2 1 -#define HAVE_EVENTFD 1 -#define HAVE_SYS_EVENTFD_H 1 #define HAVE_SENDMMSG 1 #define HAVE_MEMRCHR 1 -#define HAVE_FSETXATTR 1 -#define HAVE_FSETXATTR_5 1 -#define HAVE_LINUX_TCP_H 1 -#define HAVE_TERMIO_H 1 #define HAVE_CLOCK_GETTIME_MONOTONIC_RAW 1 /* Debian/Fedora layout; overridable at runtime with CURLOPT_CAINFO or the * SSL_CERT_FILE environment variable. */ diff --git a/pkgs/c/compat.mimalloc.lua b/pkgs/c/compat.mimalloc.lua index 41829663..c77bc5d5 100644 --- a/pkgs/c/compat.mimalloc.lua +++ b/pkgs/c/compat.mimalloc.lua @@ -112,6 +112,40 @@ package = { runtime = { libraries = { "psapi", "shell32", "user32", "advapi32", "bcrypt" }, }, + + -- `__builtin_thread_pointer()` IS NOT AVAILABLE FOR EVERY OS THE + -- TRIPLE CAN NAME, AND THE FAILURE IS A BACKEND CRASH. + -- + -- prim-tls.h:176 turns the builtin on for x86_64 with clang >= 14 + -- unless `__APPLE__`, `__CYGWIN__` or `MI_LIBC_MUSL` says + -- otherwise. Two of those three would have excluded this target + -- and neither reaches it: mcpp suppresses `__CYGWIN__` on purpose, + -- because source must not read the realisation triple as a + -- statement about Cygwin, and `MI_LIBC_MUSL` is a build option + -- upstream expects the packager to set ("Enable this when linking + -- with musl libc", CMakeLists.txt:39) rather than something it + -- detects. So the guard passes, and LLVM has no lowering for the + -- builtin on this OS: + -- + -- fatal error: error in backend: Target OS doesn't support + -- __builtin_thread_pointer() yet. + -- + -- prim-tls.h:176 opens with `#if !defined(...) /* allow user + -- override */`, so the answer is to give it one. This is the + -- Windows branch, and on a Win32 target the setting is not read at + -- all --- `_WIN32` selects `NtCurrentTeb()` three arms earlier --- + -- so it changes only the target that has no `_WIN32`. + -- + -- WHAT THIS FIXES AND WHAT IT DOES NOT. The cell goes from + -- `fails: error: build failed` to `builds`: the backend crash is + -- gone and the member compiles and links for this target. Its + -- `alloc` test then passes under one Wine and exits 1 under the + -- one this repository's CI installs, so the published reading is + -- `builds` rather than `runs`. That remainder is a separate + -- question about the TLS path the override falls back to, and it + -- is recorded here rather than folded into this one so the next + -- reader does not take a green build for a green test. + cflags = { "-DMI_USE_BUILTIN_THREAD_POINTER=0" }, }, }, } diff --git a/pkgs/c/compat.openssl.lua b/pkgs/c/compat.openssl.lua index 0cabfac8..e4b63f02 100644 --- a/pkgs/c/compat.openssl.lua +++ b/pkgs/c/compat.openssl.lua @@ -132,6 +132,41 @@ package = { include_dirs = { "include" }, deps = { }, + -- THIS ARCHIVE IS BOUND TO THE C LIBRARY IT WAS BUILT AGAINST, AND + -- SAYING SO IS THE ONLY THING THAT MAKES THAT VISIBLE. + -- + -- `install()` runs OpenSSL's own Configure and make, outside mcpp's + -- compile rules, once per installed package. `cc_override()` hands + -- that build `gcc --sysroot=` on linux and + -- `/usr/bin/cc` on macOS, so the archive it produces is a glibc (or + -- libSystem) artefact -- and the hook cannot be otherwise, because it + -- runs at install time and knows nothing about the graph any later + -- consumer will resolve. + -- + -- Linked into a graph with a different C library, it fails at symbols + -- that library does not have. Measured on x86_64-linux-gnu over + -- openkal, whose c-abi is musl: + -- + -- ld.lld: error: undefined symbol: setcontext + -- >>> referenced by async.c + -- >>> libcrypto-lib-async.o in archive .../libcrypto.a + -- + -- (musl omits the `*context` family deliberately), and + -- `__isoc23_strtol`, which is glibc's header redirection for + -- `strtol`. + -- + -- `platform-sdk` is the engine's existing word for "this package + -- brings the platform's own side into the graph" (docs/06, "Making it + -- visible to the closure"). Declaring it does not make the link + -- succeed, and is not meant to: it puts the package on every build's + -- `Target` report and lets `[build] platform-dependencies = "refuse"` + -- fail the build with the cause rather than with a missing symbol + -- three layers down. Building OpenSSL inside the graph is what would + -- make the link succeed, and that is a different change: its source + -- list comes from Configure, so it needs the snapshot treatment + -- compat.c-ares and compat.ffmpeg have. + provides = { "platform-sdk" }, + linux = { ldflags = { "-Llib", diff --git a/tests/examples/expat/tests/xml.cpp b/tests/examples/expat/tests/xml.cpp index ce605881..e371622e 100644 --- a/tests/examples/expat/tests/xml.cpp +++ b/tests/examples/expat/tests/xml.cpp @@ -102,17 +102,39 @@ int main() // the same either way: the code that just parsed must not have come from // the ecosystem's `xim:expat`, which is present whenever Mesa is and would // otherwise answer silently. + // + // A STATICALLY LINKED BINARY CANNOT ANSWER THIS, AND THAT IS NOT A + // FAILURE. musl's `dladdr` is `weak_alias(stub_dladdr, dladdr)` returning + // 0 (src/ldso/dladdr.c); the dynamic loader overrides it, and a static + // link has no loader to do so. An openkal program is statically linked, so + // the call returns 0 for every address, and the risk this check exists for + // cannot arise there either: nothing was loaded at runtime, so the only + // expat in the process is the one that was linked in. + // + // SKIPPING IT SILENTLY WOULD MAKE "no loader" AND "the loader answered + // wrongly" THE SAME READING, so the fallback asserts what distinguishes + // them. `main` is in this executable by construction; if `dladdr` cannot + // locate that either, there is no dynamic symbol information at all and + // the question is moot. If it locates `main` but not `XML_ParserCreate`, + // something is wrong and the check fails as before. { Dl_info info{}; const bool located = ::dladdr(reinterpret_cast(&XML_ParserCreate), &info) != 0 && info.dli_fname != nullptr; - check(located, "dladdr locates the code that parsed"); if (located) { const std::string from = info.dli_fname; std::printf(" resolved from: %s\n", from.c_str()); check(from.find("xim-x-expat") == std::string::npos, "it is not the ecosystem payload's libexpat"); + } else { + Dl_info self{}; + const bool anyAnswer = + ::dladdr(reinterpret_cast(&main), &self) != 0; + std::printf(" dladdr answers nothing in this image%s\n", + anyAnswer ? " EXCEPT main" : " at all (static link)"); + check(!anyAnswer, + "dladdr locates the code that parsed, or locates nothing"); } } diff --git a/tests/openkal/__pycache__/compat.cpython-313.pyc b/tests/openkal/__pycache__/compat.cpython-313.pyc deleted file mode 100644 index 132e6239..00000000 Binary files a/tests/openkal/__pycache__/compat.cpython-313.pyc and /dev/null differ diff --git a/tests/openkal/compat.py b/tests/openkal/compat.py index 77d07cc7..fbeb0032 100644 --- a/tests/openkal/compat.py +++ b/tests/openkal/compat.py @@ -13,10 +13,11 @@ adds the openkal C++ runtime named by pins.toml, and builds with the pinned toolchain. A target equal to the host is tested (`mcpp test`); another target is tested through its runner when pins.toml names one and the runner is on -PATH, and built otherwise. Each member is reported per target as one of +PATH, and has its tests built (`mcpp test --no-run`) otherwise. Each member is reported per target as one of runs the member's tests passed - builds the member built; its tests were not run on this host + builds the member's own tests compiled and linked for the target; this + host cannot run them, so `mcpp test --no-run` stopped there fails the build or the tests failed; the first diagnostic is kept and, alongside `status`, a second and orthogonal `kind` records how the @@ -204,18 +205,41 @@ def first_diagnostic(output: str) -> str: return output.strip().splitlines()[-1][:300] if output.strip() else "" +def command_for(target: str, toolchain: str, native: bool, can_run: bool) -> list: + """The command that measures one cell. + + Separated from `measure` so the choice has a criterion that runs without a + toolchain, a network or a member (`compat.py selftest`). It decides what a + published `builds` means, and the reading it produced before was about the + member's dependencies rather than the member. + """ + cmd = ["mcpp", "test", "--toolchain", toolchain] + if not native: + cmd += ["--target", target] + if not can_run: + # `mcpp test --no-run`, NOT `mcpp build`, AND THE DIFFERENCE IS THE + # WHOLE CELL. + # + # `mcpp build` builds the PACKAGE. Every member here keeps its sources + # under `tests/`, so for a target with no runner it compiled the + # member's dependencies, exited 0, and this file recorded `builds` --- a + # statement about musl and zlib with the member's name on it. Measured + # on `archive` for aarch64-macos: 1990 objects, of which none came from + # `tests/compression.cpp` or `tests/versions.cpp`. + # + # `--no-run` compiles and links the member's own tests for the target + # and does not execute them, which is exactly what this cell claims. + cmd.append("--no-run") + return cmd + + def measure(member: str, target: str, pins: dict) -> dict: work = prepare(member, pins) toolchain = pins["toolchain"] native = target == host_triple() runner = (pins.get("runners") or {}).get(target) - can_run = native or (runner and shutil.which(runner[0])) - if can_run: - cmd = ["mcpp", "test", "--toolchain", toolchain] - if not native: - cmd += ["--target", target] - else: - cmd = ["mcpp", "build", "--toolchain", toolchain, "--target", target] + can_run = bool(native or (runner and shutil.which(runner[0]))) + cmd = command_for(target, toolchain, native, can_run) proc = subprocess.run(cmd, cwd=work, capture_output=True, text=True, timeout=pins.get("timeout", 3600)) out = proc.stdout + proc.stderr @@ -434,6 +458,20 @@ def cmd_selftest(_args: argparse.Namespace) -> int: declared_not_portable({"m": {"t1": "why"}}, "m", "t2"), None), ("nor for another member", declared_not_portable({"m": {"t1": "why"}}, "n", "t1"), None), + # The command is what decides whether `builds` is about the member or + # about its dependencies. `mcpp build` was the old answer and compiled + # none of the member; these three pin the new one. + ("a target with no runner builds the member's own tests", + command_for("aarch64-macos", "llvm@22.1.8", False, False), + ["mcpp", "test", "--toolchain", "llvm@22.1.8", + "--target", "aarch64-macos", "--no-run"]), + ("a target with a runner runs them", + command_for("x86_64-windows-gnu", "llvm@22.1.8", False, True), + ["mcpp", "test", "--toolchain", "llvm@22.1.8", + "--target", "x86_64-windows-gnu"]), + ("the host names no target and runs them", + command_for("x86_64-linux-gnu", "llvm@22.1.8", True, True), + ["mcpp", "test", "--toolchain", "llvm@22.1.8"]), ] bad = 0 for name, got, want in cases: diff --git a/tests/openkal/members.toml b/tests/openkal/members.toml index 1d9172d4..e6dc9b1a 100644 --- a/tests/openkal/members.toml +++ b/tests/openkal/members.toml @@ -50,6 +50,14 @@ cmp-module = "coroutines, C++ modules" # `curl`'s `linux/tcp.h` is exactly that, `#define HAVE_LINUX_TCP_H 1` inside # `#if defined(__linux__)` in `pkgs/c/compat.curl.lua`. What qualifies is # upstream source that asks in the preprocessor where no key can answer. +[not-portable.curl] +# Both targets, one cause: this graph supplies no TLS provider, and the member's +# own test refuses a curl without one -- transfer.cpp:45 fails when +# CURL_VERSION_SSL is clear, because "a curl built with no SSL still links and +# still runs, it just silently cannot do https". +x86_64-linux-gnu = "curl's TLS backend here is compat.openssl, which builds through OpenSSL's own Configure from an install() hook and is therefore a glibc artefact: it declares provides = [\"platform-sdk\"] and fails this graph's link at setcontext and __isoc23_strtol, which musl does not have. Building OpenSSL inside the graph would change this cell." +x86_64-windows-gnu = "curl's Windows configuration is Schannel plus the checked-in lib/config-win32.h, and both are selected by _WIN32, which a C library presenting POSIX on Windows does not define. With neither HAVE_CONFIG_H nor _WIN32, curl_setup.h reads no configuration at all and stops at curl_setup.h:591 'too small curl_off_t', which names a consequence and not the cause. compat.openssl has no Windows build, so there is no second TLS provider to fall back to." + [not-portable.cmp-module] x86_64-linux-gnu = "asio's detail/config.hpp:899 includes whenever __linux__ is defined, OUTSIDE every ASIO_DISABLE_* guard, so no configuration macro prevents it. openkal runs on the Linux kernel, so __linux__ is correct; the uapi headers glibc's userspace installs beside it are not part of what openkal presents." diff --git a/tests/openkal/pins.toml b/tests/openkal/pins.toml index a18bf85a..342a6176 100644 --- a/tests/openkal/pins.toml +++ b/tests/openkal/pins.toml @@ -18,6 +18,27 @@ toolchain = "llvm@22.1.8" # index requires mcpp >= 2026.9.18.1 but this is mcpp 2026.9.17.3 [E0006]" # before a single line of the member's own source is read. # +# 2026-09-21 (second move): `mcpp` -> 2026.9.21.3, AND THIS ONE MOVES ALONE. +# +# THE HARNESS NOW NEEDS AN ENGINE FLAG. A target with no runner is measured +# with `mcpp test --no-run`, which 2026.9.21.3 is the first release to carry. +# Before it, such a target was measured with `mcpp build`, which builds the +# PACKAGE -- and every member here keeps its sources under `tests/`, so that +# compiled the member's dependencies and none of the member. The reading was +# never wrong in CI, because both targets below are runnable there (linux +# natively, windows through the Wine this workflow installs and checks); it +# was wrong the moment a third target was considered. +# +# `runtime` does not move with it: 0.15.0 is the graph this engine change was +# measured against, and moving both at once would make a red cell ambiguous +# between the two. +# +# aarch64-macos IS STILL NOT PINNED, and that is a measurement rather than an +# omission: 20 of 30 members build there and 10 do not, nine of the ten +# reaching for the Apple C environment under `#ifdef __APPLE__` on a target +# where `__APPLE__` is true and libSystem is not present. See +# docs/openkal-compat.md, "Why aarch64-macos is not a pinned target yet". + # 2026-09-21: `runtime` -> 0.15.0 AND `mcpp` -> 2026.9.21.2, AND THE TWO MOVE # TOGETHER BECAUSE THE MEASUREMENT IS ABOUT WHAT THE PAIR DOES. # @@ -74,7 +95,7 @@ toolchain = "llvm@22.1.8" # openkal-musl 0.16.0 and openkal-llvm-runtime 0.12.0), because a pin that # moves onto an unreachable or divergent asset fails every member at once and # reports it as a compatibility result. -mcpp = "2026.9.21.2" +mcpp = "2026.9.21.3" targets = ["x86_64-linux-gnu", "x86_64-windows-gnu"]