Skip to content

Commit

Permalink
Introduce otp_build check
Browse files Browse the repository at this point in the history
Perform various basic build checks on the system. This is not a complete
set of checks before a change can be introduced into the OTP daily builds.
All of these checks need to pass before a change can even be considering
for testing in OTP daily builds.
  • Loading branch information
rickard-green committed May 9, 2023
1 parent 3ec255a commit 6bcfd48
Show file tree
Hide file tree
Showing 2 changed files with 344 additions and 0 deletions.
9 changes: 9 additions & 0 deletions otp_build
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ usage ()
echo " release <target_dir> - creates a small release to <target_dir>"
echo " release [-a|-s|-t] <target_dir> - creates full release to <target_dir>"
echo " tests <dir> - Build testsuites to <dir>"
echo " check [-h|...] - Perform various build checks. See help for more info and options."
echo ""
echo "-a builds all applications"
echo "-s builds a small system (default)"
Expand Down Expand Up @@ -998,6 +999,11 @@ do_tests ()
fi
}

do_check ()
{
exec $ERL_TOP/scripts/otp_build_check "$@"
}

do_debuginfo_win32 ()
{
setup_make
Expand Down Expand Up @@ -1294,6 +1300,9 @@ case "$1" in
echo_env_cross "$2";;
env_bootstrap)
echo_env_bootstrap;;
check)
shift;
do_check "$@";;
*)
usage;;
esac
335 changes: 335 additions & 0 deletions scripts/otp_build_check
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
#!/bin/sh
#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2023. All Rights Reserved.
#
# Licensed 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.
#
# %CopyrightEnd%
#

#
# Performs a lot of (but not always all) build checking that you want to do...
#

docs=yes
dialyzer=yes
tests=all
opt_only=no
format_check=yes

have_printf=no

print_error() {
if [ $have_printf = yes ]; then
printf "\033[31mERROR: %s\033[0m\n" "$1" 1>&2
else
echo "ERROR: $1" 1>&2
fi
}

progress() {
if [ $have_printf = yes ]; then
printf "\n\033[33m*** %s ***\033[0m\n\n" "$1" 1>&2
else
echo "\n*** $1 ***\n" 1>&2
fi
}

print_usage() {
echo "Usage:"
echo " otp_build check [--help|-h] [--only-opt|-o] [--no-docs|-d] \\"
echo " [--no-dialyzer|-y] [--no-tests|-n] [--no-format-check|-f] \\"
echo " [--tests|-t <App0> ... <AppN>]"
echo ""
echo ""
echo "By default all currently implemented checks will be performed. If any"
echo "of the currently used tools are missing, checking will fail. If libraries"
echo "needed to support certain features are missing, those features will not"
echo "be checked. If any of these checks do not pass, the code is *not* ready"
echo "for testing in OTP daily builds. Note that this script does not check"
echo "all requirements for testing in OTP daily builds. These checks are the"
echo "bare minimum for even considering testing in OTP daily builds."
echo "Currently the following will be performed by default:"
echo ""
echo " * Build all applications in optimized mode. If configure already"
echo " has been run, it wont be run again."
echo " * Debug compile C-code in all applications."
echo " * Format checking of JIT code."
echo " * Run dialyzer on all applications."
echo " * Build all documentation."
echo " * Run xmllint on all documentation."
echo " * Run html link check on all documentation."
echo " * Build all tests."
echo ""
echo "Certain testing can be disabled using the following options:"
echo "* [--only-opt|-o] - Only compilebuild optimized system. No debug, etc."
echo "* [--no-docs|-d] - No documentation checking."
echo "* [--no-dialyzer|-y] - No dialyzer checking."
echo "* [--no-tests|-n] - No if building tests."
echo "* [--no-format-check|-f] - No JIT format checking."
echo "* [--tests|-t <App0> ... <AppN>] - Only build tests for listed applications"
echo ""
echo "Environment variables used:"
echo "* CONFIG_FLAGS - Arguments to pass to configure if it is executed."
echo ""
echo "Build results will be placed under the \$ERL_TOP/release/<TARGET> directory"
echo ""

}

usage () {
print_error "$1"
print_usage
exit 1
}

fail () {
print_error "$1"
exit 1
}

type printf >/dev/null 2>&1
if [ $? -eq 0 ]; then
have_printf=yes
fi

[ "$ERL_TOP" != "" ] || fail "ERL_TOP needs to be set"

cd "$ERL_TOP" 2>&1 >/dev/null || {
fail "Failed to change directory into $ERL_TOP"
}

[ -f "$ERL_TOP/OTP_VERSION" ] || fail "ERL_TOP not valid"

while [ $# -gt 0 ]; do
case $1 in
--help|-h)
print_usage
exit 0;;
--only-opt|-o)
opt_only=yes;;
--no-docs|-d)
docs=no;;
--no-dialyzer|-y)
dialyzer=no;;
--no-format-check|-f)
format_check=no;;
--no-tests|-n)
tests=none;;
--tests|-t)
shift
while [ $# -gt 0 ]; do
case $1 in
-*)
break;;
test_server|emulator|system|epmd)
;;
*)
[ -d "$ERL_TOP/lib/$1/test" ] || {
fail "Invalid application: $1"
}
;;
esac
tapps="$1 $tapps"
shift
done
[ "$tapps" != "" ] || usage "No test apps given"
tests="$tapps"
continue;;
*)
usage "Invalid option: $1"
esac
shift
done

[ -f "$ERL_TOP/make/config.status" ] || {
./configure $CONFIG_FLAGS || fail "configure failed"
}

type gmake >/dev/null 2>&1
if [ $? -eq 0 ]; then
export MAKE="gmake"
else
type make >/dev/null 2>&1
if [ $? -eq 0 ]; then
export MAKE="make"
fi
fi

target=`$MAKE target_configured` || fail "Failed to determine target directory"

unset TESTROOT
unset RELEASE_ROOT
unset ERL_LIBS
unset OTP_SMALL_BUILD
unset OTP_TINY_BUILD
unset TARGET

progress "Building OTP in $ERL_TOP"
$MAKE || fail "OTP build failed"
progress "Booting optimized runtime"
$ERL_TOP/bin/cerl -eval "erlang:halt()" || {
fail "Failed to boot runtime"
}

[ $opt_only = yes ] || {
progress "Building debug OTP in $ERL_TOP"
$MAKE TYPE=debug || fail "OTP debug build failed"
progress "Booting debug runtime"
$ERL_TOP/bin/cerl -debug -eval "erlang:halt()" || {
fail "Failed to boot debug runtime"
}
}

[ $format_check = no ] || {
clang-format --help 2>&1 >/dev/null || {
fail "clang-format not installed. Use --no-format-check option to skip."
}

progress "Checking C & C++ code formatting"
$MAKE format-check || {
fail "Failed to format C & C++ code"
}
}

progress "Releasing OTP"
$MAKE release || fail "Releasing OTP failed"

cd "$ERL_TOP/release/$target" 2>&1 >/dev/null || {
fail "Failed to change directory into release directory: $ERL_TOP/release/$target"
}

progress "Installing OTP"
./Install -minimal `pwd` || fail "Failed to install release"

progress "Booting optimized installed runtime"
./bin/erl -eval "erlang:halt()" || {
fail "Failed to boot installed runtime"
}

cd "$ERL_TOP" 2>&1 >/dev/null || {
fail "Failed to change directory into $ERL_TOP"
}

export PATH="$ERL_TOP/release/$target/bin:$PATH"

[ $docs = no ] || {
progress "Building OTP documentation"
$MAKE docs || fail "Building documentation failed"
progress "Releasing OTP documentation"
$MAKE release_docs || fail "Releasing documentation failed"
progress "Running xmllint on OTP documentation"
$MAKE xmllint || fail "xmllint of documentation failed"
progress "Running HTML check on OTP documentation"
./scripts/otp_html_check "$ERL_TOP/release/$target/" doc/index.html || {
fail "HTML check of documentation failed"
}
}

[ $dialyzer = no ] || {
progress "Running dialyzer on OTP"
$MAKE dialyzer || fail "Dialyzing OTP failed"
}

[ "$tests" = none ] || {
test_dir="$ERL_TOP/release/$target/test"
[ -d "$test_dir" ] || mkdir "$test_dir" 2>&1 >/dev/null || {
fail "Failed to create $test_dir directory"
}
if [ "$tests" = all ]; then
progress "Releasing all OTP tests"
./otp_build tests "$test_dir" || fail "Release of tests failed"
else
for tapp in $tests; do
case $tapp in
test_server)
tapp_dir="$ERL_TOP/lib/test_server"
if [ ! -d "$tapp_dir" ]; then
tapp_dir="$ERL_TOP/lib/common_test/test_server"
fi
;;
emulator) tapp_dir="$ERL_TOP/erts/emulator/test";;
system) tapp_dir="$ERL_TOP/erts/test";;
epmd) tapp_dir="$ERL_TOP/erts/epmd/test";;
*) tapp_dir="$ERL_TOP/lib/$tapp/test";;
esac
cd "$tapp_dir" 2>&1 >/dev/null || {
fail "Failed to change directory into $tapp_dir"
}
progress "Releasing $tapp tests"
$MAKE "TESTROOT=$test_dir" release_tests || {
fail "Release of $tapp tests failed"
}
done

fi

cd "$test_dir" 2>&1 >/dev/null || {
fail "Failed to change directory into $test_dir"
}

for dir in *; do

[ -d "$test_dir/$dir" ] || continue

progress "Building $dir tests"

cd "$test_dir/$dir" 2>&1 >/dev/null || {
fail "Failed to change directory into $test_dir/$dir"
}

for mfile in *_data/Makefile.first; do

[ "$mfile" != '*_data/Makefile.first' ] || continue

ddir=`dirname $mfile` || fail "dirname on $test_dir/$dir/$mfile failed"

cd "$test_dir/$dir/$ddir" 2>&1 >/dev/null || {
fail "Failed to change directory into $test_dir/$dir/$ddir"
}

$MAKE -f Makefile.first || {
fail "Make of $test_dir/$dir/$ddir/Makefile.first failed"
}

done

cd "$test_dir/$dir" 2>&1 >/dev/null || {
fail "Failed to change directory into $test_dir/$dir"
}

if [ -f Emakefile ]; then
erl -noshell -eval 'case make:all() of error -> erlang:halt(1); _ -> init:stop() end.' || {
fail "Build of $dir failed"
}
else
erlc -I `erl -noshell -eval 'io:format("~ts",[code:lib_dir(common_test)]),init:stop()'`/include -I . *.erl || {
fail "Build of $dir failed"
}
fi

done

cd "$ERL_TOP" 2>&1 >/dev/null || {
fail "Failed to change directory into $ERL_TOP"
}
}

if [ $have_printf = yes ]; then
printf "\n\033[32m*** Success! ***\033[0m\n\n"
else
echo "\n*** Success! ***\n"
fi
exit 0

0 comments on commit 6bcfd48

Please sign in to comment.