Skip to content

Commit 7332779

Browse files
committed
Added support for android and iOS
1 parent eacd810 commit 7332779

File tree

3 files changed

+91
-8
lines changed

3 files changed

+91
-8
lines changed

hook/android_ndk.dart

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import 'dart:io';
2+
3+
import 'package:logging/logging.dart';
4+
import 'package:native_toolchain_c/src/native_toolchain/android_ndk.dart' as ntc_ndk;
5+
import 'package:native_toolchain_c/src/tool/tool_instance.dart';
6+
7+
/// Resolve the Android NDK root, picking the latest installed version.
8+
/// Uses the native_toolchain_cmake resolver first, then falls back to a local scan.
9+
Future<String> resolveAndroidNdkRoot() async {
10+
try {
11+
final resolver = ntc_ndk.androidNdk.defaultResolver;
12+
if (resolver != null) {
13+
final instances = await resolver.resolve(logger: Logger.detached('android_ndk'));
14+
final ndkInstance = _pickNdkInstance(instances);
15+
final ndkPath = Directory.fromUri(ndkInstance.uri).path;
16+
if (await Directory(ndkPath).exists()) {
17+
return ndkPath;
18+
}
19+
}
20+
} catch (_) {
21+
// fall through to legacy resolution
22+
}
23+
throw Exception('Android NDK not found. Set ANDROID_NDK_ROOT or install it via Android Studio (SDK Manager > NDK).');
24+
}
25+
26+
ToolInstance _pickNdkInstance(List<ToolInstance> instances) {
27+
final ndkInstances = instances.where((i) => i.tool.name == ntc_ndk.androidNdk.name).toList();
28+
if (ndkInstances.isEmpty) {
29+
throw StateError('No Android NDK instance resolved');
30+
}
31+
32+
ndkInstances.sort(
33+
(a, b) => switch ((a.version, b.version)) {
34+
(null, null) => 0,
35+
(null, _) => 1,
36+
(_, null) => -1,
37+
(_, _) => -a.version!.compareTo(b.version!),
38+
},
39+
);
40+
41+
return ndkInstances.first;
42+
}
43+
44+
String resolveAndroidToolchainBinDir(String ndkRoot) {
45+
// Android NDK toolchain binaries live under toolchains/llvm/prebuilt/<host>/bin.
46+
// Pick the first host tag that exists for the current platform.
47+
final hostTags = switch (Platform.operatingSystem) {
48+
'macos' => const ['darwin-x86_64', 'darwin-arm64'],
49+
'linux' => const ['linux-x86_64'],
50+
'windows' => const ['windows-x86_64', 'windows-arm64'],
51+
final os => throw UnsupportedError('Unsupported host OS for Android NDK: $os'),
52+
};
53+
54+
for (final host in hostTags) {
55+
final binDir = Directory('$ndkRoot/toolchains/llvm/prebuilt/$host/bin');
56+
if (binDir.existsSync()) {
57+
return binDir.path;
58+
}
59+
}
60+
61+
throw StateError(
62+
'Android NDK toolchain bin directory not found under '
63+
'$ndkRoot/toolchains/llvm/prebuilt for host ${Platform.operatingSystem}.',
64+
);
65+
}

hook/build.dart

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import 'dart:io';
33
import 'package:code_assets/code_assets.dart';
44
import 'package:hooks/hooks.dart';
55

6+
import 'android_ndk.dart';
7+
68
const version = '3.5.4';
79
const sourceCodeUrl = 'https://github.com/openssl/openssl/releases/download/openssl-$version/openssl-$version.tar.gz';
810
const openSslDirName = 'openssl-$version';
@@ -26,7 +28,21 @@ void main(List<String> args) async {
2628

2729
// build source code, depends on the OS we are running on
2830
// Read https://github.com/openssl/openssl/blob/openssl-3.5.4/INSTALL.md#building-openssl
29-
final configName = resolveConfigName(input.config.code.targetOS, input.config.code.targetArchitecture);
31+
final configName = resolveConfigName(
32+
input.config.code.targetOS,
33+
input.config.code.targetArchitecture,
34+
input.config.code.targetOS == OS.iOS ? input.config.code.iOS.targetSdk : null,
35+
);
36+
if (input.config.code.targetOS == OS.android) {
37+
final ndkRoot = await resolveAndroidNdkRoot();
38+
environment['ANDROID_NDK_ROOT'] = ndkRoot;
39+
environment['ANDROID_NDK_HOME'] = ndkRoot;
40+
41+
final toolchainBin = resolveAndroidToolchainBinDir(ndkRoot);
42+
final existingPath = Platform.environment['PATH'] ?? '';
43+
final pathSeparator = Platform.isWindows ? ';' : ':';
44+
environment['PATH'] = '$toolchainBin$pathSeparator$existingPath';
45+
}
3046
switch (OS.current) {
3147
case OS.windows:
3248
final msvcEnv = await resolveWindowsBuildEnvironment(input.config.code.targetArchitecture);
@@ -93,12 +109,12 @@ void main(List<String> args) async {
93109
// determine the libName from OS and Link mode
94110
final libName = switch ((input.config.code.targetOS, input.config.code.linkModePreference)) {
95111
(OS.windows, LinkModePreference.static || LinkModePreference.preferStatic) => 'libcrypto_static.lib',
96-
(OS.macOS, LinkModePreference.static || LinkModePreference.preferStatic) => 'libcrypto.a',
97-
(OS.linux, LinkModePreference.static || LinkModePreference.preferStatic) => 'libcrypto.a',
112+
(OS.macOS || OS.iOS, LinkModePreference.static || LinkModePreference.preferStatic) => 'libcrypto.a',
113+
(OS.linux || OS.android, LinkModePreference.static || LinkModePreference.preferStatic) => 'libcrypto.a',
98114
(OS.windows, LinkModePreference.dynamic || LinkModePreference.preferDynamic) =>
99115
'libcrypto-3-${input.config.code.targetArchitecture.name}.dll',
100-
(OS.macOS, LinkModePreference.dynamic || LinkModePreference.preferDynamic) => 'libcrypto.dylib',
101-
(OS.linux, LinkModePreference.dynamic || LinkModePreference.preferDynamic) => 'libcrypto.so',
116+
(OS.macOS || OS.iOS, LinkModePreference.dynamic || LinkModePreference.preferDynamic) => 'libcrypto.dylib',
117+
(OS.linux || OS.android, LinkModePreference.dynamic || LinkModePreference.preferDynamic) => 'libcrypto.so',
102118
_ => throw UnsupportedError(
103119
'Unsupported target OS: ${input.config.code.targetOS.name} or link mode preference: ${input.config.code.linkModePreference.name}',
104120
),
@@ -142,7 +158,8 @@ Future<bool> isProgramInstalled(String programName) async {
142158
}
143159
}
144160

145-
String resolveConfigName(OS os, Architecture architecture) {
161+
String resolveConfigName(OS os, Architecture architecture, IOSSdk? iosSdk) {
162+
final isIosSimulator = iosSdk == IOSSdk.iPhoneSimulator;
146163
return switch ((os, architecture)) {
147164
(OS.android, Architecture.arm) => 'android-arm',
148165
(OS.android, Architecture.arm64) => 'android-arm64',
@@ -151,7 +168,7 @@ String resolveConfigName(OS os, Architecture architecture) {
151168
(OS.android, Architecture.riscv64) => 'android-riscv64',
152169

153170
(OS.iOS, Architecture.arm) => 'ios-xcrun',
154-
(OS.iOS, Architecture.arm64) => 'ios64-xcrun',
171+
(OS.iOS, Architecture.arm64) => isIosSimulator ? 'iossimulator-arm64-xcrun' : 'ios64-xcrun',
155172
(OS.iOS, Architecture.ia32) => 'iossimulator-i386-xcrun',
156173
(OS.iOS, Architecture.x64) => 'iossimulator-x86_64-xcrun',
157174

pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: openssl
22
description: OpenSSL library for Dart, exposes full C API to Dart via FFI. Native-assets build that compiles OpenSSL from source.
3-
version: 1.0.0
3+
version: 1.0.1
44
repository: https://github.com/LucazzP/openssl_dart
55

66
environment:
@@ -12,6 +12,7 @@ dependencies:
1212
code_assets: ^1.0.0
1313
logging: ^1.3.0
1414
ffi: ^2.1.5
15+
native_toolchain_c: ^0.17.4
1516
# path: ^1.9.0
1617

1718
dev_dependencies:

0 commit comments

Comments
 (0)