diff --git a/pkgs/development/libraries/capnproto/default.nix b/pkgs/development/libraries/capnproto/default.nix index cda5f005f9a2..75b5f14d67ce 100644 --- a/pkgs/development/libraries/capnproto/default.nix +++ b/pkgs/development/libraries/capnproto/default.nix @@ -21,6 +21,9 @@ stdenv.mkDerivation rec { cmakeFlags = lib.optional (!(stdenv.hostPlatform.isCompatible stdenv.buildPlatform)) "-DEXTERNAL_CAPNP"; + # Upstream 77ac9154440bcc216fda1092fd5bb51da62ae09c, modified to apply to v0.9.1. Drop on update. + patches = lib.optional stdenv.hostPlatform.isMusl ./musl-no-fibers.patch; + meta = with lib; { homepage = "https://capnproto.org/"; description = "Cap'n Proto cerealization protocol"; diff --git a/pkgs/development/libraries/capnproto/musl-no-fibers.patch b/pkgs/development/libraries/capnproto/musl-no-fibers.patch new file mode 100644 index 000000000000..bb7804fb0abb --- /dev/null +++ b/pkgs/development/libraries/capnproto/musl-no-fibers.patch @@ -0,0 +1,244 @@ +From 3d983eff304c28574c330a52d70a60145c9e157e Mon Sep 17 00:00:00 2001 +From: Jonas Vautherin +Date: Fri, 14 Jan 2022 00:14:26 +0100 +Subject: [PATCH] Add support for musl + +--- +Based on upstream 77ac9154440bcc216fda1092fd5bb51da62ae09c, +modified slightly by dtzWill to apply to v0.9.1. + +(drop whitespace change to a cmake "if (WITH_OPENSSL)", +leave the other instance of that change since it applies) +--- + +Co-authored-by: Guillaume Papin +(cherry picked from commit 77ac9154440bcc216fda1092fd5bb51da62ae09c) +--- + .github/workflows/quick-test.yml | 9 ++++++ + c++/CMakeLists.txt | 46 ++++++++++++++++++++++++++++- + c++/cmake/CapnProtoConfig.cmake.in | 32 ++++++++++++++++++++ + c++/configure.ac | 47 ++++++++++++++++++++++++++++-- + c++/src/kj/CMakeLists.txt | 11 ++++++- + 5 files changed, 141 insertions(+), 4 deletions(-) + +diff --git a/.github/workflows/quick-test.yml b/.github/workflows/quick-test.yml +index c18ef6a6..773ff043 100644 +--- a/.github/workflows/quick-test.yml ++++ b/.github/workflows/quick-test.yml +@@ -10,6 +10,15 @@ on: + - 'release-*' + + jobs: ++ Linux-musl: ++ runs-on: ubuntu-latest ++ container: alpine:latest ++ steps: ++ - uses: actions/checkout@v2 ++ - name: install dependencies ++ run: apk add autoconf automake build-base cmake libtool libucontext-dev linux-headers openssl-dev ++ - name: super-test ++ run: ./super-test.sh quick + Linux: + runs-on: ubuntu-latest + strategy: +diff --git a/c++/CMakeLists.txt b/c++/CMakeLists.txt +index 548dfd1f..5de7ab26 100644 +--- a/c++/CMakeLists.txt ++++ b/c++/CMakeLists.txt +@@ -1,4 +1,4 @@ +-cmake_minimum_required(VERSION 3.4) ++cmake_minimum_required(VERSION 3.6) + project("Cap'n Proto" CXX) + set(VERSION 0.9.1) + +@@ -64,6 +64,50 @@ elseif (WITH_OPENSSL) + find_package(OpenSSL REQUIRED COMPONENTS Crypto SSL) + endif() + ++set(WITH_FIBERS "AUTO" CACHE STRING ++ "Whether or not to build libkj-async with fibers") ++# define list of values GUI will offer for the variable ++set_property(CACHE WITH_FIBERS PROPERTY STRINGS AUTO ON OFF) ++ ++# CapnProtoConfig.cmake.in needs this variable. ++set(_WITH_LIBUCONTEXT OFF) ++ ++if (WITH_FIBERS OR WITH_FIBERS STREQUAL "AUTO") ++ set(_capnp_fibers_found OFF) ++ if (WIN32 OR CYGWIN) ++ set(_capnp_fibers_found ON) ++ else() ++ # Fibers need makecontext, setcontext, getcontext, swapcontext that may be in libc, ++ # or in libucontext (e.g. for musl). ++ # We assume that makecontext implies that the others are present. ++ include(CheckLibraryExists) ++ check_library_exists(c makecontext "" HAVE_UCONTEXT_LIBC) ++ if (HAVE_UCONTEXT_LIBC) ++ set(_capnp_fibers_found ON) ++ else() ++ # Try with libucontext ++ find_package(PkgConfig) ++ if (PKG_CONFIG_FOUND) ++ pkg_check_modules(libucontext IMPORTED_TARGET libucontext) ++ if (libucontext_FOUND) ++ set(_WITH_LIBUCONTEXT ON) ++ set(_capnp_fibers_found ON) ++ endif() ++ else() ++ set(_capnp_fibers_found OFF) ++ endif() ++ endif() ++ endif() ++ ++ if (_capnp_fibers_found) ++ set(WITH_FIBERS ON) ++ elseif(WITH_FIBERS STREQUAL "AUTO") ++ set(WITH_FIBERS OFF) ++ else() ++ message(FATAL_ERROR "Missing 'makecontext', 'getcontext', 'setcontext' or 'swapcontext' symbol in libc and no libucontext found: KJ won't be able to build with fibers. Disable fibers (-DWITH_FIBERS=OFF).") ++ endif() ++endif() ++ + if(MSVC) + # TODO(cleanup): Enable higher warning level in MSVC, but make sure to test + # build with that warning level and clean out false positives. +diff --git a/c++/cmake/CapnProtoConfig.cmake.in b/c++/cmake/CapnProtoConfig.cmake.in +index 667f502f..0580b11a 100644 +--- a/c++/cmake/CapnProtoConfig.cmake.in ++++ b/c++/cmake/CapnProtoConfig.cmake.in +@@ -62,6 +62,38 @@ if (@WITH_OPENSSL@) # WITH_OPENSSL + endif() + endif() + ++if (@_WITH_LIBUCONTEXT@) # _WITH_LIBUCONTEXT ++ set(forwarded_config_flags) ++ if(CapnProto_FIND_QUIETLY) ++ list(APPEND forwarded_config_flags QUIET) ++ endif() ++ if(CapnProto_FIND_REQUIRED) ++ list(APPEND forwarded_config_flags REQUIRED) ++ endif() ++ # If the consuming project called find_package(CapnProto) with the QUIET or REQUIRED flags, forward ++ # them to calls to find_package(PkgConfig) and pkg_check_modules(). Note that find_dependency() ++ # would do this for us in the former case, but there is no such forwarding wrapper for ++ # pkg_check_modules(). ++ ++ find_package(PkgConfig ${forwarded_config_flags}) ++ if(NOT ${PkgConfig_FOUND}) ++ # If we're here, the REQUIRED flag must not have been passed, else we would have had a fatal ++ # error. Nevertheless, a diagnostic for this case is probably nice. ++ if(NOT CapnProto_FIND_QUIETLY) ++ message(WARNING "pkg-config cannot be found") ++ endif() ++ set(CapnProto_FOUND OFF) ++ return() ++ endif() ++ ++ if (CMAKE_VERSION VERSION_LESS 3.6) ++ # CMake >= 3.6 required due to the use of IMPORTED_TARGET ++ message(SEND_ERROR "libucontext support requires CMake >= 3.6.") ++ endif() ++ ++ pkg_check_modules(libucontext IMPORTED_TARGET ${forwarded_config_flags} libucontext) ++endif() ++ + include("${CMAKE_CURRENT_LIST_DIR}/CapnProtoTargets.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/CapnProtoMacros.cmake") + +diff --git a/c++/configure.ac b/c++/configure.ac +index 72fe8456..b627bec8 100644 +--- a/c++/configure.ac ++++ b/c++/configure.ac +@@ -32,6 +32,11 @@ AC_ARG_WITH([openssl], + [build libkj-tls by linking against openssl @<:@default=check@:>@])], + [],[with_openssl=check]) + ++AC_ARG_WITH([fibers], ++ [AS_HELP_STRING([--with-fibers], ++ [build libkj-async with fibers @<:@default=check@:>@])], ++ [],[with_fibers=check]) ++ + AC_ARG_ENABLE([reflection], [ + AS_HELP_STRING([--disable-reflection], [ + compile Cap'n Proto in "lite mode", in which all reflection APIs (schema.h, dynamic.h, etc.) +@@ -195,8 +200,46 @@ AS_IF([test "$with_openssl" != no], [ + ]) + AM_CONDITIONAL([BUILD_KJ_TLS], [test "$with_openssl" != no]) + +-# CapnProtoConfig.cmake.in needs this variable. +-AC_SUBST(WITH_OPENSSL, $with_openssl) ++# Fibers need the symbols getcontext, setcontext, swapcontext and makecontext. ++# We assume that makecontext implies the rest. ++AS_IF([test "$with_fibers" != no], [ ++ libc_supports_fibers=yes ++ AC_SEARCH_LIBS([makecontext], [], [], [ ++ libc_supports_fibers=no ++ ]) ++ ++ AS_IF([test "$libc_supports_fibers" = yes], [ ++ with_fibers=yes ++ ], [ ++ # If getcontext does not exist in libc, try with libucontext ++ ucontext_supports_fibers=yes ++ AC_CHECK_LIB(ucontext, [makecontext], [], [ ++ ucontext_supports_fibers=no ++ ]) ++ AS_IF([test "$ucontext_supports_fibers" = yes], [ ++ ASYNC_LIBS="$ASYNC_LIBS -lucontext" ++ with_fibers=yes ++ ], [ ++ AS_IF([test "$with_fibers" = yes], [ ++ AC_MSG_ERROR([Missing symbols required for fibers (makecontext, setcontext, ...). Disable fibers (--without-fibers) or install libucontext]) ++ ], [ ++ AC_MSG_WARN([could not find required symbols (makecontext, setcontext, ...) -- won't build with fibers]) ++ with_fibers=no ++ ]) ++ ]) ++ ]) ++]) ++AS_IF([test "$with_fibers" = yes], [ ++ CXXFLAGS="$CXXFLAGS -DKJ_USE_FIBERS" ++], [ ++ CXXFLAGS="$CXXFLAGS -DKJ_USE_FIBERS=0" ++]) ++ ++# CapnProtoConfig.cmake.in needs these variables, ++# we force them to NO because we don't need the CMake dependency for them, ++# the dependencies are provided by the .pc files. ++AC_SUBST(WITH_OPENSSL, NO) ++AC_SUBST(_WITH_LIBUCONTEXT, NO) + + AM_CONDITIONAL([HAS_FUZZING_ENGINE], [test "x$LIB_FUZZING_ENGINE" != "x"]) + +diff --git a/c++/src/kj/CMakeLists.txt b/c++/src/kj/CMakeLists.txt +index 813fac4d..f7b4dddf 100644 +--- a/c++/src/kj/CMakeLists.txt ++++ b/c++/src/kj/CMakeLists.txt +@@ -136,6 +136,15 @@ if(NOT CAPNP_LITE) + add_library(kj-async ${kj-async_sources}) + add_library(CapnProto::kj-async ALIAS kj-async) + target_link_libraries(kj-async PUBLIC kj) ++ if(WITH_FIBERS) ++ target_compile_definitions(kj-async PUBLIC KJ_USE_FIBERS) ++ if(_WITH_LIBUCONTEXT) ++ target_link_libraries(kj-async PUBLIC PkgConfig::libucontext) ++ endif() ++ else() ++ target_compile_definitions(kj-async PUBLIC KJ_USE_FIBERS=0) ++ endif() ++ + if(UNIX) + # external clients of this library need to link to pthreads + target_compile_options(kj-async INTERFACE "-pthread") +@@ -181,7 +190,7 @@ if(NOT CAPNP_LITE) + add_library(kj-tls ${kj-tls_sources}) + add_library(CapnProto::kj-tls ALIAS kj-tls) + target_link_libraries(kj-tls PUBLIC kj-async) +- if (WITH_OPENSSL) ++ if(WITH_OPENSSL) + target_compile_definitions(kj-tls PRIVATE KJ_HAS_OPENSSL) + target_link_libraries(kj-tls PRIVATE OpenSSL::SSL OpenSSL::Crypto) + endif() +-- +2.35.1 +