User:Dicebot/Articles/Dub Intro
Contents
Quick introduction to dub
dub is source package manager for D. It has been created to simplify retrieval of 3d-party libraries and cross-platfrom building of D applications. dub is not part of official distribution right now but it has wide community adoption and can be expected to become standard tool once implementation is stabilized.
What does dub help with:
- Easy cross-platform builds via dub build
- Automatic source dependency fetching from package registry
- Dependency version control
- Making your projects easily available to community
- Running 3d-party development tools via ``dub run`` without unhygienic installation
What dub is not supposed to do:
- Packaging and distribution to the end user
Last point is important. Source package managers originally come from dynamic scripting languages (like Ruby and Python) where distributed package and source package are often the same thing. This has led to abuse of such infrastructure to do actual distribution and deployment of released projects. D is native compiled language and dub keeps distinction clear - end user is not even supposed to know about its existence, it is only here to help the developer.
Installation
There are several installation options:
- Pre-compiled binaries available on the registry web page
- Build is manually from source (as simple as running ./build.sh)
- Use package for Ubuntu/Debian or Arch Linux
By default all cached packages and temporary files are stored in ~/.dub or similar user-local folder defined for your operating system.
Basic usage
Creating new project
Most simple way to get started is to use init command:
dub init proj1
# # Creates following file structure:
# ./proj1/
# ./proj1/dub.json
# ./proj1/source
# ./proj1/source/app.d
cd proj1
dub run
# # Build output:
# proj1: ["proj1"]
# Building proj1 configuration "application", build type debug.
# Compiling...
# Linking...
# Running ./proj1
# Edit source/app.d to start your project.
dub run command uses configuration from dub.json to fetch dependencies, build and run current project (assuming it is an application project). dub build`` will do the same but without running anything and will work on all types of projects.
Adding dependencies
Key dub feature which motivated its creation most is automatic dependency management. Those are defined in dub.json, same as any other project metadata:
{
"name": "proj1",
"description": "Example D application.",
"dependencies": {
"vibe-d" : ">=0.7.18",
"cerealed" : ">=0.5.0"
}
}
All dependencies of dependencies will be fetched recursively as needed. dub will print upon first build attempt what packages it fetches and where those will be cached. After that local cached copy will be used unless remote dub.json changes or explicit dub upgrade is called.
You import modules from dependency libraries as if those were part of same project:
module app;
import vibe.d; // just works
dub will generate necessary import path flags for you automatically as part of build process.
Tools as dependencies
Some of projects in dub registry are not libraries but actual application, most commonly various tools aimed to help during development. dub does not provide any "install" command and keeps all fetched packages separated from host system, so you can't run those application directly. However, it is possible to do so via extended dub run syntax:
dub run <package name> <application arguments ...>
In that case all necessary environment variables will be set up temporarily and system will remain completely untouched after called application finishes. It is especially useful if you need to refer to binary from dependency package as part of build step for your current one.
Configurations. Testing
Configurations are supposed to represent different variants of your program / library. One possible use case for that is to define separate directory structure for tests. Built-in dub test command will run unit tests for all modules in source folders of your applications. However, if you want to keep those separate or add some sort of higher level tests, separate configuration can be used for that:
{
"name": "proj1",
"description": "Example D application.",
"sourcePaths" : [ ],
"configurations" : [
{
"name" : "app",
"targetType" : "executable",
"sourcePaths" : [ "./source" ],
},
{
"name" : "tests",
"sourcePaths" : [ "./tests" ],
"targetType" : "executable",
"targetName" : "app-tests",
}
]
}
Defining empty "sourcePaths" in common configuration block is necessary because configurations are additive to base settings.
find ./
# ./dub.json
# ./source
# ./source/app.d
# ./tests
# ./tests/app.d
dub build -c tests
dub build -c app # default
First of configurations is used as default one so it always makes sense to define it as "usual" application build configuration.
NB: please note however that in future dub releases using sub-packages will be encouraged way to achieve same goal and configurations will only stay as way to tune actual application builds. For now it is most simple approach though. Using sub-packages as some other advanced features will be covered in other articles.