Skip to content

Instantly share code, notes, and snippets.

@jpasquier
Created September 30, 2024 20:43
Show Gist options
  • Save jpasquier/f0bdfbc8d784759672e04c7a00e8f2b6 to your computer and use it in GitHub Desktop.
Save jpasquier/f0bdfbc8d784759672e04c7a00e8f2b6 to your computer and use it in GitHub Desktop.
#!/bin/bash
# ─────────────────────────────────────────────────────────────────────────────
#
# TeXpresso Build Script
# ======================
#
# Overview
# --------
#
# The **TeXpresso Build Script** is a Bash script designed to automate the
# building of the [TeXpresso](https://github.com/let-def/texpresso) project
# using Docker. This script sets up a clean build environment, compiles the
# necessary binaries, and retrieves them to your local machine. By leveraging
# Docker, the script ensures consistency across different systems and
# simplifies the build process.
#
# Features
# --------
#
# - **Automated Docker Environment Setup**: Configures a Docker container with
# all required dependencies for building TeXpresso.
# - **Multi-Stage Docker Build**: Utilizes Docker's multi-stage build to
# optimize the build process and reduce final image size.
# - **Binary Extraction**: Automatically retrieves the compiled binaries
# (`texpresso` and `texpresso-tonic`) from the Docker container to your
# current directory.
# - **Cleanup**: Removes temporary build directories and prunes unused Docker
# resources to keep your system clean.
# - **User-Friendly**: Ensures proper permissions are set for the extracted
# binaries, making them ready for immediate use.
#
# Prerequisites
# -------------
#
# Before running the script, ensure that your system meets the following
# requirements:
#
# - **Operating System**: Linux-based system.
# - **Root Privileges**: The script must be run with root privileges.
# - **Docker Installed**: Docker must be installed and running on your system.
#
# Usage
# -----
#
# Run the script with root privileges:
#
# ```
# bash sudo ./build_texpresso.sh
# ```
#
# What the Script Does
# --------------------
#
# 1. **Privilege Check**: Verifies that the script is executed as the root
# user.
# 2. **Docker Status Check**: Confirms that Docker is installed and the
# Docker daemon is running.
# 3. **Temporary Build Directory**: Creates a temporary directory for the build
# process, ensuring that temporary files do not clutter your system.
# 4. **Dockerfile Creation**: Generates a Dockerfile with two stages:
# - **Builder Stage**:
# - Based on Debian 12.
# - Installs necessary build dependencies.
# - Sets up Rust using `rustup`.
# - Clones the TeXpresso repository and its submodules.
# - Compiles the TeXpresso project.
# - **Extractor Stage**:
# - Also based on Debian 12.
# - Copies the compiled binaries from the builder stage.
# 5. **Docker Image Build**: Builds the Docker image named `texpresso-debian`
# using the generated Dockerfile.
# 6. **Docker Container Run**: Runs a container from the `texpresso-debian`
# image.
# 7. **Binary Extraction**: Copies the `texpresso` and `texpresso-tonic`
# binaries from the Docker container to the current working directory.
# 8. **Cleanup**:
# - Stops the Docker container.
# - Removes temporary build directories.
# - Prunes unused Docker images and resources.
# 9. **Permission Adjustment**: Changes the ownership of the extracted binaries
# to the original non-root user.
#
# After Running the Script
# ------------------------
#
# Upon successful execution, you will find the `texpresso` and
# `texpresso-tonic` binaries in your current directory with appropriate
# permissions.
#
# License
# -------
#
# This script is licensed under the WTFPL License
#
# ─────────────────────────────────────────────────────────────────────────────
set -eu
# This scipt uses docker and must be run as root
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit 1
fi
# Check that docker is running
if ! docker info > /dev/null 2>&1; then
echo "This script uses docker, and it isn't running - please start docker and try again!"
exit 1
fi
# Store current directory in a variable
CURRENT_DIR=$(pwd)
# Create a temporary build directory
BUILD_DIR=$(mktemp -d "${TMPDIR:-/tmp}/build-texpresso.XXXXXXXX")
trap 'rm -rf "$BUILD_DIR"' EXIT
# Create the Dockerfile
cat > "$BUILD_DIR/Dockerfile" << 'EOL'
# Stage 1: Build Stage
FROM debian:12 AS builder
# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive
ENV USER=texpresso
ENV PATH="/home/${USER}/.cargo/bin:${PATH}"
# Update and install necessary dependencies
RUN apt-get update && apt-get install -y \
build-essential \
libsdl2-dev \
libmupdf-dev \
libfreetype-dev \
libjpeg-dev \
libjbig2dec0-dev \
libharfbuzz-dev \
libopenjp2-7-dev \
libgumbo-dev \
libmujs-dev \
libssl-dev \
libfontconfig-dev \
curl \
git \
bash \
&& rm -rf /var/lib/apt/lists/*
# Create a new user for TeXpresso and create the directory with proper permissions
RUN useradd -ms /bin/bash $USER && mkdir /texpresso-bin && chown $USER:$USER /texpresso-bin
# Switch to the newly created user
USER $USER
WORKDIR /home/$USER
# Install rustup and set up the latest Rust version as the texpresso user
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y
# Clone the TeXpresso repository
RUN git clone --recurse-submodules https://github.com/let-def/texpresso.git
WORKDIR /home/$USER/texpresso
# Update Rust dependencies in the tectonic submodule to avoid version conflicts
RUN /bin/bash -c "source $HOME/.cargo/env && cd tectonic && cargo update"
# Build TeXpresso
RUN /bin/bash -c "source $HOME/.cargo/env && make all"
# Stage 2: Extraction Stage
FROM debian:12 AS extractor
# Create a directory to hold the binary
RUN mkdir /texpresso-bin
# Copy the built binary from the builder stage
COPY --from=builder /home/texpresso/texpresso/build/texpresso /texpresso-bin/
COPY --from=builder /home/texpresso/texpresso/build/texpresso-tonic /texpresso-bin/
EOL
# Build the docker image
docker build -t texpresso-debian "$BUILD_DIR"
# Run a docker image from the newly created image
docker run --name texpresso-debian texpresso-debian
# Copy the binary from the docker image to the current directory
docker cp texpresso-debian:/texpresso-bin/texpresso $CURRENT_DIR/
docker cp texpresso-debian:/texpresso-bin/texpresso-tonic $CURRENT_DIR/
# Stop the docker container
docker stop texpresso-debian
# Remove unused docker build images
docker system prune -f
# Change ownership of the binary files
chown $SUDO_USER:$SUDO_USER $CURRENT_DIR/texpresso $CURRENT_DIR/texpresso-tonic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment