diff --git a/pkgs/by-name/po/ponyc/cmake-presets.patch b/pkgs/by-name/po/ponyc/cmake-presets.patch new file mode 100644 index 000000000000..f8ee564f7a09 --- /dev/null +++ b/pkgs/by-name/po/ponyc/cmake-presets.patch @@ -0,0 +1,34 @@ +diff --git a/CMakePresets.json b/CMakePresets.json +index d12d71eb5..d337e7339 100644 +--- a/CMakePresets.json ++++ b/CMakePresets.json +@@ -9,11 +9,7 @@ + { + "name": "base", + "hidden": true, +- "binaryDir": "${sourceDir}/build/build_${presetName}", +- "cacheVariables": { +- "CMAKE_C_COMPILER": "clang", +- "CMAKE_CXX_COMPILER": "clang++" +- } ++ "binaryDir": "${sourceDir}/build/build_${presetName}" + }, + { + "name": "native", +diff --git a/lib/CMakePresets.json b/lib/CMakePresets.json +index 12d797b87..92196d931 100644 +--- a/lib/CMakePresets.json ++++ b/lib/CMakePresets.json +@@ -19,11 +19,7 @@ + { + "name": "libs", + "displayName": "Vendored LLVM + support libraries (clang)", +- "inherits": "libs-base", +- "cacheVariables": { +- "CMAKE_C_COMPILER": "clang", +- "CMAKE_CXX_COMPILER": "clang++" +- } ++ "inherits": "libs-base" + }, + { + "name": "libs-windows-x86-64", diff --git a/pkgs/by-name/po/ponyc/disable-networking-tests.patch b/pkgs/by-name/po/ponyc/disable-networking-tests.patch index 2bf7d15a58b4..fccafa80b7ed 100644 --- a/pkgs/by-name/po/ponyc/disable-networking-tests.patch +++ b/pkgs/by-name/po/ponyc/disable-networking-tests.patch @@ -1,41 +1,80 @@ -From c1283b82daff94ebac21fc20cb8df0b05aa080f8 Mon Sep 17 00:00:00 2001 -From: Morgan Jones -Date: Fri, 22 May 2026 23:06:52 -0700 -Subject: [PATCH] net: disable networking tests - ---- - packages/net/_test.pony | 18 ------------------ - 1 file changed, 18 deletions(-) - diff --git a/packages/net/_test.pony b/packages/net/_test.pony -index 1d7b2d6f..69cbeea6 100644 +index 081ce67a0..99942c05e 100644 --- a/packages/net/_test.pony +++ b/packages/net/_test.pony -@@ -20,24 +20,6 @@ actor \nodoc\ Main is TestList +@@ -26,14 +26,14 @@ actor \nodoc\ Main is TestList + + fun tag tests(test: PonyTest) => // Tests below function across all systems and are listed alphabetically +- test(_TestDNSBroadcastIP4) +- test(_TestDNSBroadcastIP6) +- test(_TestDNSUnresolvableEmpty) +- test(_TestMulticastIP4) +- test(_TestMulticastIP6) +- test(_TestNetAddressIP6Scope) +- test(_TestNetAddressNameRoundTripIP4) +- test(_TestNetAddressNameRoundTripIP6) ++// test(_TestDNSBroadcastIP4) ++// test(_TestDNSBroadcastIP6) ++// test(_TestDNSUnresolvableEmpty) ++// test(_TestMulticastIP4) ++// test(_TestMulticastIP6) ++// test(_TestNetAddressIP6Scope) ++// test(_TestNetAddressNameRoundTripIP4) ++// test(_TestNetAddressNameRoundTripIP6) test(_TestOsIpString) + test(_TestSocketResultDecoder) test(_TestTCPConnectionFailed) -- test(_TestTCPExpect) -- test(_TestTCPExpectOverBufferSize) -- test(_TestTCPExpectSetToZero) -- test(_TestTCPMute) -- test(_TestTCPProxy) -- test(_TestTCPUnmute) -- test(_TestTCPWritev) -- -- // Tests below exclude windows and are listed alphabetically -- ifdef not windows then -- test(_TestTCPConnectionToClosedServerFailed) -- test(_TestTCPThrottle) +@@ -48,36 +48,36 @@ actor \nodoc\ Main is TestList + test(_TestTCPThrottle) + test(_TestTCPUnmute) + test(_TestTCPWritev) +- test(_TestUDPEmptyDatagramDelivered) ++// test(_TestUDPEmptyDatagramDelivered) + test(_TestUDPListenFailure) +- test(_TestUDPOversizedDatagramTruncated) +- test(_TestUDPUndersizedDatagramDelivered) +- test(_TestUDPZeroSizeReadBufferDelivers) ++// test(_TestUDPOversizedDatagramTruncated) ++// test(_TestUDPUndersizedDatagramDelivered) ++// test(_TestUDPZeroSizeReadBufferDelivers) + test(_TestUnicastIP6Loopback) + + // The deterministic send-failure trigger (send to broadcast without + // SO_BROADCAST -> EACCES/WSAEACCES) is verified on linux and windows. +- ifdef linux or windows then +- test(_TestUDPCloseOnSendFailure) - end -- -- // Tests below exclude osx and are listed alphabetically ++// ifdef linux or windows then ++// test(_TestUDPCloseOnSendFailure) ++// end + + // Tests below run only on linux and are listed alphabetically +- ifdef linux then +- test(_TestBroadcastReceive) +- end ++// ifdef linux then ++// test(_TestBroadcastReceive) ++// end + + // Tests below exclude osx and are listed alphabetically - ifdef not osx then - test(_TestBroadcast) - end ++// ifdef not osx then ++// test(_TestBroadcast) ++// end + + // Tests below exclude osx and bsd and are listed alphabetically. + // They read IPv4 multicast options back with getsockopt_u32, which + // expects a 4-byte value; osx and bsd return these options as a 1-byte + // u_char, so the read-back fails there regardless of correctness. +- ifdef (not osx) and (not bsd) then +- test(_TestMulticastSockopt) +- end ++// ifdef (not osx) and (not bsd) then ++// test(_TestMulticastSockopt) ++// end class \nodoc\ _TestPing is UDPNotify let _h: TestHelper --- -2.53.0 - diff --git a/pkgs/by-name/po/ponyc/disable-process-tests.patch b/pkgs/by-name/po/ponyc/disable-process-tests.patch deleted file mode 100644 index e4ee0656655b..000000000000 --- a/pkgs/by-name/po/ponyc/disable-process-tests.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 77d703b11d298f6be88b04f7e8ca85de139e82be Mon Sep 17 00:00:00 2001 -From: Morgan Jones -Date: Mon, 5 May 2025 20:34:02 -0700 -Subject: [PATCH] process: disable KillLongRunningChild test - ---- - packages/process/_test.pony | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/packages/process/_test.pony b/packages/process/_test.pony -index fe9fdb04..756588f9 100644 ---- a/packages/process/_test.pony -+++ b/packages/process/_test.pony -@@ -18,7 +18,8 @@ actor \nodoc\ Main is TestList - test(_TestChdir) - test(_TestExpect) - test(_TestFileExecCapabilityIsRequired) -- test(_TestKillLongRunningChild) -+ // (@booxter/@numinit) Appears to be flaky. -+ // test(_TestKillLongRunningChild) - test(_TestLongRunningChild) - test(_TestNonExecutablePathResultsInExecveError) - test(_TestPrintvOrdering) --- -2.47.0 - diff --git a/pkgs/by-name/po/ponyc/fix-darwin-build.patch b/pkgs/by-name/po/ponyc/fix-darwin-build.patch deleted file mode 100644 index 47d99cfb9242..000000000000 --- a/pkgs/by-name/po/ponyc/fix-darwin-build.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/libponyc/codegen/genexe.cc b/src/libponyc/codegen/genexe.cc -index 3f0348eaa1..76b03030bf 100644 ---- a/src/libponyc/codegen/genexe.cc -+++ b/src/libponyc/codegen/genexe.cc -@@ -308,7 +308,7 @@ - snprintf(ld_cmd, ld_len, - "%s -execute -arch %.*s " - "-o %s %s %s %s " -- "-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem %s -platform_version macos '" STR(PONY_OSX_PLATFORM) "' '0.0.0'", -+ "-L\"${SDKROOT:-${DEVELOPER_DIR:-@apple-sdk@}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk}/usr/lib\" -lSystem %s -platform_version macos '" STR(PONY_OSX_PLATFORM) "' '0.0.0'", - linker, (int)arch_len, c->opt->triple, file_exe, file_o, - lib_args, ponyrt, sanitizer_arg - ); diff --git a/pkgs/by-name/po/ponyc/gencshim-pony-cc.patch b/pkgs/by-name/po/ponyc/gencshim-pony-cc.patch new file mode 100644 index 000000000000..8340ca6d893b --- /dev/null +++ b/pkgs/by-name/po/ponyc/gencshim-pony-cc.patch @@ -0,0 +1,61 @@ +diff --git a/src/libponyc/codegen/gencshim.cc b/src/libponyc/codegen/gencshim.cc +index a1722ad01a22..db742c6adaa5 100644 +--- a/src/libponyc/codegen/gencshim.cc ++++ b/src/libponyc/codegen/gencshim.cc +@@ -7,6 +7,7 @@ + #include "../ast/stringtab.h" + #include "paths.h" + #include "ponyassert.h" ++#include "nix.h" + + #ifdef _MSC_VER + # pragma warning(push) +@@ -307,8 +308,11 @@ static const char* find_macos_sdk_include(pass_opt_t* opt) + pclose(f); + } + ++ // Fall back to the Nix apple-sdk when xcrun is unavailable, mirroring the ++ // link side in genexe.cc. The unversioned MacOSX.sdk symlink keeps this ++ // independent of the SDK version. + const char* fallback = +- "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"; ++ "@apple-sdk@/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include"; + + if(dir_exists(fallback)) + { +@@ -349,6 +353,25 @@ static bool push_isystem(pass_opt_t* opt, std::vector& args, + } + + ++/* ++ Add the Nix header search directories (see nix.h) as -internal-isystem ++ entries. push_isystem skips any directory that doesn't exist, so a partial ++ toolchain degrades gracefully. ++*/ ++static bool add_nix_include_dirs(pass_opt_t* opt, ++ std::vector& args, errors_t* errors) ++{ ++ std::vector dirs; ++ nix_collect_include_dirs(opt->strtab, dirs); ++ ++ bool any = false; ++ for(size_t i = 0; i < dirs.size(); i++) ++ any |= push_isystem(opt, args, errors, "-internal-isystem", dirs[i], ""); ++ ++ return any; ++} ++ ++ + // System include directories for the target, derived from the same sysroot + // the embedded linker uses — hand-rolled like LLD rather than driven through + // clang's Driver, so the headers the shim compiles against stay consistent +@@ -488,6 +511,9 @@ static bool add_system_include_args(pass_opt_t* opt, const char* sysroot, + any |= push_isystem(opt, args, errors, "-internal-externc-isystem", + sysroot, "/usr/include"); + ++ if(sysroot[0] == '\0') ++ any |= add_nix_include_dirs(opt, args, errors); ++ + // Per-directory skipping is right (multiarch and /usr/local are + // legitimately absent on many systems), but an explicit --sysroot that + // yields nothing at all deserves a direct answer, like the macOS branch diff --git a/pkgs/by-name/po/ponyc/genexe-pony-linker.patch b/pkgs/by-name/po/ponyc/genexe-pony-linker.patch index 39fa7a117f19..c7567b998f14 100644 --- a/pkgs/by-name/po/ponyc/genexe-pony-linker.patch +++ b/pkgs/by-name/po/ponyc/genexe-pony-linker.patch @@ -1,26 +1,158 @@ -From ac4b2a65f997f7f779b9c63dbe683ba10a26fc7f Mon Sep 17 00:00:00 2001 -From: Morgan Jones -Date: Fri, 22 May 2026 23:58:29 -0700 -Subject: [PATCH] genexe: take PONY_LINKER into account - ---- - src/libponyc/codegen/genexe.cc | 3 +++ - 1 file changed, 3 insertions(+) - diff --git a/src/libponyc/codegen/genexe.cc b/src/libponyc/codegen/genexe.cc -index 48f97578..5b9f36f1 100644 +index 826d69f0bcba..897afba953bb 100644 --- a/src/libponyc/codegen/genexe.cc +++ b/src/libponyc/codegen/genexe.cc -@@ -1448,6 +1448,9 @@ static bool link_exe(compile_t* c, ast_t* program, - { - errors_t* errors = c->opt->check.errors; +@@ -22,6 +22,7 @@ LLD_HAS_DRIVER(wasm) + #include "../type/lookup.h" + #include "../../libponyrt/mem/pool.h" + #include "ponyassert.h" ++#include "nix.h" + #include -+ if(c->opt->linker == NULL) -+ c->opt->linker = getenv("PONY_LINKER"); + #include +@@ -38,6 +39,8 @@ LLD_HAS_DRIVER(wasm) + # include + #endif + ++static bool dir_has_arch_libc_crt(const char* dir, uint16_t target_machine); + - // Use embedded LLD for Linux, macOS, and Windows targets unless --linker - // escape hatch is specified. Sanitizer builds fall back to the system - // compiler driver for native compilation since sanitizer runtime libraries --- -2.53.0 - + #if defined(PONY_SANITIZER) + // Generated at configure time (top-level CMakeLists.txt, PONY_SANITIZERS_ENABLED + // block): the sanitizer runtime link fragment captured from the compiler driver. +@@ -965,6 +968,9 @@ static bool link_exe_lld_elf(compile_t* c, ast_t* program, + + program_lib_build_args_embedded(program, c->opt); + ++ std::vector env_libdirs; ++ nix_collect_link_libdirs(c->opt->strtab, env_libdirs); ++ + const char* sys_triple = system_triple(c->opt); + bool is_freebsd = target_is_freebsd(c->opt->triple); + bool is_dragonfly = target_is_dragonfly(c->opt->triple); +@@ -996,7 +1002,11 @@ static bool link_exe_lld_elf(compile_t* c, ast_t* program, + return false; + } + +- const char* dynlinker = dynamic_linker_path(c); ++ // Prefer a Nix-provided ELF interpreter (baked default or environment); ++ // fall back to the built-in FHS search when none is configured. ++ const char* dynlinker = nix_dynamic_linker(c->opt->strtab); ++ if(dynlinker[0] == '\0') ++ dynlinker = dynamic_linker_path(c); + if(!c->opt->staticbin && dynlinker == NULL) + { + errorf(errors, NULL, +@@ -1009,10 +1019,23 @@ static bool link_exe_lld_elf(compile_t* c, ast_t* program, + const char* libc_crt_dir = find_libc_crt_dir(sysroot, sys_triple, + target_machine, c->opt->strtab); + if(libc_crt_dir == NULL) ++ { ++ for(size_t i = 0; i < env_libdirs.size(); i++) ++ { ++ if(dir_has_arch_libc_crt(env_libdirs[i], target_machine)) ++ { ++ libc_crt_dir = env_libdirs[i]; ++ break; ++ } ++ } ++ } ++ if(libc_crt_dir == NULL) + { + errorf(errors, NULL, + "could not find a libc crt startup object (crt1.o or crt0.o) " +- "matching target architecture '%s' in sysroot '%s'", ++ "matching target architecture '%s' in sysroot '%s'\n" ++ " On NixOS systems, set PONY_LINK_LIBDIRS to the directory holding " ++ "the arch-matching libc startup object (crt1.o or crt0.o).", + c->opt->triple, sysroot); + return false; + } +@@ -1305,6 +1328,21 @@ static bool link_exe_lld_elf(compile_t* c, ast_t* program, + } + } + ++/* ++ Add /nix/store lib directories to the embedded linker args ++*/ ++ for(size_t i = 0; i < env_libdirs.size(); i++) ++ { ++ snprintf(buf, sizeof(buf), "-L%s", env_libdirs[i]); ++ args.push_back(stringtab(c->opt->strtab, buf)); ++ ++ if(!c->opt->staticbin) ++ { ++ args.push_back("-rpath"); ++ args.push_back(env_libdirs[i]); ++ } ++ } ++ + // Standard system library fallback paths. The paths above cover + // distro-specific locations (libc_crt_dir, gcc_lib_dir, etc.) but miss + // common install locations like /usr/local/lib (where libraries built +@@ -1732,9 +1770,10 @@ static const char* find_macos_sdk_path(strtable_t* strtab) + pclose(f); + } + +- // Hardcoded fallback. ++ // Fall back to the Nix apple-sdk when xcrun is unavailable. The unversioned ++ // MacOSX.sdk symlink keeps this independent of the SDK version. + const char* fallback = +- "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib"; ++ "@apple-sdk@/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib"; + + struct stat st; + if(stat(fallback, &st) == 0 && S_ISDIR(st.st_mode)) +@@ -1947,6 +1986,31 @@ static bool link_exe_lld_macho(compile_t* c, ast_t* program, + } + } + ++/* ++ Add /nix/store lib directories to the embedded Mach-O linker args, mirroring ++ the ELF path. On NixOS the C++ standard library, buildInputs and user FFI ++ libraries live under /nix/store, not in the SDK's usr/lib or the Homebrew and ++ /usr/local fallbacks above. nix_collect_link_libdirs() (see nix.h) gathers ++ them from the baked PONY_NIX_LINK_LIBDIRS default, the PONY_LINK_LIBDIRS / ++ NIX_LDFLAGS env vars, and the cc-wrapper's $NIX_CC/nix-support/cc-ldflags ++ (which carries the -L path on Darwin). Without this, ++ `use "lib:c++" if osx` (as used by pony-compiler) fails to link with ++ "library not found for -lc++". ++*/ ++ std::vector env_libdirs; ++ nix_collect_link_libdirs(c->opt->strtab, env_libdirs); ++ for(size_t i = 0; i < env_libdirs.size(); i++) ++ { ++ snprintf(buf, sizeof(buf), "-L%s", env_libdirs[i]); ++ args.push_back(stringtab(c->opt->strtab, buf)); ++ ++ if(!c->opt->staticbin) ++ { ++ args.push_back("-rpath"); ++ args.push_back(env_libdirs[i]); ++ } ++ } ++ + // Object file. + args.push_back(file_o); + +@@ -2417,3 +2481,21 @@ bool genexe(compile_t* c, ast_t* program) + + return true; + } ++ ++// Does `dir` hold a libc startup object (crt1.o / crt0.o) whose ELF machine ++// matches the target? Used to pick the crt directory out of the Nix libdirs ++// gathered by nix_collect_link_libdirs(). ++static bool dir_has_arch_libc_crt(const char* dir, uint16_t target_machine) ++{ ++ static const char* sentinels[] = { "crt1.o", "crt0.o" }; ++ char buf[PATH_MAX]; ++ ++ for(size_t j = 0; j < sizeof(sentinels) / sizeof(sentinels[0]); j++) ++ { ++ snprintf(buf, sizeof(buf), "%s/%s", dir, sentinels[j]); ++ if(file_exists(buf) && elf_matches_target(buf, target_machine)) ++ return true; ++ } ++ ++ return false; ++} diff --git a/pkgs/by-name/po/ponyc/nix-codegen.patch b/pkgs/by-name/po/ponyc/nix-codegen.patch new file mode 100644 index 000000000000..f56bc8cdba15 --- /dev/null +++ b/pkgs/by-name/po/ponyc/nix-codegen.patch @@ -0,0 +1,291 @@ +diff --git a/src/libponyc/codegen/nix.h b/src/libponyc/codegen/nix.h +new file mode 100644 +index 000000000000..b1368f222b91 +--- /dev/null ++++ b/src/libponyc/codegen/nix.h +@@ -0,0 +1,47 @@ ++#ifndef CODEGEN_NIX_H ++#define CODEGEN_NIX_H ++ ++#include "../ast/stringtab.h" ++ ++#include ++ ++/* ++ Nix/NixOS toolchain path discovery for the embedded LLD linker (genexe.cc) ++ and the embedded clang C-shim compiler (gencshim.cc). ++ ++ On Nix there is no FHS layout: no /usr/lib, no /lib64/ld-linux-*.so, no ++ /usr/include. The libc, libgcc, C++ runtime, buildInputs and user FFI ++ libraries all live under /nix/store, and their locations reach the compiler ++ through baked-in defaults (the -DPONY_NIX_* macros set at configure time) and ++ the cc-wrapper environment (NIX_LDFLAGS, NIX_CFLAGS_COMPILE, ++ $NIX_CC/nix-support/*). These helpers gather those paths so the embedded ++ tools link and compile without a wrapper script. ++ ++ On a plain non-Nix build every source is empty, so the collectors append ++ nothing and behaviour is unchanged. ++*/ ++ ++// Library search directories for the linker, in priority order: ++// PONY_NIX_LINK_LIBDIRS (baked default), PONY_LINK_LIBDIRS, NIX_LDFLAGS, ++// NIX_LDFLAGS_BEFORE, $NIX_CC/nix-support {orig-libc, cc-ldflags}. ++// Directories are interned into `strtab` and appended to `dirs`; existing ++// entries are left in place. ++void nix_collect_link_libdirs(strtable_t* strtab, ++ std::vector& dirs); ++ ++// Header search directories for the C-shim compiler, in priority order: ++// PONY_NIX_INCLUDE_DIRS (baked default), PONY_INCLUDE_DIRS, ++// NIX_CFLAGS_COMPILE, $NIX_CC/nix-support/libc-cflags. ++// Directories are interned into `strtab` and appended to `dirs`; existing ++// entries are left in place. ++void nix_collect_include_dirs(strtable_t* strtab, ++ std::vector& dirs); ++ ++// The ELF dynamic linker (interpreter) path, in priority order: ++// PONY_DYNAMIC_LINKER, PONY_NIX_DYNAMIC_LINKER (baked default), ++// $NIX_CC/nix-support/dynamic-linker. ++// Returns "" (never NULL) when none is configured, so the caller can test the ++// first byte and fall back to the built-in FHS search. ++const char* nix_dynamic_linker(strtable_t* strtab); ++ ++#endif +diff --git a/src/libponyc/codegen/nix.cc b/src/libponyc/codegen/nix.cc +new file mode 100644 +index 000000000000..eddfd7833103 +--- /dev/null ++++ b/src/libponyc/codegen/nix.cc +@@ -0,0 +1,220 @@ ++#include "nix.h" ++ ++#include "../ast/stringtab.h" ++ ++#include ++#include ++#include ++#include ++ ++#ifndef PATH_MAX ++# define PATH_MAX 4096 ++#endif ++ ++/* ++ The baked-in Nix defaults. package.nix passes each of these through ++ -DPONY_NIX_*="..." in NIX_CFLAGS_COMPILE at configure time, capturing the ++ cc-wrapper's libc/libgcc/pcre2/openssl lib dirs, the ELF interpreter and the ++ libc/gcc include dirs. They are empty strings on a plain source build, which ++ disables every Nix-specific path below. ++*/ ++#ifndef PONY_NIX_LINK_LIBDIRS ++# define PONY_NIX_LINK_LIBDIRS "" ++#endif ++#ifndef PONY_NIX_DYNAMIC_LINKER ++# define PONY_NIX_DYNAMIC_LINKER "" ++#endif ++#ifndef PONY_NIX_INCLUDE_DIRS ++# define PONY_NIX_INCLUDE_DIRS "" ++#endif ++ ++/* ++ Split `s` into tokens on any delimiter character in `delims`, interning each ++ token into `strtab` and appending it to `toks`. A token that would overflow ++ the buffer is dropped whole rather than truncated to a wrong path. ++*/ ++static void tokenize(const char* s, const char* delims, strtable_t* strtab, ++ std::vector& toks) ++{ ++ if(s == NULL || s[0] == '\0') ++ return; ++ ++ char buf[PATH_MAX]; ++ size_t len = 0; ++ bool overflow = false; ++ for(const char* p = s; ; p++) ++ { ++ // The '\0' test is first so strchr is never asked to match the terminator. ++ if(*p == '\0' || strchr(delims, *p) != NULL) ++ { ++ if(len > 0 && !overflow) ++ { ++ buf[len] = '\0'; ++ toks.push_back(stringtab(strtab, buf)); ++ } ++ len = 0; ++ overflow = false; ++ if(*p == '\0') ++ break; ++ } ++ else if(len < sizeof(buf) - 1) ++ { ++ buf[len++] = *p; ++ } ++ else ++ { ++ overflow = true; ++ } ++ } ++} ++ ++/* ++ Interpret a whitespace-separated linker-flag string (NIX_LDFLAGS, ++ $NIX_CC/nix-support/cc-ldflags) for library directories, handling the joined ++ -L, the separated -L , and -rpath / -rpath-link forms. ++ ++ This is how /nix/store libraries (and directories injected by pkg-config) are ++ found where other distros would look in /usr/lib and the like. ++*/ ++static void append_ldflags_dirs(const char* flags, strtable_t* strtab, ++ std::vector& dirs) ++{ ++ std::vector toks; ++ tokenize(flags, " \t\n\r", strtab, toks); ++ ++ for(size_t i = 0; i < toks.size(); i++) ++ { ++ const char* t = toks[i]; ++ if(strncmp(t, "-L", 2) == 0) ++ { ++ if(t[2] != '\0') ++ dirs.push_back(stringtab(strtab, t + 2)); ++ else if(i + 1 < toks.size()) ++ dirs.push_back(toks[++i]); ++ } ++ else if(strcmp(t, "-rpath") == 0 || strcmp(t, "-rpath-link") == 0) ++ { ++ if(i + 1 < toks.size()) ++ dirs.push_back(toks[++i]); ++ } ++ } ++} ++ ++/* ++ Interpret a whitespace-separated compiler-flag string (NIX_CFLAGS_COMPILE, ++ $NIX_CC/nix-support/libc-cflags) for header search directories, handling the ++ joined -I, the separated -I , and -isystem / -idirafter / -iquote ++ forms. This covers directories injected by pkg-config too. ++*/ ++static void append_cflags_include_dirs(const char* flags, strtable_t* strtab, ++ std::vector& dirs) ++{ ++ std::vector toks; ++ tokenize(flags, " \t\n\r", strtab, toks); ++ ++ for(size_t i = 0; i < toks.size(); i++) ++ { ++ const char* t = toks[i]; ++ if(strcmp(t, "-isystem") == 0 || strcmp(t, "-idirafter") == 0 || ++ strcmp(t, "-iquote") == 0 || strcmp(t, "-I") == 0) ++ { ++ if(i + 1 < toks.size()) ++ dirs.push_back(toks[++i]); ++ } ++ else if(strncmp(t, "-I", 2) == 0 && t[2] != '\0') ++ { ++ dirs.push_back(stringtab(strtab, t + 2)); ++ } ++ } ++} ++ ++/* ++ Read $NIX_CC/nix-support/ into `out`, trimming trailing whitespace. ++ Returns false if the file is missing, empty, or so long it would be ++ truncated -- acting on a partial flag string would be worse than ignoring it. ++*/ ++static bool read_nix_support_file(const char* nix_cc, const char* name, ++ char* out, size_t outsz) ++{ ++ char path[PATH_MAX]; ++ snprintf(path, sizeof(path), "%s/nix-support/%s", nix_cc, name); ++ ++ FILE* f = fopen(path, "rb"); ++ if(f == NULL) ++ return false; ++ ++ size_t n = fread(out, 1, outsz - 1, f); ++ // If the buffer filled and the file still has bytes, the content was ++ // truncated; reject it rather than acting on a partial flag string. ++ bool truncated = (n == outsz - 1) && (fgetc(f) != EOF); ++ fclose(f); ++ if(truncated) ++ return false; ++ out[n] = '\0'; ++ ++ while(n > 0 && (out[n - 1] == '\n' || out[n - 1] == '\r' || ++ out[n - 1] == ' ' || out[n - 1] == '\t')) ++ out[--n] = '\0'; ++ ++ return n > 0; ++} ++ ++void nix_collect_link_libdirs(strtable_t* strtab, ++ std::vector& dirs) ++{ ++ tokenize(PONY_NIX_LINK_LIBDIRS, ":", strtab, dirs); ++ tokenize(getenv("PONY_LINK_LIBDIRS"), ":", strtab, dirs); ++ append_ldflags_dirs(getenv("NIX_LDFLAGS"), strtab, dirs); ++ append_ldflags_dirs(getenv("NIX_LDFLAGS_BEFORE"), strtab, dirs); ++ ++ const char* nix_cc = getenv("NIX_CC"); ++ if(nix_cc == NULL || nix_cc[0] == '\0') ++ return; ++ ++ char buf[PATH_MAX]; ++ if(read_nix_support_file(nix_cc, "orig-libc", buf, sizeof(buf))) ++ { ++ char libdir[PATH_MAX]; ++ snprintf(libdir, sizeof(libdir), "%s/lib", buf); ++ dirs.push_back(stringtab(strtab, libdir)); ++ } ++ ++ if(read_nix_support_file(nix_cc, "cc-ldflags", buf, sizeof(buf))) ++ append_ldflags_dirs(buf, strtab, dirs); ++} ++ ++void nix_collect_include_dirs(strtable_t* strtab, ++ std::vector& dirs) ++{ ++ tokenize(PONY_NIX_INCLUDE_DIRS, ":", strtab, dirs); ++ tokenize(getenv("PONY_INCLUDE_DIRS"), ":", strtab, dirs); ++ append_cflags_include_dirs(getenv("NIX_CFLAGS_COMPILE"), strtab, dirs); ++ ++ const char* nix_cc = getenv("NIX_CC"); ++ if(nix_cc != NULL && nix_cc[0] != '\0') ++ { ++ char cflags[PATH_MAX * 4]; ++ if(read_nix_support_file(nix_cc, "libc-cflags", cflags, sizeof(cflags))) ++ append_cflags_include_dirs(cflags, strtab, dirs); ++ } ++} ++ ++const char* nix_dynamic_linker(strtable_t* strtab) ++{ ++ const char* dl = getenv("PONY_DYNAMIC_LINKER"); ++ if(dl != NULL && dl[0] != '\0') ++ return stringtab(strtab, dl); ++ ++ if(PONY_NIX_DYNAMIC_LINKER[0] != '\0') ++ return stringtab(strtab, PONY_NIX_DYNAMIC_LINKER); ++ ++ const char* nix_cc = getenv("NIX_CC"); ++ if(nix_cc != NULL && nix_cc[0] != '\0') ++ { ++ char buf[PATH_MAX]; ++ if(read_nix_support_file(nix_cc, "dynamic-linker", buf, sizeof(buf))) ++ return stringtab(strtab, buf); ++ } ++ ++ return ""; ++} +diff --git a/src/libponyc/CMakeLists.txt b/src/libponyc/CMakeLists.txt +index f4e3e42ef48f..4a477e306ac1 100644 +--- a/src/libponyc/CMakeLists.txt ++++ b/src/libponyc/CMakeLists.txt +@@ -27,6 +27,7 @@ add_library(libponyc STATIC + codegen/gendesc.c + codegen/gencshim.cc + codegen/genexe.cc ++ codegen/nix.cc + codegen/genexpr.c + codegen/genfun.c + codegen/genheader.c diff --git a/pkgs/by-name/po/ponyc/package.nix b/pkgs/by-name/po/ponyc/package.nix index 3d01332e124f..d46d5dcb16c3 100644 --- a/pkgs/by-name/po/ponyc/package.nix +++ b/pkgs/by-name/po/ponyc/package.nix @@ -7,14 +7,11 @@ cmake, coreutils, libxml2, - lto ? true, - makeWrapper, openssl, pcre2, pony-corral, python3, zlib, - # Not really used for anything real, just at build time. git, replaceVars, which, @@ -25,13 +22,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "ponyc"; - version = "0.64.0"; + version = "0.67.0"; src = fetchFromGitHub { owner = "ponylang"; repo = "ponyc"; tag = finalAttrs.version; - hash = "sha256-CdsfJO+7y7nvlDdCXdWRB4vmP9pB1Jz5CVwJuha+yds="; + hash = "sha256-9X2xaQ5nCV/sTL3WjXNDswIfNhlwgfV4/X70p1zTd2U="; fetchSubmodules = true; }; @@ -53,7 +50,6 @@ stdenv.mkDerivation (finalAttrs: { nativeBuildInputs = [ cmake - makeWrapper which python3 git @@ -64,23 +60,36 @@ stdenv.mkDerivation (finalAttrs: { buildInputs = [ libxml2 + openssl + pcre2 z3 zlib ]; patches = [ + ./cmake-presets.patch # Sandbox disallows network access, so disabling problematic networking tests ./disable-networking-tests.patch - ./disable-process-tests.patch - - # Take PONY_LINKER into account - ./genexe-pony-linker.patch + # Adds codegen/nix.cc + nix.h (the Nix toolchain-path helpers shared by the + # embedded linker and C-shim compiler) and wires them into libponyc's + # CMakeLists. Platform-independent, so applied verbatim everywhere. + ./nix-codegen.patch ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ - (replaceVars ./fix-darwin-build.patch { - inherit apple-sdk; - }) - ]; + ++ ( + let + # These patch the embedded LLD/clang codegen and reference the macOS SDK + # via @apple-sdk@; substitute it on Darwin, apply verbatim elsewhere (the + # placeholder sits in macOS-only code that other platforms never compile). + sdkPatches = [ + ./gencshim-pony-cc.patch + ./genexe-pony-linker.patch + ]; + in + if stdenv.hostPlatform.isDarwin then + map (p: replaceVars p { inherit apple-sdk; }) sdkPatches + else + sdkPatches + ); postUnpack = '' mkdir -p $NIX_BUILD_TOP/deps @@ -88,8 +97,6 @@ stdenv.mkDerivation (finalAttrs: { tar -C "$googletest" -cf $NIX_BUILD_TOP/deps/googletest-$googletestRev.tar . ''; - dontConfigure = true; - postPatch = '' substituteInPlace packages/process/_test.pony \ --replace-fail '"/bin/' '"${coreutils}/bin/' \ @@ -105,8 +112,7 @@ stdenv.mkDerivation (finalAttrs: { ''; # We do not concern ourselves with darwin as the ponyc compiler - # has logic which overrides this environmental variable in this - # case. + # has logic which overrides this environment variable. env.arch = if stdenv.hostPlatform.isx86_64 then "x86-64" @@ -118,32 +124,41 @@ stdenv.mkDerivation (finalAttrs: { this may result in crashes on incompatible CPUs! '' "native"; - preBuild = '' - extraFlags=(build_flags=-j$NIX_BUILD_CORES) - '' - + lib.optionalString stdenv.hostPlatform.isLinux '' - export PONY_LINKER="$CC" - '' - + lib.optionalString stdenv.hostPlatform.isDarwin '' - export PONY_LINKER=ld - '' - + lib.optionalString stdenv.hostPlatform.isAarch64 '' - # See this relnote about building on Raspbian: - # https://github.com/ponylang/ponyc/blob/0.46.0/.release-notes/0.45.2.md - extraFlags+=(pic_flag=-fPIC) - '' - + '' - make libs "''${extraFlags[@]}" - make configure "''${extraFlags[@]}" + # Bake the Nix link/include paths into the compiler before it is built. + preConfigure = + lib.optionalString stdenv.hostPlatform.isLinux '' + libcDir=$(dirname "$($CC -print-file-name=crt1.o)") + gccDir=$(dirname "$($CC -print-libgcc-file-name)") + gccSharedDir=$(dirname "$($CC -print-file-name=libgcc_s.so)") + dynamicLinker=$(cat "$NIX_CC/nix-support/dynamic-linker") + libcIncDir="$(cat "$NIX_CC/nix-support/orig-libc-dev")/include" + # pcre2 and openssl are baked into the compiler's link path so an installed + # ponyc can link `use "regex"` (pcre2) and `use "net/ssl"` (openssl) + # programs without a wrapper — this replaces the old wrapProgram PONYPATH. + export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -DPONY_NIX_LINK_LIBDIRS=\"$libcDir:$gccDir:$gccSharedDir:${lib.getLib pcre2}/lib:${lib.getLib openssl}/lib\" -DPONY_NIX_DYNAMIC_LINKER=\"$dynamicLinker\" -DPONY_NIX_INCLUDE_DIRS=\"$libcIncDir:$gccDir/include:$gccDir/include-fixed\"" + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + # Bake pcre2/openssl into the compiler's link path so an installed ponyc can + # link `use "regex"` / `use "net/ssl"` without a wrapper; libc and the C++ + # standard library come from the SDK (via xcrun / apple-sdk) at link time. + export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -DPONY_NIX_LINK_LIBDIRS=\"${lib.getLib pcre2}/lib:${lib.getLib openssl}/lib\"" + ''; + + # Upstream drives the build through CMakePresets (which fix the binaryDir and + # compiler), so we bypass the cmake setup hook's configurePhase and invoke the + # presets directly rather than fight its flags. + configurePhase = '' + runHook preConfigure + cmake -DJOBS=$NIX_BUILD_CORES -P lib/build-libs.cmake + cmake --preset release + runHook postConfigure ''; - enableParallelBuilding = true; - - makeFlags = [ - "PONYC_VERSION=${finalAttrs.version}" - "prefix=${placeholder "out"}" - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin ([ "bits=64" ] ++ lib.optional (!lto) "lto=no"); + buildPhase = '' + runHook preBuild + cmake --build --preset release --parallel $NIX_BUILD_CORES + runHook postBuild + ''; env.NIX_CFLAGS_COMPILE = toString [ "-Wno-error=redundant-move" @@ -152,35 +167,21 @@ stdenv.mkDerivation (finalAttrs: { doCheck = true; - enableParallelChecking = true; - nativeCheckInputs = [ procps ]; - installPhase = '' - makeArgs=(config=release prefix=$out) - '' - + lib.optionalString stdenv.hostPlatform.isDarwin '' - makeArgs+=(bits=64) - '' - + lib.optionalString (stdenv.hostPlatform.isDarwin && !lto) '' - makeArgs+=(lto=no) - '' - + '' - make "''${makeArgs[@]}" install - wrapProgram $out/bin/ponyc \ - --prefix PATH ":" "${stdenv.cc}/bin" \ - --set-default CC "$CC" \ - --set-default PONY_LINKER "$PONY_LINKER" \ - --prefix PONYPATH : "${ - lib.makeLibraryPath [ - pcre2 - openssl - (placeholder "out") - ] - }" + checkPhase = '' + runHook preCheck + ctest --preset release -L ci-core -j$NIX_BUILD_CORES + runHook postCheck ''; - # Stripping breaks linking for ponyc + installPhase = '' + runHook preInstall + cmake --install build/build_release --prefix=$out + runHook postInstall + ''; + + # Stripping breaks linking for ponyc. dontStrip = true; passthru = { @@ -189,17 +190,19 @@ stdenv.mkDerivation (finalAttrs: { }; meta = { - description = "Pony is an Object-oriented, actor-model, capabilities-secure, high performance programming language"; + description = "Object-oriented, actor-model, capabilities-secure, high performance programming language"; homepage = "https://www.ponylang.io"; license = lib.licenses.bsd2; + mainProgram = "ponyc"; maintainers = with lib.maintainers; [ kamilchm redvers numinit ]; + # Intel macOS (x86_64-darwin) is intentionally unsupported; only Apple + # Silicon is supported on Darwin. platforms = [ "x86_64-linux" - "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];