Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Dockerfile and add UID/GID support #231

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
16 changes: 11 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
FROM ubuntu:18.04
FROM ubuntu:20.04

LABEL maintainer="[email protected]"

ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
make ninja-build \
gcc g++ \
git \
python3-minimal \
lsb-release \
wget \
samba
samba \
texlive-base \
texinfo

# RUN git config --global http.sslVerify false
# RUN cd /tmp && git clone https://github.com/arichardson/bmake && cd bmake \
Expand All @@ -20,18 +24,20 @@ COPY cheribuild.json /root/.config/cheribuild.json

# deps to build QEMU+elftoolchain:
RUN apt-get update && apt-get install -y \
libtool pkg-config python-minimal autotools-dev automake autoconf libglib2.0-dev libpixman-1-dev \
libtool pkg-config python2-minimal autotools-dev automake autoconf libglib2.0-dev libpixman-1-dev \
bison groff-base libarchive-dev flex

# INSTALL clang 8.0
# INSTALL clang 10.0
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
RUN echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main" > /etc/apt/sources.list.d/llvm.list
# RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu trusty main" > /etc/apt/sources.list.d/r-toolchain.list
# RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1E9377A2BA9EF27F
RUN apt-get update && apt-get install -y clang-8 lld-8
RUN apt-get update && apt-get install -y clang-10 lld-10
Comment on lines +30 to +35
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ubuntu 20.04 itself has LLVM 10 as the default version, you shouldn't need to add the external repository (especially not one built for Ubuntu 18.04), nor should you need to install versioned packages


RUN apt-get update && apt-get install -y cmake

RUN groupadd -g 12345 -r cheri && useradd -u 12345 --no-log-init -r -g cheri cheri
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No home directory? Also, adduser is preferred and can create both the group and user in one command


VOLUME ["/cheribuild", "/source", "/build", "/output"]
ENV PATH /cheribuild:$PATH
CMD bash
8 changes: 6 additions & 2 deletions pycheribuild/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,12 @@ def real_main():
subprocess.check_call(start_cmd)
docker_run_cmd = ["docker", "exec", cheri_config.docker_container] + cheribuild_args
else:
docker_run_cmd = ["docker", "run", "--user", str(os.getuid()) + ":" + str(os.getgid()),
"--rm", "--interactive", "--tty"] + docker_dir_mappings
if cheri_config.docker_uid != "":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if I specify a UID but not a GID?

docker_run_cmd = ["docker", "run", "--user", cheri_config.docker_uid + ":" + cheri_config.docker_gid,
"--rm", "--interactive", "--tty"] + docker_dir_mappings
else:
docker_run_cmd = ["docker", "run", "--user", str(os.getuid()) + ":" + str(os.getgid()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use variables to avoid the duplication

"--rm", "--interactive", "--tty"] + docker_dir_mappings
docker_run_cmd += [cheri_config.docker_container] + cheribuild_args
run_command(docker_run_cmd, config=cheri_config, give_tty_control=True)
except subprocess.CalledProcessError as e:
Expand Down
2 changes: 2 additions & 0 deletions pycheribuild/config/chericonfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ def __init__(self, loader, action_class):
help="Attach to the same container again (note: "
"docker-container option must be an id rather than "
"a container name")
self.docker_uid = loader.add_option("docker-uid", help="UID to under Docker", default="", group=loader.docker_group)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a word? Also why "" rather than None? And could you not just default this to os.get[ug]id() so you don't need to check whether it's set?

self.docker_gid = loader.add_option("docker-gid", help="GID to under Docker", default="", group=loader.docker_group)

# compilation db options:
self.create_compilation_db = loader.add_commandline_only_bool_option(
Expand Down
162 changes: 162 additions & 0 deletions pycheribuild/projects/release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#
# Copyright (c) 2021 George V. Neville-Neil
#
# This software was developed by SRI International and the University of
# Cambridge Computer Laboratory (Department of Computer Science and
# Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
# DARPA SSITH research programme.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
import tempfile
from pathlib import Path
from typing import Optional

from pycheribuild.processutils import run_command
from pycheribuild.utils import default_make_jobs_count
from .cherisim import BuildBeriCtl, BuildCheriSim
from .project import CheriConfig, SimpleProject
from ..config.compilation_targets import CompilationTargets


repos = ["cheribuild", "cheribsd", "gdb",
"morello-llvm-project", "morello-qemu",
"morello-trusted-firmware-a", "qemu"]

class Tag(SimpleProject):
target = "tag"

@classmethod
def setup_config_options(cls, **kwargs):
super().setup_config_options(**kwargs)

cls.gittag = cls.add_config_option("gittag", help="Tag to apply")

def __init__(self, config: CheriConfig):
super().__init__(config)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These aren't needed if you're not doing anything in the overridden constructor


def process(self):
source_root = self.config.source_root
for repo in repos:
run_command("git", "-C", repo, "tag", self.gittag, cwd=source_root)

class UnTag(SimpleProject):
target = "untag"

@classmethod
def setup_config_options(cls, **kwargs):
super().setup_config_options(**kwargs)

cls.gittag = cls.add_config_option("gittag", help="Tag to apply")

def __init__(self, config: CheriConfig):
super().__init__(config)

def process(self):
source_root = self.config.source_root
for repo in repos:
run_command("git", "-C", repo, "tag", "-d", self.gittag, cwd=source_root)

class Release(SimpleProject):
project_name = "release"
do_not_add_to_targets = True

def __init__(self, config: CheriConfig):
super().__init__(config)

def process(self):
source_root = self.config.source_root

Path(source_root, "cheribuild/cheribuild.json").write_text("""{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These will have side-effects in --pretend mode I believe, and thus during the "pretend build everything" test

"source-root": "../../sources",
Copy link
Member

@jrtc27 jrtc27 Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this evaluated relative to cheribuild.py or the current working directory?

Also, this results in a non-standard layout; the standard layout is that build-root is source-root/build and output-root is source-root/output.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(answer to the first part: if loaded from a config file, relative to the file, otherwise if on the command line it's relative to the current working directory)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In hindsight I should have used a separate sources directory, but unfortunately it's too late to change that. I'm okay with doing it for the docker-based release since people using it are starting with a clean environment

Copy link
Member

@jrtc27 jrtc27 Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the reason I'm of the view we shouldn't is not a technical one but for our (and their) sanity. All our documentation talks about ~/cheri/cheribuild, ~/cheri/$project, ~/cheri/build and ~/cheri/output. If we suddenly have two different default layouts that people are exposed to they're going to mix things up and get confused, and we'll have to have documentation for them both everywhere. Using the same layout allows all our documentation to always be simple and consistent, with the only thing we need to note being that ~/cheri may (should) be somewhere else for releases to avoid conflicts (ie ~/cheri-rel-YYYYMMDD or some such, or possibly ~/cheri-rel-YYYYMMDD/cheri given the current tarball, which is a bit ugly but in a way perhaps somewhat sensible as then it looks even more like normal).

"build-root": "../../build",
"output-root": "../../output",
"skip-update": true
}
""")


class MorelloRelease(Release):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would these not be better as a single "CrossCompile" project so you have a single class that does multiple architectures?

target = "morello-release"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally we only put the architecture as a prefix when you're building a native tool, like morello-qemu (until merged into the main CHERI QEMU) or morello-llvm; when you're producing artifacts to run on that architecture it's instead a suffix.

dependencies = ["morello-llvm", "cheribsd-morello-purecap",
"gdb-native",
"gdb-morello-hybrid-for-purecap-rootfs",
"arm-none-eabi-toolchain", "morello-acpica",
"morello-scp-firmware",
"morello-trusted-firmware",
"morello-flash-images",
"disk-image-morello-purecap"]
def __init__(self, config: CheriConfig):
super().__init__(config)


def process(self):
super().process()

root = self.config.output_root.parent
output_root = self.config.output_root

install_script = Path(output_root, "install_and_run_fvp.sh")
install_script.write_text("""#!/bin/sh
dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
exec "${dir}/cheribuild.py" install-morello-fvp run-fvp-morello-purecap "$@""")
install_script.chmod(0o755)

run_command("bsdtar", "-cavf", output_root / "release-morello.tar.xz",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be putting -purecap in the names? For Morello it's perhaps unnecessary as foo-morello doesn't exist, only foo-morello-{hybrid,purecap}, so one can infer it's purecap, but for RISC-V we do have foo-riscv64 without any suffix that it might get confused with, and we should probably be consistent.

"-C", root,
"--options=xz:threads=" + str(default_make_jobs_count()),
"--options=compression-level=9", # reduce size a bit more
"--exclude=*.git",
"output/morello-sdk/firmware",
"output/cheribsd-morello-purecap.img",
"output/sdk",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing the rootfs

"sources/cheribuild",
Copy link
Member

@jrtc27 jrtc27 Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only because you've configured your cheribuild to have a non-standard layout. If I were to run this it wouldn't work. If you want a specific layout you need to assemble that yourself in a staging directory, but IMO the layout you pick should be the standard one.

cwd="/")

run_command("sha256sum", output_root / "release-morello.tar.xz")

class RISCV64Release(Release):
target = "riscv64-release"
dependencies = ["gdb-native", "qemu",
"bbl-baremetal-riscv64-purecap",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BBL should be implied by QEMU

Copy link
Member

@arichardson arichardson Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only a dependency of run-riscv64{,-purecap,-hybrid} so is needed here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. I can kinda see why (especially if you don't want to use qemu-system-riscv64cheri but a different one instead), but it's a bit surprising given QEMU's source knows about it.

"disk-image-riscv64-purecap"]

def __init__(self, config: CheriConfig):
super().__init__(config)

def process(self):
super().process()
root = self.config.output_root.parent
output_root = self.config.output_root

run_command("bsdtar", "-cavf", output_root / "release-riscv64.tar.xz",
"-C", root,
"--options=xz:threads=" + str(default_make_jobs_count()),
#"--options=compression-level=9", # reduce size a bit more
"--exclude=*.git",
"output/cheribsd-riscv64-purecap.img",
"output/rootfs-riscv64-purecap",
"output/sdk",
"sources/cheribuild",
cwd="/")

run_command("sha256sum", output_root / "release-riscv64.tar.xz")