Operating systems are complicated, C++ build systems and library management are messy, and cross compiling to another OS is fun, so we have a custom build system.
Background story about the build system.
The build system's source lives in source/ and is written in Javascript for Node.js.
- Supports .c (C), .cc/.cpp (C++), .s/.S (AT&T assembly syntax), .asm (Intel assembly syntax), .permebuf (Permebuf files).
- Builds all source files in a package's source/ subdirectory. No need to keep a list of files to build.
- Only rebuilds a file if it or a one of its dependencies have changed.
- Supports recursive dependencies between libraries. (This really wasn't that difficult since header files don't need to get built to include them, so I wonder why more build systems don't support this.)
- One command to build the universe, package it together into a bootable ISO file, and start QEMU.
- Coming soon: importing and updating external packages via git.
See ../building.md to get started building Perception.
Commands: (Replace ./build with build.bat on Windows.)
./build
- Builds everything. The kernel, all applications, and creates a Perception.iso in the root directory. (If--local
is passed then this builds all applications and libraries, but not the kernel and does not create an ISO image.)./build run
- Builds everything and starts QEMU../build run <application> --local
- Builds an application and runs it on the local OS../build kernel
- Builds the kernel../build application <application>
- Builds a particular application../build library <library>
- Builds a particular library../build clean
- Cleans up built files../build deep-clean
- Cleans up built files and all third party files. The following build will require recloning all external repositories../build update
- Updates all third party packages./.build update application <application>
- Updates a particular third party application./.build update library <library>
- Updates a particular third party library.
Flags that can be passed:
--local
- Builds for the local OS rather than Perception.--fast
- Disables compile-time optimizations to speed up building (overrides--debug
.)--debug
- Generates debug information (overrides--fast
.)--test
- Runs unit tests.
There are 3 types of packages - the kernel, libraries, and applications. The kernel lives in Kernel
, libraries live within their own directories in Libraries
, and applications live within their own directories in Applications
.
The layout of a package's directory is:
public
- For libraries, files in here will be #include'able by packages that depend on the library.source
- Where the source code lives. Any code that lives in here will be built.permebuf
- Permebuf files live here. They get compiled to C++.metadata.json
- The metadata that controls how this package will be built.
The generated files/directories inside of a package's directory are:
generated
- Intermediate files generated by the compiler go here.third_party
- Files downloaded from an external repository go here.
You do not have to provide the generated files/directories, and please don't check them into git. They will be created if they don't exist.
Normally, files ending with _test.c
or _test.cc
are ignored. When building with --test
, the rest of the application or library (or even the kernel) is linked with each individual test source file producing an executable per test source file that is ran.
Each package's directory contains a metadata.json that controls how that package gets built. Unused fields can be emitted.
dependencies
- Libraries this package depends on.include
- Additional directories within this package, who's files will be #include'able by the package's own source files.public_include
- Directories within this package that are #includeable by packages that depend on this library (and also by the package's own source files). If this is omitted, it is assumed to have one entry, which ispublic
.define
- Preprocessor symbols to define while building this package's own source files.public_define
- Preprocessor symbols to define while building this package's own source files and all packages that depend on this library.third_party
- Is this a third party package, that requires fetching from another repository?skip_local
- If true, this library is skipped when using--local
. For example, we don't need to build our own C++ standard library because we assume the host OS is providing its own.