Guide: Building Code

The first time you work with our repositories code, you’ll want to set up your development environment.

Our builds are currently tested for Ubuntu 18.04 LTS, but they should work on any up-to-date Debian-based distro. They’ll also probably work on almost any modern Linux system (though we haven’t tested.) We will be adding official support for building on Mac OS X and Windows later.

Quick Guide

Before you dive in, you should take note of what you actually need for the project you’re working on.

Developing for Anari

If you plan to work on Anari, follow sections...

  1. libdeps (you need CPGF and Eigen)
  2. Building PawLIB: As Dependency
  3. Repository Build Systems

Developing for PawLIB

If you plan to work on PawLIB, follow sections...

  1. libdeps (you actually only need CPGF)
  2. Building PawLIB: For Developing
  3. Repository Build Systems

Developing for Ratscript

If you plan to work on Ratscript, follow sections...

  1. libdeps
  2. Building PawLIB: As Dependency
  3. Repository Build Systems

Developing for SIMPLEXpress

If you plan to work on SIMPLEXpress, follow sections...

  1. libdeps
  2. Building PawLIB: As Dependency
  3. Repository Build Systems

Dependencies

libdeps

We try to keep our library dependencies to a minimum. You can quickly build all (except one) of our third-party dependency static libraries using our libdeps repository.

For the complete list of libraries and their versions, see the CHANGELOG.md file in the libdeps repository.

Building libdeps

Clone libdeps into your repositories folder. For best results, all MousePaw Media repositories you clone should be in the same directory. Then run...

$ cd libdeps
$ git checkout -b stable origin/stable

This will check out the stable remote branch of the libdeps repository. We recommend working on stable unless you specifically need the latest unstable changes.

Next, we’ll build the dependencies. All you need to do is run make <library>, where <library> is the name of the library you want to build. Alternatively, run make ready to build them all.

Once the build is done, you can find all the headers in libdeps/libs/include, and the compiled static libraries in libdeps/libs/lib. The build systems in all of our other repositories look for the library files at these locations by default.

Warning

To make it easier to update libdeps later, DO NOT EVER commit changes on the master or stable branches.

Fixing Opus “aclocal” Build Errors

If the Opus build fails on an Ubuntu-based system with a message about “aclocal”, you can quickly fix this by running...

$ make ubuntu-fix-aclocal
$ make opus

Hereafter, you can just run make opus to build that library (or make ready to build it along with all the others.)

Updating libdeps

When changes happen in libdeps, you only need to pull them in and rebuild. While make clean commands are provided, it’s generally more effective to just clean up the git repository itself.

If you’re working on the stable branch, run...

$ git clean -xdff
$ git pull origin stable
$ make ready

Note

If you’re using the master branch, just change the second command to git pull origin master.

PawLIB

Most of our repositories rely on PawLIB, which contains many common, helpful utilities and features.

Clone pawlib into your repositories folder. For best results, all MousePaw Media repositories you clone should be in the same directory.

All of the following commands will assume you’re working in the PawLIB repository folder, so make sure you run...

$ cd pawlib

Building PawLIB: As Dependency

You can work on either the master or stable branches of PawLIB. When in doubt, use stable. The repository is on master by default, so if you want to use stable, run...

$ git checkout -b stable origin/stable

PawLIB relies on CPGF, so make sure you’ve built libdeps, or otherwise specified an alternate location for CPGF

Then, simply run...

$ make ready

Building PawLIB: For Developing

If you want to test PawLIB or help build it, you should start from the master branch.

Important

Remember to create a new branch if you plan to make any changes!

We have a tester built in to PawLIB, so you can run Goldilocks tests and benchmarks on the fly. To build that, run...

$ make tester_debug

After the build, you can start the tester via...

$ ./tester_debug

It’s that simple.

Repository Build Systems

All of our own project repositories follow the same structure, and have similar build systems.

You can learn more about a repository’s build system by running make from the root of the repository.

File Structure

All C++ project repositories have the same basic directory structure, demonstrated below. Non-library projects would effectively have a project folder instead of library-tester, and would lack the library-source folder.

Folders marked with (*) are untracked in the Git repository:

Repository
├── docs ← Sphinx documentation.
│   ├── build (*) ← The compiled documentation.
│   ├── source ← The documentation source files.
│   │   └── _themes ← The Sphinx theming files.
│   └── Makefile ← The Makefile that automatically runs CMake.
├── library (*) ← Where 'make ready' puts the compiled library and its headers.
├── library-source ← The library source code.
│   ├── build_temp (*) ← Temporary build stuff. Also where CMake is run from.
│   ├── include
│   │   └── library ← The library's header files (.hpp).
│   ├── lib (*) ← The compiled library (copied from here to ../library)
│   ├── obj (*) ← Temporary build stuff.
│   ├── src ← The library's implementation files (.cpp).
│   ├── CMakeLists.txt ← The CMake build instructions for the library.
│   ├── library.cbp ← The CodeBlocks project for the library.
│   └── Makefile ← The Makefile that automatically runs CMake.
├── library-tester ← The library tester.
│   ├── bin (*) ← The compiled tester.
│   ├── build_temp (*) ← Temporary build stuff. Also where CMake is run from.
│   ├── include ← The tester's header files (.hpp).
│   ├── src ← The tester's implementation files (.cpp).
│   ├── CMakeLists.txt ← The CMake build instructions for the tester.
│   ├── library-tester.cbp ← The CodeBlocks project for the tester.
│   └── Makefile ← The Makefile that automatically runs CMake.
├── .arcconfig ← Configuration for Phabricator Arcanist.
├── .arclint ← Configuration for Arcanist linters.
├── .gitignore ← Untracks temporary build stuff and other cruft.
├── build.config.txt ← The template configuration file.
├── BUILDING.md ← User instructions for building.
├── CHANGELOG.md ← The list of versions and their changes.
├── default.config ← The default configuration file.
├── LICENSE.md ← The project's license.
├── Makefile ← The project's master Makefile.
└── README.md ← The README file.

Adding New Files

To add a new file to a project build, you need to edit that project’s CMakeLists.txt file. Look for the add_library or add_executable section, where all the project files are listed. Add your file paths (relative to the location of CMakeLists.txt) to that list.

For example, some project’s add_executable command might look like this:

add_executable(${TARGET_NAME}
    include/someproject/classA.hpp
    include/someproject/classB.hpp
    include/someproject/classC.hpp

    main.cpp
    src/classA.cpp
    src/classB.cpp
    src/classC.cpp
)

Note

Please be sure to list files in alphabetical order, in two groups: header files and source files. Keep this section clean!

Switching Dependency Locations

Although our build systems are pre-configured to use libdeps, you can override this behavior.

In the root of the repository you’re building, open build.config.txt in that directory, and save it with another name ending in .config. Then, modify the file following the instructions to specify alternative paths to the dependency libraries.

Important

You must save the .config file in the root of the repository. All levels of the build system will look for it there.

Finally, tell the build system to use your new config file, using the CONFIG=<filename> argument on the make command, where <filename> is the name of the config file (without the .conf extension). For example, if the name of the config file was mybuild.conf, then we would include the argument CONFIG=mybuild on our make command.

Using Sanitizers

If you’re compiling with Clang/LLVM, you can use the sanitizers in any of our projects. Simply include the SAN=<sanitizer> argument, where <sanitizer> is one of the Clang sanitizers.

  • SAN=address compiles with AddressSanitizer.
  • SAN=leak compiles with LeakSanitizer (which is also part of AddressSanitizer).
  • SAN=memory compiles with MemorySanitizer.
  • SAN=thread compiles with ThreadSanitizer.
  • SAN=undefined compiles with UndefinedBehaviorSanitizer.

If you’re not using Clang, this argument will be ignored.

32/64-Bit Architecture

If your system is configured for cross-compiling, you can ask the compiler to build for an x86 (32-bit) or x64 (64-bit) system by including the ARCH=32 or ARCH=64 arguments, respectively.

Warning

Our dependency libraries (libdeps) are not currently configured to switch architectures. You will need to manually compile these and point to them using a .config file.