blob: 05a2039e96eb954c24044e16dea490587f36b66f [file]
# Base configuration for linux builds and tests.
# SPDX-FileCopyrightText: The Eigen Authors
# SPDX-License-Identifier: MPL-2.0
# Shared rule sets, referenced from concrete jobs via
# rules: !reference [.rules:<name>, rules]
# Centralizing them keeps the "what triggers this job?" decision in one place.
.rules:libeigen:smoketest:
# Every merge request, except one that opted into a wider tier; see
# .agents/ci.md. The namespace guard is load-bearing: neither wider tier has
# any job outside libeigen, so a fork keeps its smoke coverage whatever it is
# labelled. The set below restates these two entries behind a namespace
# guard rather than nesting a !reference into them; keep the two in step.
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/(affected|all)-tests/"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
.rules:libeigen:smoketest:upstream-runner:
# The smoke tier, for jobs pinned to a runner only this project has: the
# riscv64 tests inherit `tags: [riscv]`, a single self-hosted machine. A fork
# that schedules them leaves them pending until the stuck-job timeout drops
# them: measured at 5563 s, 6475 s and 6786 s queued across two fork merge
# request pipelines, so its pipeline is neither green nor finished for the
# better part of two hours. allow_failure hides the eventual failure but not
# the wait. A tag the plan does not offer at all fails fast instead
# (no_matching_runner, zero queue), which is why only this one needs guarding.
# Past the first entry the namespace is known, so the rest is
# .rules:libeigen:smoketest.
rules:
- if: $CI_PROJECT_NAMESPACE != "libeigen"
when: never
- if: $CI_MERGE_REQUEST_LABELS =~ "/(affected|all)-tests/"
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
# Keeps a GPU-scoped schedule (EIGEN_CI_SCHEDULE_SCOPE=gpu, see .gitlab-ci.yml)
# from running anything but the GPU jobs. Every rule set that fires on
# "schedule" except .rules:libeigen:gpu opens with it: the job-level lists in
# the build, test and deploy files splice it in as their first entry with
# `- !reference [.rules:libeigen:gpu-schedule-guard, rules]`, while the three
# .rules:libeigen:* sets below restate the two lines, since a !reference inside
# a set that is itself !reference'd would nest.
.rules:libeigen:gpu-schedule-guard:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $EIGEN_CI_SCHEDULE_SCOPE == "gpu"
when: never
.rules:libeigen:all-tests:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $EIGEN_CI_SCHEDULE_SCOPE == "gpu"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
.rules:libeigen:gpu:
# Spelled out (rather than referencing .rules:libeigen:all-tests) to avoid
# a nested !reference, which GitLab CI has had inconsistent support for.
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/all-tests/"
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/gpu-tests/"
# No affected-tier configuration enables CUDA, HIP or SYCL, so the GPU test
# targets exist in none of them: a diff confined to these paths selects
# targets every affected build reports as unconfigured and a -R regex that
# matches nothing, and the tier goes green having compiled and run nothing.
# These jobs close that gap the way ppc64le closes it for AltiVec. They
# ignore the selection and build buildtests_gpu, which covers every GPU
# test rather than the affected subset.
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/GPU/**/*
# The two scalar headers carry their own device code paths, the .inc
# files are the CUDA/HIP alias layer, EigenTesting.cmake holds the
# nvcc/hipcc dispatch, and the harness headers decide what a GPU test
# can express; a change to any of them is invisible to a host build.
- Eigen/src/Core/arch/Default/Half.h
- Eigen/src/Core/arch/Default/BFloat16.h
- Eigen/src/Core/util/GpuHipCuda*.inc
- cmake/EigenTesting.cmake
- test/*.cu
- test/gpu_common.h
- test/gpu_test_helper.h
- test/main.h
- unsupported/Eigen/src/Tensor/*Gpu*.h
- unsupported/test/*.cu
- unsupported/test/GPU/**/*
# `gpu-tests` is the platform label for GPU and already stands alone above,
# so it composes with `affected-tests` without another entry. It is also
# why `all-platforms` covers no GPU job, and none of the compile-only sets
# below: that label means "every platform that runs the affected selection",
# and these jobs ignore the selection to build the whole GPU suite.
.rules:libeigen:affected-tests:
# Opt-in middle tier between the fixed smoke list and the full `all-tests`
# matrix: every test the diff can reach, on a small set of platforms.
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
# The rest of the affected tier is gated on the platform a job targets, by the
# diff or by a label. Two entries per set rather than one, because GitLab ANDs
# `if:` with `changes:` within an entry and this has to be an OR. A build job
# and its paired test job share a set: a test job whose build did not run has
# nothing to execute. See .agents/ci.md for the platform table.
#
# The `*-tests` labels are deliberately unscoped. GitLab makes scoped labels
# (`backend::NEON`) mutually exclusive, so a scoped axis could never express
# `neon-tests` plus `altivec-tests` -- the union is the point.
.rules:libeigen:affected-tests:sse:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/SSE/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|sse-tests/"
# A wider x86 configuration compiles the narrower backends' headers, so SSE fans
# out to all three x86 sets. Each set still names its own label, so no set
# depends on another's pattern matching a substring of it.
.rules:libeigen:affected-tests:avx:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/SSE/**/*
- Eigen/src/Core/arch/AVX/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|sse-tests|avx-tests/"
.rules:libeigen:affected-tests:avx512:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/SSE/**/*
- Eigen/src/Core/arch/AVX/**/*
- Eigen/src/Core/arch/AVX512/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|sse-tests|avx-tests|avx512-tests/"
# The AVX512-FP16 headers are excluded unless -mavx512fp16 is active, so the
# AVX512DQ build does not parse them. No `all-platforms`: these jobs and the
# SME one below compile the whole suite rather than the affected selection, and
# have no paired test job.
.rules:libeigen:affected-tests:avx512fp16:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/AVX512/*FP16*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/avx512-tests/"
.rules:libeigen:affected-tests:neon:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/NEON/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|neon-tests/"
.rules:libeigen:affected-tests:altivec:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/AltiVec/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|altivec-tests/"
.rules:libeigen:affected-tests:lsx:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/LSX/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|lsx-tests/"
.rules:libeigen:affected-tests:rvv10:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/RVV10/**/*
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|rvv-tests/"
# SME builds take the NEON headers, so an SVE-only change must trigger the SVE
# jobs, not these: keep the two backends on separate rules.
.rules:libeigen:affected-tests:sme:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/SME/**/*
# Backend selection, and the SME-specific product thresholds, live
# outside arch/ but decide whether either backend is used at all.
- Eigen/src/Core/util/ConfigureVectorization.h
- Eigen/src/Core/GeneralProduct.h
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/sme-tests/"
.rules:libeigen:affected-tests:sve:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/"
changes:
- Eigen/src/Core/arch/SVE/**/*
# As for SME: the backend is only reachable through this header.
- Eigen/src/Core/util/ConfigureVectorization.h
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|sve-tests/"
# No `changes:` entry: what MSVC catches is whole-library (instantiation limits,
# `EIGEN_STRONG_INLINE`, optimizer heap exhaustion), not confined to any subtree
# a diff could name, so there is nothing to key an automatic trigger on.
.rules:libeigen:affected-tests:windows:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_MERGE_REQUEST_LABELS =~ "/affected-tests/" && $CI_MERGE_REQUEST_LABELS =~ "/all-platforms|windows-tests/"
# Consumers of the select:tests artifacts, on either platform. Kept here rather
# than beside the jobs so the artifact contract is spelled once; ci/select.gitlab-ci.yml
# produces these paths.
.affected:build:
needs: [ select:tests ]
variables:
EIGEN_CI_BUILD_TARGET_FILE: affected/targets.txt
.affected:test:
variables:
EIGEN_CI_CTEST_REGEX_FILE: affected/ctest_regex.txt
# The smoke tier keeps the shared ccache pool that every other tier scopes per
# merge request (EIGEN_CI_CCACHE_SCOPE, set in the workflow rules; a job
# variable outranks one from a workflow rule, which is what makes this opt-out
# work). These jobs run on merge request events only, so scoping them would
# leave `<slug>-ccache` with no writer at all: the pool a first build falls
# back to would freeze at whatever wrote it last and rot from there. Sharing
# it costs little here -- a smoke build is minutes, and its objects are the
# ones most likely to match another merge request's.
.smoketest:build:
variables:
EIGEN_CI_CCACHE_SCOPE: ""
.rules:libeigen:scheduled-or-web:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $EIGEN_CI_SCHEDULE_SCOPE == "gpu"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
.rules:libeigen:scheduled-or-web:default-branch:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule" && $EIGEN_CI_SCHEDULE_SCOPE == "gpu"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
.common:linux:cross:
image: ubuntu:24.04
variables:
EIGEN_CI_TARGET_ARCH: ""
EIGEN_CI_ADDITIONAL_ARGS: ""
# If host matches target, use the following:
EIGEN_CI_C_COMPILER: ""
EIGEN_CI_CXX_COMPILER: ""
EIGEN_CI_INSTALL: "${EIGEN_CI_C_COMPILER} ${EIGEN_CI_CXX_COMPILER}"
# If host does not match the target, use the following:
EIGEN_CI_CROSS_TARGET_TRIPLE: ""
EIGEN_CI_CROSS_C_COMPILER: ${EIGEN_CI_C_COMPILER}
EIGEN_CI_CROSS_CXX_COMPILER: ${EIGEN_CI_CXX_COMPILER}
EIGEN_CI_CROSS_INSTALL: "${EIGEN_CI_CROSS_C_COMPILER} ${EIGEN_CI_CROSS_CXX_COMPILER}"
before_script:
# Call script in current shell - it sets up some environment variables.
- . ci/scripts/common.linux.before_script.sh
# Base configuration for Windows builds and tests.
.common:windows:
variables:
EIGEN_CI_MSVC_ARCH: x64
EIGEN_CI_MSVC_VER: "14.29"
EIGEN_CI_ADDITIONAL_ARGS: ""
EIGEN_CI_BEFORE_SCRIPT: ""
before_script:
- . ci/scripts/common.windows.before_script.ps1
######## Artifacts #############################################################
# Kept out of the .common:* bases so that publishing is a choice a job makes
# rather than something it inherits.
.artifacts:linux:builddir:
artifacts:
when: always
name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG"
paths:
- ${EIGEN_CI_BUILDDIR}/
exclude:
- ${EIGEN_CI_BUILDDIR}/**/*.o
- ${EIGEN_CI_BUILDDIR}/**/*.a
- ${EIGEN_CI_BUILDDIR}/**/.ninja_log
- ${EIGEN_CI_BUILDDIR}/**/.ninja_deps
- ${EIGEN_CI_BUILDDIR}/**/CMakeFiles/*.dir/**
- ${EIGEN_CI_BUILDDIR}/.cmake/**
- ${EIGEN_CI_BUILDDIR}/**/Testing/Temporary/**
expire_in: 2 days
.artifacts:windows:builddir:
artifacts:
when: always
name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_NAME"
paths:
- ${EIGEN_CI_BUILDDIR}/
exclude:
- ${EIGEN_CI_BUILDDIR}/**/*.obj
- ${EIGEN_CI_BUILDDIR}/**/*.lib
- ${EIGEN_CI_BUILDDIR}/**/.ninja_log
- ${EIGEN_CI_BUILDDIR}/**/.ninja_deps
- ${EIGEN_CI_BUILDDIR}/**/CMakeFiles/*.dir/**
- ${EIGEN_CI_BUILDDIR}/.cmake/**
- ${EIGEN_CI_BUILDDIR}/**/Testing/Temporary/**
expire_in: 2 days
# A test job links nothing, and nothing takes its artifact as needs:, so
# re-publishing the build directory it downloaded is pure duplication.
# Testing/ is dropped too: Test.xml embeds every test's stdout under
# --no-compress-output, and the <failure> bodies below carry what matters.
# A week, not two days, because the merge request widget reads this. Listed
# under both keys on purpose: reports: is what the widget parses, paths: is
# what the job's artifact panel offers for download.
.artifacts:test:results:
artifacts:
when: always
name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG"
paths:
- ${EIGEN_CI_BUILDDIR}/JUnitTestResults_*.xml
reports:
junit: ${EIGEN_CI_BUILDDIR}/JUnitTestResults_*.xml
expire_in: 1 week