-
-
Notifications
You must be signed in to change notification settings - Fork 229
DEP1
The package format is based on the existing JSON format, but used SDL instead. The new format has a few key advantages:
- More concise syntax with less puctuation and less quotation marks
- Lower nesting levels
- Supports comments
The plan is to keep full support for the JSON based package description and still use it for machine-to-machine communication, but at the same time add the new format as the preferred way for developers to write.
Example of a typical dub.sdl
file directly translated from the JSON format specification:
name "myproject"
description "A little web service of mine."
authors "Peter Parker"
homepage "http://myproject.com"
license "GPL v2"
dependency "vibe-d" version=">=0.7.11"
SDL was chosen as the preferred candidate, because it achieves the following goals:
- Support for unquoted command/key names
- No root object/table, saving a single level of nesting
- Natural attribute syntax (e.g.
dependency vibe-d path="../vibe.d"
) - Reduces nesting by using multiple tags with the same name (e.g. no "dependencies" table necessary)
- Supports arbitrary nesting in a way that could be used for natural procedural elements (e.g.
if
orfor
)
The main disadvantage of SDL is it's relatively low use in other projects. However, it can be assumed that most users will have to learn a new language in any case, because they are most probably not fluent with any of the other alternatives either.
Another point that is brought up is that the structure of the package description differs from the JSON based one and thus a separate specification is needed. This is true, but it's also maybe the main selling point for introducing a new format in the first place. The deep nesting occurring in the JSON description can be a major distraction and especially attributes can help a lot to avoid that.
Finally, it has been brought up that SDL's support for date/time fields increases the parser complexity. However, those types are not used by DUB and parsers already exist, so that this doesn't make a difference in practice whatsoever.
SDL has a structure similar to XML using nodes and attributes. The format we describe here uses nodes with a semantic that is close to a procedural command. The order matters and commands can usually occur multiple times. This is in contrast to the JSON based format, where each field name can only occur once.
The globally available commands are:
Name | Arguments | Description |
---|---|---|
name | string |
Name of the package, used to uniquely identify the package |
description | string |
Brief description of the package |
homepage | string |
URL of the project website |
authors | string ... |
List of project authors |
copyright | string |
Copyright declaration string |
license | string |
License(s) under which the project can be used |
subPackage | { ... } |
Defines a new sub-package defined in the same directory as the root project, where each entry is an object of the same format as the global dub.sdl file itself - see the sub package section for more information |
configuration | string { ... } |
Defines an explicit build configuration (specified using "--config=...") - see the configurations section for more details |
buildType | string { ... } |
Defines or overrides a build type (specified using "--build=...") - see the build settings section for valid contents of T |
x:ddoxFilterArgs | string ... |
Specifies a list of command line flags usable for controlling filter behavior for --build=ddox [experimental] |
A package may contain an arbitrary number of additional publicly visible packages. These packages can be defined using the "subPackage" command of the main dub.sdl file. They can be referenced by concatenating their name with the name of the main package using a colon as a delimiter (i.e. "main-package-name:sub-package-name").
The typical use for this feature is to split up a library into a number of parts without breaking it up into different code repositories or sub directories:
name "mylib"
targetType "none"
dependency "mylib:component1" version="~master"
dependency "mylib:component2" version="~master"
subPackage {
name "component1"
targetType "library"
sourcePaths "source/component1"
}
subPackage {
name "component2"
targetType "library"
sourcePaths "source/component2"
}
Build settings fields influence the command line options passed to the compiler and linker. All fields are optional.
Platform specific settings are supported through the use of a platform
attribute. Platform specifications are dash separated lower case platform identifiers, as defined in the D language reference. The order of these suffixes is os-architecture-compiler
, where any of these parts can be left off. Examples:
versions "PrintfDebugging"
dflags platform="dmd" "-vtls"
versions platform="x86_64" "UseAmd64Impl"
libs platform="posix" "ssl" "crypto"
sourceFiles platform="windows-x86_64-dmd" "lib/win32/mylib.lib"
Inside of build setting values, it is possible to use variables using dollar notation. $PACKAGE_DIR
contains the path to the package itself and all other variables are taken from the program environment.
Name | Arguments | Description |
---|---|---|
dependency | string version=string ... |
A single dependency - see next section for how version specifications look like |
systemDependencies | string |
A textual description of the required system dependencies (external C libraries) required by the package. This will be visible on the registry and will be displayed in case of linker errors. |
targetType | string |
Specifies a specific target type - this command does not support platform specifications |
targetName | string |
Sets the base name of the output file; type and platform specific pre- and suffixes are added automatically - this command does not support platform specifications |
targetPath | string |
The destination path of the output binary - this command does not support platform specifications |
workingDirectory | string |
The directory from which the generated executable will be run (defaults to "targetPath") - this command does not support platform specifications |
subConfiguration | string string |
Locks the dependency given in the first argument to the configurations given as the second argument - this command does not support platform specifications |
buildRequirements | string[] |
List of required settings for the build process. See the build requirements section for details. |
buildOptions | string[] |
List of build option identifiers (corresponding to compiler flags) - see the build options section for details. |
dflags | string ... |
Additional flags passed to the D compiler - note that these flags are usually specific to the compiler in use, but a set of flags is automatically translated from DMD to the selected compiler |
lflags | string ... |
Additional flags passed to the linker - note that these flags are usually specific to the linker in use |
libs | string ... |
A list of external library names - depending on the compiler, these will be converted to the proper linker flag (e.g. "ssl" might get translated to "-L-lssl") |
sourceFiles | string ... |
Additional files passed to the compiler - can be useful to add certain configuration dependent source files that are not contained in the general source folder |
sourcePaths | string ... |
Allows to customize the path where to look for source files (any folder "source" or "src" is automatically used as a source path if no sourcePaths field is given) - note that you usually also need to define "importPaths" as "sourcePaths" don't influence those |
excludedSourceFiles | string ... |
Files that should be removed for the set of already added source files (takes precedence over "sourceFiles" and "sourcePaths") |
mainSourceFile | string |
Determines the file that contains the main() function. This field can be used by dub to exclude this file in situations where a different main function is defined (e.g. for "dub test") - this field does not support platform suffixes |
copyFiles | string ... |
Files that are copied to the applications directory - typically these are DLLs on Windows |
versions | string ... |
A list of D versions to be defined during compilation |
debugVersions | string ... |
A list of D debug identifiers to be defined during compilation |
importPaths | string ... |
Additional import paths to search for D modules (the soruce/ folder is used by default as a source folder, if it exists) |
stringImportPaths | string ... |
Additional import paths to search for string imports/views (the views/ folder is used by default as a string import folder, if it exists) |
preGenerateCommands | string ... |
A list of shell commands that is executed before project generation is started |
postGenerateCommands | string ... |
A list of shell commands that is executed after project generation is finished |
preBuildCommands | string ... |
A list of shell commands that is executed always before the project is built |
postBuildCommands | string ... |
A list of shell commands that is executed always after the project is built |
Some examples of typical simple version specifications:
- Require a certain version: "==1.3.0"
- Require a minimum version: ">=1.3.0"
- Require a version range: ">=1.3.0 <=1.3.4"
- Use the GIT master branch: "~master"
Numbered versions are formatted and compared according to the SemVer specification.
In addition to the version, additional fields can be added to further control how a dependency is being searched or used:
- Use a folder to source a package from:
dependency "somedep" version="~master" path="path/to/package"
- Indicate an optional dependency, so that it is used only if it is already installed:
depdendency "somedep" version="~master" optional=true
[work in progress]
The following values are recognized for the "targetType" field:
Value | Description |
---|---|
"autodetect" | Automatically detects the target type. This is the default global value and causes dub to try and generate "application" and "library" configurations. Use of other values limits the auto-generated configurations to either of the two. This value is not allowed inside of a configuration block. |
"none" | Does not generate an output file. This is useful for packages that are supposed to drag in other packages using its "dependencies" field. |
"executable" | Generates an executable binary |
"library" | Specifies that the package is to be used as a library, without limiting the actual type of library. This should be the default for most libraries. |
"sourceLibrary" | This target type does not generate a binary, but rather forces dub to add all source files directly to the same compiler invocation as the dependent project. |
"staticLibrary" | Forces output as a static library container. |
"dynamicLibrary" | Forces output as a dynamic/shared library. |
The following values are recognized as array items in the buildRequirements
field:
Value | Description |
---|---|
"allowWarnings" | Warnings do not abort compilation |
"silenceWarnings" | Don't show warnings |
"disallowDeprecations" | Using deprecated features aborts compilation |
"silenceDeprecations" | Don't show deprecation warnings |
"disallowInlining" | Avoid function inlining, even in release builds |
"disallowOptimization" | Avoid optimizations, even in release builds |
"requireBoundsCheck" | Always perform bounds checks |
"requireContracts" | Leave assertions and contracts enabled in release builds |
"noDefaultFlags" | Does not emit any of the default build flags (e.g. -debug, -unittest, -w, -property), but still emits import folder flags and version flags (This flag should never be used for released packages and is indended purely as a development/debugging tool) |
In addition to platform specific build settings, it is possible to define build configurations. Build configurations add or override build settings to the global ones. To choose a configuration, use dub --config=. By default, the first configuration that matches the target type and build platform is selected automatically. The configurations are defined by adding a "configurations" field.
If no configurations are specified, dub automatically tries to detect the two default configurations "application" and "library". The "application" configuration is only added if at least one of the following files is found: source/app.d, source/.d, src/app.d, src/.d. Those files are expected to contain only the application entry point (usually main()) and are only added to the "application" configuration.
The following example defines "metro-app" and "desktop-app" configurations that are only available on Windows and a "glut-app" configuration that is available on all platforms.
...
name "somepackage"
configuration "metro-app" {
targetType "executable"
platforms "windows"
versions "MetroApp"
libs "d3d11"
}
configuration "desktop-app" {
targetType "executable"
platforms "windows"
versions "DesktopApp"
libs "d3d9"
}
configuration "glut-app" {
targetType "executable"
versions "GlutApp"
}
You can choose a specific configuration for certain dependencies by using the "subConfigurations" field:
...
dependency "somepackage" version=">=1.0.0"
subConfiguration "somepackage" "glut-app"
If no configuration is specified for a package, the first one that matches the current platform is chosen (see the "platforms" field below).
In addition to the usual build settings, the following fields are recognized inside of a configuration block:
Name | Arguments | Description |
---|---|---|
name [required] | string |
Name of the configuration |
platforms | string ... |
A list of platform suffixes (as used for the build settings) to limit on which platforms the configuration applies |