Skip to content

ENT-12600: detect-environment: Document and refactor #1737

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9e62056
detect-environment: Fixed shellcheck issues
larsewi Jun 6, 2025
5dd5779
detect-environment: Refactored cross target detection
larsewi Jun 6, 2025
4525c4b
detect-environment: Consistent identation in detect_os
larsewi Jun 6, 2025
972bc83
detect-environment: Fix indentation in "functions" sourced check
larsewi Jun 9, 2025
dcaee37
detect-environment: Document detect_os function
larsewi Jun 9, 2025
c468644
detect-environment: Put ;; on separate line
larsewi Jun 9, 2025
b85559c
detect-environment: Removed version substitution of code-names
larsewi Jun 9, 2025
58af4d6
detect-environment: Don't look for a 1-digit major release number
larsewi Jun 9, 2025
b9236cd
detect-environment: Document the detect_distribution
larsewi Jun 9, 2025
ede6c72
detect-environment: Simplified RHEL distro detection
larsewi Jun 9, 2025
eec2842
detect-environment: Remove parsing of /etc/SuSE-release
larsewi Jun 10, 2025
d1cdd42
detect-environment: changed two if's to if/elif
larsewi Jun 10, 2025
846657e
detect-environment: Put ;; on separate line
larsewi Jun 10, 2025
b8a4716
detect-environment: Document detect_packaging function
larsewi Jun 10, 2025
db2d94a
detect-environment: Put ;; on separate line
larsewi Jun 10, 2025
669311b
detect-environment: Moved version detection to detect_os
larsewi Jun 10, 2025
a503829
detect-environment: Document the detect_arch function
larsewi Jun 10, 2025
f69964f
detect-environment: Removed RPMBUILD_CMD environment variable
larsewi Jun 10, 2025
5e87c9d
Maybe we need this after all?
larsewi Jun 16, 2025
652e383
detect-environment: Remove call to function fatal
larsewi Jun 10, 2025
20005aa
detect-environment: Document the detect_tools function
larsewi Jun 10, 2025
2cc69b5
detect-environment: Put ;; on separate line
larsewi Jun 10, 2025
1f0a1ac
detect-environment: Document the detect_cores function
larsewi Jun 10, 2025
2e67550
detect-environment: Filter the output of env
larsewi Jun 10, 2025
d02fbb9
detect-environment: Added some log messages
larsewi Jun 10, 2025
5c636f1
configure: replace reference to $VER with $OS_VERSION
larsewi Jun 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build-scripts/configure
Original file line number Diff line number Diff line change
@@ -72,7 +72,7 @@ case "$WITH_SYSTEMD" in
esac

# RHEL 8 requires an SELinux policy
if [ "x$OS" = "xrhel" ] && [ "${VER%\.*}" -gt "7" ]; then
if [ "x$OS" = "xrhel" ] && [ "${OS_VERSION%\.*}" -gt "7" ]; then
var_append ARGS "--with-selinux-policy"
fi

352 changes: 196 additions & 156 deletions build-scripts/detect-environment
Original file line number Diff line number Diff line change
@@ -9,12 +9,15 @@

if [ "$_IS_FUNCTIONS_SOURCED" != yes ]
then
echo 'FATAL: You must source "functions" script before "detect-environment"!'
exit 100
echo 'FATAL: You must source "functions" script before "detect-environment"!'
exit 100
fi


detect_labels()
# Detects and sets the CROSS_TARGET environment variable based on patterns
# in the label variable (see labels.txt), specifically for MinGW cross-
# compilation targets. However, if CROSS_TARGET is already set in the
# environment it will take precedence.
detect_cross_target()
{
case "$label" in
*_x86_64_mingw*)
@@ -26,197 +29,195 @@ detect_labels()
export CROSS_TARGET
;;
esac

if [ -n "$CROSS_TARGET" ]; then
echo "Detected cross target $CROSS_TARGET"
else
echo "No cross target detected"
fi
}

# This function exports operating system specific variables:
# - OS usually contains a specific distribution (e.g. Debian)
# - OS_VERSION operating system version (but is not always defined)
#
# Furthermore, the following variable is set, but it's not exported:
# - OS_FAMILY usually contains the kernel name (e.g. Linux)
detect_os()
{
case "$CROSS_TARGET" in
'')
# The UNAME_S, UNAME_R and UNAME_V variables are set in the "functions"
# script from the command substitution of `uname -s`, `uname -r` and
# `uname -v` which outputs the kernel name, the kernel release and the
# kernel version respectively.

case "$UNAME_S" in
Linux)
Linux)
OS_FAMILY=linux
detect_distribution;;
SunOS)
detect_distribution
;;
SunOS)
OS_FAMILY=solaris
OS=solaris
OS_VERSION=`echo $UNAME_R | sed -e 's/^5\.//'`
OS_VERSION=$(echo "$UNAME_R" | sed -e 's/^5\.//')
;;
AIX)
AIX)
OS_FAMILY=aix
OS_VERSION=`uname -v`.$UNAME_R
OS_VERSION=$(uname -v).$UNAME_R
OS=aix
# LIBPATH on AIX serves the same function as LD_LIBRARY_PATH on
# Linux. However, Java also uses this environment variable, and it
# apparently messes with the library look-ups during packaging. This
# line definitely doesn't belong here. But I'll leave it for now.
unset LIBPATH
;;
Darwin)
Darwin)
OS_FAMILY=darwin
OS=darwin;;
FreeBSD)
OS=darwin
;;
FreeBSD)
OS_FAMILY=freebsd
OS=freebsd;;
NetBSD)
OS=freebsd
OS_VERSION=$UNAME_R
;;
NetBSD)
OS_FAMILY=netbsd
OS=netbsd;;
OS=netbsd
;;
HP-UX)
OS_FAMILY=hpux
OS=hpux;;
*)
echo "Unable to detect operating system: $UNAME_S"
exit 42;;
OS=hpux
OS_VERSION=$UNAME_R
;;
*)
echo "Unable to detect operating system: $UNAME_S"
exit 42
;;
esac
;;
*-mingw)
OS_FAMILY=mingw
OS=mingw;;
OS=mingw
;;
*)
echo "Unknown cross-compilation target: $CROSS_TARGET"
exit 42;;
exit 42
;;
esac

echo "Detected OS $OS $OS_VERSION"
export OS OS_VERSION
}

# The uname command does not reveal the specific distribution on Linux. Hence,
# we'll need to parse it from different files located in the /etc/ directory.
# Unfortunately, there is no standard across the existing distributions. Thus,
# this is going to be a bit messy.
detect_distribution()
{
if [ -f /etc/redhat-release ]; then
REL=$(cat /etc/redhat-release)
case "$REL" in
"CentOS "*)
VER="$(echo "$REL" | sed -e 's/^CentOS.* release \([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/')"
if ! echo "$VER" | egrep '^[0-9]+\.[0-9]+$' > /dev/null
then
echo "Unknown CentOS version: $VER"
exit 42
fi

# Example output for CentOS:
# CentOS Linux release 7.6.1810 (Core)
OS=centos
OS_VERSION="$VER"
;;
"Red Hat Enterprise Linux AS release "*)
VER=${REL#Red Hat Enterprise Linux AS release }
case "$VER" in
[0-9]" "*)
MAJOR=${VER%% *};;
*)
echo "Unknown RHEL AS major version: $VER"
exit 42;;
esac

case "$VER" in
*Update" "[0-9]")")
MINOR=${VER#*Update }
MINOR=${MINOR%\)};;
*)
echo "Unknnown RHEL AS minor version: $VER"
exit 42;;
esac

"Red Hat Enterprise Linux "*)
# Example output for RHEL:
# Red Hat Enterprise Linux release 8.10 (Ootpa)
OS=rhel
OS_VERSION="$MAJOR.$MINOR"
;;
"Red Hat Enterprise Linux Server release "*)
VER=${REL#Red Hat Enterprise Linux Server release }
VER=${VER% \(*};
if ! echo "$VER" | egrep '^[0-9]+.[0-9]+$' > /dev/null
then
echo "Unknown RHEL Server version: $VER"
exit 42
fi

OS=rhel
OS_VERSION="$VER"
*)
echo "Error: Could not determine Linux distro from /etc/redhat-release: $REL"
exit 42
;;
esac

"Red Hat Enterprise Linux release "*)
VER=${REL#Red Hat Enterprise Linux release }
VER=${VER% \(*};
if ! echo "$VER" | egrep '^[0-9]+.[0-9]+$' > /dev/null
then
echo "Unknown RHEL Server version: $VER"
exit 42
fi
# Common for all of these is that the version number starts just after the
# substring 'release '. Hence we reset the match (with \K) just after
# substring and extract the major and minor version.
version_string=$(echo "$REL" | grep -oP 'release \K\d+\.\d+')

OS=rhel
OS_VERSION="$VER"
;;
# Make sure we actually found a match
if [ -z "$version_string" ]; then
echo "Error: Could not determine version number from /etc/redhat-release: $REL"
exit 42
fi
OS_VERSION=$version_string

*)
echo "Unknown RedHat-like distribution: $REL"
exit 42;;
esac
elif [ -f /etc/lsb-release ] && grep -q Ubuntu /etc/lsb-release; then
# This file was introduced by Linux Standard Base (LSB) which an attempt to
# standardize the Linux ecosystem. Unfortunately it was not adopted by many
# Linux distributions. Ubuntu dropped the support for LSB in 2015. However,
# the /etc/lsb-release file is still available as of Ubuntu 24.
#
# It might be naive to assume the file will continue to exist and that the
# existence of the file is only present in Ubuntu. Hence, if this breaks in
# the future, you'll know why.
#
# Example output of /etc/lsb-release:
#
# DISTRIB_ID=Ubuntu
# DISTRIB_RELEASE=24.04
# DISTRIB_CODENAME=noble
# DISTRIB_DESCRIPTION="Ubuntu 24.04.2 LTS"

# Get the line containing 'DISTRIB_RELEASE='
REL=$(grep DISTRIB_RELEASE= /etc/lsb-release)

# Remove the 'DISTRIB_RELEASE=' part
REL=${REL#DISTRIB_RELEASE=}

# Verify that we can find a valid version number
case "$REL" in
[0-9].[0-9][0-9]|[0-9][0-9].[0-9][0-9])
[0-9][0-9].[0-9][0-9])
;;
*)
echo "Unknown Ubuntu release: $REL"
exit 42;;
exit 42
;;
esac

OS=ubuntu
OS_VERSION="$REL"
elif [ -f /etc/debian_version ]; then
# This file contains only the version number.
#
# Example output of /etc/debian_version
# 12.11

REL=$(cat /etc/debian_version)
if ! echo "$REL" | egrep '^[0-9]+\.[0-9]+(\.[0-9]+)?$' > /dev/null
if ! echo "$REL" | grep -E '^[0-9]+\.[0-9]+(\.[0-9]+)?$' > /dev/null
then
case "$REL" in
wheezy*)
REL=7.0
;;
jessie*)
REL=8.0
;;
stretch*)
REL=9.0
;;
buster*)
REL=10.0
;;
*)
echo "Unable to detect version of Debian: $REL"
exit 42;;
esac
echo "Unable to detect version of Debian: $REL"
exit 42
fi

OS=debian
OS_VERSION="$REL"
elif [ -f /etc/SuSE-release ]; then
# This file is gone starting with suse 13 or something. This whole section
# can be removed when support for suse 12 and lower is dropped. I wish to
# see that day.
REL=$(head -n1 /etc/SuSE-release)
case "$REL" in
"SUSE Linux Enterprise Server "*)
MAJOR=$(grep '^VERSION' /etc/SuSE-release | awk '{print $3}')
MINOR=$(grep '^PATCHLEVEL' /etc/SuSE-release | awk '{print $3}')

if [ -z "$MAJOR" -o -z "$MINOR" ]; then
echo "Unable to detect version of SLES: $MAJOR.$MINOR"
fi

OS=sles
OS_VERSION="$MAJOR.$MINOR"
;;
"openSUSE "*)
VERSION=$(grep '^VERSION' /etc/SuSE-release | awk '{print $3}')
OS=opensuse
OS_VERSION="$VERSION"
;;
*)
echo "Unknown SUSE distribution: $REL"
exit 42;;
esac
elif [ -f /etc/os-release ]; then
# see https://en.opensuse.org/SDB:Find_openSUSE_version for rules of
# parsing this file

# Example output for /etc/os-release:
#
# NAME="SLES"
# VERSION="12-SP5"
# VERSION_ID="12.5"
# PRETTY_NAME="SUSE Linux Enterprise Server 12 SP5"
# ID="sles"
# ANSI_COLOR="0;32"
# CPE_NAME="cpe:/o:suse:sles:12:sp5"

os="$(sh -c ". /etc/os-release; echo \$ID")"
ver="$(sh -c ". /etc/os-release; echo \$VERSION_ID")"
if [ "$os" = "sles" ]; then
OS=sles
OS_VERSION="$ver"
fi
if expr "$os" : "opensuse" >/dev/null; then
elif expr "$os" : "opensuse" >/dev/null; then
# If the string begins with "opensuse", then strip the remaining part. It
# can be "opensuse-leap" or "opensuse-tumbleweed"
OS=opensuse
OS_VERSION="$ver"
@@ -234,6 +235,10 @@ detect_distribution()
fi
}

# This function determines which dependency packaging scripts shall be used
# based on the operating system and available packaging tools. E.g., if rpm is
# detected, then the "pkg-build-rpm" script will be called from the
# "install-dependencies" script.
detect_packaging()
{
if [ -f /bin/rpm ]; then
@@ -256,115 +261,150 @@ detect_packaging()

case "$OS" in
aix)
PACKAGING=lpp;;
PACKAGING=lpp
;;
mingw)
PACKAGING=msi;;
PACKAGING=msi
;;
*)
PACKAGING=$DEP_PACKAGING;;
esac

echo "Detected dependency packaging $DEP_PACKAGING"
echo "Detected packaging $PACKAGING"
export DEP_PACKAGING PACKAGING
}

# This function determines which architecture to build for based on the system
# we're building on. Unless we are cross compiling, then it's determined by the
# CROSS_TARGET variable.
detect_arch()
{
case "$DEP_PACKAGING" in
deb)
ARCH=`dpkg --print-architecture`;;
ARCH=$(dpkg --print-architecture)
;;
rpm)
ARCH=`rpm --eval '%{_arch}'`;;
ARCH=$(rpm --eval '%{_arch}')
;;
solaris)
case $UNAME_M in
sun*)
ARCH=sparc;;
ARCH=sparc
;;
i86pc)
ARCH=i86pc;;
ARCH=i86pc
;;
*)
echo "Unknown Solaris architecture: $UNAME_M";;
esac;;
echo "Unknown Solaris architecture: $UNAME_M"
;;
esac
;;

freebsd)
ARCH=$UNAME_M
OS_VERSION=$UNAME_R ;;
;;
hpux)
ARCH=$UNAME_M
OS_VERSION=$UNAME_R ;;
;;
*)
echo "Unknown packaging system"
exit 42;;
exit 42
;;
esac

# Windows is build on Debian. Hence we need to determine the architecture
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Windows is build on Debian. Hence we need to determine the architecture
# We need to determine the architecture

Windows is built on Ubuntu-16, not Debian, and I don't think that is important to this area of code which distribution is involved.

# based on the 'CROSS_TARGET' variable which is derived from the 'label'
# variable instead of the system that we are building on.
case "$CROSS_TARGET" in
'')
;;
x86-*)
ARCH=x86;;
ARCH=x86
;;
x64-*)
ARCH=x64;;
ARCH=x64
;;
*)
echo "Unknown cross-compilation target: $CROSS_TARGET"
exit 42;;
exit 42
;;
esac

echo "Detected architecture $ARCH"
export ARCH
}

# This function detects the path to various tools needed by the build system.
# It's useful if the specified tool is not in PATH, or if the PATH resolution
# picks up the wrong tool, or if e.g. gmake is preferred over make.
detect_tools()
{
# We look for GNU Make because
# various dependencies have various requirements
MAKE=`func_whereis gmake make`
MAKE=$(func_whereis gmake make)

if $MAKE -v | grep GNU
then
export MAKE
echo "Detected make path $MAKE"
else
fatal "GNU Make not found"
echo "Error: GNU Make not found"
exit 42
fi

if [ "x$OS" = "xaix" ] && [ "x$OS_VERSION" = "x5.3" ]; then
RPMBUILD_CMD=rpm
else
RPMBUILD_CMD=rpmbuild
fi
export RPMBUILD_CMD
export RPMBUILD_CMD=rpmbuild

FUSER=`func_whereis fuser`
# fuser displays the PIDs of processes using specified files or file
# systems. We use it to kill processes that can mess with the build process.
FUSER=$(func_whereis fuser)
export FUSER
echo "Detected fuser path $FUSER"

PATCH=`func_whereis gpatch patch`
# We use it to submit patches to the dependencies.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# We use it to submit patches to the dependencies.
# We use patch to apply patches to the dependencies.

PATCH=$(func_whereis gpatch patch)
export PATCH
echo "Detected patch path $PATCH"
}

# This function appends the -j/--jobs option to the MAKEFLAGS environment
# variable based on the number of cores. However, the variable is overwritten in
# the "install-dependencies" script. I created a ticket fix this (see
# ENT-13041).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no doubt! over-rode to -j1 even! :(

detect_cores()
{
case "$OS_FAMILY" in
aix)
echo "Detected OS family is aix"
NUM_CORES="$(lscfg | grep proc | wc -l)";;
NUM_CORES="$(lscfg | grep -c proc)"
;;
solaris)
echo "Detected OS family is solaris"
NUM_CORES="$(psrinfo |wc -l)";;
NUM_CORES="$(psrinfo |wc -l)"
;;
linux)
echo "Detected OS family is linux"
NUM_CORES="$(cat /proc/cpuinfo | grep '^processor' | wc -l)";;
NUM_CORES="$(grep -c '^processor' /proc/cpuinfo)"
;;
hpux)
echo "Detected OS family is hpux"
NUM_CORES="$(ioscan -k -C processor |grep processor | wc -l)";;
NUM_CORES="$(ioscan -k -C processor | grep -c processor)"
;;
*)
echo "Detected OS family is UNKNOWN, defaulting amount of CPU cores to 1"
NUM_CORES=1;;
NUM_CORES=1
;;
esac

# Make number of jobs one higher than core count, to account for I/O, network, etc.
echo "Detected amount of CPU cores is $NUM_CORES"
MAKEFLAGS="${MAKEFLAGS:--j$(($NUM_CORES + 1))}"
MAKEFLAGS="${MAKEFLAGS:--j$((NUM_CORES + 1))}"
export MAKEFLAGS
}

detect_environment()
{
detect_labels
detect_cross_target
detect_os
detect_packaging
detect_arch
@@ -386,7 +426,7 @@ detect_environment
echo
echo
echo "==================== Current environment ========================"
env
env | grep -E "^(label|CROSS_TARGET|UNAME|OS|OS_VERSION|DEP_PACKAGING|PACKAGING|ARCH|MAKE|FUSER|PATCH|MAKEFLAGS)="
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line will definitely get lost in refactorings. Maybe we could instead append to a string near each of these and use that here! That way when someone copy/pastas a section about FUSER it will come with all the bits to make this line work.

echo "================================================================="
echo
echo
2 changes: 2 additions & 0 deletions build-scripts/install-dependencies
Original file line number Diff line number Diff line change
@@ -8,6 +8,8 @@
PATH=$PATH:$BASEDIR/buildscripts/deps-packaging

# Not all dependencies support building in parallel.
# TODO: Investigate if this is still the case or disable parallel jobs for only
# the dependencies that not support it. (ENT-13041)
MAKEFLAGS=-j1

set -x
2 changes: 1 addition & 1 deletion build-scripts/package
Original file line number Diff line number Diff line change
@@ -178,7 +178,7 @@ case "$PACKAGING" in
# - argv[2] = a b
# Also note that $RPMBUILD_OPTIONS might have spaces
# which must be preserved
eval "$RPMBUILD_CMD" -bb \
eval rpmbuild -bb \
--define "'_topdir $BASEDIR/$PKG'" \
--define "'buildprefix $BUILDPREFIX'" \
--define "'_basedir $BASEDIR'" \
2 changes: 1 addition & 1 deletion deps-packaging/pkg-build-rpm
Original file line number Diff line number Diff line change
@@ -112,7 +112,7 @@ fi
# example cmd --define 'a b':
# - argv[1] = --define
# - argv[2] = a b
eval $RPMBUILD_CMD -bb \
eval rpmbuild -bb \
--define "'_topdir $BASEDIR/$PKGNAME'" \
--define "'version $VERSION'" \
--define "'buildprefix $BUILDPREFIX'" \