From c89c464746709f8373dc7e7a57e8200d79f64e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Hinderer?= Date: Tue, 11 Aug 2020 16:03:27 +0200 Subject: Split Inria CI's extra-checks job, take #1 This job did actually do two different things: 1. Check that the compiler can be built without the world.opt target 2. Run sanitizers This commit thus splits the extra-checks job into two separate ones that are defined as Jenkins pipeline jobs named sanitizers and step-by-step-build. --- tools/ci/inria/extra-checks | 233 -------------------------- tools/ci/inria/lsan-suppr.txt | 2 - tools/ci/inria/sanitizers/Jenkinsfile | 41 +++++ tools/ci/inria/sanitizers/lsan-suppr.txt | 2 + tools/ci/inria/sanitizers/script | 157 +++++++++++++++++ tools/ci/inria/step-by-step-build/Jenkinsfile | 44 +++++ tools/ci/inria/step-by-step-build/script | 26 +++ 7 files changed, 270 insertions(+), 235 deletions(-) delete mode 100755 tools/ci/inria/extra-checks delete mode 100644 tools/ci/inria/lsan-suppr.txt create mode 100644 tools/ci/inria/sanitizers/Jenkinsfile create mode 100644 tools/ci/inria/sanitizers/lsan-suppr.txt create mode 100755 tools/ci/inria/sanitizers/script create mode 100644 tools/ci/inria/step-by-step-build/Jenkinsfile create mode 100755 tools/ci/inria/step-by-step-build/script (limited to 'tools') diff --git a/tools/ci/inria/extra-checks b/tools/ci/inria/extra-checks deleted file mode 100755 index 7997dd037d..0000000000 --- a/tools/ci/inria/extra-checks +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/sh -#************************************************************************** -#* * -#* OCaml * -#* * -#* Damien Doligez, Xavier Leroy, projet Gallium, INRIA Paris * -#* * -#* Copyright 2018 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -# This script is run on Inria's continuous-integration servers to recompile -# from scratch, adding more run-time checks ("sanitizers") to the C code, -# and run the test suite. - -# In this context, it is necessary to skip a few tests whose behaviour -# is modified by the instrumentation: - -export OCAMLTEST_SKIP_TESTS="tests/afl-instrumentation/afltest.ml \ -tests/runtime-errors/stackoverflow.ml" - -# To know the slave's architecture, this script looks at the OCAML_ARCH -# environment variable. For a given node NODE, this variable can be defined -# in Jenkins at the following address: -# https://ci.inria.fr/ocaml/computer/NODE/configure - -# Other environment variables that are honored: -# OCAML_JOBS number of jobs to run in parallel (make -j) - -# Command-line arguments: -# -jNN pass "-jNN" option to make for parallel builds - -error () { - echo "$1" >&2 - exit 3 -} - -arch_error() { - configure_url="https://ci.inria.fr/ocaml/computer/${NODE_NAME}/configure" - msg="Unknown architecture. Make sure the OCAML_ARCH environment" - msg="$msg variable has been defined." - msg="$msg\nSee ${configure_url}" - error "$msg" -} - -######################################################################### - -# Print each command before its execution -set -x - -# stop on error -set -e - -# be considerate towards other potential users of the test machine -case "${OCAML_ARCH}" in - bsd|macos|linux) renice 10 $$ ;; -esac - -# set up variables - -make=make -jobs='' - -case "${OCAML_ARCH}" in - bsd) make=gmake ;; - macos) ;; - linux) ;; - cygwin|cygwin64|mingw|mingw64|msvc|msvc64) - error "Don't run this test under Windows";; - *) arch_error;; -esac - -case "${OCAML_JOBS}" in - [1-9]|[1-9][0-9]) jobs="-j${OCAML_JOBS}" ;; -esac - -# parse optional command-line arguments - -while [ $# -gt 0 ]; do - case $1 in - -j[1-9]|-j[1-9][0-9]) jobs="$1";; - *) error "unknown option $1";; - esac - shift -done - -# Tell gcc to use only ASCII in its diagnostic outputs. -export LC_ALL=C - -# How to run the test suite -if test -n "$jobs" && test -x /usr/bin/parallel; then - export PARALLEL="$jobs $PARALLEL" - run_testsuite="$make -C testsuite parallel" -else - run_testsuite="$make -C testsuite all" -fi - -# A tool that makes error backtraces nicer -# Need to pick the one that matches clang-9 and is named "llvm-symbolizer" -# (/usr/bin/llvm-symbolizer-9 doesn't work, that would be too easy) -export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-9/bin/llvm-symbolizer -export TSAN_SYMBOLIZER_PATH="$ASAN_SYMBOLIZER_PATH" - -######################################################################### - -# Cleanup repository -git clean -q -f -d -x - -######################################################################### - -echo "======== old school build ==========" - -instdir="$HOME/ocaml-tmp-install-$$" -./configure --prefix "$instdir" --disable-dependency-generation - -# Build the system without using world.opt -make $jobs world -make $jobs opt -make $jobs opt.opt -make install - -rm -rf "$instdir" - -# It's a build system test only, so we don't bother testing the compiler - -######################################################################### - -echo "======== clang 9, address sanitizer, UB sanitizer ==========" - -git clean -q -f -d -x - -# Use clang 9 - -# These are the undefined behaviors we want to check -# Others occur on purpose e.g. signed arithmetic overflow -ubsan="\ -bool,\ -builtin,\ -bounds,\ -enum,\ -nonnull-attribute,\ -nullability,\ -object-size,\ -pointer-overflow,\ -returns-nonnull-attribute,\ -shift-exponent,\ -unreachable" - -# Select address sanitizer and UB sanitizer, with trap-on-error behavior -sanitizers="-fsanitize=address -fsanitize-trap=$ubsan" - -# Don't optimize too much to get better backtraces of errors - -./configure \ - CC=clang-9 \ - CFLAGS="-O1 -fno-omit-frame-pointer $sanitizers" \ - --disable-stdlib-manpages --enable-dependency-generation - -# Build the system. We want to check for memory leaks, hence -# 1- force ocamlrun to free memory before exiting -# 2- add an exception for ocamlyacc, which doesn't free memory - -OCAMLRUNPARAM="c=1" \ -LSAN_OPTIONS="suppressions=$(pwd)/tools/ci/inria/lsan-suppr.txt" \ -make $jobs - -# Run the testsuite. -# We deactivate leak detection for two reasons: -# - The suppressed leak detections related to ocamlyacc mess up the -# output of the tests and are reported as failures by ocamltest. -# - The Ocaml runtime does not free the memory when a fatal error -# occurs. - -# We already use sigaltstack for stack overflow detection. Our use -# interacts with ASAN's. Hence, we tell ASAN not to use it. - -ASAN_OPTIONS="detect_leaks=0,use_sigaltstack=0" $run_testsuite - -######################################################################### - -echo "======== clang 9, thread sanitizer ==========" - -git clean -q -f -d -x - -# Select thread sanitizer -# Don't optimize too much to get better backtraces of errors - -./configure \ - CC=clang-9 \ - CFLAGS="-O1 -fno-omit-frame-pointer -fsanitize=thread" \ - --disable-stdlib-manpages --enable-dependency-generation - -# Build the system -make $jobs - -# Run the testsuite. -# ThreadSanitizer complains about fork() in threaded programs, -# we ask it to just continue in this case. -TSAN_OPTIONS="die_after_fork=0" $run_testsuite - -######################################################################### - -# This is a failed attempt at using the memory sanitizer -# (to detect reads from uninitialized memory). -# Some alarms are reported that look like false positive -# and are impossible to debug. - -# echo "======== clang 6.0, memory sanitizer ==========" - -# git clean -q -f -d -x - -# # Use clang 6.0 -# # Memory sanitizer doesn't like the static data generated by ocamlopt, -# # hence build bytecode only -# # Select memory sanitizer -# # Don't optimize at all to get better backtraces of errors - -# ./configure \ -# CC=clang-9 \ -# CFLAGS="-O0 -g -fno-omit-frame-pointer -fsanitize=memory" \ -# --disable-native-compiler -# # A tool that makes error backtraces nicer -# # Need to pick the one that matches clang-6.0 -# export MSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer - -# # Build the system (bytecode only) and test -# make $jobs -# $run_testsuite diff --git a/tools/ci/inria/lsan-suppr.txt b/tools/ci/inria/lsan-suppr.txt deleted file mode 100644 index 160e7fc68b..0000000000 --- a/tools/ci/inria/lsan-suppr.txt +++ /dev/null @@ -1,2 +0,0 @@ -# ocamlyacc doesn't clean memory on exit -leak:ocamlyacc diff --git a/tools/ci/inria/sanitizers/Jenkinsfile b/tools/ci/inria/sanitizers/Jenkinsfile new file mode 100644 index 0000000000..77dc0e140a --- /dev/null +++ b/tools/ci/inria/sanitizers/Jenkinsfile @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Sebastien Hinderer, INRIA Paris */ +/* */ +/* Copyright 2020 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Pipeline for the sanitizers job on Inria's CI */ + +pipeline { + agent { label 'ocaml-linux-64' } + stages { + stage('Compiling and testing OCaml with sanitizers') { + steps { + sh 'tools/ci/inria/sanitizers/script' + } + } + } + post { + always { + emailext ( + to: 'ocaml-ci-notifications@inria.fr', + subject: 'Job $JOB_NAME $BUILD_STATUS (build #$BUILD_NUMBER)', + body: 'Changes since the last successful build:\n\n' + + '${CHANGES, format="%r %a %m"}\n\n' + + 'See the attached build log or check console output here:\n' + + '$BUILD_URL\n', + /* recipientProviders: [[$class: 'DevelopersRecipientProvider']], */ + attachLog: true + ) + } + } +} diff --git a/tools/ci/inria/sanitizers/lsan-suppr.txt b/tools/ci/inria/sanitizers/lsan-suppr.txt new file mode 100644 index 0000000000..160e7fc68b --- /dev/null +++ b/tools/ci/inria/sanitizers/lsan-suppr.txt @@ -0,0 +1,2 @@ +# ocamlyacc doesn't clean memory on exit +leak:ocamlyacc diff --git a/tools/ci/inria/sanitizers/script b/tools/ci/inria/sanitizers/script new file mode 100755 index 0000000000..5f8e5b6e7a --- /dev/null +++ b/tools/ci/inria/sanitizers/script @@ -0,0 +1,157 @@ +#!/bin/sh +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, Xavier Leroy, projet Gallium, INRIA Paris * +#* * +#* Copyright 2018 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +# This script is run on Inria's continuous-integration servers to recompile +# from scratch, adding more run-time checks ("sanitizers") to the C code, +# and run the test suite. + +# In this context, it is necessary to skip a few tests whose behaviour +# is modified by the instrumentation: + +export OCAMLTEST_SKIP_TESTS="tests/afl-instrumentation/afltest.ml \ +tests/runtime-errors/stackoverflow.ml" + +jobs=-j8 +make=make + +######################################################################### + +# Print each command before its execution +set -x + +# stop on error +set -e + +# Tell gcc to use only ASCII in its diagnostic outputs. +export LC_ALL=C + +# How to run the test suite +if test -n "$jobs" && test -x /usr/bin/parallel; then + export PARALLEL="$jobs $PARALLEL" + run_testsuite="$make -C testsuite parallel" +else + run_testsuite="$make -C testsuite all" +fi + +# A tool that makes error backtraces nicer +# Need to pick the one that matches clang-9 and is named "llvm-symbolizer" +# (/usr/bin/llvm-symbolizer-9 doesn't work, that would be too easy) +export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-9/bin/llvm-symbolizer +export TSAN_SYMBOLIZER_PATH="$ASAN_SYMBOLIZER_PATH" + +######################################################################### + +echo "======== clang 9, address sanitizer, UB sanitizer ==========" + +git clean -q -f -d -x + +# Use clang 9 + +# These are the undefined behaviors we want to check +# Others occur on purpose e.g. signed arithmetic overflow +ubsan="\ +bool,\ +builtin,\ +bounds,\ +enum,\ +nonnull-attribute,\ +nullability,\ +object-size,\ +pointer-overflow,\ +returns-nonnull-attribute,\ +shift-exponent,\ +unreachable" + +# Select address sanitizer and UB sanitizer, with trap-on-error behavior +sanitizers="-fsanitize=address -fsanitize-trap=$ubsan" + +# Don't optimize too much to get better backtraces of errors + +./configure \ + CC=clang-9 \ + CFLAGS="-O1 -fno-omit-frame-pointer $sanitizers" \ + --disable-stdlib-manpages --enable-dependency-generation + +# Build the system. We want to check for memory leaks, hence +# 1- force ocamlrun to free memory before exiting +# 2- add an exception for ocamlyacc, which doesn't free memory + +OCAMLRUNPARAM="c=1" \ +LSAN_OPTIONS="suppressions=$(pwd)/tools/ci/inria/sanitizers/lsan-suppr.txt" \ +make $jobs + +# Run the testsuite. +# We deactivate leak detection for two reasons: +# - The suppressed leak detections related to ocamlyacc mess up the +# output of the tests and are reported as failures by ocamltest. +# - The Ocaml runtime does not free the memory when a fatal error +# occurs. + +# We already use sigaltstack for stack overflow detection. Our use +# interacts with ASAN's. Hence, we tell ASAN not to use it. + +ASAN_OPTIONS="detect_leaks=0,use_sigaltstack=0" $run_testsuite + +######################################################################### + +echo "======== clang 9, thread sanitizer ==========" + +git clean -q -f -d -x + +# Select thread sanitizer +# Don't optimize too much to get better backtraces of errors + +./configure \ + CC=clang-9 \ + CFLAGS="-O1 -fno-omit-frame-pointer -fsanitize=thread" \ + --disable-stdlib-manpages --enable-dependency-generation + +# Build the system +make $jobs + +# Run the testsuite. +# ThreadSanitizer complains about fork() in threaded programs, +# we ask it to just continue in this case. +TSAN_OPTIONS="die_after_fork=0" $run_testsuite + +######################################################################### + +# This is a failed attempt at using the memory sanitizer +# (to detect reads from uninitialized memory). +# Some alarms are reported that look like false positive +# and are impossible to debug. + +# echo "======== clang 6.0, memory sanitizer ==========" + +# git clean -q -f -d -x + +# # Use clang 6.0 +# # Memory sanitizer doesn't like the static data generated by ocamlopt, +# # hence build bytecode only +# # Select memory sanitizer +# # Don't optimize at all to get better backtraces of errors + +# ./configure \ +# CC=clang-9 \ +# CFLAGS="-O0 -g -fno-omit-frame-pointer -fsanitize=memory" \ +# --disable-native-compiler +# # A tool that makes error backtraces nicer +# # Need to pick the one that matches clang-6.0 +# export MSAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer + +# # Build the system (bytecode only) and test +# make $jobs +# $run_testsuite diff --git a/tools/ci/inria/step-by-step-build/Jenkinsfile b/tools/ci/inria/step-by-step-build/Jenkinsfile new file mode 100644 index 0000000000..b2b0d499de --- /dev/null +++ b/tools/ci/inria/step-by-step-build/Jenkinsfile @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Sebastien Hinderer, INRIA Paris */ +/* */ +/* Copyright 2020 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +/* Pipeline for the step-by-step-build job on Inria's CI */ + +/* Build OCaml the legacy way (without using the world.opt target) */ + +pipeline { + agent { label 'ocaml-linux-64' } + stages { + stage('Building the OCaml compiler step by step ' + + + '(without using the world.opt target)') { + steps { + sh 'tools/ci/inria/step-by-step-build/script' + } + } + } + post { + always { + emailext ( + to: 'ocaml-ci-notifications@inria.fr', + subject: 'Job $JOB_NAME $BUILD_STATUS (build #$BUILD_NUMBER)', + body: 'Changes since the last successful build:\n\n' + + '${CHANGES, format="%r %a %m"}\n\n' + + 'See the attached build log or check console output here:\n' + + '$BUILD_URL\n', + /* recipientProviders: [[$class: 'DevelopersRecipientProvider']], */ + attachLog: true + ) + } + } +} diff --git a/tools/ci/inria/step-by-step-build/script b/tools/ci/inria/step-by-step-build/script new file mode 100755 index 0000000000..52d498d6f0 --- /dev/null +++ b/tools/ci/inria/step-by-step-build/script @@ -0,0 +1,26 @@ +#!/bin/sh +#************************************************************************** +#* * +#* OCaml * +#* * +#* Sebastien Hinderer projet Cambium, INRIA Paris * +#* * +#* Copyright 2020 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +jobs=8 +instdir="$HOME/ocaml-tmp-install-$$" +./configure --prefix "$instdir" --disable-dependency-generation +make $jobs world +make $jobs opt +make $jobs opt.opt +make install +rm -rf "$instdir" +# It's a build system test only, so we don't bother testing the compiler + ''' -- cgit v1.2.1