Add CI to build docs
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..369ae25
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,41 @@
+qrc_*cxx
+*.orig
+*.pyc
+*.diff
+diff
+*.save
+save
+*.old
+*.gmo
+*.qm
+core
+core.*
+*.bak
+*~
+*.build*
+*.moc.*
+*.moc
+ui_*
+CMakeCache.txt
+tags
+.*.swp
+activity.png
+*.out
+*.php*
+*.log
+*.orig
+*.rej
+log
+patch
+*.patch
+a
+a.*
+lapack/testing
+lapack/reference
+.*project
+.settings
+Makefile
+!ci/build.gitlab-ci.yml
+!scripts/buildtests.in
+!Eigen/Core
+!Eigen/src/Core
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..e8962d0
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+# This file is part of Eigen, a lightweight C++ template library
+# for linear algebra.
+#
+# Copyright (C) 2023, The Eigen Authors
+#
+# This Source Code Form is subject to the terms of the Mozilla
+# Public License v. 2.0. If a copy of the MPL was not distributed
+# with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+stages:
+  - build
+  - deploy
+
+variables:
+  # CMake build directory.
+  EIGEN_CI_BUILDDIR: .build
+  # Specify the CMake build target.
+  EIGEN_CI_BUILD_TARGET: ""
+  # If a test regex is specified, that will be selected.
+  # Otherwise, we will try a label if specified.
+  EIGEN_CI_CTEST_REGEX: ""
+  EIGEN_CI_CTEST_LABEL: ""
+  EIGEN_CI_CTEST_ARGS: ""
+
+include:
+  - "/ci/common.gitlab-ci.yml"
+  - "/ci/build.linux.gitlab-ci.yml"
+  - "/ci/deploy.gitlab-ci.yml"
diff --git a/ci/build.linux.gitlab-ci.yml b/ci/build.linux.gitlab-ci.yml
new file mode 100644
index 0000000..a99c4e3
--- /dev/null
+++ b/ci/build.linux.gitlab-ci.yml
@@ -0,0 +1,30 @@
+# Base configuration for linux cross-compilation.
+.build:linux:cross:
+  extends: .common:linux:cross
+  stage: build
+  variables:
+    EIGEN_CI_BUILD_TARGET: buildtests
+  script:
+    - . ci/scripts/build.linux.script.sh
+  tags:
+    - saas-linux-2xlarge-amd64
+  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/"
+  cache:
+    key: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG-BUILD"
+    paths:
+      - ${EIGEN_CI_BUILDDIR}/
+
+build:linux:docs:
+  extends: .build:linux:cross
+  variables:
+    EIGEN_CI_TARGET_ARCH: any
+    EIGEN_CI_BUILD_TARGET: doc
+    EIGEN_CI_INSTALL: ca-certificates clang flex python3 bison graphviz
+    EIGEN_CI_C_COMPILER: clang
+    EIGEN_CI_CXX_COMPILER: clang++
+    EIGEN_CI_BEFORE_SCRIPT: ". ci/scripts/build_and_install_doxygen.sh Release_1_13_2"
+  rules:
+    - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
diff --git a/ci/common.gitlab-ci.yml b/ci/common.gitlab-ci.yml
new file mode 100644
index 0000000..24da58b
--- /dev/null
+++ b/ci/common.gitlab-ci.yml
@@ -0,0 +1,24 @@
+# Base configuration for linux builds and tests.
+.common:linux:cross:
+  image: ubuntu:20.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
+  artifacts:
+    when: always
+    name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG"
+    paths:
+      - ${EIGEN_CI_BUILDDIR}/
+    expire_in: 5 days
diff --git a/ci/deploy.gitlab-ci.yml b/ci/deploy.gitlab-ci.yml
new file mode 100644
index 0000000..b340df7
--- /dev/null
+++ b/ci/deploy.gitlab-ci.yml
@@ -0,0 +1,25 @@
+# Upload docs if pipeline succeeded.
+deploy:docs:
+  stage: deploy
+  image: busybox
+  dependencies: [ build:linux:docs ]
+  variables:
+    PAGES_PREFIX: docs-nightly
+  script:
+    - echo "Deploying site to $CI_PAGES_URL"
+    - mv ${EIGEN_CI_BUILDDIR}/doc/html public
+  pages:
+    path_prefix: $PAGES_PREFIX
+    expire_in: never
+  artifacts:
+    name: "$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG"
+    paths:
+      - public
+  tags:
+    - saas-linux-small-amd64
+  rules:
+    - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_PROJECT_NAMESPACE == "libeigen"
+    - if: $CI_PIPELINE_SOURCE == "web" && $CI_PROJECT_NAMESPACE == "libeigen"
+    - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_NAMESPACE == "libeigen"
+      variables:
+        PAGES_PREFIX: docs-$CI_COMMIT_REF_NAME
diff --git a/ci/scripts/build.linux.script.sh b/ci/scripts/build.linux.script.sh
new file mode 100755
index 0000000..d00edbf
--- /dev/null
+++ b/ci/scripts/build.linux.script.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+set -x
+
+# Create and enter build directory.
+rootdir=`pwd`
+mkdir -p ${EIGEN_CI_BUILDDIR}
+cd ${EIGEN_CI_BUILDDIR}
+
+# Configure build.
+cmake -G Ninja                                                   \
+  -DCMAKE_CXX_COMPILER=${EIGEN_CI_CXX_COMPILER}                  \
+  -DCMAKE_C_COMPILER=${EIGEN_CI_C_COMPILER}                      \
+  -DCMAKE_CXX_COMPILER_TARGET=${EIGEN_CI_CXX_COMPILER_TARGET}    \
+  ${EIGEN_CI_ADDITIONAL_ARGS} ${rootdir}
+
+target=""
+if [[ ${EIGEN_CI_BUILD_TARGET} ]]; then
+  target="--target ${EIGEN_CI_BUILD_TARGET}"
+fi
+
+# Builds (particularly gcc) sometimes get killed, potentially when running
+# out of resources.  In that case, keep trying to build the remaining
+# targets (k0), then try to build again with a single thread (j1) to minimize
+# resource use.
+cmake --build . ${target} -- -k0 || cmake --build . ${target} -- -k0 -j1
+
+# Return to root directory.
+cd ${rootdir}
+
+set +x
diff --git a/ci/scripts/build_and_install_doxygen.sh b/ci/scripts/build_and_install_doxygen.sh
new file mode 100644
index 0000000..9cb47b7
--- /dev/null
+++ b/ci/scripts/build_and_install_doxygen.sh
@@ -0,0 +1,6 @@
+git clone --depth 1 --branch $1 https://github.com/doxygen/doxygen.git
+cmake -B doxygen/.build -G Ninja                                 \
+  -DCMAKE_CXX_COMPILER=${EIGEN_CI_CXX_COMPILER}                  \
+  -DCMAKE_C_COMPILER=${EIGEN_CI_C_COMPILER}                      \
+  doxygen
+cmake --build doxygen/.build -t install
diff --git a/ci/scripts/common.linux.before_script.sh b/ci/scripts/common.linux.before_script.sh
new file mode 100755
index 0000000..622e62f
--- /dev/null
+++ b/ci/scripts/common.linux.before_script.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -x
+
+echo "Running ${CI_JOB_NAME}"
+
+# Get architecture and display CI configuration.
+export ARCH=`uname -m`
+export NPROC=`nproc`
+echo "arch=$ARCH, target=${EIGEN_CI_TARGET_ARCH}"
+echo "Processors: ${NPROC}"
+echo "CI Variables:"
+export | grep EIGEN
+
+# Set noninteractive, otherwise tzdata may be installed and prompt for a
+# geographical region.
+export DEBIAN_FRONTEND=noninteractive
+apt-get update -y > /dev/null
+apt-get install -y --no-install-recommends ninja-build cmake git > /dev/null
+
+# Install required dependencies and set up compilers.
+# These are required even for testing to ensure that dynamic runtime libraries
+# are available.
+if [[ "$ARCH" == "${EIGEN_CI_TARGET_ARCH}" || "${EIGEN_CI_TARGET_ARCH}" == "any" ]]; then
+  apt-get install -y --no-install-recommends ${EIGEN_CI_INSTALL} > /dev/null;
+  export EIGEN_CI_CXX_IMPLICIT_INCLUDE_DIRECTORIES="";
+  export EIGEN_CI_CXX_COMPILER_TARGET="";
+else
+  apt-get install -y --no-install-recommends ${EIGEN_CI_CROSS_INSTALL} > /dev/null;
+  export EIGEN_CI_C_COMPILER=${EIGEN_CI_CROSS_C_COMPILER};
+  export EIGEN_CI_CXX_COMPILER=${EIGEN_CI_CROSS_CXX_COMPILER};
+  export EIGEN_CI_CXX_COMPILER_TARGET=${EIGEN_CI_CROSS_TARGET_TRIPLE};
+  # Tell the compiler where to find headers and libraries if using clang.
+  # NOTE: this breaks GCC since it messes with include path order
+  #       (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129)
+  if [[ "${EIGEN_CI_CROSS_CXX_COMPILER}" == *"clang"* ]]; then
+    export CPLUS_INCLUDE_PATH="/usr/${EIGEN_CI_CROSS_TARGET_TRIPLE}/include";
+    export LIBRARY_PATH="/usr/${EIGEN_CI_CROSS_TARGET_TRIPLE}/lib64";
+  fi
+fi
+
+echo "Compilers: ${EIGEN_CI_C_COMPILER} ${EIGEN_CI_CXX_COMPILER}"
+
+if [ -n "$EIGEN_CI_BEFORE_SCRIPT" ]; then eval "$EIGEN_CI_BEFORE_SCRIPT"; fi
+
+set +x