diff --git a/.github/workflows/early-access.yaml b/.github/workflows/early-access.yaml index a04eb661a..11f1f920f 100644 --- a/.github/workflows/early-access.yaml +++ b/.github/workflows/early-access.yaml @@ -31,7 +31,7 @@ jobs: default-build: name: 'Default build (without Graal)' if: startsWith(github.event.head_commit.message, '[release] Release ') != true - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: 'Checkout' uses: actions/checkout@v3 @@ -52,7 +52,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-20.04, macOS-10.15, windows-2019 ] + os: [ ubuntu-22.04, macOS-10.15, windows-2019 ] runs-on: ${{ matrix.os }} steps: @@ -79,22 +79,38 @@ jobs: run: ./mvnw clean -Dmrm=false -B -ntp -e - name: 'Patch Graal libs for only requiring glibc 2.12' + if: ${{ env.OS == 'linux' }} shell: bash run: | - if [[ $OS == linux ]] && [[ $GRAALVM_HOME ]] && [[ -d "$GRAALVM_HOME/lib/static/linux-amd64/glibc" ]]; then - mkdir -p client/target/graalvm-libs-for-glibc-2.12 - echo "memcpy memcpy@GLIBC_2.2.5" >client/target/glibc.redef - echo "posix_spawn posix_spawn@GLIBC_2.2.5" >>client/target/glibc.redef - find "$GRAALVM_HOME/lib/static/linux-amd64/glibc" -name '*.a' | while IFS= read -r input; do - output="client/target/graalvm-libs-for-glibc-2.12/$(basename -- "$input")" - objcopy --redefine-syms=client/target/glibc.redef -- "$input" "$output" 2>/dev/null - done - find /usr/lib -name libz.a | xargs -r -I {} objcopy --redefine-syms=client/target/glibc.redef {} client/target/graalvm-libs-for-glibc-2.12/libz.a - fi + mkdir -p client/target/graalvm-libs-for-glibc-2.12 + + : patch common libraries + ( find "$GRAALVM_HOME/lib/static/linux-amd64/glibc" -name '*.a' + ls -1 /lib/x86_64-linux-gnu/libz.a + ls -1 "$GRAALVM_HOME/lib/svm/clibraries/linux-amd64/libjvm.a" + ls -1 "$GRAALVM_HOME/lib/svm/clibraries/linux-amd64/liblibchelper.a" + ) | while IFS= read -r input; do + output="client/target/graalvm-libs-for-glibc-2.12/$(basename -- "$input")" + objcopy --redefine-syms=client/src/main/resources/glibc/glibc.redef -- "$input" "$output" 2>/dev/null + done + + : patch gcc startfile + gcc -O3 -Wall -Wextra -Werror -Wconversion -Wsign-conversion -Wcast-qual -pedantic -c -o client/target/dynamic-libc-start.o client/src/main/resources/glibc/dynamic-libc-start.c + ld -r /lib/x86_64-linux-gnu/Scrt1.o client/target/dynamic-libc-start.o -o client/target/graalvm-libs-for-glibc-2.12/Scrt1.o + objcopy --redefine-syms=client/src/main/resources/glibc/glibc.redef client/target/graalvm-libs-for-glibc-2.12/Scrt1.o 2>/dev/null - name: 'Build native distribution' run: ./mvnw verify -Pnative -Dmrm=false -B -ntp -e + - name: 'Verify native binary for only requiring glibc 2.12' + if: ${{ env.OS == 'linux' }} + shell: bash + run: | + (( 4 == "$(ldd client/target/mvnd | awk '{print $1}' | sort -u | grep -c 'lib\(c\|dl\|rt\|pthread\)\.so\.[0-9]')" )) || ( ldd client/target/mvnd && false ) + err=0 + objdump -T client/target/mvnd | grep GLIBC_ | grep -v 'GLIBC_\([01]\|2\.[0-9]\|2\.1[012]\)[^0-9]' || err=$? + (( err == 1 )) + - name: 'Upload daemon test logs' if: always() uses: actions/upload-artifact@v3 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index de6a1ede6..6891e8d60 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -35,7 +35,7 @@ jobs: strategy: fail-fast: true matrix: - os: [ ubuntu-20.04, macOS-10.15, windows-2019 ] + os: [ ubuntu-22.04, macOS-10.15, windows-2019 ] runs-on: ${{ matrix.os }} steps: @@ -62,22 +62,38 @@ jobs: run: ./mvnw clean -Dmrm=false -B -ntp -e - name: 'Patch Graal libs for only requiring glibc 2.12' + if: ${{ env.OS == 'linux' }} shell: bash run: | - if [[ $OS == linux ]] && [[ $GRAALVM_HOME ]] && [[ -d "$GRAALVM_HOME/lib/static/linux-amd64/glibc" ]]; then - mkdir -p client/target/graalvm-libs-for-glibc-2.12 - echo "memcpy memcpy@GLIBC_2.2.5" >client/target/glibc.redef - echo "posix_spawn posix_spawn@GLIBC_2.2.5" >>client/target/glibc.redef - find "$GRAALVM_HOME/lib/static/linux-amd64/glibc" -name '*.a' | while IFS= read -r input; do - output="client/target/graalvm-libs-for-glibc-2.12/$(basename -- "$input")" - objcopy --redefine-syms=client/target/glibc.redef -- "$input" "$output" 2>/dev/null - done - find /usr/lib -name libz.a | xargs -r -I {} objcopy --redefine-syms=client/target/glibc.redef {} client/target/graalvm-libs-for-glibc-2.12/libz.a - fi + mkdir -p client/target/graalvm-libs-for-glibc-2.12 + + : patch common libraries + ( find "$GRAALVM_HOME/lib/static/linux-amd64/glibc" -name '*.a' + ls -1 /lib/x86_64-linux-gnu/libz.a + ls -1 "$GRAALVM_HOME/lib/svm/clibraries/linux-amd64/libjvm.a" + ls -1 "$GRAALVM_HOME/lib/svm/clibraries/linux-amd64/liblibchelper.a" + ) | while IFS= read -r input; do + output="client/target/graalvm-libs-for-glibc-2.12/$(basename -- "$input")" + objcopy --redefine-syms=client/src/main/resources/glibc/glibc.redef -- "$input" "$output" 2>/dev/null + done + + : patch gcc startfile + gcc -O3 -Wall -Wextra -Werror -Wconversion -Wsign-conversion -Wcast-qual -pedantic -c -o client/target/dynamic-libc-start.o client/src/main/resources/glibc/dynamic-libc-start.c + ld -r /lib/x86_64-linux-gnu/Scrt1.o client/target/dynamic-libc-start.o -o client/target/graalvm-libs-for-glibc-2.12/Scrt1.o + objcopy --redefine-syms=client/src/main/resources/glibc/glibc.redef client/target/graalvm-libs-for-glibc-2.12/Scrt1.o 2>/dev/null - name: 'Build native distribution' run: ./mvnw verify -Pnative -Dmrm=false -B -ntp -e -DskipTests -s .mvn/release-settings.xml + - name: 'Verify native binary for only requiring glibc 2.12' + if: ${{ env.OS == 'linux' }} + shell: bash + run: | + (( 4 == "$(ldd client/target/mvnd | awk '{print $1}' | sort -u | grep -c 'lib\(c\|dl\|rt\|pthread\)\.so\.[0-9]')" )) || ( ldd client/target/mvnd && false ) + err=0 + objdump -T client/target/mvnd | grep GLIBC_ | grep -v 'GLIBC_\([01]\|2\.[0-9]\|2\.1[012]\)[^0-9]' || err=$? + (( err == 1 )) + - name: 'Upload artifact' uses: actions/upload-artifact@v3 with: @@ -90,7 +106,7 @@ jobs: source: name: 'Build source distributions' - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: 'Check out repository' uses: actions/checkout@v3 @@ -123,7 +139,7 @@ jobs: target/maven-mvnd-*.tar.gz release: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: [build, source] steps: diff --git a/client/pom.xml b/client/pom.xml index 69f2c32f8..88790678b 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -34,6 +34,7 @@ 11 + true @@ -199,7 +200,10 @@ - -H:CLibraryPath=${project.build.directory}/graalvm-libs-for-glibc-2.12 + -H:CCompilerPath=${basedir}/src/main/resources/glibc/gcc + -H:CCompilerOption=-B${project.build.directory}/graalvm-libs-for-glibc-2.12 + -H:CLibraryPath=${project.build.directory}/graalvm-libs-for-glibc-2.12 + false @@ -235,6 +239,32 @@ + + org.codehaus.mojo + exec-maven-plugin + + ${patchelf.skip} + patchelf + + --add-needed + libpthread.so.0 + --add-needed + librt.so.1 + --add-needed + libdl.so.2 + ${project.build.directory}/mvnd + + + + + add-needed-glibc-so + + exec + + package + + + diff --git a/client/src/main/resources/glibc/dynamic-libc-start.c b/client/src/main/resources/glibc/dynamic-libc-start.c new file mode 100644 index 000000000..56cd7e7ac --- /dev/null +++ b/client/src/main/resources/glibc/dynamic-libc-start.c @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* ref: + * https://elixir.bootlin.com/glibc/glibc-2.37.9000/source/csu/libc-start.c + * https://elixir.bootlin.com/glibc/glibc-2.33.9000/source/csu/elf-init.c#L68 + */ + +#define _GNU_SOURCE +#include +#include + +__asm__(".symver dlsym,dlsym@GLIBC_2.2.5"); +__asm__(".symver dlvsym,dlvsym@GLIBC_2.2.5"); + +/* These magic symbols are provided by the linker. */ +extern void (*__init_array_start[])(int, char **, char **) __attribute__ ((visibility ("hidden"))); +extern void (*__init_array_end[])(int, char **, char **) __attribute__ ((visibility ("hidden"))); +extern void _init(void); + +/* These functions are passed to __libc_start_main by the startup code. + These get statically linked into each program. */ + +static void +__libc_csu_init(const int argc, char **const argv, char **const envp) +{ + _init(); + const __auto_type size = __init_array_end - __init_array_start; + for (__auto_type i = 0; i < size; ++i) + (*__init_array_start[i])(argc, argv, envp); +} + +int +__dynamic_libc_start_main(int (*const main)(int, char **, char **), + const int argc, + char ** const argv, + __typeof(&__libc_csu_init) init, + void (*const fini)(void), + void (*const rtld_fini)(void), + void (*const stack_end)) +{ + _Static_assert(sizeof(uintptr_t) >= sizeof(void*), "uintptr_t should contain a object pointer"); + _Static_assert(sizeof(uintptr_t) <= sizeof(&__dynamic_libc_start_main), "function pointer should contain an uintptr_t"); + + const __auto_type __libc_start_main = (__typeof(&__dynamic_libc_start_main))(uintptr_t)dlsym(RTLD_DEFAULT, "__libc_start_main"); + if (!dlvsym(RTLD_DEFAULT, "__libc_start_main", "GLIBC_2.34")) { + init = &__libc_csu_init; // old runtime glibc, ver < 2.34 + } + + return __libc_start_main(main, argc, argv, init, fini, rtld_fini, stack_end); +} diff --git a/client/src/main/resources/glibc/gcc b/client/src/main/resources/glibc/gcc new file mode 100755 index 000000000..6b147c669 --- /dev/null +++ b/client/src/main/resources/glibc/gcc @@ -0,0 +1,27 @@ +#!/bin/sh + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set -euf + +base=$(dirname -- "$0") + +# fix glibc api version on the fly +find . -name '*.o' -print0 | xargs -0rn 1 objcopy --redefine-syms="$base/glibc.redef" + +exec gcc "$@" diff --git a/client/src/main/resources/glibc/glibc.redef b/client/src/main/resources/glibc/glibc.redef new file mode 100644 index 000000000..103421598 --- /dev/null +++ b/client/src/main/resources/glibc/glibc.redef @@ -0,0 +1,35 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +__libc_start_main __dynamic_libc_start_main +clock_gettime clock_gettime@GLIBC_2.2.5 +dlopen dlopen@GLIBC_2.2.5 +dlsym dlsym@GLIBC_2.2.5 +memcpy memcpy@GLIBC_2.2.5 +posix_spawn posix_spawn@GLIBC_2.2.5 +pthread_attr_getguardsize pthread_attr_getguardsize@GLIBC_2.2.5 +pthread_attr_getstack pthread_attr_getstack@GLIBC_2.2.5 +pthread_attr_setstacksize pthread_attr_setstacksize@GLIBC_2.2.5 +pthread_condattr_setclock pthread_condattr_setclock@GLIBC_2.3.3 +pthread_create pthread_create@GLIBC_2.2.5 +pthread_getattr_np pthread_getattr_np@GLIBC_2.2.5 +pthread_join pthread_join@GLIBC_2.2.5 +pthread_kill pthread_kill@GLIBC_2.2.5 +pthread_setname_np pthread_setname_np@GLIBC_2.12 +sem_destroy sem_destroy@GLIBC_2.2.5 +sem_init sem_init@GLIBC_2.2.5 +sem_post sem_post@GLIBC_2.2.5 +sem_wait sem_wait@GLIBC_2.2.5 diff --git a/native/pom.xml b/native/pom.xml index ec281bee1..6626e49f3 100644 --- a/native/pom.xml +++ b/native/pom.xml @@ -71,7 +71,6 @@ org.codehaus.mojo exec-maven-plugin - 3.0.0 info.picocli diff --git a/pom.xml b/pom.xml index 26af1edf2..4c80b9aa5 100644 --- a/pom.xml +++ b/pom.xml @@ -485,6 +485,11 @@ maven-wrapper-plugin 3.1.1 + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 +