Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[native_toolchain_c] Add linking on Linux #987

Merged
merged 32 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/native.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ jobs:
- run: dart pub get -C test_data/add_asset_link/
if: ${{ matrix.package == 'native_assets_builder' }}

- run: dart pub get -C test_data/treeshaking_native_libs/
if: ${{ matrix.package == 'native_assets_builder' }}

- run: dart pub get -C example/build/native_add_app/
if: ${{ matrix.package == 'native_assets_cli' }}

Expand Down
33 changes: 33 additions & 0 deletions pkgs/native_assets_builder/test/build_runner/link_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,39 @@ void main() async {
);
});
});

test('treeshaking assets using CLinker', timeout: longTimeout, () async {
await inTempDir((tempUri) async {
await copyTestProjects(targetUri: tempUri);
final packageUri = tempUri.resolve('treeshaking_native_libs/');

// First, run `pub get`, we need pub to resolve our dependencies.
await runPubGet(
workingDirectory: packageUri,
logger: logger,
);

final buildResult = await build(
packageUri,
logger,
dartExecutable,
linkingEnabled: true,
);
expect(buildResult.assets.length, 0);
expect(buildResult.assetsForLinking.length, 1);

final logMessages = <String>[];
final linkResult = await link(
packageUri,
logger,
dartExecutable,
buildResult: buildResult,
capturedLogs: logMessages,
);
expect(linkResult.assets.length, 1);
expect(linkResult.assets.first, isA<NativeCodeAsset>());
});
});
}

Iterable<String> _getNames(List<AssetImpl> assets) =>
Expand Down
12 changes: 12 additions & 0 deletions pkgs/native_assets_builder/test_data/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@
- simple_data_asset/bin/deep_modify_data_asset.dart.debug
- some_dev_dep/bin/some_dev_dep.dart
- some_dev_dep/pubspec.yaml
- treeshaking_native_libs/pubspec.yaml
mosuem marked this conversation as resolved.
Show resolved Hide resolved
- treeshaking_native_libs/lib/treeshaking_native_libs.dart
- treeshaking_native_libs/lib/src/treeshaking_native_libs.dart
- treeshaking_native_libs/lib/src/treeshaking_native_libs_bindings_generated.dart
- treeshaking_native_libs/src/native_add.h
- treeshaking_native_libs/src/native_multiply.h
- treeshaking_native_libs/src/native_add.c
- treeshaking_native_libs/src/native_multiply.c
- treeshaking_native_libs/hook/link.dart
- treeshaking_native_libs/hook/build.dart
- treeshaking_native_libs/bin/treeshaking_native_libs.dart
- treeshaking_native_libs/ffigen.yaml
- wrong_build_output_2/hook/build.dart
- wrong_build_output_2/pubspec.yaml
- wrong_build_output_3/hook/build.dart
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:treeshaking_native_libs/treeshaking_native_libs.dart';

void main(List<String> args) {
print(add(5, 3));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Run with `flutter pub run ffigen --config ffigen.yaml`.
name: NativeCalcBindings
description: |
Bindings for `src/native_add.h` and `src/native_multiply.h`.

Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`.
output: "lib/src/treeshaking_native_libs_bindings_generated.dart"
headers:
entry-points:
- "src/native_add.h"
- "src/native_multiply.h"
include-directives:
- "src/native_add.h"
- "src/native_multiply.h"
preamble: |
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
comments:
style: any
length: full
ffi-native:
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';

void main(List<String> arguments) async {
await build(arguments, (config, output) async {
final cbuilder = CBuilder.library(
name: config.packageName + (config.linkingEnabled ? '_static' : ''),
assetName: 'src/${config.packageName}_bindings_generated.dart',
sources: [
'src/native_add.c',
'src/native_multiply.c',
],
linkModePreference: config.linkingEnabled
? LinkModePreference.static
: LinkModePreference.dynamic,
);
await cbuilder.run(
config: config,
output: output,
linkInPackage: config.linkingEnabled ? config.packageName : null,
logger: Logger('')
..level = Level.ALL
..onRecord.listen((record) {
print('${record.level.name}: ${record.time}: ${record.message}');
}),
);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:native_toolchain_c/native_toolchain_c.dart';

void main(List<String> arguments) async {
await link(
arguments,
(config, output) async {
final linker = CLinker.library(
name: config.packageName,
assetName: config.assets.single.id.split('/').skip(1).join('/'),
linkerOptions: LinkerOptions.treeshake(symbols: ['add']),
mosuem marked this conversation as resolved.
Show resolved Hide resolved
sources: [config.assets.single.file!.toFilePath()],
);
await linker.run(
config: config,
output: output,
logger: Logger('')
..level = Level.ALL
..onRecord.listen((record) {
print('${record.level.name}: ${record.time}: ${record.message}');
}),
);
},
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'treeshaking_native_libs_bindings_generated.dart' as bindings;

int add(int a, int b) => bindings.add(a, b);
int multiply(int a, int b) => bindings.multiply(a, b);
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
import 'dart:ffi' as ffi;

@ffi.Native<ffi.Int32 Function(ffi.Int32, ffi.Int32)>(symbol: 'add')
external int add(
int a,
int b,
);

@ffi.Native<ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr)>(symbol: 'multiply')
external int multiply(
int a,
int b,
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

export 'src/treeshaking_native_libs.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: treeshaking_native_libs
description: Treeshake symbols by name from a native library.
version: 0.1.0

publish_to: none

environment:
sdk: '>=3.3.0 <4.0.0'

dependencies:
logging: ^1.1.1
# native_assets_cli: ^0.7.1
native_assets_cli:
path: ../../../native_assets_cli/
# native_toolchain_c: ^0.5.2
native_toolchain_c:
path: ../../../native_toolchain_c/

dev_dependencies:
ffigen: ^8.0.2
lints: ^3.0.0
some_dev_dep:
path: ../some_dev_dep/
test: ^1.23.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "native_add.h"

int32_t add(int32_t a, int32_t b) {
return a + b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <stdint.h>

#if _WIN32
#define MYLIB_EXPORT __declspec(dllexport)
#else
#define MYLIB_EXPORT
#endif

MYLIB_EXPORT int32_t add(int32_t a, int32_t b);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "native_multiply.h"

MYLIB_EXPORT intptr_t multiply(intptr_t a, intptr_t b) {
return a * b;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <stdint.h>

#if _WIN32
#define MYLIB_EXPORT __declspec(dllexport)
#else
#define MYLIB_EXPORT
#endif

MYLIB_EXPORT intptr_t multiply(intptr_t a, intptr_t b);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:test/test.dart';
import 'package:treeshaking_native_libs/treeshaking_native_libs.dart';

void main() {
mosuem marked this conversation as resolved.
Show resolved Hide resolved
test('native add test', () {
final result = add(4, 6);
expect(result, equals(10));
});
}
5 changes: 4 additions & 1 deletion pkgs/native_toolchain_c/lib/native_toolchain_c.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
/// A library to invoke the native C compiler installed on the host machine.
library;

export 'src/cbuilder/cbuilder.dart';
export 'src/cbuilder/cbuilder.dart' show CBuilder;
mosuem marked this conversation as resolved.
Show resolved Hide resolved
export 'src/cbuilder/clinker.dart' show CLinker, LinkerOptions;
export 'src/cbuilder/language.dart' show Language;
export 'src/cbuilder/output_type.dart' show OutputType;
export 'src/utils/env_from_bat.dart';
Loading