| @@ -0,0 +1,27 @@ | |||
| .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 | |||
| @@ -0,0 +1,27 @@ | |||
| # -*- 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 = {} | |||
| @@ -0,0 +1,192 @@ | |||
| ``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. | |||
| @@ -0,0 +1,11 @@ | |||
| .. _guide: | |||
| User Guide | |||
| ########## | |||
| .. toctree:: | |||
| :maxdepth: 2 | |||
| design | |||
| layout | |||
| toolchains | |||
| @@ -0,0 +1,123 @@ | |||
| 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. | |||
| @@ -0,0 +1,80 @@ | |||
| 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. | |||
| @@ -0,0 +1,24 @@ | |||
| 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` | |||
| @@ -0,0 +1,16 @@ | |||
| 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 | |||