Serenity Operating System
at master 234 lines 18 kB view raw view rendered
1# Advanced Build Instructions 2 3This file covers a few advanced scenarios that go beyond what the basic build guide provides. 4 5## Customizing the disk image 6 7To add, modify or remove files of the disk image's file system, e.g. to change the default keyboard layout, you can create a shell script with the name `sync-local.sh` in the project root, with content like this: 8 9```sh 10#!/bin/sh 11 12set -e 13 14cat << 'EOF' > mnt/etc/Keyboard.ini 15[Mapping] 16Keymaps=de 17EOF 18 19# Add a file in anon's home dir 20cp /somewhere/on/your/system/file.txt mnt/home/anon 21``` 22 23 24This will configure your keymap to German (`de`) instead of US English. See [`Base/res/keymaps/`](../Base/res/keymaps/) for a full list. Note that the `keymap` program itself will also modify the `/etc/Keyboard.ini` config file, but this way the change will persist across image rebuilds. 25 26## Ninja build targets 27 28The `Meta/serenity.sh` script provides an abstraction over the build targets which are made available by CMake. The 29following build targets cannot be accessed through the script and have to be used directly by changing the current 30directory to `Build/x86_64` and then running `ninja <target>`: 31 32- `ninja limine-image`: Builds a disk image (`limine_disk_image`) with Limine 33- `ninja grub-image`: Builds a disk image (`grub_disk_image`) with GRUB 34- `ninja extlinux-image`: Builds a disk image (`extlinux_disk_image`) with extlinux 35- `ninja check-style`: Runs the same linters the CI does to verify project style on changed files 36- `ninja install-ports`: Copies the entire ports tree into the installed rootfs for building ports in Serenity 37- `ninja lint-shell-scripts`: Checks style of shell scripts in the source tree with shellcheck 38- `ninja all_generated`: Builds all generated code. Useful for running analysis tools that can use compile_commands.json without a full system build 39- `ninja configure-components`: See the [Component Configuration](#component-configuration) section below. 40 41## CMake build options 42 43There are some optional features that can be enabled during compilation that are intended to help with specific types of development work or introduce experimental features. Currently, the following build options are available: 44- `ENABLE_ADDRESS_SANITIZER` and `ENABLE_KERNEL_ADDRESS_SANITIZER`: builds in runtime checks for memory corruption bugs (like buffer overflows and memory leaks) in Lagom test cases and the kernel, respectively. 45- `ENABLE_KERNEL_UNDEFINED_SANITIZER`: builds in runtime checks for detecting undefined behavior in the kernel. 46- `ENABLE_KERNEL_COVERAGE_COLLECTION`: enables the KCOV API and kernel coverage collection instrumentation. Only useful for coverage guided kernel fuzzing. 47- `ENABLE_USERSPACE_COVERAGE_COLLECTION`: enables coverage collection instrumentation for userspace. Currently only works with a Clang build. 48- `ENABLE_MEMORY_SANITIZER`: enables runtime checks for uninitialized memory accesses in Lagom test cases. 49- `ENABLE_UNDEFINED_SANITIZER`: builds in runtime checks for [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) (like null pointer dereferences and signed integer overflows) in Lagom test cases. 50- `ENABLE_COMPILER_EXPLORER_BUILD`: Skip building non-library entities in Lagom (this only applies to Lagom). 51- `ENABLE_FUZZERS`: builds [fuzzers](../Meta/Lagom/ReadMe.md#fuzzing) for various parts of the system. 52- `ENABLE_FUZZERS_LIBFUZZER`: builds Clang libFuzzer-based [fuzzers](../Meta/Lagom/ReadMe.md#fuzzing) for various parts of the system. 53- `ENABLE_FUZZERS_OSSFUZZ`: builds OSS-Fuzz compatible [fuzzers](../Meta/Lagom/ReadMe.md#fuzzing) for various parts of the system. 54- `ENABLE_EXTRA_KERNEL_DEBUG_SYMBOLS`: sets -Og and -ggdb3 compile options for building the Kernel. Allows for easier debugging of Kernel code. By default, the Kernel is built with -O2 instead. 55- `ENABLE_ALL_THE_DEBUG_MACROS`: used for checking whether debug code compiles on CI. This should not be set normally, as it clutters the console output and makes the system run very slowly. Instead, enable only the needed debug macros, as described below. 56- `ENABLE_ALL_DEBUG_FACILITIES`: used for checking whether debug code compiles on CI. Enables both `ENABLE_ALL_THE_DEBUG_MACROS` and `ENABLE_EXTRA_KERNEL_DEBUG_SYMBOLS`. 57- `ENABLE_COMPILETIME_FORMAT_CHECK`: checks for the validity of `std::format`-style format string during compilation. Enabled by default. 58- `ENABLE_PCI_IDS_DOWNLOAD`: downloads the [`pci.ids` database](https://pci-ids.ucw.cz/) that contains information about PCI devices at build time, if not already present. Enabled by default. 59- `BUILD_LAGOM`: builds [Lagom](../Meta/Lagom/ReadMe.md), which makes various SerenityOS libraries and programs available on the host system. 60- `ENABLE_KERNEL_LTO`: builds the kernel with link-time optimization. 61- `ENABLE_MOLD_LINKER`: builds the userland with the [`mold` linker](https://github.com/rui314/mold). `mold` can be built by running `Toolchain/BuildMold.sh`. 62- `ENABLE_JAKT`: builds the `jakt` compiler as a Lagom host tool and enables building applications and libraries that are written in the jakt language. 63- `JAKT_SOURCE_DIR`: `jakt` developer's local checkout of the jakt programming language for rapid testing. To use a local checkout, set to an absolute path when changing the CMake cache of Lagom. e.g. ``cmake -S Meta/Lagom -B Build/lagom -DENABLE_JAKT=ON -DJAKT_SOURCE_DIR=/home/me/jakt`` 64- `INCLUDE_WASM_SPEC_TESTS`: downloads and includes the WebAssembly spec testsuite tests. In order to use this option, you will need to install `prettier` and `wabt`. wabt version 1.0.23 or higher is required to pre-process the WebAssembly spec testsuite. 65- `INCLUDE_FLAC_SPEC_TESTS`: downloads and includes the xiph.org FLAC test suite. 66- `SERENITY_TOOLCHAIN`: Specifies whether to use the established GNU toolchain, or the experimental Clang-based toolchain for building SerenityOS. See the [Clang-based toolchain](#clang-based-toolchain) section below. 67- `SERENITY_ARCH`: Specifies which architecture to build for. Currently supported options are `x86_64`. 68- `BUILD_<component>`: builds the specified component, e.g. `BUILD_HEARTS` (note: must be all caps). Check the components.ini file in your build directory for a list of available components. Make sure to run `ninja clean` and `rm -rf Build/x86_64/Root` after disabling components. These options can be easily configured by using the `ConfigureComponents` utility. See the [Component Configuration](#component-configuration) section below. 69- `BUILD_EVERYTHING`: builds all optional components, overrides other `BUILD_<component>` flags when enabled 70 71Many parts of the SerenityOS codebase have debug functionality, mostly consisting of additional messages printed to the debug console. This is done via the `<component_name>_DEBUG` macros, which can be enabled individually at build time. They are listed in [this file](../Meta/CMake/all_the_debug_macros.cmake). 72 73To toggle or change a build option, see the [CMake Cache Manipulation](#cmake-cache-manipulation) section below. 74 75## CMake Cache Manipulation 76 77CMake caches variables and options in the binary directory. This allows a developer to tailor variables that are `set()` within the persistent configuration cache. 78 79There are three main ways to manipulate the cache: 80- `cmake path/to/binary/dir -DVAR_NAME=Value` 81- `ccmake` (TUI interface) 82- `cmake-gui` 83 84Options can be set via the initial `cmake` invocation that creates the binary directory to set the initial cache for the binary directory. 85Once the binary directory exists, any of the three options above can be used to change the value of cache variables. 86 87For example, boolean options such as `ENABLE_<setting>` or `<component_name>_DEBUG` can be enabled with the value `ON` and disabled with `OFF`: 88 89```console 90# Reconfigure an existing binary directory with process debug enabled 91$ cmake -B Build/x86_64 -DPROCESS_DEBUG=ON 92``` 93 94For more information on how the CMake cache works, see the CMake guide for [Running CMake](https://cmake.org/runningcmake/). Additional context is available in the CMake documentation for 95[variables](https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#variables) and [set()](https://cmake.org/cmake/help/latest/command/set.html#set-cache-entry). 96 97## SuperBuild configuration 98 99Serenity uses host tools written in idiomatic Serenity C++ to generate code and data for the main target build. 100The "SuperBuild" pattern helps to separate the host build of core Serenity libraries from the target build of the 101entire operating system environment. The SuperBuild allows clear separation of the host and target builds in the project's CMakeLists 102and unifies the approach taken towards different compiler toolchains and architectures. 103 104The recommended way to build and run the system, `./Meta/serenity.sh run`, invokes the SuperBuild equivalently to the commands below: 105 106```console 107$ cmake -GNinja -S Meta/CMake/Superbuild -B Build/superbuild-x86_64 -DSERENITY_ARCH=x86_64 -DSERENITY_TOOLCHAIN=GNU 108$ cmake --build Build/superbuild-x86_64 109$ ninja -C Build/x86_64 setup-and-run 110``` 111 112The CMake configuration of the `superbuild-<arch>` directory configures two [ExternalProjects](https://cmake.org/cmake/help/latest/module/ExternalProject.html). 113The first project is `lagom`, which is the host build of the project. For more information on Lagom, see the [Lagom ReadMe](../Meta/Lagom/ReadMe.md). It is used 114to build all the code generators and other host tools needed for the main Serenity build. The second project is the main build, which compiles the system for the 115target architecture using the selected toolchain. 116 117The `superbuild-<arch>` configuration also generates the [CMake toolchain file](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling) 118for the selected compiler toolchain and architecture via the `-DSERENITY_ARCH` and `-DSERENITY_TOOLCHAIN` arguments to the SuperBuild configuration step. 119The Serenity project depends on the install step of the Lagom build, as it uses [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) to locate 120the host tools for use in the code generation custom commands. 121 122The SuperBuild build steps are roughly equivalent to the following commands: 123 124```console 125# Generate CMakeToolchain.txt 126mkdir -p Build/x86_64 127cp Toolchain/CMake/GNUToolchain.txt.in Build/x86_64/CMakeToolchain.txt 128sed -i 's/@SERENITY_ARCH@/x86_64/g' Build/x86_64/CMakeToolchain.txt 129sed -i 's/@SERENITY_SOURCE_DIR@/'"$PWD"'/g' Build/x86_64/CMakeToolchain.txt 130sed -i 's/@SERENITY_BUILD_DIR@/'"$PWD"'\/Build\/x86_64/g' Build/x86_64/CMakeToolchain.txt 131 132# Configure and install Lagom 133cmake -GNinja -S Meta/Lagom -B Build/lagom -DCMAKE_INSTALL_PREFIX=${PWD}/Build/lagom-install 134ninja -C Build/lagom install 135# Configure and install Serenity, pointing it to Lagom's install prefix 136cmake -GNinja -B Build/x86_64 -DCMAKE_PREFIX_PATH=${PWD}/Build/lagom-install -DSERENITY_ARCH=x86_64 -DCMAKE_TOOLCHAIN_FILE=${PWD}/Build/x86_64/CMakeToolchain.txt 137ninja -C Build/x86_64 install 138``` 139 140Directing future `ninja` or `cmake --build` invocations to the `superbuild-<arch>` directory ensures that any headers or cpp files shared between the 141host and target builds will be rebuilt, and the new host tools and libraries will be staged to the lagom-install directory. This is where the superbuild 142differs from manually entering the commands above, it establishes a dependency between the install stage of lagom and the configure/build stages of Serenity. 143 144The main limitation of the SuperBuild is that any non-option CMake cache variables such as component configuration or debug flag settings must be done 145after a build has started. That is, the CMakeCache.txt for the Serenity and Lagom builds is not created until the SuperBuild build starts and reaches the 146proper stage for the build in question. For more information on the CMake cache see the [CMake Cache Manipulation](#cmake-cache-manipulation) section above. 147 148The debug flags might be manipulated after a build per the following commands: 149 150```console 151# Initial build, generate binary directories for both child builds 152$ cmake -GNinja -S Meta/CMake/Superbuild -B Build/superbuild-x86_64 -DSERENITY_ARCH=x86_64 -DSERENITY_TOOLCHAIN=GNU 153$ cmake --build Build/superbuild-x86_64 154 155# Turn on process debug and don't build the browser for the Serenity build 156$ cmake -B Build/x86_64 -DPROCESS_DEBUG=ON -DBUILD_BROWSER=OFF 157$ ninja -C Build/x86_64 install 158 159# Build host tests in Lagom build 160$ cmake -S Meta/Lagom -B Build/lagom -DBUILD_LAGOM=ON 161$ ninja -C Build/lagom install 162``` 163 164## Component Configuration 165 166For selecting which components of the system to build and install, a helper program, `ConfigureComponents` is available. 167 168It requires `whiptail` as a dependency, which is available on most systems in the `newt` or `libnewt` package. To build and run it, run the following commands from the `Build/x86_64` directory: 169```console 170$ ninja configure-components 171``` 172 173This will prompt you which build type you want to use and allows you to customize it by manually adding or removing certain components. It will then run a CMake command based on the selection as well as `ninja clean` and `rm -rf Root` to remove old build artifacts. 174 175## Tests 176 177For information on running host and target tests, see [Running Tests](RunningTests.md). The documentation there explains the difference between host tests run with Lagom and 178target tests run on SerenityOS. It also contains useful information for debugging CI test failures. 179 180## Running SerenityOS with VirtualBox and VMware 181 182Outside of QEMU, Serenity will run on VirtualBox and VMware. If you're curious, see how to [install Serenity on VirtualBox](VirtualBox.md) or [install Serenity on VMware](VMware.md). 183 184## Running SerenityOS on bare metal 185 186Bare curious users may even consider sourcing suitable hardware to [install Serenity on a physical PC.](BareMetalInstallation.md) 187 188## Filesystem performance on Windows 189 190If you're using the native Windows QEMU binary, QEMU is not able to access the ext4 root partition 191of the WSL2 installation without going via the 9P network file share. The root of your WSL2 distro will begin at the 192network path `\\wsl$\{distro-name}`. 193 194Alternatively, you may prefer to copy `Build/_disk_image` and `Build/Kernel/Kernel` to a native Windows partition (e.g. 195`/mnt/c`) before running `ninja run`, in which case `SERENITY_DISK_IMAGE` will be a regular Windows path (e.g. 196`'D:\serenity\_disk_image'`). 197 198## Clang-based toolchain 199 200SerenityOS can also be built with the [Clang](https://en.wikipedia.org/wiki/Clang) compiler instead of GCC. This is 201useful for stopping us from relying on compiler-specific behavior, and the built-in static analyzer helps us catch more 202bugs. Code compiled with both of these toolchains works identically in most cases, with the limitation that ports 203can't be built with Clang yet. 204 205To build the Clang-based toolchain, run `BuildClang.sh` from the `Toolchain` directory. The script will build a Clang 206toolchain that is capable of building applications for the build host and serenity. 207 208**Warning:** While the build script is running, your computer may slow down extremely or even lock up for short 209intervals. This generally happens if you have more CPU cores than free RAM in gigabytes. To fix this, limit the number 210of parallel compile tasks be setting the `MAKEJOBS` environment variable to a number less than your CPU core count. 211 212Once the build script finishes, you can use it to compile SerenityOS. Either set the `SERENITY_TOOLCHAIN` build 213option to `Clang` as shown [above](#cmake-build-options), or pass `Clang` as the TOOLCHAIN option to 214`Meta/serenity.sh`, for example: `Meta/serenity.sh run x86_64 Clang`. 215 216### Serenity-aware clang tools 217 218Building the clang-based toolchain also builds libTooling-based tools such as clang-format, clang-tidy and (optionally) 219clangd that are aware of SerenityOS as a valid target. These tools will be installed into ``Toolchain/Local/clang/bin`` by 220the script. Pointing your editor's plugins to the custom-built clang tools and a ``compile_commands.json`` from a clang build 221of Serenity can enable richer error reporting than the tools that are installed for the build host. 222 223To enable building clangd as part of the clang toolchain, set ``CLANG_ENABLE_CLANGD`` to ON in 224``Toolchain/CMake/LLVMConfig.cmake`` before running BuildClang.sh. If you already built the clang toolchain and would like to 225enable the custom clangd build, change the CMake cache variable ``CLANG_ENABLE_CLANGD`` to ON in ``Toolchain/Build/clang/llvm`` 226and re-install with ``cd Toolchain/Build/clang/llvm && cmake ../../../Tarballs/llvm-project-$LLVM_VERSION.src/llvm -DCLANG_ENABLE_CLANGD=ON && ninja install/strip``, where $LLVM_VERSION should be tab-completable in your shell. 227 228## Clang-format updates 229 230Some OS distributions don't ship bleeding-edge clang-format binaries. Below are 3 options to acquire an updated clang-format tool, in order of preference: 231 2321) If you have a Debian-based (apt-based) distribution, use the [LLVM apt repositories](https://apt.llvm.org) to install the latest release of clang-format. 2332) Compile the SerenityOS-patched LLVM from source using ``Toolchain/BuildClang.sh`` as described above and use the compiled ``Toolchain/Local/clang/bin/clang-format`` binary in your editor and terminal. The meta-lint-ci pre-commit hook will automatically pick up the Toolchain clang-format binary. 2343) Compile LLVM from source as described in the LLVM documentation [here](https://llvm.org/docs/GettingStarted.html#compiling-the-llvm-suite-source-code).