Skip to content

Commit

Permalink
Build GTK3 support for linux x86-64 to maximize compatibility
Browse files Browse the repository at this point in the history
Recently all SWT builds for Linux x86-64 have been done on a new
Debian image. This leads to requiring such a new distro to be
able to run SWT successfully.

This change builds GTK3 and common code on an older debian container
to increase the range of versions we support. Only GTK4's key library,
libswt-pi4-gtk*.so is shipped from a build on the new debian container.

We continue to build all of the natives on latest debian so we benefit
from compiler warnings/errors and other such tooling.

As part of the build all .so files are checked to ensure their
dependencies are as expected. In particular glibc version is checked
for all symbols and all libraries are checked.

The version of glibc 2.14 was chosen as that is what the effective
requirement has been for a while for SWT (at least since Eclipse 4.26/2022-12)

Fixes #1791
  • Loading branch information
jonahgraham committed Feb 5, 2025
1 parent 54dad6c commit ac830ac
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 14 deletions.
45 changes: 31 additions & 14 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@

def runOnNativeBuildAgent(String platform, Closure body) {
def final nativeBuildStageName = 'Build SWT-native binaries'
if (platform == 'gtk.linux.x86_64') {
def dockerImage = null
switch (platform) {
case 'gtk.linux.x86_64':
dockerImage = 'eclipse/platformreleng-debian-swtgtk3nativebuild:10'
break
case 'gtk4.linux.x86_64':
dockerImage = 'eclipse/platformreleng-debian-swtnativebuild:12'
break
}
if (dockerImage != null) {
podTemplate(inheritFrom: 'basic' /* inherit general configuration */, containers: [
containerTemplate(name: 'swtbuild', image: 'eclipse/platformreleng-debian-swtnativebuild:12',
containerTemplate(name: 'swtbuild', image: dockerImage,
resourceRequestCpu:'1000m', resourceRequestMemory:'512Mi',
resourceLimitCpu:'2000m', resourceLimitMemory:'4096Mi',
alwaysPullImage: true, command: 'cat', ttyEnabled: true)
Expand Down Expand Up @@ -199,6 +208,7 @@ pipeline {
'gtk.linux.ppc64le',\
'gtk.linux.riscv64',\
'gtk.linux.x86_64',\
'gtk4.linux.x86_64',\
'win32.win32.aarch64',\
'win32.win32.x86_64'
}
Expand All @@ -220,22 +230,29 @@ pipeline {
runOnNativeBuildAgent("${PLATFORM}") {
cleanWs() // Workspace is not cleaned up by default, so we do it explicitly
echo "OS: ${os}, ARCH: ${arch}"
unstash "swt.binaries.sources.${ws}"
unstash "swt.binaries.sources.${ws == 'gtk4' ? 'gtk' : ws }"
dir('jdk.resources') {
unstash "jdk.resources.${os}.${arch}"
}
withEnv(['MODEL=' + arch, "OUTPUT_DIR=${WORKSPACE}/libs", "SWT_JAVA_HOME=${WORKSPACE}/jdk.resources"]) {
if (isUnix()){
sh '''
sh '''#!/bin/bash -x
mkdir libs
if [ "${PLATFORM}" = "gtk.linux.aarch64" ]; then
sh build.sh -gtk3 install
elif [ "${PLATFORM}" = "gtk.linux.ppc64le" ]; then
sh build.sh -gtk3 install
elif [ "${PLATFORM}" = "gtk.linux.riscv64" ]; then
sh build.sh -gtk3 install
else
if [[ ${PLATFORM} == gtk.linux.* ]]; then
sh build.sh -gtk3 checklibs install
elif [[ ${PLATFORM} == gtk4.linux.* ]]; then
# We build both 3 + 4, but we only keep libswt-pi4-gtk
# We build both to help catch build errors as this
# build runs against more modern gcc/libs and helps
# with verification
sh build.sh -gtk3 checklibs
sh build.sh clean
sh build.sh -gtk4 checklibs install-pi-only
elif [[ ${PLATFORM} == cocoa.macosx.* ]]; then
sh build.sh install
else
echo "Unexpected build platform ${PLATFORM}"
exit 1
fi
ls -1R libs
'''
Expand All @@ -258,11 +275,11 @@ pipeline {
steps {
dir("libs/${PLATFORM}") {
unstash "swt.binaries.${PLATFORM}"
sh '''
sh '''#!/bin/bash -x
if [[ ${PLATFORM} == cocoa.macosx.* ]]; then
binariesExtension='jnilib'
signerUrl='https://cbi.eclipse.org/macos/codesign/sign'
elif [[ ${PLATFORM} == gtk.linux.* ]]; then
elif [[ ${PLATFORM} == gtk.linux.* || ${PLATFORM} == gtk4.linux.* ]]; then
binariesExtension='so'
elif [[ ${PLATFORM} == win32.win32.* ]]; then
binariesExtension='dll'
Expand All @@ -278,7 +295,7 @@ pipeline {
done
fi
fi
cp *.$binariesExtension "${WORKSPACE}/eclipse.platform.swt/binaries/org.eclipse.swt.${PLATFORM}/"
cp *.$binariesExtension "${WORKSPACE}/eclipse.platform.swt/binaries/org.eclipse.swt.${PLATFORM/gtk4/gtk}/"
'''
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ if [ "${MODEL}" = "" ]; then
else
MODEL=`uname -m`
fi
export MODEL
fi
case $MODEL in
"x86_64")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash
###############################################################################
# Copyright (c) 2020, 2025 Kichwa Coders Canada Inc and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
# which accompanies this distribution, and is available at
# https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
###############################################################################

set -eu
set -o pipefail

SCRIPT=$( basename "${BASH_SOURCE[0]}" )

###
# Check that executable/so ${FILE}
# use glibc symbols no greater than ${ALLOWED_GLIBC_VERSION} and depend on
# no libs other than ${ALLOWED_LIBS}
FILE=$1; shift
ALLOWED_GLIBC_VERSION=$1; shift
ALLOWED_LIBS="$@"; shift

# grep that doesn't exit 1 on 0 matches
mygrep() { grep "$@" || test $? = 1; }

# Check for permitted libraries using `readelf -d` looking for shared
# libraries that are listed as needed. e.g. lines like:
# 0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
readelf -d ${FILE} | mygrep -E '\(NEEDED\)' | while read needed; do
needed=${needed//*Shared library: [/}
needed=${needed//]*/}
if [[ ! " ${ALLOWED_LIBS} " =~ " ${needed} " ]]; then
echo "ERROR: $FILE has illegal dependency of ${needed}"
exit 1
fi
done

# The way the version check is done is that all symbol version info is extracted
# from relocations match @GLIBC_*, the versions are sorted with the max
# allowed version added to the list too. And then we check the last entry in
# the list to make sure it is == to max allowed version.
objdump -R ${FILE} | mygrep @GLIBC_ | while read version; do
echo ${version//*@GLIBC_}
done > /tmp/version_check
echo ${ALLOWED_GLIBC_VERSION} >> /tmp/version_check
max_version_in_use=$(cat /tmp/version_check | sort --unique --version-sort | tail -n1)
if [ "$max_version_in_use" != "$ALLOWED_GLIBC_VERSION" ]; then
echo "ERROR: $FILE has dependency on glibc greater than allowed version of ${ALLOWED_GLIBC_VERSION} for at least the following symbols"
# This only lists greatest version number symbols
objdump -R ${FILE} | grep @GLIBC_${max_version_in_use}
exit 1
fi
41 changes: 41 additions & 0 deletions bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/make_linux.mak
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,44 @@ glx_structs.o: glx_structs.c
glx_stats.o: glx_stats.c glx_stats.h
$(CC) $(CFLAGS) $(GLXCFLAGS) -c glx_stats.c

#
# Permitted dependencies and glibc versions
#
# This does not include libraries that are dynamically loaded with dlopen,
# The purpose of this list, and the version limit on glibc is to ensure
# eclipse swt will be able to start on the widest range on Linuxes.
# All other error handling regarding missing/problematic libraries
# can be done at runtime.
ifeq ($(MODEL),x86_64)
PERMITTED_LIBRARIES=libc.so.6 libpthread.so.0 libdl.so.2 libm.so.6
ifeq ($(GTK_VERSION), 4.0)
PERMITTED_GLIBC_VERSION=2.34
PERMITTED_GTK_LIBRARIES = libgtk-4.so.1
else
PERMITTED_GLIBC_VERSION=2.14
PERMITTED_GTK_LIBRARIES = libgtk-3.so.0 libgdk-3.so.0 libcairo.so.2 libgthread-2.0.so.0
endif
checklibs: all
$(info Verifying $(ALL_SWT_LIBS) have permitted dependencies)
./check_dependencies.sh $(SWT_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES)
./check_dependencies.sh $(AWT_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES) libjawt.so
./check_dependencies.sh $(SWTPI_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES) $(PERMITTED_GTK_LIBRARIES)
./check_dependencies.sh $(CAIRO_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES) libcairo.so.2
./check_dependencies.sh $(ATK_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES) libatk-1.0.so.0
./check_dependencies.sh $(GLX_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES) libGL.so.1 libGLU.so.1
./check_dependencies.sh $(WEBKIT_LIB) $(PERMITTED_GLIBC_VERSION) $(PERMITTED_LIBRARIES) libgio-2.0.so.0 libgobject-2.0.so.0 libglib-2.0.so.0
else
# We don't enforce max version and library sets on non-x86-64 because
# 1. We build on native hardware for those platforms so we don't have
# ability to use docker to adjust dependency versions as easily
# 2. The other platforms that are newer are generally faster moving
# and it is less likely to break users to have harder version
# requirements.
# As we get bigger user base on non-x86-64 we should start enforcing
# upper bounds for them too.
checklibs: all
endif

#
# Install
#
Expand All @@ -253,6 +291,9 @@ glx_stats.o: glx_stats.c glx_stats.h
install: all
cp $(ALL_SWT_LIBS) $(OUTPUT_DIR)

install-pi-only: all
cp $(SWTPI_LIB) $(OUTPUT_DIR)

#
# Clean
#
Expand Down

0 comments on commit ac830ac

Please sign in to comment.