.SILENT: | |||||
.PHONY: docs docs-server docs-watch docs-sync-server | |||||
_invalid: | |||||
echo "Specify a target name to execute" | |||||
docs: | |||||
sphinx-build -b html \ | |||||
docs \ | |||||
_build/docs \ | |||||
-Wqaj8 | |||||
echo "Docs generated to _build/docs" | |||||
docs-server: docs | |||||
echo "Docs are visible on http://localhost:9794/" | |||||
cd _build/docs && \ | |||||
python -m http.server 9794 | |||||
docs-watch: docs | |||||
+sh tools/docs-watch.sh | |||||
docs-sync-server: docs | |||||
cd _build/docs && \ | |||||
browser-sync start --server \ | |||||
--reload-delay 300 \ | |||||
--watch **/*.html |
# -*- coding: utf-8 -*- | |||||
# Refer: http://www.sphinx-doc.org/en/master/config | |||||
# -- Project information ----------------------------------------------------- | |||||
project = 'dds' | |||||
copyright = '2019, vector-of-bool' | |||||
author = 'vector-of-bool' | |||||
# The short X.Y version | |||||
version = '' | |||||
# The full version, including alpha/beta/rc tags | |||||
release = '0.1.0' | |||||
# -- General configuration --------------------------------------------------- | |||||
extensions = [] | |||||
templates_path = ['_templates'] | |||||
source_suffix = '.rst' | |||||
master_doc = 'index' | |||||
language = None | |||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] | |||||
pygments_style = None | |||||
# -- Options for HTML output ------------------------------------------------- | |||||
html_theme = 'pyramid' | |||||
html_theme_options = {} | |||||
html_static_path = [] | |||||
html_sidebars = {} |
``dds`` Design and Rationale | |||||
############################ | |||||
``dds`` has been designed from the very beginning as an extremely opinionated | |||||
hybrid *build system* and *package manager*. Unlike most build systems however, | |||||
``dds`` has a hyper-specific focus on a particular aspect of software | |||||
development: C++ libraries. | |||||
This may sound pointless, right? Libraries are useless unless we can use them | |||||
to build applications! | |||||
Indeed, applications *are* essential, but that is "not our job." | |||||
Another design decision is that ``dds`` is built to be driven by automated | |||||
tools as well as humans. ``dds`` will not build your AAA console game, nor will | |||||
it compile an OS kernel. Instead, the build system of your AAA console game or | |||||
OS kernel can *use* ``dds``. | |||||
Background | |||||
********** | |||||
I'm going to say something somewhat controversial: C++ doesn't need "package | |||||
management." At least, not *generalize* "package management." C++ needs | |||||
*library* "package management." | |||||
The C and C++ compilation model is inherently *more complex* than almost any | |||||
other language in use today. This isn't to say "bad," but rather than it is | |||||
built to meet extremely high and strange demands. It also comes with a large | |||||
burden of *legacy*. Meeting both of these requirements simultaneously presents | |||||
incredible implementation challenges. | |||||
Despite the vast amount of work put into build systems and tooling, virtually | |||||
all developers are using them *incorrectly* and/or *dangerously* without | |||||
realizing it. Despite this work, we seem to be a great distance from a unified | |||||
library package distribution and consumption mechanism. | |||||
Tabula Rasa | |||||
*********** | |||||
``dds`` attempts to break from the pattern of legacy demands and strange usage | |||||
demands in a few ways. The major differences between ``dds`` and other build | |||||
systems like CMake, Meson, build2, SCons, MSBuild, etc. is that of *tradeoffs*. | |||||
If you opt-in to have your library built by ``dds``, you forgoe | |||||
*customizability* in favor of *simplicity* and *ease*. | |||||
``dds`` takes a look at what is needed to build and develop *libraries* and | |||||
hyper-optimizes for that use case. It is also built with a very strong, very | |||||
opinionated idea of *how* libraries should be constructed and used. These | |||||
prescriptions are not at all arbitrary, though. They are built upon the | |||||
observations of the strengths and weaknesses of build systems in use throughout | |||||
industry and community. | |||||
There is some ambiguity on the term "build system." It can mean one of two | |||||
things: | |||||
1. A *proper noun* "Build System," such as CMake, Meson, Autotools, or even | |||||
Gulp, WebPack, and Mix. These are specific tools that have been developed | |||||
for the implementation of the second definition: | |||||
2. A general noun "build system" refers to the particular start-to-finish | |||||
process through which a specific piece of software is mapped from its raw | |||||
*inputs* (source code, resource libraries, toolchains) to the outputs | |||||
(applications, appliances, libraries, or web sites). | |||||
For example, LLVM and Blender both use the CMake "Build System," but their | |||||
"build system" is not the same. The "build system" for each is wildly | |||||
different, despite both using the same underlying "Build System." | |||||
``dds`` takes a massive divergence at this point. One project using ``dds`` as | |||||
their build system has an identical build process to every other project using | |||||
``dds``. Simply running :code:`dds -F` is enough to build *any* ``dds`` | |||||
project. | |||||
In order to reach this uniformity and simplicity, ``dds`` drops almost all | |||||
aspects of project-by-project customizability. Instead, ``dds`` affords the | |||||
developer a contract: | |||||
If you play by my rules, you get to play in my space. | |||||
.. _design.rules: | |||||
The Rules | |||||
********* | |||||
We've talked an awful lot about the "rules" and "restrictions" that ``dds`` | |||||
imposes, but what are they? | |||||
.. _design.rules.not-apps: | |||||
``dds`` Is not Made for Complex Applications | |||||
=============================================== | |||||
Alright, this one isn't a "rule" as much as a recommendation: If you are | |||||
building an application that *needs* some build process functionality that | |||||
``dds`` does not provide, ``dds`` is only open to changes that do not | |||||
violate any of the other existing rules. | |||||
.. note:: | |||||
**However:** If you are a *library* author and you find that ``dds`` | |||||
cannot correctly build your library without violating other rules, we may | |||||
have to take a look. This is certainly not to say it will allow arbitrary | |||||
customization features to permit the rules to be bent arbitrarily: Read | |||||
on. | |||||
``dds`` contains a minimal amount of functionality for building simple | |||||
applications, but it is certainly not its primary purpose (See the ``--apps`` | |||||
flag). | |||||
.. _design.rules.change: | |||||
*Your* Code Should Be Changed Before ``dds`` Should Be Changed | |||||
================================================================= | |||||
The wording of this rule means that the onus is on the library developer to | |||||
meet the expectations that ``dds`` prescribes in order to make the build | |||||
work. | |||||
If your library meets all the requirements outlined in this document but you | |||||
still find trouble in making your build work, this is grounds for change in | |||||
``dds``, either in clarifying the rules or tweaking ``dds`` functionality. | |||||
.. _design.rules.layout: | |||||
Library Projects Must Meet the Layout Requirements | |||||
================================================== | |||||
This is a very concrete requirement. ``dds`` prescribes a particular project | |||||
structure layout with minimal differing options. ``dds`` prescribes the | |||||
`Pitchfork`_ layout requirements. | |||||
.. note:: | |||||
These prescriptions are not as draconian as they may sound upon first | |||||
reading. Refer to the :doc:`layout` page for more information. | |||||
.. _Pitchfork: https://api.csswg.org/bikeshed/?force=1&url=https://raw.githubusercontent.com/vector-of-bool/pitchfork/develop/data/spec.bs | |||||
.. _design.rules.no-cond-compile: | |||||
A Library Build Must Successfully Compile All Source Files | |||||
========================================================== | |||||
Almost all Build Systems have a concept of *conditionally* adding a source file | |||||
to a build. ``dds`` elides this feature in place of relying on in-source | |||||
conditional compilation. | |||||
.. _design.rules.no-lazy-code-gen: | |||||
All Code Must Be in Place Before Building | |||||
========================================= | |||||
``dds`` does not provide code-generation functionality. Instead, any | |||||
generated code should be generated and committed to the repository to be only | |||||
ever modified through such generation scripts. | |||||
.. _design.rules.one-binary-per-src: | |||||
All Compilable Files in a ``src/`` Directory Must Link Together | |||||
=============================================================== | |||||
As part of the prescribed project layout, the ``src/`` project directory | |||||
contains source files. ``dds`` requires that *all* source files in a given | |||||
``src/`` directory should link together cleanly. Practically, this means that | |||||
every ``src/`` directory must correspond to *exactly* one library. | |||||
.. _design.rules.include: | |||||
No Arbitrary ``#include`` Directories | |||||
===================================== | |||||
Only ``src/`` and ``include/`` will ever be used as the basis for header | |||||
resolution while building a library, so all ``#include`` directives should be | |||||
relative to those directories. Refer to :ref:`guide.layout.include`. | |||||
.. _design.rules.uniform-compile: | |||||
All Files Compile with the Same Options | |||||
======================================= | |||||
When DDS compiles a library, every source file will be compiled with an | |||||
identical set of options. Additionally, when DDS compiles a dependency tree, | |||||
every library in that dependency tree will be compiled with an identical set of | |||||
options. Refer to the :doc:`toolchains` page for more information. |
.. _guide: | |||||
User Guide | |||||
########## | |||||
.. toctree:: | |||||
:maxdepth: 2 | |||||
design | |||||
layout | |||||
toolchains |
Project Layout | |||||
############## | |||||
The layout expected by ``dds`` is based on the `Pitchfork layout`_ (PFL). | |||||
``dds`` does not make use of every provision of the layout document, but the | |||||
features it does have are based on PFL. | |||||
.. _Pitchfork layout: https://api.csswg.org/bikeshed/?force=1&url=https://raw.githubusercontent.com/vector-of-bool/pitchfork/develop/data/spec.bs | |||||
In particular, the following directories are used: | |||||
- ``src/`` | |||||
- ``include/`` | |||||
- ``libs/`` | |||||
- ``_build/`` (the default build output directory used by ``dds``). | |||||
Note that the ``libs/*/`` directories can contain their own ``src/`` and | |||||
``include/`` directories, the purposes and behaviors of which match those of | |||||
their top-level counterparts. | |||||
.. _guide.layout.include: | |||||
Include Directories and Header Resolution | |||||
***************************************** | |||||
A compiler's "include path" is the list of directories in which it will attempt | |||||
to resolve ``#include`` directives. | |||||
The layout prescriptions permit either ``src/``, ``include/``, or both. In the | |||||
presence of both, the ``include/`` directory is used as the *public* include | |||||
directory, and ``src/`` is used as the *private* include directory. When only | |||||
one of either is present, that directory will be treated as the *public* | |||||
include directory (and there will be no *private* include directory). | |||||
.. _guide.layout.sources: | |||||
Source Files | |||||
************ | |||||
``dds`` distinguishes between *headers* and *compilable* sources. The heuristic | |||||
used is based on common file extensions: | |||||
The following are considered to be *header* source files: | |||||
- ``.h`` | |||||
- ``.hpp`` | |||||
- ``.hxx`` | |||||
- ``.inl`` | |||||
- ``.h++`` | |||||
While the following are considered to be *compilable* source files: | |||||
- ``.c`` | |||||
- ``.cpp`` | |||||
- ``.cc`` | |||||
- ``.cxx`` | |||||
- ``.c++`` | |||||
``dds`` will compile every compilable source file that appears in the ``src/`` | |||||
directory. ``dds`` will not compile compilable source files that appear in the | |||||
``include/`` directory and will issue a warning on each file found. | |||||
.. _guide.layout.apps-tests: | |||||
Applications and Tests | |||||
********************** | |||||
``dds`` will recognize certain compilable source files as belonging to | |||||
applications and tests. If a compilable source file stem ends with ``.main`` or | |||||
``.test``, that source file is assumed to correspond to an executable to | |||||
generate. The filename stem before the ``.main`` or ``.test`` will be used as | |||||
the name of the generated executable. For example: | |||||
- ``foo.main.cpp`` will generate an executable named ``foo``. | |||||
- ``bar.test.cpp`` will generate an executable named ``bar``. | |||||
- ``cat-meow.main.cpp`` will generate an executable named ``cat-meow``. | |||||
- ``cats.musical.test.cpp`` will generate an executable named ``cats.musical``. | |||||
.. note:: | |||||
``dds`` will automatically append the appropriate filename extension to the | |||||
generated executables based on the host and toolchain. | |||||
If the inner extension is ``.main``, then ``dds`` will assume the corresponding | |||||
executable to be an *application*. If the inner extension is ``.test``, ``dds`` | |||||
will assume the executable to be a test. | |||||
The building of tests and applications can be controlled when running | |||||
``dds build``. If tests are built, ``dds`` will automatically execute those | |||||
tests in parallel once the executables have been generated. | |||||
In any case, the executables are associated with a *library*, and, when those | |||||
executables are linked, the associated library (and its dependencies) will be | |||||
linked into the final executable. There is no need to manually specify this | |||||
linking behavior. | |||||
.. _guide.layout.libraries: | |||||
Libraries | |||||
********* | |||||
The *library* is a fundamental unit of consumable code, and ``dds`` is | |||||
specifically built to work with them. When you are in ``dds``, the library is | |||||
the center of everything. | |||||
A *source root* is a directory that contains the ``src/`` and/or ``include/`` | |||||
directories. The ``src/`` and ``include/`` directories are themselves | |||||
*source directories*. A single *source root* will always correspond to exactly | |||||
one library. If the library has any compilable sources then ``dds`` will use | |||||
those sources to generate a static library file that is linked into runtime | |||||
binaries. If a library contains only headers then ``dds`` will not generate an | |||||
archive to be included in downstream binaries, but it will still generate link | |||||
rules for the dependencies of a header-only library. | |||||
In the previous section, :ref:`guide.layout.apps-tests`, it was noted that | |||||
applications and tests are associated with a library. This association is | |||||
purely based on being collocated within the same source root. | |||||
When an executable is built within the context of a library, that library (and | |||||
all of its dependencies) will be linked into that executable. |
Toolchains | |||||
########## | |||||
One of the core components of ``dds`` is that of the *toolchain*. A toolchain | |||||
encompasses the environment used to build and link source code, including, but | |||||
not limited to: | |||||
#. The executable binaries that constitute the language implementation: | |||||
Compilers, linkers, and archive managers. | |||||
#. The configuration of those tools, including most options given to those | |||||
tools when they are invoked. | |||||
#. The set of preprocessor macros and language features that are active during | |||||
compilation. | |||||
When a build is run, every file in the entire tree (including dependencies) | |||||
will be compiled, archived, and linked using the same toolchain. | |||||
This page provides an introduction on how one can make use of toolchains most | |||||
effectively in your project. | |||||
Passing a Toolchain | |||||
******************* | |||||
In ``dds``, the default format of a toolchain is that of a single file that | |||||
describes the entire toolchain, and uses the extension ``.tc.dds`` by | |||||
convention. When running a build for a project, the ``dds`` executable will | |||||
look for a file named ``toolchain.tc.dds`` by default, and will error out if | |||||
this file does not exist. A different toolchain can be provided by passing the | |||||
toolchain file for the ``--toolchain`` (or ``-T``) option on the command line:: | |||||
$ dds build -T my-toolchain.tc.dds | |||||
Alternatively, you can pass the name of a built-in toolchain. See below. | |||||
Built-in Toolchains | |||||
******************* | |||||
For convenience, ``dds`` includes several built-in toolchains that can be | |||||
accessed in the ``--toolchain`` command-line option using a colon ``:`` | |||||
prefix:: | |||||
$ dds build -T :gcc | |||||
``dds`` will treat the leading colon (``:``) as a name for a built-in | |||||
toolchain (this means that a toolchain's filepath may not begin with a colon). | |||||
There are several built-in toolchains that may be specified: | |||||
``:gcc`` | |||||
Uses the default ``gcc`` and ``g++`` executables, linkers, and options | |||||
thereof. | |||||
``:gcc-N`` (for some integer ``N``) | |||||
Equivalent to ``:gcc``, but uses the ``gcc-N`` and ``g++-N`` executables. | |||||
``:clang`` | |||||
Equivalent to ``:gcc``, but uses the ``clang`` and ``clang++`` executables. | |||||
``:clang-N`` (for some integer ``N``) | |||||
Equivalent to ``:clang``, but uses the ``clang-N`` and ``clang++-N`` | |||||
executables. | |||||
``:msvc`` | |||||
Compiles and links using the Visual C++ toolchain. | |||||
The following pseudo-toolchains are also available: | |||||
``:ccache:XYZ`` | |||||
Uses built-in toolchain ``:XYZ``, but prefixes all compile commands with | |||||
``ccache``. | |||||
.. note:: | |||||
**IMPORTANT**: ``dds`` will *not* automatically load the Visual C++ | |||||
environment. To use Visual C++, ``dds`` must be executed from the | |||||
appropriate environment in order for the Visual C++ toolchain executables | |||||
and files to be available. | |||||
DDS | |||||
###### | |||||
**dds** is the Drop-Dead-Simple Build and Library Management Tool. | |||||
dds is a hybrid build system and package manager with a unique twist. | |||||
There's a lot to learn, but I'm glad you're here! I hope you find ``dds`` | |||||
useful to you and your projects. | |||||
If you're completely new and have no idea what the project is about, check out | |||||
the :doc:`guide/design` page to get started. | |||||
.. toctree:: | |||||
:maxdepth: 2 | |||||
guide/index | |||||
Indices and tables | |||||
================== | |||||
* :ref:`genindex` | |||||
* :ref:`modindex` | |||||
* :ref:`search` |
set -eu | |||||
THIS_SCRIPT=$(readlink -m $0) | |||||
HERE=$(dirname ${THIS_SCRIPT}) | |||||
ROOT=$(dirname ${HERE}) | |||||
while true; do | |||||
echo "Watching for changes..." | |||||
inotifywait -r ${ROOT}/docs/ -q \ | |||||
-e modify \ | |||||
-e close_write \ | |||||
-e move \ | |||||
-e delete \ | |||||
-e create | |||||
make docs || : | |||||
done |