dds
Alpha Release 4 is Available!
Along with the brand new website, the fourth dds
alpha version has been posted.
Get it from the downloads page!
What’s Happened?
Quite a lot has been going on since my last dds
alpha release… You’ll have
to excuse my tardiness in posting updates.
Besides the new stressors we all find ourselves living with, I’ve been spending
a lot of time yak-shaving on dds
tasks. (For those that are unaware, yak
shaving refers to “any apparently useless activity which, by allowing you to
overcome intermediate difficulties, allows you to solve a larger problem.” It
is a delightfully useful bit of jargon.)
So what, pray tell, have I been yak-shaving on? dds
, of course! The very
first important feature that I want to get working is a better package
distribution story. At the moment, dds
obtains packages by shallow-cloning a
Git repository, and the package listing is only stored in a local catalog
database: There are no remote catalog/repository capabilities yet.
Unfortunately, I have placed some restrictions on myself that have prevented me from pulling libraries that would otherwise be very useful in achieving this goal (e.g. Boost.Beast for HTTP, libsodium for file signing). I set out on a path to bootstrap a lot of these components myself. A herculean task, to be sure. Am I up to the challenge?
Kind of?
I made a lot of good progress, and I have a lot of useful code to show for my
yak-shaving efforts, but I haven’t made enough progress yet that would directly
affect dds
itself.
This is what one would call “Letting perfect become the enemy of good.”
To this end, I have postponed my yak-shaving efforts in lieu of getting a “good enough” package distribution story in place, where “good enough” means “good enough to be a useful tool.”
What’s New?
The most significant change to dds
with alpha 4 is updates to the package
catalog.
A Domain
I felt it prudent to give dds
a dedicated website and domain. While browsing
the options available, one particular name caught my eye, and I simply
couldn’t pass up the opportunity:
It is still very early, but documentation and information about dds
is now
available online at dds.pizza
Catalog Changes
While we don’t yet have a central (or private) software repository solution,
dds
still allows you to download and build project dependencies through a
local catalog database.
The catalog database is a file that enumerates packages (and versions thereof)
with information about how they may be obtained. The catalog has been included
since Alpha 2, but it has always started out empty. You download dds
, but it
has no support for any existing packages! Pretty useless, right?
When dds
builds a project, it will first solve the dependencies of that
project using the local repository and the local catalog. The local repository
contains sources for packages that have been downloaded previously, and dds
will use them to build from. If a dependency solution identifies a package that
is not yet in the local repository, dds
will use the information stored in
the catalog to obtain a copy of the sources of that package and place it in the
local repository, ready to be built. This all happens automatically as part of
the build process.
To add entries to the catalog, one must write a JSON5 file that describes the packages and how they are to be obtained. This file is then imported from the command line:
$ dds catalog import --json catalog-data.json5
The available packages can be enumerated with a command:
$ dds catalog list
[...]
spdlog@1.6.0
spdlog@1.6.1
spdlog@1.7.0
tomlpp@1.0.0
tomlpp@1.1.0
tomlpp@1.2.0
[...]
More information can be obtained about any package using catalog show
with
the package-id:
$ dds catalog show spdlog@1.7.0
Name: spdlog
Version: 1.7.0
Depends: fmt@[>=6.0.0]
Git URL: https://github.com/gabime/spdlog.git
Git Ref: v1.7.0
Description:
Fast C++ logging library
There are several other catalog
subcommands, but they are not relevant.
Everything mentioned above has been around since Alpha 2. So what’s new?
A Shipping Catalog!
dds
uses itself to build itself, and it manages its own dependencies in a
catalog as outlined above. The dds
repository contains a catalog.json
file
that is used to populate its own catalog with its dependencies. Until now, that
catalog file hasn’t been anything more than part of dds
’s CI process.
With dds
Alpha 4, upon the initial migrations to the catalog database, dds
will seed the catalog with the contents of the catalog.json
that is contained
in its own repository!
This means that dds
will finally be able to download several common
packages straight out-of-the-box.
In addition to dds
’s own dependencies, several common and useful C and C++
libraries have been added to the catalog.json
, even if they aren’t yet used
by dds
itself (This also means that they are less thoroughly tested). Upon
initial start-up, dds
will be able to pull the following packages as
dependencies:
- Abseil
- Asio
- Boost.LEAF
- Boost.mp11
- Boost.PFR (AKA
magic_get
) - Catch2
- Cereal
- CTRE *
- fmt *
- Inja
- libsodium
- lua
- magic_enum
- ms-wil * (Windows Implementation Library**)
- nameof
- neo-concepts *
- neo-fun *
- neo-sqlite3 *
- nlohmann-json **
- pcg-cpp (PCG random)
- pegtl
- pubgrub *
- pybind11
- range-v3 *
- semver *
- sol2
- spdlog *
- tomlpp
- vob-json5 *
- vob-semester *
- zlib
Libraries marked
*
are used directly bydds
and are known to integrate correctly. Libraries marked**
are only available in outdated pinned versions.neo-
,vob-
, andsemver
libraries are my own.
It’s a modest list so far, but hopefully enough to get something useful started.
These initial entries are only created the first time the local catalog database is created, so users with existing catalog files won’t see them appear.
In such case, adding/reloading these initial entries can be done with the
--initial
flag:
$ dds catalog import --initial
Automated Transforms
Of the above listed dependencies, many are ready to be built and imported by
dds
simply by their directory layout matching what dds
expects. A few,
however, have their own unique layouts that need to be “patched up” so that
dds
can build and import them.
As part of a transitional period to allow dds
to consume libraries that do
not yet meet its layout requirements, catalog listings can now contain
“filesystem transformations,” that instruct dds
how to rearrange the result
of git clone
such that dds
can build and import the libraries therein.
For example, the Lua source tree can be built by dds
by simply moving the
source files from the top-level directory into a src
subdirectory. This is
encoded in the catalog.json
as:
{
move: {
from: ".",
to: "src/",
include: ["*.c", "*.h"]
}
}
More details are included in the updated documentation.
Updating the Catalog
While dds
doesn’t have a central package catalog that it knows how to
download to update its local copy, the catalog.json
that is used to seed the
database is available to download. Combined with catalog import
, one can
import that catalog JSON file in a single line:
$ curl -Ls dds.pizza/ctlg | dds catalog import --stdin
(Windows users can use Invoke-WebRequest
in PowerShell for the same effect.)
This “poor-man’s apt-get” isn’t perfect, but it’s good enough for experimenting with an alpha release. A future release will have “for real” remote catalog and package distribution capabilities.
Other Changes
Dependency “Statements”
The depends
key was previously a JSON object with keys being package names
and values being version range strings, much like they are in NPM’s
package.json
. This has been changed to depends
being an array of strings,
with an abbreviated syntax of “dependency statements.” The transform is simple:
{
depends: {
foo: "^1.2.3"
}
}
becomes:
{
depends: [
"foo^1.2.3"
]
}
Using a JSON object for depends
is deprecated and will be removed in the next
release.
Similarly, the arguments to build-deps
required a space separating the
package name and the range string:
$ dds build-deps "foo ^1.2.3"
which was reflected in the CMake PMM module. This is unnecessarily awkward and strange looking. To change this, one must simply remove the whitespace. This will also reduce need for seemingly-arbitrary argument quoting:
$ dds build-deps foo^1.2.3
Test Timeouts
Each test is now permitted ten seconds to execute before it is considered to be stuck, after which it will be terminated.
This time will probably be lowered in a future release.
Parallel Downloads
When dds
git-clones dependencies, it will now do so in parallel rather than
serially. This can help reduce CI times for projects which would have a large
number of dependencies.
Removals
Prior dds
alphas used a primitive key/value pair file format. While it worked
okay, it was needlessly esoteric. With Alpha 3, these files were replaced
with JSON5 configuration files. The old .dds
-file support was left in place,
but deprecated with a warning. Alpha 4 removes this completely, and dds
no
longer accepts package.dds
/library.dds
files. This can be a breaking change
if your local repository contains any packages of this shape, and may require
that the offending package directories be deleted.
Other Tweaks
- The
.inc
and.ipp
file extensions are now recognized as header files. - Compile and link commands are generated using relative paths. This fixes
issues with absurdly long command-line strings producing errors from
Windows’
CreateProcess
.
What’s Next?
There has been a lot of work towards having a real package repository as opposed to simply cloning Git repositories. While the git-clone method can go far, it will become hard to manage, as it requires manually keeping track of metadata in the catalog. Despite this work, it has not yet made its way into a public release.
Implementing remote catalog updates and package repositories is currently at the top of my priorities, so it will receive the most attention.
Once we have a real package catalog, there are several more features that I want to address:
- Conditional dependencies (e.g. “I depend on
foo
only on Windows”) - Dependency toggles/knobs for dependees. (e.g. “Enable encrypted streams in
networking library
XYZ
.”). - Conditional dependencies based on feature toggles (e.g. “I,
XYZ
, requirelibsodium
if the dependee wants me to provide encryption.”) - Better test framework integrations
- Command-line APIs for IDEs and editors