Skip to content

Commit

Permalink
Test implementation of virtual packages
Browse files Browse the repository at this point in the history
Virtual packages are packages that are compiled and installed into the system, but are not assembled into a source package for package managers. One advantage of virtual packages is that they can use sources (including values from configured variables) from regular packages. This will allow us to easily create special virtual packages that will have to resolve cyclic dependencies in regular packages.

PS: not ready for review yet, please wait
  • Loading branch information
Maxython committed Oct 11, 2024
1 parent da4bfd3 commit 2d349ba
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 136 deletions.
105 changes: 66 additions & 39 deletions build-package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,50 @@ termux_check_package_in_building_packages_list() {
return $?
}

# Sets up variables for parsing the package during compilation
termux_get_pkg_builder_dir_and_pkg_builder_script() {
TERMUX_PKG_NAME="${1}"
if [[ ${TERMUX_PKG_NAME} == *"/"* ]]; then
# Path to directory which may be outside this repo:
if [ ! -d "${TERMUX_PKG_NAME}" ]; then termux_error_exit "'${TERMUX_PKG_NAME}' seems to be a path but is not a directory"; fi
export TERMUX_PKG_BUILDER_DIR=$(realpath "${TERMUX_PKG_NAME}")
TERMUX_PKG_NAME=$(basename "${TERMUX_PKG_NAME}")
else
# Package name:
for package_directory in $TERMUX_PACKAGES_DIRECTORIES; do
if [ -d "${TERMUX_SCRIPTDIR}/${package_directory}/${TERMUX_PKG_NAME}" ]; then
export TERMUX_PKG_BUILDER_DIR=${TERMUX_SCRIPTDIR}/$package_directory/$TERMUX_PKG_NAME
break
elif [ -n "${TERMUX_IS_DISABLED=""}" ] && [ -d "${TERMUX_SCRIPTDIR}/disabled-packages/${TERMUX_PKG_NAME}" ]; then
export TERMUX_PKG_BUILDER_DIR=$TERMUX_SCRIPTDIR/disabled-packages/$TERMUX_PKG_NAME
break
fi
done
if [ -z "${TERMUX_PKG_BUILDER_DIR}" ]; then
termux_error_exit "No package $TERMUX_PKG_NAME found in any of the enabled repositories. Are you trying to set up a custom repository?"
fi
fi
TERMUX_PKG_BUILDER_SCRIPT=$TERMUX_PKG_BUILDER_DIR/build.sh
if test ! -f "$TERMUX_PKG_BUILDER_SCRIPT"; then
termux_error_exit "No build.sh script at package dir $TERMUX_PKG_BUILDER_DIR!"
fi
}

# Removes included sources in a virtual package
# Should only be run on error or when the script exits.
termux_remove_include_virtual_files() {
[ "$TERMUX_VIRTUAL_PKG" = "false" ] || [ "$TERMUX_VIRTUAL_PKG_INCLUDE" = "false" ] && return
for file in $TERMUX_VIRTUAL_PKG_INCLUDE; do
rm -fr "${TERMUX_VIRTUAL_PKG_BUILDER_DIR}/${file}"
done
}

termux_restore_variables_by_virtual_pkg() {
TERMUX_PKG_NAME="$TERMUX_VIRTUAL_PKG_NAME"
export TERMUX_PKG_BUILDER_DIR="$TERMUX_VIRTUAL_PKG_BUILDER_DIR"
TERMUX_PKG_BUILDER_SCRIPT="$TERMUX_VIRTUAL_PKG_BUILDER_SCRIPT"
}

# Special hook to prevent use of "sudo" inside package build scripts.
# build-package.sh shouldn't perform any privileged operations.
sudo() {
Expand Down Expand Up @@ -586,31 +630,10 @@ for ((i=0; i<${#PACKAGE_LIST[@]}; i++)); do
fi

# Check the package to build:
TERMUX_PKG_NAME=$(basename "${PACKAGE_LIST[i]}")
export TERMUX_PKG_BUILDER_DIR=
if [[ ${PACKAGE_LIST[i]} == *"/"* ]]; then
# Path to directory which may be outside this repo:
if [ ! -d "${PACKAGE_LIST[i]}" ]; then termux_error_exit "'${PACKAGE_LIST[i]}' seems to be a path but is not a directory"; fi
export TERMUX_PKG_BUILDER_DIR=$(realpath "${PACKAGE_LIST[i]}")
else
# Package name:
for package_directory in $TERMUX_PACKAGES_DIRECTORIES; do
if [ -d "${TERMUX_SCRIPTDIR}/${package_directory}/${TERMUX_PKG_NAME}" ]; then
export TERMUX_PKG_BUILDER_DIR=${TERMUX_SCRIPTDIR}/$package_directory/$TERMUX_PKG_NAME
break
elif [ -n "${TERMUX_IS_DISABLED=""}" ] && [ -d "${TERMUX_SCRIPTDIR}/disabled-packages/${TERMUX_PKG_NAME}" ]; then
export TERMUX_PKG_BUILDER_DIR=$TERMUX_SCRIPTDIR/disabled-packages/$TERMUX_PKG_NAME
break
fi
done
if [ -z "${TERMUX_PKG_BUILDER_DIR}" ]; then
termux_error_exit "No package $TERMUX_PKG_NAME found in any of the enabled repositories. Are you trying to set up a custom repository?"
fi
fi
TERMUX_PKG_BUILDER_SCRIPT=$TERMUX_PKG_BUILDER_DIR/build.sh
if test ! -f "$TERMUX_PKG_BUILDER_SCRIPT"; then
termux_error_exit "No build.sh script at package dir $TERMUX_PKG_BUILDER_DIR!"
fi
termux_get_pkg_builder_dir_and_pkg_builder_script "${PACKAGE_LIST[i]}"

trap 'termux_remove_include_virtual_files' ERR EXIT

termux_step_setup_variables
termux_step_handle_buildarch
Expand All @@ -633,7 +656,9 @@ for ((i=0; i<${#PACKAGE_LIST[@]}; i++)); do
termux_step_override_config_scripts
fi

termux_step_create_timestamp_file
if [ "$TERMUX_VIRTUAL_PKG" == "false" ]; then
termux_step_create_timestamp_file
fi

if [ "$TERMUX_CONTINUE_BUILD" == "false" ]; then
cd "$TERMUX_PKG_CACHEDIR"
Expand Down Expand Up @@ -670,24 +695,26 @@ for ((i=0; i<${#PACKAGE_LIST[@]}; i++)); do
termux_step_post_make_install
termux_step_install_service_scripts
termux_step_install_license
cd "$TERMUX_PKG_MASSAGEDIR"
termux_step_extract_into_massagedir
termux_step_massage
cd "$TERMUX_PKG_MASSAGEDIR/$TERMUX_PREFIX_CLASSICAL"
termux_step_post_massage
cd "$TERMUX_PKG_MASSAGEDIR"
if [ "$TERMUX_PACKAGE_FORMAT" = "debian" ]; then
termux_step_create_debian_package
elif [ "$TERMUX_PACKAGE_FORMAT" = "pacman" ]; then
termux_step_create_pacman_package
else
termux_error_exit "Unknown packaging format '$TERMUX_PACKAGE_FORMAT'."
if [ "$TERMUX_VIRTUAL_PKG" == "false" ]; then
cd "$TERMUX_PKG_MASSAGEDIR"
termux_step_extract_into_massagedir
termux_step_massage
cd "$TERMUX_PKG_MASSAGEDIR/$TERMUX_PREFIX_CLASSICAL"
termux_step_post_massage
cd "$TERMUX_PKG_MASSAGEDIR"
if [ "$TERMUX_PACKAGE_FORMAT" = "debian" ]; then
termux_step_create_debian_package
elif [ "$TERMUX_PACKAGE_FORMAT" = "pacman" ]; then
termux_step_create_pacman_package
else
termux_error_exit "Unknown packaging format '$TERMUX_PACKAGE_FORMAT'."
fi
# Saving a list of compiled packages for further work with it
termux_add_package_to_built_packages_list "$TERMUX_PKG_NAME"
fi
# Saving a list of compiled packages for further work with it
if termux_check_package_in_building_packages_list "${TERMUX_PKG_BUILDER_DIR#${TERMUX_SCRIPTDIR}/}"; then
sed -i "\|^${TERMUX_PKG_BUILDER_DIR#${TERMUX_SCRIPTDIR}/}$|d" "$TERMUX_BUILD_PACKAGE_CALL_BUILDING_PACKAGES_LIST_FILE_PATH"
fi
termux_add_package_to_built_packages_list "$TERMUX_PKG_NAME"
termux_step_finish_build
) 5< "$TERMUX_BUILD_LOCK_FILE"
done
Expand Down
71 changes: 11 additions & 60 deletions packages/glib/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ TERMUX_PKG_DESCRIPTION="Library providing core building blocks for libraries and
TERMUX_PKG_LICENSE="LGPL-2.1"
TERMUX_PKG_MAINTAINER="@termux"
TERMUX_PKG_VERSION="2.80.5"
TERMUX_PKG_REVISION=2
TERMUX_PKG_REVISION=3
TERMUX_PKG_SRCURL=https://download.gnome.org/sources/glib/${TERMUX_PKG_VERSION%.*}/glib-${TERMUX_PKG_VERSION}.tar.xz
TERMUX_PKG_SHA256=9f23a9de803c695bbfde7e37d6626b18b9a83869689dd79019bf3ae66c3e6771
TERMUX_PKG_AUTO_UPDATE=true
TERMUX_PKG_DEPENDS="libandroid-support, libffi, libiconv, pcre2, resolv-conf, zlib"
TERMUX_PKG_BUILD_DEPENDS="gobject-introspection"
TERMUX_PKG_BREAKS="glib-dev"
TERMUX_PKG_REPLACES="glib-dev"
TERMUX_PKG_VERSIONED_GIR=false
Expand Down Expand Up @@ -67,68 +68,11 @@ termux_step_host_build() {
termux_step_pre_configure() {
# glib checks for __BIONIC__ instead of __ANDROID__:
CFLAGS+=" -D__BIONIC__=1"
_PREFIX="$TERMUX_PKG_TMPDIR/prefix"
local _WRAPPER_BIN="${TERMUX_PKG_BUILDDIR}/_wrapper/bin"
rm -rf "$_PREFIX" "$_WRAPPER_BIN"
mkdir -p "$_PREFIX" "$_WRAPPER_BIN"

sed '/^export PKG_CONFIG_LIBDIR=/s|$|:'${_PREFIX}'/lib/pkgconfig|' \
"${TERMUX_STANDALONE_TOOLCHAIN}/bin/pkg-config" \
> "${_WRAPPER_BIN}/pkg-config"
chmod +x "${_WRAPPER_BIN}/pkg-config"
export PKG_CONFIG="${_WRAPPER_BIN}/pkg-config"
export PATH="${_WRAPPER_BIN}:${PATH}"

# Magic happens here.
# I borrowed nested building method from https://github.com/termux/termux-packages/blob/1244c75380beefc7f7da9744d55aa88df1640acb/x11-packages/qbittorrent/build.sh#L21-L28
# and modified termux_step_configure_meson in runtime to make it use another prefix
# Also I used advice from here https://github.com/termux/termux-packages/issues/20447#issuecomment-2156066062

# Running a subshell to not mess with variables
(
# Building `glib` with `-Dintrospection=disabled` and installing it to temporary directory
TERMUX_PKG_BUILDDIR="$TERMUX_PKG_TMPDIR/glib-build"
mkdir -p "$TERMUX_PKG_BUILDDIR"
TERMUX_PKG_EXTRA_CONFIGURE_ARGS="${TERMUX_PKG_EXTRA_CONFIGURE_ARGS/"-Dintrospection=enabled"/"-Dintrospection=disabled"}"
termux_setup_gir

cd "$TERMUX_PKG_BUILDDIR"
TERMUX_PREFIX="$_PREFIX" termux_step_configure
cd "$TERMUX_PKG_BUILDDIR"
termux_step_make
cd "$TERMUX_PKG_BUILDDIR"
termux_step_make_install
)

# Running a subshell to not mess with variables
(
# Building `gobject-introspection` and installing it to temporary directory
TERMUX_PKG_BUILDER_DIR="$TERMUX_SCRIPTDIR/packages/gobject-introspection"
TERMUX_PKG_BUILDDIR="$TERMUX_PKG_TMPDIR/gobject-introspection-build"
TERMUX_PKG_SRCDIR="$TERMUX_PKG_TMPDIR/gobject-introspection-src"
mkdir -p "$TERMUX_PKG_BUILDDIR" "$TERMUX_PKG_SRCDIR"
# Sourcing another build script for nested build
. "$TERMUX_PKG_BUILDER_DIR/build.sh"
cd "$TERMUX_PKG_CACHEDIR"

termux_step_get_source
termux_step_get_dependencies_python
termux_step_patch_package

termux_step_pre_configure

cd "$TERMUX_PKG_BUILDDIR"
TERMUX_PREFIX="$_PREFIX" termux_step_configure
cd "$TERMUX_PKG_BUILDDIR"
termux_step_make
cd "$TERMUX_PKG_BUILDDIR"
termux_step_make_install
)

# Place the GIR files inside the root of the GIR directory (gir/.) of the package
termux_setup_gir

# The package will be built with using gobject-introspection we built before...
# Workaround: Remove cyclic dependency between gir and glib
sed -i "/Requires:/d" "${TERMUX_PREFIX}/lib/pkgconfig/gobject-introspection-1.0.pc"
}

termux_step_post_make_install() {
Expand All @@ -139,6 +83,13 @@ termux_step_post_make_install() {
"${TERMUX_PREFIX}/lib/pkgconfig/${pc}" \
> "${TERMUX_PREFIX}/opt/glib/cross/lib/x86_64-linux-gnu/pkgconfig/${pc}"
done

# Workaround: Restore deleted line in pre-configure step
echo "Requires: glib-2.0 gobject-2.0" >> "${TERMUX_PREFIX}/lib/pkgconfig/gobject-introspection-1.0.pc"
}

termux_step_post_massage() {
rm -v lib/pkgconfig/gobject-introspection-1.0.pc
}

termux_step_create_debscripts() {
Expand Down
17 changes: 10 additions & 7 deletions scripts/build/termux_step_finish_build.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
termux_step_finish_build() {
echo "termux - build of '$TERMUX_PKG_NAME' done"
echo "termux - build of $(test "${TERMUX_VIRTUAL_PKG}" = "true" && echo "virtual") '$TERMUX_PKG_NAME' done"
test -t 1 && printf "\033]0;%s - DONE\007" "$TERMUX_PKG_NAME"

mkdir -p "$TERMUX_BUILT_PACKAGES_DIRECTORY"
echo "$TERMUX_PKG_FULLVERSION" > "$TERMUX_BUILT_PACKAGES_DIRECTORY/$TERMUX_PKG_NAME"
if [ "$TERMUX_VIRTUAL_PKG" = "false" ]; then
mkdir -p "$TERMUX_BUILT_PACKAGES_DIRECTORY"
echo "$TERMUX_PKG_FULLVERSION" > "$TERMUX_BUILT_PACKAGES_DIRECTORY/$TERMUX_PKG_NAME"

for subpackage in "$TERMUX_PKG_BUILDER_DIR"/*.subpackage.sh; do
local subpkg_name="$(basename $subpackage | sed 's@\.subpackage\.sh@@g')"
echo "$TERMUX_PKG_FULLVERSION" > "$TERMUX_BUILT_PACKAGES_DIRECTORY/${subpkg_name}"
done
fi

for subpackage in "$TERMUX_PKG_BUILDER_DIR"/*.subpackage.sh; do
local subpkg_name="$(basename $subpackage | sed 's@\.subpackage\.sh@@g')"
echo "$TERMUX_PKG_FULLVERSION" > "$TERMUX_BUILT_PACKAGES_DIRECTORY/${subpkg_name}"
done
exit 0
}
7 changes: 7 additions & 0 deletions scripts/build/termux_step_setup_variables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ termux_step_setup_variables() {
TERMUX_PKG_SEPARATE_SUB_DEPENDS=false # when set to true in a package, subpackage(s) of package will not be added to the dependency of the parent package (only for algorithms `scripts/buildorder.py`)
TERMUX_PKG_ACCEPT_PKG_IN_DEP=false # allows you to add an initial package as a dependency, if any requested package (and their dependencies) will have a dependency on it (only for algorithms `scripts/buildorder.py`)

TERMUX_VIRTUAL_PKG=false
TERMUX_VIRTUAL_PKG_SRC=""
TERMUX_VIRTUAL_PKG_INCLUDE=""
TERMUX_VIRTUAL_PKG_NAME="$TERMUX_PKG_NAME"
TERMUX_VIRTUAL_PKG_BUILDER_DIR="$TERMUX_PKG_BUILDER_DIR"
TERMUX_VIRTUAL_PKG_BUILDER_SCRIPT="$TERMUX_PKG_BUILDER_SCRIPT"

unset CFLAGS CPPFLAGS LDFLAGS CXXFLAGS
unset TERMUX_MESON_ENABLE_SOVERSION # setenv to enable SOVERSION suffix for shared libs built with Meson
}
49 changes: 48 additions & 1 deletion scripts/build/termux_step_start_build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
termux_step_start_build() {
# shellcheck source=/dev/null
source "$TERMUX_PKG_BUILDER_SCRIPT"

if [ -n "$TERMUX_VIRTUAL_PKG_SRC" ]; then
export TERMUX_VIRTUAL_PKG=true
fi
if [ "$TERMUX_VIRTUAL_PKG" = "true" ]; then
if [ -z "${TERMUX_PKG_VERSION:=}" ]; then
TERMUX_PKG_VERSION="0"
fi
if [ -n "$TERMUX_VIRTUAL_PKG_SRC" ]; then
# Parsing the original package
termux_get_pkg_builder_dir_and_pkg_builder_script "$TERMUX_VIRTUAL_PKG_SRC"
# Checking that the original package is not a virtual package
(
local TERMUX_VIRTUAL_PKG_SRC_ORG="$TERMUX_VIRTUAL_PKG_SRC"
TERMUX_VIRTUAL_PKG=false
TERMUX_VIRTUAL_PKG_SRC=""
source "$TERMUX_PKG_BUILDER_SCRIPT"
if [ "$TERMUX_VIRTUAL_PKG" = "true" ] || [ -n "$TERMUX_VIRTUAL_PKG_SRC" ]; then
termux_error_exit "Virtual package '${TERMUX_VIRTUAL_PKG_NAME}' specifies virtual package '${TERMUX_VIRTUAL_PKG_SRC_ORG}' as source package. Cannot use virtual package as source."
fi
)
# Mixing the original package with the virtual package
source "$TERMUX_PKG_BUILDER_SCRIPT"
source "$TERMUX_VIRTUAL_PKG_BUILDER_SCRIPT"
# Setting the source in the virtual package
termux_step_setup_virtual_srcs
# Restoring variables by virtual package
termux_restore_variables_by_virtual_pkg
fi
fi

# Path to hostbuild marker, for use if package has hostbuild step
TERMUX_HOSTBUILD_MARKER="$TERMUX_PKG_HOSTBUILD_DIR/TERMUX_BUILT_FOR_$TERMUX_PKG_VERSION"

Expand Down Expand Up @@ -62,7 +93,7 @@ termux_step_start_build() {
fi
fi

echo "termux - building $TERMUX_PKG_NAME for arch $TERMUX_ARCH..."
echo "termux - building $(test "${TERMUX_VIRTUAL_PKG}" = "true" && echo "virtual") $TERMUX_PKG_NAME for arch $TERMUX_ARCH..."
test -t 1 && printf "\033]0;%s...\007" "$TERMUX_PKG_NAME"

# Avoid exporting PKG_CONFIG_LIBDIR until after termux_step_host_build.
Expand Down Expand Up @@ -116,3 +147,19 @@ termux_step_start_build() {
done
fi
}

termux_step_setup_virtual_srcs() {
[ "$TERMUX_VIRTUAL_PKG_INCLUDE" = "false" ] && return

if [ -z "$TERMUX_VIRTUAL_PKG_INCLUDE" ]; then
export TERMUX_VIRTUAL_PKG_INCLUDE=$(find "$TERMUX_PKG_BUILDER_DIR" -mindepth 1 -maxdepth 1 \
! -name "build.sh" ! -name "*.subpackage.sh" -exec basename {} ';')
fi

for src in $TERMUX_VIRTUAL_PKG_INCLUDE; do
if [ -e "${TERMUX_VIRTUAL_PKG_BUILDER_DIR}/${src}" ]; then
termux_error_exit "conflict, file '${src}' already exists."
fi
ln -sr "${TERMUX_PKG_BUILDER_DIR}/${src}" "${TERMUX_VIRTUAL_PKG_BUILDER_DIR}"
done
}
Loading

0 comments on commit 2d349ba

Please sign in to comment.