Redub v1.36.4: Incremental compilation, automation on EMSDK, WASI-SDK, Android-SDK, LDC-Addon and much more

Hipreme msnmancini at hotmail.com
Thu Nov 5 04:19:14 UTC 2026


Hello guys, I've come to announce big changes in redub:


I'm posting a full changelog on the golden version below, but if 
you want to know one of the main highlights:

- Redub has got a manual D parser which is able to get imports of 
most projects, with basic template, string mixin, mixin template 
evaluation, so it can parse structures such as `template t(string 
mod){mixin("import ",mod,";");}` or even in structures such as 
variadic string[]... arguments being used in the import context. 
Think of a powered libdparse but it's main focus is on detecting 
`import`.

- Hashing became 2x faster, competitive with Makefile (I've 
adopted fixed a bug where a reparse would happen needlessly)
- Cache is now using only 20% of the space it needed from before, 
I've adopted a binary format (faster load and write too)
- You can now build and test directly to multiple platforms, such 
as wasm or android, no extra work needed, this is as minimal as 
it gets:
```d
redub install ldc 1.43.0 --addon=android
redub init --android android-hello
cd android-hello
redub install android-sdk
redub install android-ndk
redub --target=android --bundle=android
```
> This is as minimal as it gets, and will have your app running 
> on your smartphone




- [**Cross Compilation Targets**](#redub-cross-compile) - Adds 
support to build targets, selecting a compiler, architecture and 
other configuration by just calling `redub --target=PSVita`
- [**LDC Addon**](#redub-ldc-addon) - Since `v1.35.2`: Adds 
support to installing LDC addon, together with target presets
- **Auto PATH setup** - Since `v1.32.0`: Adds a way to auto setup 
redub paths in your system. Call `redub setup` and it will 
install redub, redub's ldc and redub's dmd in the PATH.
- **Cache Sharing** - Since `v1.33.2`: Whenever you build a 
library which has the same versions and flags between parallel 
projects, the built library will be reused.
- [**Incremental Compilation**](#redub-incremental-compilation) - 
Since `v1.34.0`: Redub is able to parse your root project and 
detect whether it is better to use a single compilation unit vs 
per module in parallel
- **Build Time Regression Warn** - Since `v1.35.0`: Redub now 
also warns you if you've done some change that done a big 
regression in the build time, allowing you to be aware of your 
own changes.
- [**Built-in Cross Runner**](#built-in-targets) - Since 
`v1.36.1`: It is now possible to use redub to run D on android 
and web without any modification: `redub --target=android 
--bundle=android`|`redub --target=wasm` - builds and runs a 
server loading your executable




## Redub Cross Compile
- **1.30.0**: Added cross compilation definition support via the 
`--target` flag.

Ever wanted to configure a default compiler/arch based on the 
configuration? Now you can (mostly). This is an example on how a 
`target` will look in your recipe JSON:

```json
{
   "name": "my-project",
   "targets": {
     "wasm": {
       "compiler": "ldc2",
       "arch": "wasm32-unknown-unknown-wasm"
     },
     "PSVita": {
       "compiler": "ldc2",
       "arch": "armv7a-unknown-unknown-eabi",
       "dflags": [
         "--revert=dtorfields",
         "-mcpu=cortex-a9",
         "-mattr=+neon,+neonfp,+thumb-mode",
         "-fvisibility=hidden",
         "-gcc=$VITASDK/bin/arm-vita-eabi-gcc",
         "--relocation-model=static"
       ],
       "versions": ["PSVita"],
       "dependencies": {
         "custom-rt": {"path": "my/custom/runtime"}
       },
       "runCommand": ["nxlink", "${DUB_ROOT_PACKAGE}.nro"] //New 
addition to redub. If you're cross-compiling, you can define a 
specific run command that will be used instead of just launching 
from shell the executable.
     }
   }
}
```
Now you can just call `redub --target=wasm` or `redub 
--target=PSVita` and every dependency will inherit this 
configuration.

### Built-in targets
Since `v1.36.1`: use `redub --target=<name>`; a recipe target 
with the same name overrides the preset. Addons require LDC 1.43+ 
(`redub install ldc --addon=<group>`).

| Target | Addon | SDK | Environment | Run |
| --- | --- | --- | --- | --- |
| `windows`, `windows-i686`, `windows-arm64` | `windows` | N/A | 
N/A | native |
| `macos`, `macos-arm64` | N/A | Apple tooling to link | N/A | 
native |
| `android`, `android-armv7a`, `android-x86_64`, `android-i686` | 
`android` | NDK + SDK build-tools/platform | `ANDROID_NDK_HOME`, 
`CC`, `PATH` | `adb` push/run; APK via `--bundle=android` |
| `wasi`, `wasi-p2` | `wasi` | WASI SDK | `WASI_SDK_PATH`, `CC`, 
`PATH` | `redub serve` (p2 needs `jco`) |
| `emscripten` | `emscripten` | Emscripten SDK | `EMSDK`, `PATH`, 
`EMSDK_NODE`, `EMSDK_PYTHON` | `redub serve` with its `.js` glue |
| `wasm`, `web` | N/A | N/A | N/A | `redub serve` |

**Remarks**
**Remarks**
- **macOS:** compiles everywhere; linking needs Apple tooling. 
Use `--build=syntax` for a pure syntax check.
- **Android – setup:** redub finds the NDK via env/Android Studio 
paths or `redub install android-ndk`. For APK packaging, `redub 
install android-sdk` installs platform-tools, build-tools, a 
platform and a JDK 17 when none is found (all in the workspace 
and found automatically). `adb` (platform-tools) is 
auto-downloaded and `ANDROID_SERIAL` selects a device.
- **Android – run on a device:** `redub run --target=android` 
pushes and runs the `.so`; with `--bundle=android` it builds the 
APK, installs it, starts the launcher activity and streams 
`logcat`.
- **Android – build an APK:** `redub build --target=android 
--bundle=android` requires `extern(C) void 
android_d_main(void*)`; the APK uses the redub icon and 
permissions go in `"bundleConfiguration": { "permissions": 
["INTERNET"] }`.
- **Android – start a project:** `redub init --android <dir>` 
creates an OpenGL ES + touch template 
(`bundleConfiguration.opengl = true`, callbacks 
`redub_android_init/draw/touch/destroy`).
- **Android – customize the glue:** the selected bridge lives in 
`android/glue/source/redub_{minimal,opengl}_bridge.c`; the glue C 
project is created in `android/glue` (edit its `dub.json` flags 
or add sources under `source/`); redub builds it only for Android 
bundles and caches the result.
- **Android – example:** see `tests/android`.
- **WASI:** install the SDK with `redub install wasi-sdk`; p1 
runs in the browser via `redub serve`; p2 outputs are components, 
transpile with `jco`.
- **Emscripten:** install with `redub install emsdk`; no system 
Python needed.
- **wasm/web:** no SDK; links with `--no-entry` and 
`--allow-undefined`, so use `-betterC` or provide an entry 
point/runtime. `env.js` can provide JS imports for `extern(C)`; 
builds create a template in the project root.
- **serve:** `redub serve [<artifact|dir>] [--port=8080] 
[--host=127.0.0.1] [--no-open]` serves the build directory, opens 
the browser (unless `--no-open`), and generates 
`index.html`/`redub.js` when missing.




## Redub Incremental Compilation
Depending on the project size, it may be more useful to build it 
in parallel per module vs in a single command how it is done by 
default. Note that this is only valid for the root project.

The `auto` option will parse your D source and identify whether 
it is cheaper to use incremental-prallel or full-once, which is 
the default behavior. It is also possible to override that in 2 
ways:
`auto` also execute multiple compilation strategies and collect 
in its cache the build timings to get which strategy is faster 
and better decide.

- **Project Configuration**:
```json
"redub": {
   "buildStrategy": "incremental-parallel",
   "buildStats": false, //Do not collect build stats. Since we're 
not using auto, there's not much gain by doing that.
   "trustedNoImportMixins": [ //Mixins that can't be resolved but 
you guarantee they do not import anything.
     "my.NoImportMixin"
   ]
}
```
- **Command Line**:

```
   --build-strategy Root build strategy: 
|auto|full-once|incremental-once|incremental-parallel|full-parallel|. Overrides the project's redub config.
   strategy              incremental  processes                    
       link
   full-once             no           1 compiler                   
       same invocation
   incremental-once      yes          1 compiler + 1 linker        
       separate
   incremental-parallel  yes          N compilers (1 per module) + 
link  separate
   full-parallel         no           N compilers (1 per module) + 
link  separate
   auto(default)         picks full-once or incremental-parallel 
from module count/weight;
                          fewer than 4 cores picks 
incremental-once.
   link is separate whenever per-module objects are reused
```



More information about the Digitalmars-d-announce mailing list