Get Involved

Creating New Repos

When starting a new project using Plywood, you must typically create a new repo to hold that project. This new repo will hold the source code, modules and extern providers for your project. You can also combine multiple projects into a single repo, but either way, you'll have to create a new repo at some point.

Each repo is stored in a directory immediately below the repos directory in the workspace root. At a minimum, each repo must contain the following:

To demonstrate what an add-on repo looks like, there's a example repo on GitHub named primesieve. Try cloning this repo into your workspace and building the PrimeSieve sample application it contains. This repo should be cloned directly underneath the repos folder relative to your workspace root:

$ cd repos
$ git clone

After cloning this add-on repo, there should be a repos/primesieve folder relative to the workspace root.

plywood repos plywood info.pylon src PrimeSieve PrimeSieve.modules.cpp Main.cpp primesieve new files workspace root

Let's look at the contents of primesieve.

Contents of the primesieve Repo


The info.pylon file holds basic information about the repo. This file contains a single JSON object. The object's dependsOn property lists other repos are required by this repo. In this case, the primesieve repo depends only on the built-in plywood repo:

  "dependsOn": ["plywood"]

Repos are only allowed to use modules and extern providers defined inside themselves, inside one of the repo dependencies listed in info.pylon, or inside a transitive dependency. Cyclic dependencies between repos are not allowed.


In Plywood, files having the filename suffix .modules.cpp that are located anywhere within a repo are used to add modules and extern providers to that repo. The file must begin with the directive #include <ply-build-repo/Module.h>.

In this case, the PrimeSieve.modules.cpp file contains a single C++ function. The comment before the function, // [ply module="PrimeSieve"], tells PlyTool that the function is a module function that defines a new module named PrimeSieve:

#include <ply-build-repo/Module.h>

// [ply module="PrimeSieve"]
void module_PrimeSieve(ModuleArgs* args) {
    args->buildTarget->targetType = BuildTargetType::EXE;
    args->addSourceFiles(".", false);
    args->addTarget(Visibility::Private, "runtime");

Any time a target based on PrimeSieve is added to a build folder (by running plytool target add PrimeSieve) and a build system is generated for that build folder, PlyTool executes the C++ function provided here in order to initialize that target. In this case, the function does three things:

  1. Marks the target as an executable.
  2. Adds all the source code in the current directory "." to the target. In this case, the current directory contains a single source file, Main.cpp. The false argument tells PlyTool not to recurse into subdirectories, which isn't relevant here since there aren't any subdirectories.
  3. Adds a target named runtime as a dependency of the current target. Because plywood is listed as child repo of the current repo, the dependency target will be initialized from the runtime module located in the plywood repo.

This is the only source file belonging to the PrimeSieve module. It contains the source code for the PrimeSieve application itself. This source file begins with an #include statement:

#include <ply-runtime/Base.h>

Because the plywood.runtime module was listed as a dependency of the the PrimeSieve module, the header file will be found in repos/plywood/src/runtime relative to the workspace root.

Building the PrimeSieve Application

To build PrimeSieve in its own build folder, execute the following commands in the workspace root, where the plytool executable is located. (This executable was created when you set up the Plywood workspace.) If you're running on Linux or macOS, replace plytool with ./plytool instead:

$ plytool folder create PrimeSieve
$ plytool target add PrimeSieve
$ plytool generate

The plytool folder create command creates a new build folder. The name of the build folder is not important as long as it's unique.

The plytool target add command adds a new compilation target to the build folder based on the PrimeSieve module. The PrimeSieve module will be found in the primesieve repo because that's the only repo that contains a module with that name. If you ever have multiple repos that define modules with the same name, you'll have to specify the fully qualified name of the module, which in this case would be primesieve.PrimeSieve.

The plytool generate command creates a new build system in the build folder. This build system will contain a compilation target based on the PrimeSieve module as well as compilation targets for all dependencies of that module, which in this case are the runtime module (defined in the plywood repo) and the platform module (also defined in the plywood repo). Incidentally, you can view a tree diagram of the modules required by a build folder by running plytool target graph:

$ plytool target graph
Initializing repo registry...
Dependency graph for folder 'PrimeSieve':
    `-- runtime
        `-- platform

The build system for PrimeSieve should now be located in the data/build/PrimeSieve/build directory relative to the workspace root. Open the project files in your IDE (such as Visual Studio or Xcode), then build and it yourself.