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