Skip to content

Commit

Permalink
Rework build script; add support for macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
rgov committed Feb 17, 2019
1 parent 1cc10ea commit d52c1e3
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 66 deletions.
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
workspace/
workspace-linux/
workspace-mac/
ws/
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
workspace/
workspace-linux/
workspace-mac/
ws/
install-build-deps.sh
courgette.log
39 changes: 10 additions & 29 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,46 +1,27 @@
# Dockerfile for a container capable of building the Courgette target of
# Chromium.
#
# https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md
# Chromium for Linux.

FROM ubuntu:trusty

WORKDIR /root
VOLUME /root/out

# Install bootstrap dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
python

# Install depot_tools
RUN git clone --depth 1 \
https://chromium.googlesource.com/chromium/tools/depot_tools.git
ENV PATH=$PATH:/root/depot_tools

# Get the code
WORKDIR chromium
RUN fetch --nohooks --no-history chromium

# Install additional build dependencies
WORKDIR src
RUN ./build/install-build-deps.sh \
# Install the build dependencies
COPY install-build-deps.sh .
RUN ./install-build-deps.sh \
--no-arm --no-chromeos-fonts --no-nacl \
--no-prompt

# Run the hooks
RUN gclient runhooks

# Configure the build
RUN mkdir -p out/Default \
&& (echo "enable_nacl = false"; echo "symbol_level = 0") \
>> out/Default/args.gn \
&& gn gen out/Default

# Copy in the build script
WORKDIR /root
# Copy in the build script and packaging materials
COPY build.sh .
COPY packaging courgette
COPY deb-package ./deb-package
RUN chmod +x build.sh
CMD ["/root/build.sh"]

# Set the container command to run the build script
VOLUME /ws
CMD ["/root/build.sh", "/ws", "no-update"]
64 changes: 52 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,62 @@ Courgette lives inside the Chromium repository and must be compiled using the
complex Chromium build system. It is not offered as an official standalone
installable package.

This repository describes a Docker container that builds Courgette for Linux
x86_64.
This repository contains a build script that automates the process of compiling
Courgette.

Prebuilt packages may be found on the [release page][releases], but these are
not kept up to date.

[releases]: https://github.com/rgov/courgette-build/releases


## Debian and macOS

Please follow the [platform-specific guides][guides] on building Chromium to
install the initial dependencies such as `git`.

[guides]: https://www.chromium.org/developers/how-tos/get-the-code

The build script handles the rest:

./build.sh ./workspace

This produces a binary at `./workspace/chromium/src/out/Default/courgette`.

It also produces a Debian package at
`./workspace/courgette-linux_{version}-{date}+{revision}_{arch}.deb` for Linux
builds, or a similarly-named zip archive for macOS builds.

Use `ldd` (Linux) or `otool -L` (macOS) to view which shared libraries that
Courgette links against, such as `libbase` and `libc++`.


## Debian, using a Docker container

You can construct a Docker container with all of the build dependencies ready
to go:

./build.sh ./workspace fetch-only
cp ./workspace/chromium/src/build/install-build-deps.sh .
docker build -t courgette-build .
docker run -v "$(pwd):/root/out" courgette-build

Each time the `docker run` command is executed, the latest Chromium sources are
fetched and built, and `courgette-{version}.deb` is created in the current
directory.
To execute a build inside the container, run:

The Docker container image is very large, so when no longer needed, it can be
deleted with:
docker run -v "$(pwd)/workspace:/ws" courgette-build

docker rmi courgette-build
### macOS host notes

Prebuilt packages may be found on the [release page][releases], but these are
not kept up to date.
- Docker makes a copy of the entire directory while building a container
image. The `.dockerignore` file is configured to exclude `./workspace`, as
a checkout of Chromium sources can easily exceed 10GB. If you use another
workspace name, it is strongly advised to place it outside of this
directory.

[releases]: https://github.com/rgov/courgette-build/releases
- Using the same workspace for macOS and Docker-based Debian builds is
currently not possible. It *may* be possible to clone a workspace created
with the `fetch-only` option before any further steps have been applied:

```
./build.sh ./workspace fetch-only
cp -ca workspace workspace-linux
```
176 changes: 153 additions & 23 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,31 +1,161 @@
#!/bin/sh -e
#!/bin/bash -e

# This is the second half of the process of building Courgette; the Dockerfile
# sets up the environment and configures the build. Now we need to actually
# perform the build and package the results.
# This script builds the Courgette target from Chromium. It works on macOS and
# Linux. Please see the accompanying README.md file.
#
# https://chromium.googlesource.com/chromium/src/+/master/docs/linux_build_instructions.md
# https://www.chromium.org/developers/how-tos/get-the-code

cd /root/chromium/src
GITHASH=$(git rev-parse --short HEAD)
function status {
printf '\E[33m'
echo "$@"
printf '\E[0m'
}

if [ "$#" -eq 0 ]; then
echo "Usage: $0 workspace-dir [fetch-only|no-update]" >&2
exit 1
fi

# Enter the workspace
mkdir -p "$1"
cd "$1"

# Install depot_tools
if [ ! -d depot_tools ]; then
status "[*] Cloning depot_tools"
git clone --depth 1 \
https://chromium.googlesource.com/chromium/tools/depot_tools.git
elif [ "$2" != "no-update" ]; then
status "[*] Updating depot_tools"
pushd depot_tools
git pull
popd
fi

export PATH="$(pwd)/depot_tools:${PATH}"

# Is this our first build?
if [ ! -f .first-build-finished ]; then
FIRST_BUILD=1
else
FIRST_BUILD=0
fi

# Get the code
if [ ! -d chromium/src ]; then
status "[*] Fetching Chromium sources"
mkdir -p chromium
pushd chromium
git config --global core.precomposeUnicode true
fetch --nohooks --no-history chromium
popd
elif [ "$2" != "no-update" ]; then
status "[*] Updating Chromium sources"
pushd chromium/src
git rebase-update
popd
fi

# Update the checkout and re-sync dependencies and hooks
git rebase-update
gclient sync
# Stop here if we just wanted to fetch the code
if [ "$2" = "fetch-only" ]; then
exit 0
fi

# Install additional build dependencies
if [ $FIRST_BUILD -eq 1 ] && [ "$(uname -s)" = "Linux" ]; then
status "[*] Installing build dependencies"
pushd chromium/src
./build/install-build-deps.sh \
--no-arm --no-chromeos-fonts --no-nacl \
--no-prompt
popd
fi

# Run the hooks
pushd chromium/src
if [ $FIRST_BUILD -eq 1 ]; then
status "[*] Running hooks"
gclient runhooks
elif [ "$2" != "no-update" ]; then
status "[*] Running hooks"
gclient sync
fi
popd

# Configure the build
if [ ! -d chromium/src/out/Default ]; then
status "[*] Configuring"
pushd chromium/src
mkdir -p out/Default
(echo "enable_nacl = false"; echo "symbol_level = 0") > out/Default/args.gn
gn gen out/Default
popd
fi

# Build Courgette
status "[*] Building Courgette"
pushd chromium/src
autoninja -C out/Default courgette
popd
touch .first-build-finished

# Create the version string
pushd chromium/src
DATE=$(date +"%Y%m%d")
GITHASH=$(git rev-parse --short HEAD)
VERSION="1.0.0-${DATE}+${GITHASH}"
popd

# Build the Debian package on Linux
if [ "$(uname -s)" = "Linux" ]; then
status "[*] Creating Debian package"

# Copy the packaging template into the workspace
rm -rf courgette
cp -r "$(dirname "$0")"/deb-package courgette

# Copy the Courgette binary into the package
mkdir -p courgette/usr/bin
cp chromium/src/out/Default/courgette courgette/usr/bin

# Copy all built libraries it depends on in as well
mkdir -p courgette/usr/lib
LIBDEPS=$(ldd chromium/src/out/Default/courgette \
| grep 'chromium' \
| awk '{ print $3 }')
cp $LIBDEPS courgette/usr/lib

# Patch up the control file
ARCH=$(dpkg --print-architecture)
sed -i \
-e "s/@VERSION@/$VERSION/g" \
-e "s/@ARCH@/$ARCH/g" \
courgette/DEBIAN/control

# Build the package
dpkg-deb --build courgette
mv courgette.deb "courgette-linux_${VERSION}_${ARCH}.deb"
rm -rf courgette
fi

# Build the Debian package
mkdir -p /root/courgette/usr/bin /root/courgette/usr/lib
cp out/Default/courgette /root/courgette/usr/bin
cp $(ldd out/Default/courgette | grep '/root' | awk '{ print $3 }') \
/root/courgette/usr/lib
sed -i "s/@GITHASH@/$GITHASH/g" \
/root/courgette/DEBIAN/control
dpkg-deb --build /root/courgette
mv /root/courgette.deb /root/out/courgette-${GITHASH}.deb

# Install the Debian package and test it
dpkg -i /root/out/courgette-*.deb
courgette --help 2>&1 | grep -q 'genbsdiff'
# Build a zip archive on macOS
if [ "$(uname -s)" = "Darwin" ]; then
status "[*] Creating archive"

# Create the archive directory
rm -rf courgette
mkdir courgette

# Copy the courgette binary into the directory
cp chromium/src/out/Default/courgette courgette
LIBDEPS=$(otool -L chromium/src/out/Default/courgette \
| grep '@rpath' \
| awk '{ print $1 }' \
| sed 's,@rpath/,chromium/src/out/Default/,g')
cp $LIBDEPS courgette

# Make the zip archive
ARCH=$(uname -m)
zip -r "courgette-mac_${VERSION}_${ARCH}.zip" courgette
rm -rf courgette
fi
4 changes: 2 additions & 2 deletions packaging/DEBIAN/control → deb-package/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: courgette
Version: 1.0.0-@GITHASH@
Architecture: amd64
Version: @VERSION@
Architecture: @ARCH@
Maintainer: "Ryan Govostes" <[email protected]>
Description: Courgette binary patching tool

0 comments on commit d52c1e3

Please sign in to comment.