Go to file
2024-03-06 00:03:20 -06:00
src improved error messages and began documentation 2024-03-05 23:54:20 -06:00
.gitignore first commit; core functionality done 2024-03-03 21:46:19 -06:00
Cargo.lock improved error messages and began documentation 2024-03-05 23:54:20 -06:00
Cargo.toml improved error messages and began documentation 2024-03-05 23:54:20 -06:00
install.sh added build instructions to readme 2024-03-04 17:08:27 -06:00
LICENSE added readme and license 2024-03-03 21:53:29 -06:00
README.md typos 2024-03-06 00:03:20 -06:00
uninstall.sh added build instructions to readme 2024-03-04 17:08:27 -06:00

ngen

Build file generator (engine) for the Ninja build system.

Licensed under the GPLv3.

Methodology and Overview

The problem with existing meta build systems---or makefile generators---like Meson and CMake is that they are needlessly complex for small-to-medium-sized C/C++ projects. These projects are just large enough that hand-writing a makefile would be painful, but trying to configure a large meta build system would be just as painful. It is unacceptable that building a simple project with 10 .c files and a library requires knowledge of a unique, obscure configuration language which is constantly changing.

ngen aims to make generating build files for these small C/C++ projects as simple as possible by using a basic key-value configuration file using patterns that any experienced programmer should be familiar with. In doing so, ngen fills the gap between writing your own makefile and wrangling with CMakeLists.txt.

ngen generates files for the small and modern Ninja build system. "Where other build systems are high-level languages Ninja aims to be an assembler," according to Ninja's website. It can be thought of as a simpler, faster replacement for the classic make. It is used by default by Meson; CMake can also be configured to use ninja as a backend. Ninja is used by used by Google to build Chromium, v8, etc., and it is also used to build LLVM. (All this to say, Ninja is commonly used and it is likely installed on your system already.)

Building

Build: cargo build --release

Install: sudo sh install.sh

Uninstall: sudo sh uninstall.sh

Usage

What follows is a tutorial of how to set up ngen for an existing executable project. If you are looking for a reference, look .

The first thing you will need is an ngen.toml file. This is what will specify all of the build parameters, such as compilation flags, source files to track, etc. Start by creating this file and opening it in your editor.

The simplest valid ngen.toml just lists the source files you want to track. Lets say you have a executable project that looks like this:

example
├── ngen.toml
└── src
    ├── foobar.c
    ├── functions.c
    ├── include
    │   ├── foobar.h
    │   ├── functions.h
    │   ├── main.h
    │   └── util.h
    ├── main.c
    └── util.c

In your ngen.toml, write the following:

sources = [
  "src/main.c",
  "src/util.c",
  "src/functions.c",
  "src/foobar.c",
]

The sources key is a list of strings, each specifying a single source file name.

Now run ngen. This will generate a build.ninja file in the current working directory. You won't ever have to touch this file; that's what ngen is for. You also won't ever have to run ngen yourself again (unless your build.ninja gets deleted); Ninja will take care of regenerating the build file if ngen.toml changes.

With your build.ninja generated, run ninja on the command line. That's it! Your project is now built, you will find the executable at build/main/a.out. Remember, you can also freely add and remove files from the above list without running ngen again: Ninja will regenerate the build.ninja for you.

Now, while this is functional, it isn't very useful. It is very likely that you will want to specify a compiler (gcc/clang), pass some flags, link some libraries into your final executable, and definitely name your program something other than "a.out." ngen makes these things dead simple, too.

The outfile key is a string that specifies the name of the file produced by the linker (see below).

Lets set this to "example."

outfile = "example"

The compiler key is a string that specifies the program that will be used to turn .c files into .o files.

By default, if not specified, compiler is set to "cc," which on Linux systems should be a C compiler. It should be noted that the compiler you choose must support the -MD and -MF flags to generate dependency files (both gcc and clang support this). Lets say we want to use "gcc." Add the following line to your ngen.toml:

compiler = "gcc"

The compiler_flags key is a list of strings that contains the arguments to be passed to the compiler during the compilation of each source file.

It is not necessary to add the -c or -o outfile flags, ngen will take care of this for you. For example, add the following to your ngen.toml:

compiler_flags = ["-Wall", "-Wextra -O2"]

The linker key is a string that specifies the program that will be used to combine the .o files into the final outfile.

If the linker key is not found, it will be set to the value of compiler. For this example, we don't have to change anything here.

The linker_flags key is a list of strings that contains the arguments to be passed to the linker during the linking of the outfile.

Library flags (-lm, -lyourlib) should NOT be included here. This is for linker options, not libraries. The syntax is the same as compiler_flags. There is nothing we have to set here.

The linker_libs key is a list of strings that contains the link library arguments to be linked to the outfile.

THIS is where library flags (-lm, -lyourlib) go. Lets say our example project needs the math library:

linker_libs = ["-lm"]

Now, our ngen.toml looks like this:

outfile = "example"
compiler = "gcc"
compiler_flags = ["-Wall", "-Wextra -O2"]
linker_libs = ["-lm"]
sources = [
  "src/main.c",
  "src/util.c",
  "src/functions.c",
  "src/foobar.c",
]

This is a much more realistic looking project. Once again, any changes to any of these values will be automatically picked up by Ninja and accounted for in the build. Running ninja -v immediately after saving ngen.toml should show that the options you set were recognized, and your files were rebuilt accordingly.

TODO: explain

  • seperate targets
  • config table