# Building for Linux

## Checking out

Obtain the source code via git clone.

```sh
git clone https://chromium.googlesource.com/chromiumos/platform/crosvm
```

## Setting up the development environment

Crosvm uses submodules to manage external dependencies. Initialize them via:

```sh
git submodule update --init
```

It is recommended to enable automatic recursive operations to keep the submodules in sync with the
main repository (But do not push them, as that can conflict with `repo`):

```sh
git config submodule.recurse true
git config push.recurseSubmodules no
```

Crosvm development best works on Debian derivatives. First install rust via https://rustup.rs/. Then
for the rest, we provide a script to install the necessary packages on Debian:

```sh
./tools/install-deps
```

For other systems, please see below for instructions on
[Using the development container](#using-the-development-container).

### Setting up for cross-compilation

Crosvm is built and tested on x86, aarch64 and armhf. Your host needs to be set up to allow
installation of foreign architecture packages.

On Debian this is as easy as:

```sh
sudo dpkg --add-architecture arm64
sudo dpkg --add-architecture armhf
sudo apt update
```

On ubuntu this is a little harder and needs some
[manual modifications](https://askubuntu.com/questions/430705/how-to-use-apt-get-to-download-multi-arch-library)
of APT sources.

For other systems (**including gLinux**), please see below for instructions on
[Using the development container](#using-the-development-container).

With that enabled, the following scripts will install the needed packages:

```sh
./tools/install-aarch64-deps
./tools/install-armhf-deps
```

### Using the development container

We provide a Debian container with the required packages installed. With
[Docker installed](https://docs.docker.com/get-docker/), it can be started with:

```sh
./tools/dev_container
```

The container image is big and may take a while to download when first used. Once started, you can
follow all instructions in this document within the container shell.

Instead of using the interactive shell, commands to execute can be provided directly:

```sh
./tools/dev_container cargo build
```

Note: The container and build artifacts are preserved between calls to `./tools/dev_container`. If
you wish to start fresh, use the `--reset` flag.

## Building a binary

If you simply want to try crosvm, run `cargo build`. Then the binary is generated at
`./target/debug/crosvm`. Now you can move to [Example Usage](../running_crosvm/example_usage.md).

If you want to enable [additional features](../running_crosvm/features.md), use the `--features`
flag. (e.g. `cargo build --features=gdb`)

## Development

### Iterative development

You can use cargo as usual for crosvm development to `cargo build` and `cargo test` single crates
that you are working on.

If you are working on aarch64 specific code, you can use the `set_test_target` tool to instruct
cargo to build for aarch64 and run tests on a VM:

```sh
./tools/set_test_target vm:aarch64 && source .envrc
cd mycrate && cargo test
```

The script will start a VM for testing and write environment variables for cargo to `.envrc`. With
those `cargo build` will build for aarch64 and `cargo test` will run tests inside the VM.

The aarch64 VM can be managed with the `./tools/aarch64vm` script.

### Running all tests

Crosvm cannot use `cargo test --workspace` because of various restrictions of cargo. So we have our
own test runner:

```sh
./tools/run_tests
```

Which will run all tests locally. Since we have some architecture-dependent code, we also have the
option of running tests within an aarch64 VM:

```sh
./tools/run_tests --target=vm:aarch64
```

When working on a machine that does not support cross-compilation (e.g. gLinux), you can use the dev
container to build and run the tests.

```sh
./tools/dev_container ./tools/run_tests --target=vm:aarch64
```

It is also possible to run tests on a remote machine via ssh. The target architecture is
automatically detected:

```sh
./tools/run_tests --target=ssh:hostname
```

However, it is your responsibility to make sure the required libraries for crosvm are installed and
password-less authentication is set up. See `./tools/impl/testvm/cloud_init.yaml` for hints on what
the VM has installed.

### Presubmit checks

To verify changes before submitting, use the `presubmit` script:

```sh
./tools/presubmit
```

This will run clippy, formatters and runs all tests. The presubmits will use the dev container to
build for other platforms if your host is not set up to do so.

To run checks faster, they can be run in parallel in multiple tmux panes:

```sh
./tools/presubmit --tmux
```

The `--quick` variant will skip some slower checks, like building for other platforms altogether:

```sh
./tools/presubmit --quick
```

## Known issues

- By default, crosvm is running devices in sandboxed mode, which requires seccomp policy files to be
  set up. For local testing it is often easier to `--disable-sandbox` to run everything in a single
  process.
- If your Linux header files are too old, you may find minijail rejecting seccomp filters for
  containing unknown syscalls. You can try removing the offending lines from the filter file, or add
  `--seccomp-log-failures` to the crosvm command line to turn these into warnings. Note that this
  option will also stop minijail from killing processes that violate the seccomp rule, making the
  sandboxing much less aggressive.
- Seccomp policy files have hardcoded absolute paths. You can either fix up the paths locally, or
  set up an awesome hacky symlink:
  `sudo mkdir /usr/share/policy && sudo ln -s /path/to/crosvm/seccomp/x86_64 /usr/share/policy/crosvm`.
  We'll eventually build the precompiled policies
  [into the crosvm binary](http://crbug.com/1052126).
- Devices can't be jailed if `/var/empty` doesn't exist. `sudo mkdir -p /var/empty` to work around
  this for now.
- You need read/write permissions for `/dev/kvm` to run tests or other crosvm instances. Usually
  it's owned by the `kvm` group, so `sudo usermod -a -G kvm $USER` and then log out and back in
  again to fix this.
- Some other features (networking) require `CAP_NET_ADMIN` so those usually need to be run as root.