Merge "Build system improvements for packaging" from Pekka

"
This patch series attempts to decouple package build and release
infrastructure, which is internal to Scylla (the company). The goal of
this series is to make it easy for humans and machines to build the full
Scylla distribution package artifacts, and make it easy to quickly
verify them.

The improvements to build system are done in the following steps.

1. Make scylla.git a super-module, which has git submodules for
   scylla-jmx and scylla-tools.  A clone of scylla.git is now all that
   is needed to access all source code of all the different components
   that make up a Scylla distribution, which is a preparational step to
   adding "dist" ninja build target. A scripts/sync-submodules.sh helper
   script is included, which allows easy updating of the submodules to the
   latest head of the respective git repositories.

2. Make builds reproducible by moving the remaining relocatable package
   specific build options from reloc/build_reloc.sh to the build system.
   After this step, you can build the exact same binaries from the git
   repository by using the dbuild version from scylla.git.

3. Add a "dist" target to ninja build, which builds all .rpm and .deb
   packages with one command. To build a release, run:

   $ ./tools/toolchain/dbuild ./configure.py --mode release

   $ ./tools/toolchain/dbuild ninja-build dist

   and you will now have .rpm and .deb packages to all the components of
   a Scylla distribution.

4. Add a "dist-check" target to ninja build for verification of .rpm and
   .deb packages in one command. To verify all the built packages, run:

   $  ninja-build dist-check

   Please note that you must run this step on the host, because the
   target uses Docker under the hood to verify packages by installing
   them on different Linux distributions.

   Currently only CentOS 7 verification is supported.

All these improvements are done so that backward compatibility is
retained. That is, any existing release infrastructure or other build
scripts are completely unaffacted.

Future improvements to consider:

- Package repository generation: add a "ninja repo" command to generate
  a .rpm and .deb repositories, which can be uploaded to a web site.
  This makes it possible to build a downloadable Scylla distribution
  from scylla.git. The target requires some configuration, which user
  has to provide. For example, download URL locations and package
  signing keys.

- Amazon Machine Image (AMI) support: add a "ninja ami" command to
  simplify the steps needed to generate a Scylla distribution AMI.

- Docker image support: add a "ninja docker" command to simplify the
  steps needed to generate a Scylla distribution Docker image.

- Simplify and unify package build: simplify and unify the various shell
  scripts needed to build packages in different git repositories. This
  step will break backward compatiblity and can be done only after
  relevant build scripts and release infrastructure is updated.
"

* 'penberg/packaging/v5' of github.com:penberg/scylla:
  docs: Update packaging documentation
  build: Add "dist-check" target
  scripts/testing: Add "dist-check" for package verification
  build: Add "dist" target
  reloc: Add '--builddir' option to build_deb.sh
  build: Add "-ffile-prefix-map" to cxxflags
  docs: Document sync-submodules.sh script in maintainer.md
  sync-submodules.sh: Add script for syncing submodules
  Add scylla-tools submodule
  Add scylla-jmx submodule
This commit is contained in:
Avi Kivity
2020-06-18 12:59:52 +03:00
12 changed files with 351 additions and 96 deletions

6
.gitmodules vendored
View File

@@ -12,3 +12,9 @@
[submodule "abseil"]
path = abseil
url = ../abseil-cpp
[submodule "scylla-jmx"]
path = scylla-jmx
url = ../scylla-jmx
[submodule "scylla-tools"]
path = scylla-tools
url = ../scylla-tools-java

View File

@@ -32,6 +32,8 @@ import tempfile
import textwrap
from distutils.spawn import find_executable
curdir = os.getcwd()
tempfile.tempdir = "./build/tmp"
configure_args = str.join(' ', [shlex.quote(x) for x in sys.argv[1:]])
@@ -1206,6 +1208,8 @@ args.user_ldflags = forced_ldflags + ' ' + args.user_ldflags
args.user_cflags += ' -Wno-error=stack-usage='
args.user_cflags += f"-ffile-prefix-map={curdir}=."
seastar_cflags = args.user_cflags
if args.target != '':
seastar_cflags += ' -march=' + args.target
@@ -1428,6 +1432,10 @@ with open(buildfile_tmp, 'w') as f:
description = COPY $out
rule package
command = scripts/create-relocatable-package.py --mode $mode $out
rule rpmbuild
command = reloc/build_rpm.sh --reloc-pkg $in --builddir $out
rule debbuild
command = reloc/build_deb.sh --reloc-pkg $in --builddir $out
''').format(**globals()))
for mode in build_modes:
modeval = modes[mode]
@@ -1672,6 +1680,13 @@ with open(buildfile_tmp, 'w') as f:
f.write('build build/{mode}/scylla-package.tar.gz: package build/{mode}/scylla build/{mode}/iotune build/SCYLLA-RELEASE-FILE build/SCYLLA-VERSION-FILE build/debian/debian | always\n'.format(**locals()))
f.write(' pool = submodule_pool\n')
f.write(' mode = {mode}\n'.format(**locals()))
f.write(f'build build/dist/{mode}/redhat: rpmbuild build/{mode}/scylla-package.tar.gz\n')
f.write(f' pool = submodule_pool\n')
f.write(f' mode = {mode}\n')
f.write(f'build build/dist/{mode}/debian: debbuild build/{mode}/scylla-package.tar.gz\n')
f.write(f' pool = submodule_pool\n')
f.write(f' mode = {mode}\n')
f.write(f'build dist-server-{mode}: phony build/dist/{mode}/redhat build/dist/{mode}/debian\n')
f.write('rule libdeflate.{mode}\n'.format(**locals()))
f.write(' command = make -C libdeflate BUILD_DIR=../build/{mode}/libdeflate/ CFLAGS="{libdeflate_cflags}" CC={args.cc} ../build/{mode}/libdeflate//libdeflate.a\n'.format(**locals()))
f.write('build build/{mode}/libdeflate/libdeflate.a: libdeflate.{mode}\n'.format(**locals()))
@@ -1693,6 +1708,65 @@ with open(buildfile_tmp, 'w') as f:
'build check: phony {}\n'.format(' '.join(['{mode}-check'.format(mode=mode) for mode in modes]))
)
f.write(textwrap.dedent(f'''\
build dist-server-deb: phony {' '.join(['build/dist/{mode}/debian'.format(mode=mode) for mode in build_modes])}
build dist-server-rpm: phony {' '.join(['build/dist/{mode}/redhat'.format(mode=mode) for mode in build_modes])}
build dist-server: phony dist-server-rpm dist-server-deb
rule build-submodule-reloc
command = cd $reloc_dir && ./reloc/build_reloc.sh
rule build-submodule-rpm
command = cd $dir && ./reloc/build_rpm.sh --reloc-pkg $artifact
rule build-submodule-deb
command = cd $dir && ./reloc/build_deb.sh --reloc-pkg $artifact
build scylla-jmx/build/scylla-jmx-package.tar.gz: build-submodule-reloc
reloc_dir = scylla-jmx
build dist-jmx-rpm: build-submodule-rpm scylla-jmx/build/scylla-jmx-package.tar.gz
dir = scylla-jmx
artifact = build/scylla-jmx-package.tar.gz
build dist-jmx-deb: build-submodule-deb scylla-jmx/build/scylla-jmx-package.tar.gz
dir = scylla-jmx
artifact = build/scylla-jmx-package.tar.gz
build dist-jmx: phony dist-jmx-rpm dist-jmx-deb
build scylla-tools/build/scylla-tools-package.tar.gz: build-submodule-reloc
reloc_dir = scylla-tools
build dist-tools-rpm: build-submodule-rpm scylla-tools/build/scylla-tools-package.tar.gz
dir = scylla-tools
artifact = build/scylla-tools-package.tar.gz
build dist-tools-deb: build-submodule-deb scylla-tools/build/scylla-tools-package.tar.gz
dir = scylla-tools
artifact = build/scylla-tools-package.tar.gz
build dist-tools: phony dist-tools-rpm dist-tools-deb
rule build-python-reloc
command = ./reloc/python3/build_reloc.sh
rule build-python-rpm
command = ./reloc/python3/build_rpm.sh
rule build-python-deb
command = ./reloc/python3/build_deb.sh
build build/release/scylla-python3-package.tar.gz: build-python-reloc
build dist-python-rpm: build-python-rpm build/release/scylla-python3-package.tar.gz
build dist-python-deb: build-python-deb build/release/scylla-python3-package.tar.gz
build dist-python: phony dist-python-rpm dist-python-deb
build dist-deb: phony dist-server-deb dist-python-deb dist-jmx-deb dist-tools-deb
build dist-rpm: phony dist-server-rpm dist-python-rpm dist-jmx-rpm dist-tools-rpm
build dist: phony dist-server dist-python dist-jmx dist-tools
'''))
f.write(textwrap.dedent(f'''\
build dist-check: phony {' '.join(['dist-check-{mode}'.format(mode=mode) for mode in build_modes])}
rule dist-check
command = ./tools/testing/dist-check/dist-check.sh --mode $mode
'''))
for mode in build_modes:
f.write(textwrap.dedent(f'''\
build dist-check-{mode}: dist-check
mode = {mode}
'''))
f.write(textwrap.dedent('''\
rule configure
command = {python} configure.py $configure_args

View File

@@ -1,90 +1,60 @@
# Building Scylla Packages
This document describes how to build Scylla's packages for supported Linux distributions.
This document describes how to build Scylla's packages.
The build system generates _relocatable packages_, which means that the packages contain all the dependencies they need, and you can, therefore, install and run the same binaries on all Linux distributions.
The packages are built using Scylla's `dbuild` tool, which builds the packages in a Docker container.
The relocatable package tarball is used as a base for building the Linux distribution specific packages, `.rpm`s and `.deb`s.
### Scylla Server
## Building
To build a tarball, which contains the full Scylla server, run (remember to substitute `<mode>` with, for example, `release`):
In these instructions, we use `dbuild` to build the packages, but you can also build packages without it.
The first step is to run `configure.py`, which generates the `build.ninja` file (equivalent of a `Makefile`):
```
./tools/toolchain/dbuild ./reloc/build_reloc.sh --mode <mode>
./tools/toolchain/dbuild ./configure.py --mode=<mode>
```
This step generates the following tarball:
(where `mode` is `release`, `dev`, or `debug`)
The second step is to build the packages with the `dist` target.
```
build/<mode>/scylla-package.tar.gz
./tools/toolchain/dbuild ninja-build dist
```
You can then generate RPM packages with:
## Artifacts
The `dist` target generates the following tarballs (*relocatable packages*), which can be installed on any Linux distribution:
### Relocatable package artifacts
* `build/<mode>/scylla-package.tar.gz`
* `build/release/scylla-python3-package.tar.gz`
* `scylla-jmx/build/scylla-jmx-package.tar.gz`
* `scylla-tools/build/scylla-tools-package.tar.gz`
### RPM package artifacts
* `build/dist/<mode>/redhat/RPMS/x86_64/scylla-*.rpm`
* `build/dist/<mode>/redhat/RPMS/x86_64/scylla-conf-*.rpm`
* `build/dist/<mode>/redhat/RPMS/x86_64/scylla-debuginfo-*.rpm`
* `build/dist/<mode>/redhat/RPMS/x86_64/scylla-kernel-conf-*.rpm`
* `build/dist/<mode>/redhat/RPMS/x86_64/scylla-server-*.rpm`
* `build/redhat/RPMS/x86_64/scylla-python3-*.rpm`
* `scylla-jmx/build/redhat/RPMS/noarch/scylla-jmx-*.rpm`
* `scylla-tools/build/redhat/RPMS/noarch/scylla-tools-*.rpm`
* `scylla-tools/build/redhat/RPMS/noarch/scylla-tools-core-*.rpm`
### Debian package artifacts
## Verifying
To verify built Scylla packages, run the following command:
```
./tools/toolchain/dbuild ./reloc/build_rpm.sh --reloc-pkg build/<mode>/scylla-package.tar.gz
ninja-build dist-check
```
This step generates the following RPM packages:
```
build/redhat/RPMS/x86_64/scylla-666.development-0.20190807.7d0c99e268.x86_64.rpm
build/redhat/RPMS/x86_64/scylla-server-666.development-0.20190807.7d0c99e268.x86_64.rpm
build/redhat/RPMS/x86_64/scylla-debuginfo-666.development-0.20190807.7d0c99e268.x86_64.rpm
build/redhat/RPMS/x86_64/scylla-conf-666.development-0.20190807.7d0c99e268.x86_64.rpm
build/redhat/RPMS/x86_64/scylla-kernel-conf-666.development-0.20190807.7d0c99e268.x86_64.rpm
```
You can also generate deb packages with:
```
./tools/toolchain/dbuild ./reloc/build_deb.sh --reloc-pkg build/debug/scylla-package.tar.gz
```
This step generates the following deb packages:
```
build/debian/scylla-server-dbg_666.development-0.20190807.7d0c99e268-1_amd64.deb
build/debian/scylla-conf_666.development-0.20190807.7d0c99e268-1_amd64.deb
build/debian/scylla-kernel-conf_666.development-0.20190807.7d0c99e268-1_amd64.deb
build/debian/scylla-server_666.development-0.20190807.7d0c99e268-1_amd64.deb
build/debian/scylla_666.development-0.20190807.7d0c99e268-1_amd64.deb
```
### Python interpreter
To build a tarball, which contains a [portable Python interpreter](https://www.scylladb.com/2019/02/14/the-complex-path-for-a-simple-portable-python-interpreter-or-snakes-on-a-data-plane/), run:
```
./tools/toolchain/dbuild ./reloc/python3/build_reloc.sh
```
This step generates the following tarball:
```
build/release/scylla-python3-package.tar.gz
```
You can then generate a RPM package:
```
./tools/toolchain/dbuild ./reloc/python3/build_rpm.sh
```
This step generates the following RPM package:
```
build/redhat/RPMS/x86_64/scylla-python3-3.7.2-0.20190807.689fc72bab.x86_64.rpm
```
You can also generate a deb package with:
```
./tools/toolchain/dbuild ./reloc/python3/build_deb.sh
```
This step generates the following deb package:
```
build/debian/scylla-python3_3.7.2-0.20190807.689fc72bab-1_amd64.deb
```
Please note that you need to run `dist-check` on the host because it
requires Docker to perform the verification.

View File

@@ -137,25 +137,20 @@ Note: git contains a bug where branch descriptions with the
characters `['":\.]` confuse it. Best to search-and-replace those
characters with nothing.
## Updating seastar submodule references
## Updating submodule references
Seastar is updated upstream independently of Scylla. We want
to periodically (and upon contributor request) syncrhonize
scylla.git to include the latest seastar.git.
Submodules are maintained in separate repositories. For example, Seastar
is developed upstream independently of Scylla. We want to periodically
(and upon contributor request) synchronize scylla.git to include the
latest submodules.
1. Check out the `next` branch and synchronize it using `git pull`
2. `cd seastar`, check out `master`, and synchronize with upstream
using `git pull`
3. Go back to the scylla directory, and issue the command
`git submodule summary seastar`; this generates a change log.
4. Verify that all lines in the change log start with '>'. Lines
that start with '<' indicate non-fast-forward changes. If that
happens, fire three red flares from your flare pistol.
5. Use `git commit seastar` to update the submodule. Use something
like "Update seastar submodule" for the subject and the log from
step 3 for the body. If any of those commits fix an issue, add
a "Fixes #wxyz" entry.
6. Use `git push` to publish your work.
2. Run the `scripts/sync-submodules.sh` script, which will open a git
commit log editor for every submodule to show that commits are being
updated.
3. Edit the submodule update commits with any necessary additional
imformation. For example, amend the message with `Fixes` tags.
4. Use `git push` to publish your work.
## Backporting patches

View File

@@ -5,10 +5,12 @@ print_usage() {
echo "build_deb.sh -target <codename> --dist --rebuild-dep --reloc-pkg build/release/scylla-package.tar.gz"
echo " --dist create a public distribution package"
echo " --reloc-pkg specify relocatable package path"
echo " --builddir specify Debian package build path"
exit 1
}
RELOC_PKG=build/release/scylla-package.tar.gz
BUILDDIR=build/debian
OPTS=""
while [ $# -gt 0 ]; do
case "$1" in
@@ -21,6 +23,10 @@ while [ $# -gt 0 ]; do
RELOC_PKG=$2
shift 2
;;
"--builddir")
BUILDDIR="$2"
shift 2
;;
*)
print_usage
;;
@@ -36,8 +42,8 @@ RELOC_PKG=$(readlink -f $RELOC_PKG)
if [[ ! $OPTS =~ --reloc-pkg ]]; then
OPTS="$OPTS --reloc-pkg $RELOC_PKG"
fi
rm -rf build/debian
mkdir -p build/debian/scylla-package
tar -C build/debian/scylla-package -xpf $RELOC_PKG
cd build/debian/scylla-package
rm -rf $BUILDDIR
mkdir -p $BUILDDIR/scylla-package
tar -C $BUILDDIR/scylla-package -xpf $RELOC_PKG
cd $BUILDDIR/scylla-package
exec ./scylla/dist/debian/build_deb.sh $OPTS

View File

@@ -2,14 +2,12 @@
. /etc/os-release
COMMON_FLAGS="--cflags=-ffile-prefix-map=$PWD=."
DEFAULT_MODE="release"
print_usage() {
echo "Usage: build_reloc.sh [OPTION]..."
echo ""
echo " --configure-flags FLAGS specify extra build flags passed to 'configure.py' (common: '$COMMON_FLAGS')"
echo " --configure-flags FLAGS specify extra build flags passed to 'configure.py'"
echo " --mode MODE specify build mode (default: '$DEFAULT_MODE')"
echo " --jobs JOBS specify number of jobs"
echo " --clean clean build directory"
@@ -59,7 +57,7 @@ while [ $# -gt 0 ]; do
esac
done
FLAGS="$COMMON_FLAGS $FLAGS"
FLAGS="$FLAGS"
if [ ! -e reloc/build_reloc.sh ]; then
echo "run build_reloc.sh in top of scylla dir"

38
scripts/sync-submodules.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
#
set -euo pipefail
submodules=(
seastar
scylla-jmx
scylla-tools
)
for submodule in "${submodules[@]}"; do
GIT_DIR="$submodule/.git" git pull --ff-only origin master
SUMMARY=$(git submodule summary $submodule)
if grep '^ *<' <<< "$SUMMARY"; then
echo "Non fast-forward changes detected! Fire three red flares from your flare pistol."
exit 1
fi
if [ ! -z "$SUMMARY" ]; then
git commit --edit -m "Update $submodule submodule" -m "$SUMMARY" $submodule
fi
done

1
scylla-jmx Submodule

Submodule scylla-jmx added at b2195734cc

1
scylla-tools Submodule

Submodule scylla-tools added at 1639b12061

View File

@@ -0,0 +1,70 @@
#!/bin/bash -e
#
# Copyright (C) 2020 ScyllaDB
#
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
#
PROGRAM=$(basename $0)
print_usage() {
echo "Usage: $PROGRAM [OPTION]..."
echo ""
echo " --mode MODE The build mode of 'scylla' to verify (options: 'release', 'dev', and 'debug')."
exit 1
}
while [ $# -gt 0 ]; do
case "$1" in
"--mode")
MODE=$2
shift 2
;;
"--help")
print_usage
;;
*)
print_usage
;;
esac
done
if [ -z "$MODE" ]; then
print_usage
fi
if [ -f /.dockerenv ]; then
echo "error: running $PROGRAM in Docker is not supported, please run on host."
exit 1
fi
docker_images=(
docker.io/centos:7
)
for docker_image in "${docker_images[@]}"
do
install_sh="$(pwd)/tools/testing/dist-check/$docker_image.sh"
if [ -f "$install_sh" ]; then
docker run -i --rm -v $(pwd):$(pwd) $docker_image /bin/bash -c "cd $(pwd) && $install_sh --mode $MODE"
else
echo "internal error: $install_sh does not exist, please create one to verify packages on $docker_image."
exit 1
fi
done

View File

@@ -0,0 +1,31 @@
#!/bin/bash -e
#
# Copyright (C) 2020 ScyllaDB
#
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
#
source "$(dirname $0)/util.sh"
echo "Installing Scylla ($MODE) packages on $PRETTY_NAME..."
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
yum install -y -q deltarpm
yum update -y -q
yum install -y "${SCYLLA_RPMS[@]}"

View File

@@ -0,0 +1,65 @@
#
# Copyright (C) 2020 ScyllaDB
#
#
# This file is part of Scylla.
#
# Scylla is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Scylla is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Scylla. If not, see <http://www.gnu.org/licenses/>.
#
PROGRAM=$(basename $0)
print_usage() {
echo "Usage: $PROGRAM [OPTION]..."
echo ""
echo " --mode MODE Specify the Scylla server build mode to install."
exit 1
}
while [ $# -gt 0 ]; do
case "$1" in
"--mode")
MODE=$2
shift 2
;;
"--help")
print_usage
;;
*)
print_usage
;;
esac
done
if [ -z "$MODE" ]; then
print_usage
fi
SCYLLA_PRODUCT=$(cat build/SCYLLA-PRODUCT-FILE)
SCYLLA_RELEASE=$(cat build/SCYLLA-RELEASE-FILE)
SCYLLA_PYTHON_RELEASE=$(cat build/redhat/scylla-python3/SCYLLA-RELEASE-FILE)
SCYLLA_JMX_PRODUCT=$(cat scylla-jmx/build/SCYLLA-PRODUCT-FILE)
SCYLLA_JMX_RELEASE=$(cat scylla-jmx/build/SCYLLA-RELEASE-FILE)
SCYLLA_TOOLS_PRODUCT=$(cat scylla-tools/build/SCYLLA-PRODUCT-FILE)
SCYLLA_TOOLS_RELEASE=$(cat scylla-tools/build/SCYLLA-RELEASE-FILE)
SCYLLA_RPMS=(
build/dist/$MODE/redhat/RPMS/x86_64/$SCYLLA_PRODUCT-*$SCYLLA_RELEASE*.rpm
build/redhat/RPMS/x86_64/$SCYLLA_PRODUCT-python3-*$SCYLLA_PYTHON_RELEASE*.rpm
scylla-jmx/build/redhat/RPMS/noarch/$SCYLLA_JMX_PRODUCT*$SCYLLA_JMX_RELEASE*.rpm
scylla-tools/build/redhat/RPMS/noarch/$SCYLLA_TOOLS_PRODUCT*$SCYLLA_TOOLS_RELEASE*.rpm
)
source /etc/os-release