Native Assets Build Hooks
dart_cpp_bridge uses Dart’s Native Assets mechanism to build and bundle the C++ library automatically. Instead of manually compiling a DLL / .so / .dylib and distributing it, you write a small hook/build.dart that invokes DcbCMakeBuilder. The Dart / Flutter tooling then runs this hook during dart run, flutter run, or flutter build, producing a bundled [CodeAsset] that the generated FFI bindings load at runtime.
What the hook does
Section titled “What the hook does”hook/build.dart is a normal Dart program executed by the Native Assets pipeline. It receives a BuildInput describing the target platform and produces a BuildOutput containing declared code assets. For dart_cpp_bridge, the hook:
- Selects a platform config (
WindowsConfig,LinuxConfig,MacosConfig,IosConfig, orAndroidConfig) based oninput.config.code.targetOS. - Invokes
DcbCMakeBuilderwith that config, the CMakesourceDir, the desired asset name, and the library base name. - Lets the builder configure, compile, locate, and emit the native library as a
CodeAsset.
Dart / Flutter takes care of caching, invalidation, and bundling the resulting library into the app or package.
Minimal hook example
Section titled “Minimal hook example”import 'package:code_assets/code_assets.dart';import 'package:dart_cpp_bridge/hook.dart';import 'package:hooks/hooks.dart';
void main(List<String> args) async { await build(args, (input, output) async { final config = switch (input.config.code.targetOS) { OS.windows => WindowsConfig(), OS.linux => LinuxConfig(), OS.macOS => MacosConfig(), OS.iOS => IosConfig(), OS.android => AndroidConfig( ndkPath: r'C:\Users\<you>\AppData\Local\Android\Sdk\ndk\<version>', ), final os => throw UnsupportedError('Unsupported target platform: $os'), };
await DcbCMakeBuilder( config: config, sourceDir: 'native', assetName: 'src/native_gen/dcb_bindings.dart', libName: 'my_project', ).run(input: input, output: output); });}Save this as hook/build.dart at the project root. The sourceDir points at the directory containing CMakeLists.txt (commonly native/). assetName is the identifier used by @Native(assetId: 'package:<package>/<assetName>') in the generated bindings. libName is the CMake output name (e.g. my_project.dll, libmy_project.so).
DcbCMakeBuilder
Section titled “DcbCMakeBuilder”DcbCMakeBuilder is the reusable CMake-driven builder exposed by package:dart_cpp_bridge/hook.dart. It performs three steps inside input.outputDirectory/dcb_build/:
- Configure —
cmake -S <sourceDir> -B <buildDir> [generator] [defines]. - Build —
cmake --build <buildDir> --config <Release|Debug> [--parallel]. - Emit — locate the produced library and add it to
output.assets.codeas aCodeAsset.
Constructor options:
| Parameter | Type | Default | Purpose |
|---|---|---|---|
config |
DcbPlatformConfig |
required | Platform-specific config (WindowsConfig, LinuxConfig, MacosConfig, IosConfig, AndroidConfig). |
assetName |
String |
required | Code asset identifier consumed by generated FFI bindings. |
assetPackage |
String? |
building package | Override the package namespace of the emitted asset. Use 'dart_cpp_bridge' when embedding the runtime via WHOLE_ARCHIVE. |
sourceDir |
String? |
package root | CMake source directory relative to the package root. Usually 'native'. |
libName |
String? |
package name | CMake library base name. Must match add_library(<name> ...) in CMakeLists.txt. |
extraDefines |
List<String> |
[] |
Extra -D flags passed to the CMake configure step. Applied on all platforms. |
useDefaultCmakeArgs |
bool |
true |
Whether to inject the builder’s generated CMake configure arguments. Set to false when the project owns these settings in CMakeLists.txt or extraDefines. |
buildOptions |
DcbBuildOptions |
DcbBuildOptions() |
Debug/release override, parallel build toggle, and compile_commands.json control. |
Disable the builder’s default CMake arguments
Section titled “Disable the builder’s default CMake arguments”If the project’s own CMakeLists.txt already controls the generator, toolchain, architecture, build type, and runtime linkage, disable the builder-generated arguments:
await DcbCMakeBuilder( config: config, sourceDir: 'native', assetName: 'src/native_gen/dcb_bindings.dart', libName: 'my_project', useDefaultCmakeArgs: false, extraDefines: const [ '-DMY_PROJECT_FEATURE=ON', ],).run(input: input, output: output);With false, the builder skips generated configure arguments such as -G, architecture, toolchain, CMAKE_BUILD_TYPE, runtime linkage, BUILD_SHARED_LIBS, and CMAKE_EXPORT_COMPILE_COMMANDS. The required -S/-B arguments, the later cmake --build invocation, --parallel, and explicitly supplied extraDefines are still kept. In this mode DcbBuildOptions.debug no longer sets the configure-time build type, and copyCompileCommands does not force CMake to generate the file (the builder still copies it if the project generates one itself).
CMake dependency ownership
Section titled “CMake dependency ownership”The dart/native CMake project can be embedded in a larger CMake build. By
default it retains a self-contained FetchContent path for the pinned
standalone Asio and stdexec dependencies. If the host project already owns
these dependencies through a package manager, a monorepo, or its own
FetchContent declarations, turn off the corresponding fetch options before
adding the bridge:
# Set these before add_subdirectory(dart_cpp_bridge/dart/native ...).set(DCB_FETCH_STDEXEC OFF CACHE BOOL "" FORCE)set(DCB_FETCH_ASIO OFF CACHE BOOL "" FORCE)
# The host project must provide these targets before add_subdirectory:# STDEXEC::stdexec# asio_iface, or a package that exposes asio::asioadd_subdirectory(path/to/dart_cpp_bridge/dart/native ${CMAKE_CURRENT_BINARY_DIR}/dcb_runtime)With DCB_FETCH_STDEXEC=OFF, the supplied stdexec target must include the
Asio adapter (STDEXEC_ENABLE_ASIO=ON) and use the same Asio implementation
as the bridge. With DCB_FETCH_ASIO=OFF, provide an existing asio_iface
target, or make find_package(asio CONFIG) expose asio::asio. The bridge
then links its runtime target against these host-provided targets without
downloading or patching Asio/stdexec itself.
This only changes ownership of Asio and stdexec. Other native dependencies and the Dart API headers keep their existing build/download behavior.
Selecting the Asio namespace
Section titled “Selecting the Asio namespace”The public C++ headers use DCB_ASIO_NS for Asio types and functions. The
namespace is selected consistently for the runtime and downstream business
code:
| CMake option | DCB_ASIO_NS |
Dependency |
|---|---|---|
| default | asio |
standalone Asio |
-DDCB_USE_BOOST_ASIO=ON |
boost::asio |
Boost.Asio supplied by the host project or the selected stdexec setup |
Write integration code against the macro instead of hard-coding asio:::
#include <dart_cpp_bridge/runtime.hpp>
DCB_ASIO_NS::io_context io;DCB_ASIO_NS::post(io, [] { // work on the selected Asio implementation});When using Boost.Asio, set DCB_USE_BOOST_ASIO=ON and make the matching Boost
headers/targets available to the host build. In host-provided stdexec mode,
stdexec must also be configured for the Boost Asio adapter. DCB_ASIO_NS is
the bridge’s supported namespace switch; business code should not define a
second hard-coded Asio namespace of its own.
CMake generator selection
Section titled “CMake generator selection”CmakeGenerator selects the CMake build-system generator. The right choice depends on the platform and whether the host has the matching toolchain on PATH.
| Generator | Value | Platforms | Notes |
|---|---|---|---|
msbuild |
CmakeGenerator.msbuild |
Windows only | Visual Studio multi-config generator. Requires no extra PATH setup; CMake auto-detects MSBuild. |
ninja |
CmakeGenerator.ninja |
All | Fast single-config generator. On Windows, MSVC/clang-cl builds initialize the MSVC environment automatically; MSYS2 builds use their own ucrt64 toolchain environment. |
makefiles |
CmakeGenerator.makefiles |
Linux, macOS, iOS | Unix Makefiles single-config generator. Always available but slower than Ninja. |
- On Windows,
WindowsCompiler.msvcwithgenerator: nulllets CMake auto-select the Visual Studio generator.clangCl,msys2Clang, andmsys2Gccdefault to Ninja so the selected compiler is not silently replaced by the MSVC toolset. - On Windows,
msys2Clangandmsys2Gccsupport Ninja only.CmakeGenerator.msbuildis rejected for these GNU-style toolchains, andCmakeGenerator.makefilesis not supported on Windows. - On Linux / macOS / iOS, leaving
generatorasnulllets CMake pick Unix Makefiles. Setninjawhenninjais on PATH. - On Android,
ninjais the default because the NDK bundles it.
When a generator path is required but not on PATH, pass generatorPath (e.g. ninja.exe or MSBuild.exe).
Platform configs
Section titled “Platform configs”Each platform has a dedicated config class controlling generator, compiler, runtime linkage, and cross-compilation settings.
Windows (WindowsConfig)
Section titled “Windows (WindowsConfig)”WindowsConfig( cmake: 'cmake', dynamicCrt: true, // true = /MD, false = /MT (MSVC/clang-cl only) bundleCrt: true, // copy MSVCP140 / VCRUNTIME140 next to the DLL vsInstallPath: r'C:\Program Files\Microsoft Visual Studio\2022\Community', architecture: 'x64', // 'x64' or 'arm64' generator: CmakeGenerator.ninja, generatorPath: null, compiler: WindowsCompiler.msvc, // msvc | clangCl | msys2Clang | msys2Gcc clangClPath: null, // explicit clang-cl.exe path when compiler is clangCl msys2Path: null, // explicit MSYS2 root when compiler is msys2Clang/Gcc staticRuntime: true, // statically link MSYS2 C++ runtime (self-contained DLL) extraDefines: const [],)Field reference:
| Field | Type | Default | Description |
|---|---|---|---|
cmake |
String |
'cmake' |
CMake executable. Absolute path or command resolved via PATH. |
dynamicCrt |
bool |
true |
Link the MSVC C runtime dynamically (/MD) when true, or statically (/MT) when false. MSVC-style toolchains only (msvc / clangCl). |
bundleCrt |
bool |
true |
Copy the matching runtime DLLs next to the output DLL: MSVC CRT DLLs (MSVCP140.dll, VCRUNTIME140.dll, VCRUNTIME140_1.dll) for msvc/clangCl when dynamicCrt is true; MSYS2 runtime DLLs (libgcc_s_seh-1.dll, libstdc++-6.dll, libwinpthread-1.dll) for msys2Clang/msys2Gcc when staticRuntime is false. |
vsInstallPath |
String? |
null |
Visual Studio / Build Tools installation root. When null, the builder auto-detects via vswhere.exe, then falls back to well-known paths. |
architecture |
String |
'x64' |
Target architecture passed to CMake -A. Supported: 'x64', 'arm64'. |
generator |
CmakeGenerator? |
null |
CMake generator. null lets CMake auto-select (typically Visual Studio / MSBuild on Windows; Ninja when compiler is clangCl / msys2Clang / msys2Gcc). |
generatorPath |
String? |
null |
Explicit path to the generator executable. For ninja: path to ninja.exe. For msbuild: path to MSBuild.exe. |
compiler |
WindowsCompiler |
msvc |
msvc = MSVC cl.exe (default). clangCl = LLVM clang-cl (MSVC-compatible). msys2Clang / msys2Gcc = GNU/MinGW-style MSYS2 ucrt64 clang / gcc. |
clangClPath |
String? |
null |
Explicit path to clang-cl.exe when compiler is clangCl. When null, the builder auto-detects after vcvars: VS-bundled clang-cl first, then PATH → C:\Program Files\LLVM\bin\clang-cl.exe → LLVM registry key. |
msys2Path |
String? |
null |
Explicit MSYS2 root (e.g. D:\msys2) when compiler is msys2Clang / msys2Gcc. When null, resolved from MSYS2_ROOT → C:\msys64 → C:\msys2 → D:\msys2. |
staticRuntime |
bool |
true |
MSYS2 toolchains only: statically link libgcc / libstdc++ / winpthread into the DLL (self-contained, no runtime DLLs needed on PATH). When false, the MSYS2 runtime DLLs are bundled next to the output if bundleCrt is true. |
extraDefines |
List<String> |
[] |
Extra -D definitions passed to the CMake configure step. |
Key behaviors:
dynamicCrt: trueproduces a DLL that depends on the MSVC runtime. SetbundleCrt: trueto copy the correct runtime DLLs next to the output so the app loads the matching version.dynamicCrt: falselinks the CRT statically (/MT) for a self-contained DLL.- For
msvcandclangCl,vsInstallPathis used both for selecting the CMake/MSBuild generator and for locatingvcvarsall.batwhen Ninja is requested. - For MSVC-style Ninja builds (
msvc/clangCl), the builder callsvcvarsall.bat <arch>from the resolved VS installation automatically, but only when the current process does not already have a VS developer environment (VSCMD_VER,LIB, orPATHcontaining MSVC paths). MSYS2 builds do not use this environment. compiler: WindowsCompiler.clangClbuilds with LLVMclang-cl. WithCmakeGenerator.ninja(the default for clang-cl whengeneratorisnull), the builder initializes the MSVC environment viavcvarsall.batfirst, then locates clang-cl: an explicitclangClPathwins, then a VS-bundled clang-cl (visible on the vcvars PATH when the “C++ Clang tools for Windows” component is installed), then PATH / LLVM installs / the LLVM registry key. The resolved compiler is passed as-DCMAKE_C(XX)_COMPILER=<clang-cl>and its directory is added toPATHfor the CMake process, so clang-cl does not need to be on PATH globally. WithCmakeGenerator.msbuild, the builder passes-T clangclto select the clang-cl toolset inside Visual Studio.compiler: WindowsCompiler.msys2Clang/msys2Gccbuild with the GNU/MinGW-style MSYS2 ucrt64 clang / gcc (x86_64-w64-windows-gnutarget,mingw-w64-ucrt-x86_64-clang/-gccpackages). Only the Ninja generator is supported (the default whengeneratorisnull). The MSYS2 root is resolved frommsys2Path→MSYS2_ROOT→C:\msys64→C:\msys2→D:\msys2, and-DCMAKE_C(XX)_COMPILER=<root>\ucrt64\bin\clang(++).exe(orgcc(++).exe) is passed; no vcvars environment is needed. By default (staticRuntime: true) libgcc / libstdc++ / winpthread are statically linked into the DLL, so the output only depends on the system UCRT and needs no MSYS2 runtime DLLs on PATH at runtime. WithstaticRuntime: falsethe output depends on the MSYS2 runtime DLLs (libgcc_s_seh-1.dll,libstdc++-6.dll,libwinpthread-1.dllfrom<root>\ucrt64\bin) — they are bundled next to the output whenbundleCrtistrue.
Windows compiler examples
Section titled “Windows compiler examples”Use clangCl when you want LLVM’s MSVC-compatible driver while keeping the
Visual Studio headers, libraries, and ABI:
WindowsConfig( compiler: WindowsCompiler.clangCl, generator: CmakeGenerator.ninja, // Optional with Ninja; auto-detection also finds VS-bundled or installed LLVM. clangClPath: r'C:\Program Files\LLVM\bin\clang-cl.exe',)With the clangCl compiler, install the Visual Studio C++ workload (for its
headers, libraries, and MSVC STL) plus either the VS “C++ Clang tools for
Windows” component or a standalone LLVM installation. The hook initializes the
MSVC environment before locating clang-cl.exe. It checks an explicit clangClPath, the VS-bundled
Clang tools, PATH, common LLVM installations, and the LLVM registry key. For
the Visual Studio generator, CMake’s clangcl toolset is selected instead.
Use MSYS2 when you want the GNU/MinGW-style ucrt64 toolchain. Install the
matching package (mingw-w64-ucrt-x86_64-clang or
mingw-w64-ucrt-x86_64-gcc) and point the hook at the MSYS2 root when it is not
in one of the auto-detected locations:
WindowsConfig( compiler: WindowsCompiler.msys2Clang, // or WindowsCompiler.msys2Gcc generator: CmakeGenerator.ninja, // MSYS2 is Ninja-only msys2Path: r'D:\msys2', staticRuntime: true, // no MSYS2 runtime DLLs at load time)The MSYS2 ucrt64 environment is x64-only. The hook resolves
msys2Path → MSYS2_ROOT → C:\msys64 → C:\msys2 → D:\msys2, adds
<root>\ucrt64\bin to the CMake process PATH, and does not invoke
vcvarsall.bat. With staticRuntime: false, keep that directory on the
application PATH or set bundleCrt: true so the hook copies
libgcc_s_seh-1.dll, libstdc++-6.dll, and libwinpthread-1.dll beside the
output DLL. dynamicCrt controls only MSVC-style (msvc / clangCl) builds.
Linux (LinuxConfig)
Section titled “Linux (LinuxConfig)”LinuxConfig( cmake: 'cmake', generator: CmakeGenerator.ninja, generatorPath: null, compiler: '/usr/bin/clang++', toolchainFile: null, staticLibStdCpp: true, extraDefines: const [],)Field reference:
| Field | Type | Default | Description |
|---|---|---|---|
cmake |
String |
'cmake' |
CMake executable. |
generator |
CmakeGenerator? |
null |
ninja or makefiles. null lets CMake auto-select (usually Unix Makefiles). |
generatorPath |
String? |
null |
Explicit path to ninja or make when not on PATH. |
compiler |
String? |
null |
C++ compiler executable (e.g. /usr/bin/clang++). Passed as -DCMAKE_CXX_COMPILER=<path>. |
toolchainFile |
String? |
null |
CMake toolchain file for cross-compilation. Passed as -DCMAKE_TOOLCHAIN_FILE=<path>. Takes precedence over compiler. |
staticLibStdCpp |
bool |
true |
Statically link libstdc++ into the output .so so it does not depend on the target system’s libstdc++.so.6 version. |
extraDefines |
List<String> |
[] |
Extra -D definitions passed to CMake. |
Key behaviors:
- Defaults to static
libstdc++linkage so the.sois self-contained. toolchainFilecan be used for cross-compilation; it takes precedence overcompiler.
macOS (MacosConfig)
Section titled “macOS (MacosConfig)”MacosConfig( cmake: 'cmake', generator: CmakeGenerator.ninja, generatorPath: null, compiler: null, deploymentTarget: '13.0', universal: false, extraDefines: const [],)Field reference:
| Field | Type | Default | Description |
|---|---|---|---|
cmake |
String |
'cmake' |
CMake executable. |
generator |
CmakeGenerator? |
null |
ninja or makefiles. null lets CMake auto-select. |
generatorPath |
String? |
null |
Explicit path to ninja or make. |
compiler |
String? |
null |
C++ compiler executable. null uses AppleClang. Passed as -DCMAKE_CXX_COMPILER=<path>. |
deploymentTarget |
String? |
null |
Minimum macOS deployment target (e.g. '13.0'). Maps to CMAKE_OSX_DEPLOYMENT_TARGET. |
universal |
bool |
false |
Build a universal arm64 + x86_64 binary. Sets CMAKE_OSX_ARCHITECTURES=arm64;x86_64. |
extraDefines |
List<String> |
[] |
Extra -D definitions. |
Key behaviors:
- Single-config generator (Ninja or Unix Makefiles).
CMAKE_BUILD_TYPEis set at configure time. deploymentTargetmaps toCMAKE_OSX_DEPLOYMENT_TARGET.universal: trueadds botharm64andx86_64architectures.
iOS (IosConfig)
Section titled “iOS (IosConfig)”IosConfig( cmake: 'cmake', generator: CmakeGenerator.ninja, generatorPath: null, developerDir: null, deploymentTarget: null, extraDefines: const [],)Field reference:
| Field | Type | Default | Description |
|---|---|---|---|
cmake |
String |
'cmake' |
CMake executable. |
generator |
CmakeGenerator? |
null |
ninja or makefiles. |
generatorPath |
String? |
null |
Explicit path to ninja or make. |
developerDir |
String? |
null |
Xcode developer directory. When set, passed via the DEVELOPER_DIR environment variable. null uses xcode-select -p. |
deploymentTarget |
String? |
null |
Minimum iOS deployment target override (e.g. '15.0'). null uses input.config.code.iOS.targetVersion. |
extraDefines |
List<String> |
[] |
Extra -D definitions. |
Key behaviors:
- Cross-compiles with
-DCMAKE_SYSTEM_NAME=iOS. - The hooks system tells the builder whether the target is device (
iphoneos) or simulator (iphonesimulator), and the target architecture. - iOS requires static linking; the builder honors the hooks
linkModePreference. - The minimum deployment target is floored at
14.0because the C++20 runtime usesstd::atomic::wait/notify.
Android (AndroidConfig)
Section titled “Android (AndroidConfig)”AndroidConfig( cmake: 'cmake', ndkPath: r'C:\Users\<you>\AppData\Local\Android\Sdk\ndk\29.0.14206865', abi: null, // null = derive from targetArchitecture androidPlatform: 21, staticStl: true, generator: CmakeGenerator.ninja, extraDefines: const [],)Field reference:
| Field | Type | Default | Description |
|---|---|---|---|
cmake |
String |
'cmake' |
CMake executable. On Windows, if not on PATH, the builder probes the VS-bundled CMake. |
ndkPath |
String |
required | Android NDK root directory. The builder derives the toolchain file from <ndkPath>/build/cmake/android.toolchain.cmake. |
abi |
String? |
null |
Target ABI. null derives from input.config.code.targetArchitecture: arm64 → arm64-v8a, arm → armeabi-v7a, x64 → x86_64, ia32 → x86. |
androidPlatform |
int |
21 |
Minimum Android API level. Passed as -DANDROID_PLATFORM=android-<level>. |
staticStl |
bool |
true |
true links c++_static; false links c++_shared and registers libc++_shared.so as an additional code asset. |
generator |
CmakeGenerator? |
CmakeGenerator.ninja |
CMake generator. The NDK bundles Ninja, so Ninja is the default. |
extraDefines |
List<String> |
[] |
Extra -D definitions. |
Key behaviors:
- Uses the NDK’s CMake toolchain file at
<ndkPath>/build/cmake/android.toolchain.cmake. staticStl: truelinksc++_static(self-contained.so).staticStl: falselinksc++_sharedand the builder registerslibc++_shared.soas an additional code asset so it is packaged into the APK.- On Windows, if
cmakeis not on PATH the builder probes the Visual Studio CMake bundled with the IDE. When using Ninja on Windows, the builder also ensures the bundledninja.exeis on PATH.
Build options
Section titled “Build options”DcbBuildOptions controls behavior across platforms:
DcbBuildOptions( debug: null, // null = auto-detect from linkingEnabled parallel: true, // pass --parallel to cmake --build copyCompileCommands: true, // generate and copy compile_commands.json compileCommandsPath: 'compile_commands.json', // relative to package root)Field reference:
| Field | Type | Default | Description |
|---|---|---|---|
debug |
bool? |
null |
Force Debug (true) or Release (false). null infers from input.config.linkingEnabled. |
parallel |
bool |
true |
Pass --parallel to cmake --build, enabling multi-file compilation. |
copyCompileCommands |
bool |
true |
Pass -DCMAKE_EXPORT_COMPILE_COMMANDS=ON and copy the generated compile_commands.json after a successful build. |
compileCommandsPath |
String |
'compile_commands.json' |
Relative path under the package root where compile_commands.json is copied. Parent directories are created automatically. |
When debug is null, the builder infers it from input.config.linkingEnabled:
linkingEnabled == true→ AOT / release →ReleaselinkingEnabled == false→ JIT / debug →Debug
This matches the Native Assets convention used by dart run versus dart compile / Flutter release builds.
compile_commands.json
Section titled “compile_commands.json”By default, the builder:
- Passes
-DCMAKE_EXPORT_COMPILE_COMMANDS=ONto CMake (for generators that support it, such as Ninja or Makefiles). - After a successful build, copies the generated
compile_commands.jsonto the package root next topubspec.yaml.
To place the file elsewhere, set compileCommandsPath to a relative path:
const DcbBuildOptions( copyCompileCommands: true, compileCommandsPath: 'build/compile_commands.json',)The destination is resolved relative to the package root, and any missing parent directories are created automatically. Set copyCompileCommands: false to disable generation and copying entirely.
Asset name and package
Section titled “Asset name and package”The generated FFI bindings load the native library through a @Native annotation like:
@Native<IntPtr Function()>(assetId: 'package:my_project/src/native_gen/dcb_bindings.dart')DcbCMakeBuilder emits a CodeAsset whose name is the assetName you passed, and whose package defaults to the building package. The builder also supports assetPackage: 'dart_cpp_bridge' for downstream libraries that embed the runtime via WHOLE_ARCHIVE and want runtime @Native annotations to resolve against their combined library.
Caching and invalidation
Section titled “Caching and invalidation”The builder writes a stamp file into the build directory recording the exact CMake configure arguments. If you change a config value (for example, switching Android STL from c++_static to c++_shared or changing the ABI), the builder detects the difference and wipes the stale build directory before reconfiguring.
It also declares all files under sourceDir with common native extensions (.c, .cpp, .h, .hpp, .cmake, CMakeLists.txt, etc.) as hook dependencies, so changing business code automatically triggers a rebuild.
Windows MSVC environment details
Section titled “Windows MSVC environment details”When CmakeGenerator.ninja is used on Windows, the builder must ensure cl.exe, link.exe, and the Windows SDK paths are available. It does this automatically:
- Resolve the VS installation root (
vsInstallPath→vswhere.exe→ well-known paths). - Locate
<vsRoot>\VC\Auxiliary\Build\vcvarsall.bat. - If the current process already has a VS developer environment (
VSCMD_VERset, orLIB/PATHcontaining MSVC paths), reuse it. - Otherwise, run
vcvarsall.bat <arch> >nul 2>&1 && setand capture the environment variables. - Pass the captured environment to the CMake configure and build processes.
If vcvarsall.bat cannot be found or fails, the builder logs a warning and falls back to the current environment. In that case Ninja may fail to locate cl.exe.
Debugging hook failures
Section titled “Debugging hook failures”When a hook fails, the Native Assets runner prints the path to a log directory. Look for:
stdout.txt— contains[dcb]log lines fromDcbCMakeBuilder, including the exact CMake command line.stderr.txt— CMake errors, compiler errors, andDcbCMakeExceptionmessages.
Common issues:
| Symptom | Likely cause | Fix |
|---|---|---|
cmake not found |
CMake not on PATH | Install CMake >= 3.25 and ensure it is on PATH. |
vcvarsall.bat not found |
Using Ninja on Windows without MSVC env | Install VS Build Tools, set vsInstallPath, or switch to CmakeGenerator.msbuild. |
libc++_shared.so not found |
Android NDK path wrong / ABI mismatch | Verify ndkPath. If abi is omitted, check that input.config.code.targetArchitecture is supported. |
Could not locate built library |
CMake output name mismatch | Ensure libName matches add_library() in CMakeLists.txt. |
Version mismatch error from dcb_gen_tool |
dart_cpp_bridge and dcb_gen_tool versions differ |
Run dart pub upgrade dart_cpp_bridge or update dcb_gen_tool. |
Further reading
Section titled “Further reading”- Native Assets on dart.dev
- Project Directory Structure — where
hook/build.dart,native/, and generated files live - Getting Started — end-to-end setup from dependencies to first generated call
- Architecture Design — how the built library is consumed at runtime