From 730551c925246b4fd64ad4c52cb82466aba757d6 Mon Sep 17 00:00:00 2001 From: Frederik Seiffert Date: Wed, 18 Jan 2023 16:04:36 +0100 Subject: [PATCH 1/3] Consolidate CMake options --- phases/11-libobjc2.sh | 1 - phases/12-libdispatch.sh | 1 - scripts/toolchain.sh | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/phases/11-libobjc2.sh b/phases/11-libobjc2.sh index a63a88d..ff523cc 100755 --- a/phases/11-libobjc2.sh +++ b/phases/11-libobjc2.sh @@ -20,7 +20,6 @@ cd build-${ABI_NAME} ${CMAKE} .. \ ${CMAKE_OPTIONS} \ - -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \ -DGNUSTEP_CONFIG= `# prevent cmake from finding gnustep-config in install root` \ -DOLDABI_COMPAT=false `# we're using gnustep-2.0 ABI, which may not be mixed with earlier versions'` \ diff --git a/phases/12-libdispatch.sh b/phases/12-libdispatch.sh index 39959a9..25ee26b 100755 --- a/phases/12-libdispatch.sh +++ b/phases/12-libdispatch.sh @@ -20,7 +20,6 @@ cd build-${ABI_NAME} ${CMAKE} .. \ ${CMAKE_OPTIONS} \ - -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \ -DBUILD_SHARED_LIBS=YES \ -DINSTALL_PRIVATE_HEADERS=YES \ `# use blocks runtime from libobjc2 with libdispatch-own-blocksruntime.patch` \ diff --git a/scripts/toolchain.sh b/scripts/toolchain.sh index 2f0b15d..30905ec 100755 --- a/scripts/toolchain.sh +++ b/scripts/toolchain.sh @@ -58,6 +58,7 @@ export LIBS="-lc++_shared" # common options for CMake-based projects # CMAKE_FIND_USE_CMAKE_PATH=false fixes finding incorrect libraries in $TOOLCHAIN/lib[64] instead of $TOOLCHAIN/sysroot/usr/lib/$ANDROID_TARGET, e.g. for libc++abi.a for libobjc2. CMAKE_OPTIONS=" \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} \ -DCMAKE_FIND_USE_CMAKE_PATH=false \ From 3b983d2f0e12c7b698a0a1ab4c724aaa8766ced7 Mon Sep 17 00:00:00 2001 From: Frederik Seiffert Date: Wed, 18 Jan 2023 16:13:04 +0100 Subject: [PATCH 2/3] Add OpenSSL and libcurl libraries Enables support for NSURLSession in GNUstep Base. --- README.md | 4 +- patches/gnustep-base-curl-cacert.patch | 48 ++++++++++++++++++++++++ phases/15-icu.sh | 2 +- phases/18-openssl.sh | 51 ++++++++++++++++++++++++++ phases/19-libcurl.sh | 33 +++++++++++++++++ scripts/common.sh | 20 ++++++++-- 6 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 patches/gnustep-base-curl-cacert.patch create mode 100755 phases/18-openssl.sh create mode 100755 phases/19-libcurl.sh diff --git a/README.md b/README.md index b592fbe..1e2f36f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The toolchain is built using the Android NDK (installed e.g. via [Android Studio Libraries --------- -The toolchain currently compiles the following libraries for Android: +The toolchain consists of the following libraries: * [GNUstep Base Library](https://github.com/gnustep/libs-base) (Foundation) * [GNUstep CoreBase Library](https://github.com/gnustep/libs-corebase) (CoreFoundation) @@ -21,6 +21,8 @@ The toolchain currently compiles the following libraries for Android: * [libiconv](https://www.gnu.org/software/libiconv/) * [libxml2](https://github.com/GNOME/libxml2) * [libxslt](https://github.com/GNOME/libxslt) +* [libcurl](https://github.com/curl/curl) +* [OpenSSL](https://github.com/KDAB/android_openssl) * [ICU](https://github.com/unicode-org/icu) diff --git a/patches/gnustep-base-curl-cacert.patch b/patches/gnustep-base-curl-cacert.patch new file mode 100644 index 0000000..502508e --- /dev/null +++ b/patches/gnustep-base-curl-cacert.patch @@ -0,0 +1,48 @@ +diff --git a/Source/GSEasyHandle.m b/Source/GSEasyHandle.m +index 576a41205..7eb15d512 100644 +--- a/Source/GSEasyHandle.m ++++ b/Source/GSEasyHandle.m +@@ -173,6 +173,24 @@ @implementation GSEasyHandle + struct curl_slist *_headerList; + } + ++#ifdef __ANDROID__ ++static NSData *CABundleData() { ++ static NSData *result = nil; ++ static dispatch_once_t predicate; ++ ++ dispatch_once(&predicate, ^{ ++ NSString *caBundlePath = [[NSBundle mainBundle] pathForResource:@"cacert" ofType:@"pem"]; ++ if (caBundlePath) { ++ result = [[NSData alloc] initWithContentsOfFile:caBundlePath]; ++ } else { ++ NSLog(@"Warning: missing CA bundle path (cacert.pem) in app bundle"); ++ } ++ }); ++ ++ return result; ++} ++#endif ++ + - (instancetype) initWithDelegate: (id)delegate + { + if (nil != (self = [super init])) +@@ -184,6 +202,18 @@ - (instancetype) initWithDelegate: (id)delegate + _errorBuffer = memset(eb, 0, sizeof(char) * (CURL_ERROR_SIZE + 1)); + + [self setupCallbacks]; ++ ++#ifdef __ANDROID__ ++ // set CA certificate store (must be stored in app bundle) ++ NSData *caBundleData = CABundleData(); ++ if (caBundleData) { ++ struct curl_blob blob; ++ blob.data = (void *)caBundleData.bytes; ++ blob.len = caBundleData.length; ++ blob.flags = CURL_BLOB_COPY; ++ handleEasyCode(curl_easy_setopt(_rawHandle, CURLOPT_CAINFO_BLOB, &blob)); ++ } ++#endif + } + + return self; diff --git a/phases/15-icu.sh b/phases/15-icu.sh index 4532956..44bb05a 100755 --- a/phases/15-icu.sh +++ b/phases/15-icu.sh @@ -6,7 +6,7 @@ set -e # make any subsequent failing command exit the script PROJECT=icu GITHUB_REPO=unicode-org/icu -TAG=$(get_latest_github_release_tag $GITHUB_REPO) +TAG=$(get_latest_github_release_tag $GITHUB_REPO release-) # don't clean project for subsequent builds so that the build for the current # machine is preserved, and because each ABI builds into separate directory diff --git a/phases/18-openssl.sh b/phases/18-openssl.sh new file mode 100755 index 0000000..b97fc12 --- /dev/null +++ b/phases/18-openssl.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -e # make any subsequent failing command exit the script + +. `dirname $0`/../scripts/common.sh + +PROJECT=openssl +GITHUB_REPO=KDAB/android_openssl + +# load environment and prepare project +if ! prepare_project $PROJECT $GITHUB_REPO; then + exit 0 +fi + +case $ABI_NAME in + armeabi-v7a) + ABI_FOLDER=arm + ;; + arm64-v8a) + ABI_FOLDER=arm64 + ;; + *) + ABI_FOLDER=$ABI_NAME +esac + +echo -e "\n### Installing headers" + +cp -Rf no-asm/static/include/ ${INSTALL_PREFIX}/include + +echo -e "\n### Installing libraries" + +cp -f latest/$ABI_FOLDER/*.so ${INSTALL_PREFIX}/lib + +# create version-less symlinks for libcrypto/libssl.so to versioned libraries +libraries=`ls latest/$ABI_FOLDER/*.so` +cd ${INSTALL_PREFIX}/lib +for lib in $libraries; do + libname=`basename $lib` + if [[ $libname =~ ([a-z]+)[0-9\_]+.so ]]; then + ln -sf $libname ${BASH_REMATCH[1]}.so + fi +done + +echo -e "\n### Downloading CA bundle (must be installed into Android app bundle)" +mkdir -p "$CACHE_ROOT" +cd "$CACHE_ROOT" +ETAG="cacert-etag.txt" +[ -f $ETAG ] && ETAG_COMPARE="--etag-compare $ETAG" +curl --show-error --fail-with-body --remote-name --etag-save $ETAG $ETAG_COMPARE https://curl.se/ca/cacert.pem +mkdir -p ${INSTALL_PREFIX}/etc/ssl/ +cp -f cacert.pem ${INSTALL_PREFIX}/etc/ssl/ diff --git a/phases/19-libcurl.sh b/phases/19-libcurl.sh new file mode 100755 index 0000000..20524b0 --- /dev/null +++ b/phases/19-libcurl.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e # make any subsequent failing command exit the script + +. `dirname $0`/../scripts/common.sh + +PROJECT=libcurl +GITHUB_REPO=curl/curl +TAG=$(get_latest_github_release_tag $GITHUB_REPO curl-) + +# load environment and prepare project +if ! prepare_project $PROJECT $GITHUB_REPO $TAG; then + exit 0 +fi + +. "$ROOT_DIR"/scripts/toolchain.sh + +echo -e "\n### Running cmake" +mkdir -p build-${ABI_NAME} +cd build-${ABI_NAME} + +${CMAKE} .. \ + ${CMAKE_OPTIONS} \ + -DBUILD_SHARED_LIBS=YES \ + -DBUILD_CURL_EXE=NO \ + -DCURL_CA_BUNDLE=NONE `# disable CA bundle path, needs to be read at runtime from app bundle` \ + -DCMAKE_FIND_ROOT_PATH=${INSTALL_PREFIX} `# make CMake look for OpenSSL in installation directory` \ + +echo -e "\n### Building" +make -j${MAKE_JOBS} + +echo -e "\n### Installing" +make install diff --git a/scripts/common.sh b/scripts/common.sh index 566b988..29ee05b 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -10,12 +10,24 @@ export ROOT_DIR="$PWD" get_latest_github_release_tag () { GITHUB_REPO=$1 + TAG_PREFIX=$2 + + # use GitHub token authentication on CI to prevent rate limit errors + if [ -n "$GITHUB_TOKEN" ]; then + GITHUB_AUTHORIZATION_HEADER="Authorization: Bearer $GITHUB_TOKEN" + fi + + # get the tags JSON from the GitHub API and parse it manually, + # or output it to stderr if the server returns an error + github_tags=`curl \ + --silent --show-error --fail-with-body \ + --header "$GITHUB_AUTHORIZATION_HEADER" \ + https://api.github.com/repos/$GITHUB_REPO/tags` - # get the tags JSON from the GitHub API and parse it manually - curl -s https://api.github.com/repos/$GITHUB_REPO/tags \ + echo "$github_tags" \ | grep '"name":' \ | sed -E 's/.*"([^"]+)".*/\1/' \ - | egrep '^(release\-|v)[0-9]+[\.-][0-9]+([\.-][0-9]+)?$' \ + | egrep "^${TAG_PREFIX:-[a-z_-]+}[0-9]+[\._-][0-9]+([\._-][0-9]+)?\$" \ | head -n 1 } @@ -73,7 +85,7 @@ prepare_project () { if [ "$NO_UPDATE" != true ]; then # check out tag/branch if any if [ -n $TAG ]; then - echo -e "\n### Checking out $TAG" + echo -e "\n### Checking out \"$TAG\"" git fetch --tags git checkout -q $TAG fi From 7fd92011a2605ba952a90937d89437546c70549e Mon Sep 17 00:00:00 2001 From: Frederik Seiffert Date: Fri, 20 Jan 2023 10:44:24 +0100 Subject: [PATCH 3/3] CI: provide GitHub token to build script Enables preventing rate limit errors. --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 153cac5..1b4afeb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,6 +51,8 @@ jobs: fi - name: Build toolchain + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | ./build.sh --ndk $ANDROID_NDK_LATEST_HOME --dist-root HOME/${{matrix.android-dir}}/GNUstep