Skip to content

Adding a new cheribuild target

Alexander Richardson edited this page Mar 17, 2022 · 2 revisions

For simple projects it might be sufficient to set CC/CXX to cross-compile correctly. However, many projects require additional environment variables/command line flags/etc. In that case an easy way to cross-compile them for CheriBSD is adding a new cheribuild target. This will ensure files are installed to the expected directories in the root file system and will ensure third-party libraries are found with pkg-config, etc. For CMake-based projects you will also be able to run cheribuild.py <target> --test to run the tests inside CheriBSD using ctest.

Adding a new target

In order to add a new target, you will need to create a new myproject.py file inside pycheribuild/projects/cross/. The following code examples show how to add targets for various build systems.

CMake

A really simple example is eigen:

from .crosscompileproject import CrossCompileCMakeProject, GitRepository


class BuildEigen(CrossCompileCMakeProject):
    target = "eigen"
    repository = GitRepository("https://gitlab.com/libeigen/eigen.git")

Slightly more complicated (libexpat) since the CMakeLists.txt is not in the root directory:

from .crosscompileproject import CrossCompileCMakeProject
from ..project import DefaultInstallDir, GitRepository
from ...config.compilation_targets import CompilationTargets

from pathlib import Path


class BuildExpat(CrossCompileCMakeProject):
    target = "libexpat"
    native_install_dir = DefaultInstallDir.BOOTSTRAP_TOOLS
    repository = GitRepository("https://github.com/libexpat/libexpat")
    root_cmakelists_subdirectory = Path("expat")

If the build system expects additional arguments, you can override the setup() method:

    def setup(self):
        super().setup()
        self.add_cmake_options(ENABLE_FEATURE_FOO=False)
        # Documentation is built by default if Doxygen is installed. Skip it to reduce build time.
        self.add_cmake_options(CMAKE_DISABLE_FIND_PACKAGE_Doxygen=True)

Autotools (or anything configure script that accepts similar arguments)

For example rsync - this project cannot be built using a separate build directory and the ./configure check for gettimeofday fails, so we override the environment variable for it.

from .crosscompileproject import CrossCompileAutotoolsProject, DefaultInstallDir, GitRepository


class BuildRsync(CrossCompileAutotoolsProject):
    repository = GitRepository("https://github.com/CTSRD-CHERI/rsync.git")
    native_install_dir = DefaultInstallDir.BOOTSTRAP_TOOLS
    cross_install_dir = DefaultInstallDir.ROOTFS_OPTBASE
    build_in_source_dir = True  # Cannot build out-of-source

    def configure(self, **kwargs):
        # The rsync check for gettimeofday timzeone argument fails because the prototype for exit is missing (-Werror)
        self.configure_environment.update(rsync_cv_HAVE_GETTIMEOFDAY_TZ="yes")
        super().configure(**kwargs)

Another example - libffi (./configure doesn't exist in the source need to run autogen.sh first):

from .crosscompileproject import CrossCompileAutotoolsProject, GitRepository
from ...config.compilation_targets import CompilationTargets

class BuildLibFFI(CrossCompileAutotoolsProject):
    repository = GitRepository("https://github.com/libffi/libffi.git")
    target = "libffi"
    supported_architectures = CompilationTargets.ALL_FREEBSD_AND_CHERIBSD_TARGETS + [CompilationTargets.NATIVE]

    def configure(self, **kwargs):
        self.run_cmd(self.source_dir / "autogen.sh", cwd=self.source_dir)
        super().configure(**kwargs)

More complex examples

The above should work for most projects, but some may require additional steps. For more examples, you can look at the existing projects.