summaryrefslogtreecommitdiff
path: root/ci.sh
diff options
context:
space:
mode:
Diffstat (limited to 'ci.sh')
-rwxr-xr-xci.sh197
1 files changed, 84 insertions, 113 deletions
diff --git a/ci.sh b/ci.sh
index 45d5218..342eac0 100755
--- a/ci.sh
+++ b/ci.sh
@@ -5,8 +5,8 @@
# license that can be found in the LICENSE file.
# Continuous integration helper module. This module is meant to be called from
-# the .gitlab-ci.yml file during the continuous integration build, as well as
-# from the command line for developers.
+# workflows during the continuous integration build, as well as from the
+# command line for developers.
set -eu
@@ -21,7 +21,10 @@ CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH:-}
CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER:-}
CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER:-}
CMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM:-}
+SKIP_BUILD="${SKIP_BUILD:-0}"
SKIP_TEST="${SKIP_TEST:-0}"
+FASTER_MSAN_BUILD="${FASTER_MSAN_BUILD:-0}"
+TARGETS="${TARGETS:-all doc}"
TEST_SELECTOR="${TEST_SELECTOR:-}"
BUILD_TARGET="${BUILD_TARGET:-}"
ENABLE_WASM_SIMD="${ENABLE_WASM_SIMD:-0}"
@@ -32,6 +35,8 @@ else
fi
# Whether we should post a message in the MR when the build fails.
POST_MESSAGE_ON_ERROR="${POST_MESSAGE_ON_ERROR:-1}"
+# By default, do a lightweight debian HWY package build.
+HWY_PKG_OPTIONS="${HWY_PKG_OPTIONS:---set-envvar=HWY_EXTRA_CONFIG=-DBUILD_TESTING=OFF -DHWY_ENABLE_EXAMPLES=OFF -DHWY_ENABLE_CONTRIB=OFF}"
# Set default compilers to clang if not already set
export CC=${CC:-clang}
@@ -69,13 +74,18 @@ if [[ "${ENABLE_WASM_SIMD}" -ne "0" ]]; then
CMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -msimd128"
fi
+if [[ "${ENABLE_WASM_SIMD}" -eq "2" ]]; then
+ CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -DHWY_WANT_WASM2"
+ CMAKE_C_FLAGS="${CMAKE_C_FLAGS} -DHWY_WANT_WASM2"
+fi
+
if [[ ! -z "${HWY_BASELINE_TARGETS}" ]]; then
CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -DHWY_BASELINE_TARGETS=${HWY_BASELINE_TARGETS}"
fi
# Version inferred from the CI variables.
-CI_COMMIT_SHA=${CI_COMMIT_SHA:-${GITHUB_SHA:-}}
-JPEGXL_VERSION=${JPEGXL_VERSION:-${CI_COMMIT_SHA:0:8}}
+CI_COMMIT_SHA=${GITHUB_SHA:-}
+JPEGXL_VERSION=${JPEGXL_VERSION:-}
# Benchmark parameters
STORE_IMAGES=${STORE_IMAGES:-1}
@@ -139,6 +149,7 @@ detect_clang_version() {
fi
local clang_version=$("${CC:-clang}" --version | head -n1)
clang_version=${clang_version#"Debian "}
+ clang_version=${clang_version#"Ubuntu "}
local llvm_tag
case "${clang_version}" in
"clang version 6."*)
@@ -171,27 +182,6 @@ on_exit() {
local retcode="$1"
# Always cleanup the CLEANUP_FILES.
cleanup
-
- # Post a message in the MR when requested with POST_MESSAGE_ON_ERROR but only
- # if the run failed and we are not running from a MR pipeline.
- if [[ ${retcode} -ne 0 && -n "${CI_BUILD_NAME:-}" &&
- -n "${POST_MESSAGE_ON_ERROR}" && -z "${CI_MERGE_REQUEST_ID:-}" &&
- "${CI_BUILD_REF_NAME}" = "master" ]]; then
- load_mr_vars_from_commit
- { set +xeu; } 2>/dev/null
- local message="**Run ${CI_BUILD_NAME} @ ${CI_COMMIT_SHORT_SHA} failed.**
-
-Check the output of the job at ${CI_JOB_URL:-} to see if this was your problem.
-If it was, please rollback this change or fix the problem ASAP, broken builds
-slow down development. Check if the error already existed in the previous build
-as well.
-
-Pipeline: ${CI_PIPELINE_URL}
-
-Previous build commit: ${CI_COMMIT_BEFORE_SHA}
-"
- cmd_post_mr_comment "${message}"
- fi
}
trap 'retcode=$?; { set +x; } 2>/dev/null; on_exit ${retcode}' INT TERM EXIT
@@ -203,7 +193,7 @@ trap 'retcode=$?; { set +x; } 2>/dev/null; on_exit ${retcode}' INT TERM EXIT
# running from a merge request pipeline).
MR_HEAD_SHA=""
# The common ancestor between the current commit and the tracked branch, such
-# as master. This includes a list
+# as main. This includes a list
MR_ANCESTOR_SHA=""
# Populate MR_HEAD_SHA and MR_ANCESTOR_SHA.
@@ -216,30 +206,23 @@ merge_request_commits() {
# changes on the Pull Request if needed. This fetches 10 more commits which
# should be enough given that PR normally should have 1 commit.
git -C "${MYDIR}" fetch -q origin "${GITHUB_SHA}" --depth 10
- MR_HEAD_SHA="$(git rev-parse "FETCH_HEAD^2" 2>/dev/null ||
+ if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
+ MR_HEAD_SHA="$(git rev-parse "FETCH_HEAD^2" 2>/dev/null ||
echo "${GITHUB_SHA}")"
+ else
+ MR_HEAD_SHA="${GITHUB_SHA}"
+ fi
else
- # CI_BUILD_REF is the reference currently being build in the CI workflow.
- MR_HEAD_SHA=$(git -C "${MYDIR}" rev-parse -q "${CI_BUILD_REF:-HEAD}")
+ MR_HEAD_SHA=$(git -C "${MYDIR}" rev-parse -q "HEAD")
fi
- if [[ -n "${CI_MERGE_REQUEST_IID:-}" ]]; then
- # Merge request pipeline in CI. In this case the upstream is called "origin"
- # but it refers to the forked project that's the source of the merge
- # request. We need to get the target of the merge request, for which we need
- # to query that repository using our CI_JOB_TOKEN.
- echo "machine gitlab.com login gitlab-ci-token password ${CI_JOB_TOKEN}" \
- >> "${HOME}/.netrc"
- git -C "${MYDIR}" fetch "${CI_MERGE_REQUEST_PROJECT_URL}" \
- "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
- MR_ANCESTOR_SHA=$(git -C "${MYDIR}" rev-parse -q FETCH_HEAD)
- elif [[ -n "${GITHUB_BASE_REF:-}" ]]; then
+ if [[ -n "${GITHUB_BASE_REF:-}" ]]; then
# Pull request workflow in GitHub Actions. GitHub checkout action uses
# "origin" as the remote for the git checkout.
git -C "${MYDIR}" fetch -q origin "${GITHUB_BASE_REF}"
MR_ANCESTOR_SHA=$(git -C "${MYDIR}" rev-parse -q FETCH_HEAD)
else
- # We are in a local branch, not a merge request.
+ # We are in a local branch, not a pull request workflow.
MR_ANCESTOR_SHA=$(git -C "${MYDIR}" rev-parse -q HEAD@{upstream} || true)
fi
@@ -258,40 +241,6 @@ merge_request_commits() {
set -x
}
-# Load the MR iid from the landed commit message when running not from a
-# merge request workflow. This is useful to post back results at the merge
-# request when running pipelines from master.
-load_mr_vars_from_commit() {
- { set +x; } 2>/dev/null
- if [[ -z "${CI_MERGE_REQUEST_IID:-}" ]]; then
- local mr_iid=$(git rev-list --format=%B --max-count=1 HEAD |
- grep -F "${CI_PROJECT_URL}" | grep -F "/merge_requests" | head -n 1)
- # mr_iid contains a string like this if it matched:
- # Part-of: <https://gitlab.com/wg1/jpeg-xlm/merge_requests/123456>
- if [[ -n "${mr_iid}" ]]; then
- mr_iid=$(echo "${mr_iid}" |
- sed -E 's,^.*merge_requests/([0-9]+)>.*$,\1,')
- CI_MERGE_REQUEST_IID="${mr_iid}"
- CI_MERGE_REQUEST_PROJECT_ID=${CI_PROJECT_ID}
- fi
- fi
- set -x
-}
-
-# Posts a comment to the current merge request.
-cmd_post_mr_comment() {
- { set +x; } 2>/dev/null
- local comment="$1"
- if [[ -n "${BOT_TOKEN:-}" && -n "${CI_MERGE_REQUEST_IID:-}" ]]; then
- local url="${CI_API_V4_URL}/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes"
- curl -X POST -g \
- -H "PRIVATE-TOKEN: ${BOT_TOKEN}" \
- --data-urlencode "body=${comment}" \
- --output /dev/null \
- "${url}"
- fi
- set -x
-}
# Set up and export the environment variables needed by the child processes.
export_env() {
@@ -452,9 +401,12 @@ cmake_configure() {
}
cmake_build_and_test() {
+ if [[ "${SKIP_BUILD}" -eq "1" ]]; then
+ return 0
+ fi
# gtest_discover_tests() runs the test binaries to discover the list of tests
# at build time, which fails under qemu.
- ASAN_OPTIONS=detect_leaks=0 cmake --build "${BUILD_DIR}" -- all doc
+ ASAN_OPTIONS=detect_leaks=0 cmake --build "${BUILD_DIR}" -- $TARGETS
# Pack test binaries if requested.
if [[ "${PACK_TEST:-}" == "1" ]]; then
(cd "${BUILD_DIR}"
@@ -547,6 +499,7 @@ cmd_coverage_report() {
# Only print coverage information for the libjxl directories. The rest
# is not part of the code under test.
--filter '.*jxl/.*'
+ --exclude '.*_gbench.cc'
--exclude '.*_test.cc'
--exclude '.*_testonly..*'
--exclude '.*_debug.*'
@@ -576,7 +529,7 @@ cmd_test() {
(cd "${BUILD_DIR}"
export UBSAN_OPTIONS=print_stacktrace=1
[[ "${TEST_STACK_LIMIT}" == "none" ]] || ulimit -s "${TEST_STACK_LIMIT}"
- ctest -j $(nproc --all || echo 1) --output-on-failure "$@")
+ ctest -j $(nproc --all || echo 1) ${TEST_SELECTOR} --output-on-failure "$@")
}
cmd_gbench() {
@@ -652,7 +605,6 @@ cmd_msan() {
local msan_c_flags=(
-fsanitize=memory
-fno-omit-frame-pointer
- -fsanitize-memory-track-origins
-DJXL_ENABLE_ASSERT=1
-g
@@ -661,6 +613,13 @@ cmd_msan() {
# Force gtest to not use the cxxbai.
-DGTEST_HAS_CXXABI_H_=0
)
+ if [[ "${FASTER_MSAN_BUILD}" -ne "1" ]]; then
+ msan_c_flags=(
+ "${msan_c_flags[@]}"
+ -fsanitize-memory-track-origins
+ )
+ fi
+
local msan_cxx_flags=(
"${msan_c_flags[@]}"
@@ -724,6 +683,15 @@ cmd_msan_install() {
local msan_prefix="${HOME}/.msan/${CLANG_VERSION}"
rm -rf "${msan_prefix}"
+ local TARGET_OPTS=""
+ if [[ -n "${BUILD_TARGET}" ]]; then
+ TARGET_OPTS=" \
+ -DCMAKE_C_COMPILER_TARGET=\"${BUILD_TARGET}\" \
+ -DCMAKE_CXX_COMPILER_TARGET=\"${BUILD_TARGET}\" \
+ -DCMAKE_SYSTEM_PROCESSOR=\"${BUILD_TARGET%%-*}\" \
+ "
+ fi
+
declare -A CMAKE_EXTRAS
CMAKE_EXTRAS[libcxx]="\
-DLIBCXX_CXX_ABI=libstdc++ \
@@ -745,6 +713,7 @@ cmd_msan_install() {
-DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS}" \
-DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS}" \
-DCMAKE_INSTALL_PREFIX="${msan_prefix}" \
+ ${TARGET_OPTS} \
${CMAKE_EXTRAS[${project}]}
cmake --build "${proj_build}"
ninja -C "${proj_build}" install
@@ -788,7 +757,7 @@ _cmd_ossfuzz() {
-e MSAN_LIBS_PATH="/work/msan" \
-e JPEGXL_EXTRA_ARGS="${jpegxl_extra_args}" \
-v "${MYDIR}":/src/libjxl \
- -v "${MYDIR}/tools/ossfuzz-build.sh":/src/build.sh \
+ -v "${MYDIR}/tools/scripts/ossfuzz-build.sh":/src/build.sh \
-v "${real_build_dir}":/work \
gcr.io/oss-fuzz/libjxl
}
@@ -902,7 +871,7 @@ run_benchmark() {
--input "${src_img_dir}/*.png"
--codec=jpeg:yuv420:q85,webp:q80,jxl:d1:6,jxl:d1:6:downsampling=8,jxl:d5:6,jxl:d5:6:downsampling=8,jxl:m:d0:2,jxl:m:d0:3,jxl:m:d2:2
--output_dir "${output_dir}"
- --noprofiler --show_progress
+ --show_progress
--num_threads="${num_threads}"
)
if [[ "${STORE_IMAGES}" == "1" ]]; then
@@ -917,15 +886,7 @@ run_benchmark() {
return ${PIPESTATUS[0]}
)
- if [[ -n "${CI_BUILD_NAME:-}" ]]; then
- { set +x; } 2>/dev/null
- local message="Results for ${CI_BUILD_NAME} @ ${CI_COMMIT_SHORT_SHA} (job ${CI_JOB_URL:-}):
-$(cat "${output_dir}/results.txt")
-"
- cmd_post_mr_comment "${message}"
- set -x
- fi
}
# Helper function to wait for the CPU temperature to cool down on ARM.
@@ -1153,18 +1114,6 @@ cmd_arm_benchmark() {
cmd_cpuset "${RUNNER_CPU_ALL:-}"
cat "${runs_file}"
- if [[ -n "${CI_BUILD_NAME:-}" ]]; then
- load_mr_vars_from_commit
- { set +x; } 2>/dev/null
- local message="Results for ${CI_BUILD_NAME} @ ${CI_COMMIT_SHORT_SHA} (job ${CI_JOB_URL:-}):
-
-\`\`\`
-$(column -t -s " " "${runs_file}")
-\`\`\`
-"
- cmd_post_mr_comment "${message}"
- set -x
- fi
}
# Generate a corpus and run the fuzzer on that corpus.
@@ -1184,22 +1133,38 @@ cmd_fuzz() {
)
}
-# Runs the linter (clang-format) on the pending CLs.
+# Runs the linters (clang-format, build_cleaner, buildirier) on the pending CLs.
cmd_lint() {
merge_request_commits
{ set +x; } 2>/dev/null
- local versions=(${1:-6.0 7 8 9 10 11})
+ local versions=(${1:-16 15 14 13 12 11 10 9 8 7 6.0})
local clang_format_bins=("${versions[@]/#/clang-format-}" clang-format)
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
local ret=0
local build_patch="${tmpdir}/build_cleaner.patch"
- if ! "${MYDIR}/tools/build_cleaner.py" >"${build_patch}"; then
+ if ! "${MYDIR}/tools/scripts/build_cleaner.py" >"${build_patch}"; then
ret=1
echo "build_cleaner.py findings:" >&2
"${COLORDIFF_BIN}" <"${build_patch}"
- echo "Run \`tools/build_cleaner.py --update\` to apply them" >&2
+ echo "Run \`tools/scripts/build_cleaner.py --update\` to apply them" >&2
+ fi
+
+ # It is ok, if buildifier is not installed.
+ if which buildifier >/dev/null; then
+ local buildifier_patch="${tmpdir}/buildifier.patch"
+ local bazel_files=`git -C ${MYDIR} ls-files | grep -E "/BUILD$|WORKSPACE|.bzl$"`
+ set -x
+ buildifier -d ${bazel_files} >"${buildifier_patch}"|| true
+ { set +x; } 2>/dev/null
+ if [ -s "${buildifier_patch}" ]; then
+ ret=1
+ echo 'buildifier have found some problems in Bazel build files:' >&2
+ "${COLORDIFF_BIN}" <"${buildifier_patch}"
+ echo 'To fix them run (from the base directory):' >&2
+ echo ' buildifier `git ls-files | grep -E "/BUILD$|WORKSPACE|.bzl$"`' >&2
+ fi
fi
local installed=()
@@ -1218,7 +1183,7 @@ cmd_lint() {
git -C "${MYDIR}" "${clang_format}" --binary "${clang_format}" \
--style=file --diff "${MR_ANCESTOR_SHA}" -- >"${tmppatch}" || true
{ set +x; } 2>/dev/null
- if grep -E '^--- ' "${tmppatch}">/dev/null; then
+ if grep -E '^--- ' "${tmppatch}" | grep -v 'a/third_party' >/dev/null; then
if [[ -n "${LINT_OUTPUT:-}" ]]; then
cp "${tmppatch}" "${LINT_OUTPUT}"
fi
@@ -1326,6 +1291,7 @@ cmd_debian_stats() {
build_debian_pkg() {
local srcdir="$1"
local srcpkg="$2"
+ local options="${3:-}"
local debsdir="${BUILD_DIR}/debs"
local builddir="${debsdir}/${srcpkg}"
@@ -1341,7 +1307,7 @@ build_debian_pkg() {
done
(
cd "${builddir}"
- debuild -b -uc -us
+ debuild "${options}" -b -uc -us
)
}
@@ -1353,7 +1319,7 @@ cmd_debian_build() {
build_debian_pkg "${MYDIR}" "jpeg-xl"
;;
highway)
- build_debian_pkg "${MYDIR}/third_party/highway" "highway"
+ build_debian_pkg "${MYDIR}/third_party/highway" "highway" "${HWY_PKG_OPTIONS}"
;;
*)
echo "ERROR: Must pass a valid source package name to build." >&2
@@ -1374,7 +1340,7 @@ cmd_bump_version() {
local newver="${1:-}"
if ! which dch >/dev/null; then
- echo "Run:\n sudo apt install debhelper"
+ echo "Missing dch\nTo install it run:\n sudo apt install devscripts"
exit 1
fi
@@ -1402,9 +1368,13 @@ cmd_bump_version() {
-e "s/(set\\(JPEGXL_MINOR_VERSION) [0-9]+\\)/\\1 ${minor})/" \
-e "s/(set\\(JPEGXL_PATCH_VERSION) [0-9]+\\)/\\1 ${patch})/" \
-i lib/CMakeLists.txt
+ sed -E \
+ -e "s/(LIBJXL_VERSION: )[0-9\\.]+/\\1 ${major}.${minor}.${patch}/" \
+ -e "s/(LIBJXL_ABI_VERSION: )[0-9\\.]+/\\1 ${major}.${minor}/" \
+ -i .github/workflows/conformance.yml
# Update lib.gni
- tools/build_cleaner.py --update
+ tools/scripts/build_cleaner.py --update
# Mark the previous version as "unstable".
DEBCHANGE_RELEASE_HEURISTIC=log dch -M --distribution unstable --release ''
@@ -1418,11 +1388,11 @@ cmd_authors() {
merge_request_commits
local emails
local names
- readarray -t emails < <(git log --format='%ae' "${MR_HEAD_SHA}...${MR_ANCESTOR_SHA}")
- readarray -t names < <(git log --format='%an' "${MR_HEAD_SHA}...${MR_ANCESTOR_SHA}")
+ readarray -t emails < <(git log --format='%ae' "${MR_ANCESTOR_SHA}..${MR_HEAD_SHA}")
+ readarray -t names < <(git log --format='%an' "${MR_ANCESTOR_SHA}..${MR_HEAD_SHA}")
for i in "${!names[@]}"; do
echo "Checking name '${names[$i]}' with email '${emails[$i]}' ..."
- "${MYDIR}"/tools/check_author.py "${emails[$i]}" "${names[$i]}"
+ "${MYDIR}"/tools/scripts/check_author.py "${emails[$i]}" "${names[$i]}"
done
}
@@ -1450,7 +1420,7 @@ Where cmd is one of:
benchmark Run the benchmark over the default corpus.
fast_benchmark Run the benchmark over the small corpus.
- coverage Buils and run tests with coverage support. Runs coverage_report as
+ coverage Build and run tests with coverage support. Runs coverage_report as
well.
coverage_report Generate HTML, XML and text coverage report after a coverage
run.
@@ -1483,6 +1453,7 @@ You can pass some optional environment variables as well:
- FUZZER_MAX_TIME: "fuzz" command fuzzer running timeout in seconds.
- LINT_OUTPUT: Path to the output patch from the "lint" command.
- SKIP_CPUSET=1: Skip modifying the cpuset in the arm_benchmark.
+ - SKIP_BUILD=1: Skip the build stage, cmake configure only.
- SKIP_TEST=1: Skip the test stage.
- STORE_IMAGES=0: Makes the benchmark discard the computed images.
- TEST_STACK_LIMIT: Stack size limit (ulimit -s) during tests, in KiB.