Example

A package my_package that ships prebuilt libmy_lib binaries on GitHub Releases, can build them from C sources, and tree-shakes them in its link hook.

lib/src/hook_helpers/library.dart

import 'package:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';
import 'package:prebuilt_code_assets/prebuilt_code_assets.dart';
import 'package:record_use/record_use.dart' as record_use;

import 'hashes.dart'; // Generated by tool/regenerate_hashes.dart.

const _recordUseMapping = {'myAdd': 'my_add', 'myMultiply': 'my_multiply'};

final myLibrary = PrebuiltLibrary(
  name: 'my_lib',
  assetName: 'my_package.dart',
  releaseConfig: PrebuiltReleaseConfig.github(
    owner: 'my-org',
    repo: 'my_package',
    version: version,
    fileHashes: fileHashes,
    libraryName: 'my_lib',
  ),
  buildFromSource: (input, output, {required static, checkoutPath}) async {
    final builderOutput = BuildOutputBuilder();
    await CBuilder.library(
      name: 'my_lib',
      assetName: 'my_package.dart',
      sources: ['src/my_lib.c'],
      linkModePreference: static
          ? LinkModePreference.static
          : LinkModePreference.dynamic,
    ).run(input: input, output: builderOutput);
    final built = BuildOutput(builderOutput.json);
    output.dependencies.addAll(built.dependencies);
    return built.assets.code.single.file!;
  },
  usedSymbols: SymbolsResolvers.fromRecordUseMapping(
    const record_use.Library('package:my_package/src/bindings.dart'),
    _recordUseMapping,
  ),
);

hook/build.dart and hook/link.dart

// hook/build.dart
import 'package:hooks/hooks.dart';
import 'package:my_package/src/hook_helpers/library.dart';

Future<void> main(List<String> args) async {
  await build(args, (input, output) => myLibrary.build(input: input, output: output));
}
// hook/link.dart
import 'package:hooks/hooks.dart';
import 'package:my_package/src/hook_helpers/library.dart';

Future<void> main(List<String> args) async {
  await link(args, (input, output) => myLibrary.link(input: input, output: output));
}

Release tooling

// tool/precompile_binaries.dart
// dart tool/precompile_binaries.dart --target-os linux --target-arch x64
import 'package:my_package/src/hook_helpers/library.dart';
import 'package:prebuilt_code_assets/tools.dart';

Future<void> main(List<String> args) =>
    runPrecompileBinariesCli(args, library: myLibrary);
// tool/regenerate_hashes.dart
// dart tool/regenerate_hashes.dart <version> [<directory with binaries>]
import 'package:prebuilt_code_assets/prebuilt_code_assets.dart';
import 'package:prebuilt_code_assets/tools.dart';

Future<void> main(List<String> args) => runRegenerateHashesCli(
  args,
  defaultVersion: '1.0.0',
  releaseConfigForVersion: (version) => PrebuiltReleaseConfig.github(
    owner: 'my-org',
    repo: 'my_package',
    version: version,
    fileHashes: const {},
    libraryName: 'my_lib',
  ),
);

test/integration_test.dart in this repository runs this whole flow end to end.