175 lines
5.9 KiB
Markdown
175 lines
5.9 KiB
Markdown
# ngen
|
|
Build file generator (engine) for the [Ninja build
|
|
system](https://ninja-build.org/).
|
|
|
|
Licensed under the GPLv3.
|
|
|
|
## Methodology and Overview
|
|
|
|
The problem with existing meta build systems---or makefile generators---like
|
|
[Meson](https://mesonbuild.com/) and [CMake](https://cmake.org/) 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](https://ninja-build.org/)
|
|
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 <SOMEWHERE>.
|
|
|
|
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:
|
|
|
|
```txt
|
|
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:
|
|
|
|
```toml
|
|
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 file; thats 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. Thats it!
|
|
Your project is now built, you will find it in `build/main/a.out`. Remember, you
|
|
can also freely add and remove files from this 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 exectuable, and definitly 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."
|
|
|
|
```toml
|
|
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`:
|
|
|
|
```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`:
|
|
|
|
```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. There is nothing we have to set here; the sytax
|
|
works the same as `compiler_flags`.
|
|
|
|
**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:
|
|
|
|
```toml
|
|
linker_libs = ["-lm"]
|
|
```
|
|
|
|
Now, our `ngen.toml` looks like this:
|
|
|
|
```toml
|
|
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` should show that the options you set were recognized,
|
|
and your files were rebuilt accordingly.
|
|
|
|
TODO: explain
|
|
- seperate targets
|
|
- config table
|