Skip to content

Commit fcc783c

Browse files
authored
[native_x] Add support for minimum iOS and MacOS versions (#1239)
Closes: * #1133 Also adds the same for MacOS. Maybe the fields should be `targetMinimumIosSdk` and `targetMinimumMacOSSdk` as theoretically speaking there's also a target SDK version. (But as with the Android NDK API version, that defaults to whatever version your compiler is I believe.) (This PR should be followed up by passing these values from Flutter tools.)
1 parent efd9b93 commit fcc783c

File tree

24 files changed

+699
-45
lines changed

24 files changed

+699
-45
lines changed

.github/workflows/health.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ jobs:
1414
uses: dart-lang/ecosystem/.github/workflows/health.yaml@main
1515
with:
1616
coverage_web: false
17-
checks: "version,changelog,license,do-not-submit,breaking,coverage"
17+
# TODO(https://github.com/dart-lang/native/issues/1242): Add coverage back.
18+
checks: "version,changelog,license,do-not-submit,breaking"
1819
use-flutter: true
1920
sdk: master
2021
permissions:

pkgs/native_assets_builder/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## 0.7.1-wip
22

3-
- Nothing yet.
3+
- Use `HookConfig.targetIosSdk` and `HookConfig.targetMacosSdk` optional
4+
values, and add examples to fail builds based on this.
45

56
## 0.7.0
67

pkgs/native_assets_builder/lib/src/build_runner/build_runner.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class NativeAssetsBuildRunner {
4747
required BuildModeImpl buildMode,
4848
CCompilerConfigImpl? cCompilerConfig,
4949
IOSSdkImpl? targetIOSSdk,
50+
int? targetIOSVersion,
51+
int? targetMacOSVersion,
5052
int? targetAndroidNdkApi,
5153
required bool includeParentEnvironment,
5254
PackageLayout? packageLayout,
@@ -61,6 +63,8 @@ class NativeAssetsBuildRunner {
6163
buildMode: buildMode,
6264
cCompilerConfig: cCompilerConfig,
6365
targetIOSSdk: targetIOSSdk,
66+
targetIOSVersion: targetIOSVersion,
67+
targetMacOSVersion: targetMacOSVersion,
6468
targetAndroidNdkApi: targetAndroidNdkApi,
6569
includeParentEnvironment: includeParentEnvironment,
6670
packageLayout: packageLayout,
@@ -82,6 +86,8 @@ class NativeAssetsBuildRunner {
8286
required BuildModeImpl buildMode,
8387
CCompilerConfigImpl? cCompilerConfig,
8488
IOSSdkImpl? targetIOSSdk,
89+
int? targetIOSVersion,
90+
int? targetMacOSVersion,
8591
int? targetAndroidNdkApi,
8692
required bool includeParentEnvironment,
8793
PackageLayout? packageLayout,
@@ -98,6 +104,8 @@ class NativeAssetsBuildRunner {
98104
buildMode: buildMode,
99105
cCompilerConfig: cCompilerConfig,
100106
targetIOSSdk: targetIOSSdk,
107+
targetIOSVersion: targetIOSVersion,
108+
targetMacOSVersion: targetMacOSVersion,
101109
targetAndroidNdkApi: targetAndroidNdkApi,
102110
includeParentEnvironment: includeParentEnvironment,
103111
packageLayout: packageLayout,
@@ -116,6 +124,8 @@ class NativeAssetsBuildRunner {
116124
required BuildModeImpl buildMode,
117125
CCompilerConfigImpl? cCompilerConfig,
118126
IOSSdkImpl? targetIOSSdk,
127+
int? targetIOSVersion,
128+
int? targetMacOSVersion,
119129
int? targetAndroidNdkApi,
120130
required bool includeParentEnvironment,
121131
PackageLayout? packageLayout,
@@ -161,6 +171,8 @@ class NativeAssetsBuildRunner {
161171
cCompilerConfig,
162172
targetIOSSdk,
163173
targetAndroidNdkApi,
174+
targetIOSVersion,
175+
targetMacOSVersion,
164176
supportedAssetTypes,
165177
hook,
166178
resourceIdentifiers,
@@ -192,6 +204,8 @@ class NativeAssetsBuildRunner {
192204
CCompilerConfigImpl? cCompilerConfig,
193205
IOSSdkImpl? targetIOSSdk,
194206
int? targetAndroidNdkApi,
207+
int? targetIOSVersion,
208+
int? targetMacOSVersion,
195209
Iterable<String>? supportedAssetTypes,
196210
Hook hook,
197211
Uri? resourceIdentifiers,
@@ -236,6 +250,8 @@ class NativeAssetsBuildRunner {
236250
targetArchitecture: target.architecture,
237251
buildMode: buildMode,
238252
targetIOSSdk: targetIOSSdk,
253+
targetIOSVersion: targetIOSVersion,
254+
targetMacOSVersion: targetMacOSVersion,
239255
cCompiler: cCompilerConfig,
240256
targetAndroidNdkApi: targetAndroidNdkApi,
241257
resourceIdentifierUri: resourcesFile?.uri,
@@ -253,6 +269,8 @@ class NativeAssetsBuildRunner {
253269
buildMode: buildMode,
254270
linkModePreference: linkModePreference,
255271
targetIOSSdk: targetIOSSdk,
272+
targetIOSVersion: targetIOSVersion,
273+
targetMacOSVersion: targetMacOSVersion,
256274
cCompiler: cCompilerConfig,
257275
dependencyMetadata: dependencyMetadata,
258276
targetAndroidNdkApi: targetAndroidNdkApi,
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:logging/logging.dart';
6+
import 'package:native_assets_cli/native_assets_cli.dart' show OS;
7+
import 'package:native_assets_cli/native_assets_cli_internal.dart'
8+
show IOSSdkImpl, Target;
9+
import 'package:test/test.dart';
10+
11+
import '../helpers.dart';
12+
import 'helpers.dart';
13+
14+
const Timeout longTimeout = Timeout(Duration(minutes: 5));
15+
16+
// Simulate needing some version of the API.
17+
const minNdkApiVersionForThisPackage = 28;
18+
const minIosVersionForThisPackage = 16;
19+
const minMacOSVersionForThisPackage = 13;
20+
21+
final List<(Target, List<(int sdkVersion, bool success)>)> osConfig = [
22+
(
23+
Target.androidArm64,
24+
[
25+
(minNdkApiVersionForThisPackage, true),
26+
(minNdkApiVersionForThisPackage - 1, false)
27+
]
28+
),
29+
if (OS.current == OS.macOS) ...[
30+
(
31+
Target.macOSArm64,
32+
[
33+
(minMacOSVersionForThisPackage, true),
34+
(minMacOSVersionForThisPackage - 1, false)
35+
]
36+
),
37+
(
38+
Target.iOSArm64,
39+
[
40+
(minIosVersionForThisPackage, true),
41+
(minIosVersionForThisPackage - 1, false)
42+
]
43+
),
44+
],
45+
];
46+
47+
final List<(String hook, String testPath)> hooks = [
48+
('build', 'fail_on_os_sdk_version/'),
49+
('link', 'fail_on_os_sdk_version_link/'),
50+
];
51+
52+
void main() async {
53+
for (final (target, versions) in osConfig) {
54+
for (final (version, success) in versions) {
55+
final statusString = success ? 'succeed' : 'fail';
56+
for (final (hook, packagePath) in hooks) {
57+
test('$statusString $hook for $target sdk version',
58+
timeout: longTimeout, () async {
59+
await inTempDir((tempUri) async {
60+
await copyTestProjects(targetUri: tempUri);
61+
final packageUri = tempUri.resolve(packagePath);
62+
63+
await runPubGet(
64+
workingDirectory: packageUri,
65+
logger: logger,
66+
);
67+
68+
{
69+
final logMessages = <String>[];
70+
final (buildResult, linkResult) = await buildAndLink(
71+
target: target,
72+
targetIOSSdk:
73+
(target.os == OS.iOS) ? IOSSdkImpl.iPhoneOS : null,
74+
targetIOSVersion: (target.os == OS.iOS) ? version : null,
75+
targetMacOSVersion: (target.os == OS.macOS) ? version : null,
76+
targetAndroidNdkApi: (target.os == OS.android) ? version : null,
77+
packageUri,
78+
createCapturingLogger(logMessages, level: Level.SEVERE),
79+
dartExecutable,
80+
);
81+
final fullLog = logMessages.join('\n');
82+
if (hook == 'build') {
83+
expect(buildResult.success, success);
84+
} else {
85+
assert(hook == 'link');
86+
expect(buildResult.success, true);
87+
expect(linkResult.success, success);
88+
}
89+
if (!success) {
90+
expect(
91+
fullLog,
92+
contains(
93+
'The native assets for this package require at least',
94+
),
95+
);
96+
}
97+
}
98+
});
99+
});
100+
}
101+
}
102+
}
103+
}

pkgs/native_assets_builder/test/build_runner/helpers.dart

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'dart:io';
88
import 'package:file_testing/file_testing.dart';
99
import 'package:logging/logging.dart';
1010
import 'package:native_assets_builder/native_assets_builder.dart';
11+
import 'package:native_assets_builder/src/model/hook_result.dart';
1112
import 'package:native_assets_cli/native_assets_cli_internal.dart';
1213
import 'package:test/test.dart';
1314

@@ -40,6 +41,11 @@ Future<BuildResult> build(
4041
List<String>? capturedLogs,
4142
PackageLayout? packageLayout,
4243
String? runPackageName,
44+
IOSSdkImpl? targetIOSSdk,
45+
int? targetIOSVersion,
46+
int? targetMacOSVersion,
47+
int? targetAndroidNdkApi,
48+
Target? target,
4349
}) async =>
4450
await runWithLog(capturedLogs, () async {
4551
final result = await NativeAssetsBuildRunner(
@@ -48,16 +54,23 @@ Future<BuildResult> build(
4854
).build(
4955
buildMode: BuildModeImpl.release,
5056
linkModePreference: linkModePreference,
51-
target: Target.current,
57+
target: target ?? Target.current,
5258
workingDirectory: packageUri,
5359
cCompilerConfig: cCompilerConfig,
5460
includeParentEnvironment: includeParentEnvironment,
5561
packageLayout: packageLayout,
5662
runPackageName: runPackageName,
63+
targetIOSSdk: targetIOSSdk,
64+
targetIOSVersion: targetIOSVersion,
65+
targetMacOSVersion: targetMacOSVersion,
66+
targetAndroidNdkApi: targetAndroidNdkApi,
5767
);
5868

5969
if (result.success) {
6070
await expectAssetsExist(result.assets);
71+
for (final assetsForLinking in result.assetsForLinking.values) {
72+
await expectAssetsExist(assetsForLinking);
73+
}
6174
}
6275

6376
return result;
@@ -74,6 +87,11 @@ Future<LinkResult> link(
7487
PackageLayout? packageLayout,
7588
required BuildResult buildResult,
7689
Uri? resourceIdentifiers,
90+
IOSSdkImpl? targetIOSSdk,
91+
int? targetIOSVersion,
92+
int? targetMacOSVersion,
93+
int? targetAndroidNdkApi,
94+
Target? target,
7795
}) async =>
7896
await runWithLog(capturedLogs, () async {
7997
final result = await NativeAssetsBuildRunner(
@@ -82,13 +100,17 @@ Future<LinkResult> link(
82100
).link(
83101
linkModePreference: linkModePreference,
84102
buildMode: BuildModeImpl.release,
85-
target: Target.current,
103+
target: target ?? Target.current,
86104
workingDirectory: packageUri,
87105
cCompilerConfig: cCompilerConfig,
88106
includeParentEnvironment: includeParentEnvironment,
89107
packageLayout: packageLayout,
90108
buildResult: buildResult,
91109
resourceIdentifiers: resourceIdentifiers,
110+
targetIOSSdk: targetIOSSdk,
111+
targetIOSVersion: targetIOSVersion,
112+
targetMacOSVersion: targetMacOSVersion,
113+
targetAndroidNdkApi: targetAndroidNdkApi,
92114
);
93115

94116
if (result.success) {
@@ -98,6 +120,75 @@ Future<LinkResult> link(
98120
return result;
99121
});
100122

123+
Future<(BuildResult, LinkResult)> buildAndLink(
124+
Uri packageUri,
125+
Logger logger,
126+
Uri dartExecutable, {
127+
LinkModePreferenceImpl linkModePreference = LinkModePreferenceImpl.dynamic,
128+
CCompilerConfigImpl? cCompilerConfig,
129+
bool includeParentEnvironment = true,
130+
List<String>? capturedLogs,
131+
PackageLayout? packageLayout,
132+
String? runPackageName,
133+
IOSSdkImpl? targetIOSSdk,
134+
int? targetIOSVersion,
135+
int? targetMacOSVersion,
136+
int? targetAndroidNdkApi,
137+
Target? target,
138+
Uri? resourceIdentifiers,
139+
}) async =>
140+
await runWithLog(capturedLogs, () async {
141+
final buildRunner = NativeAssetsBuildRunner(
142+
logger: logger,
143+
dartExecutable: dartExecutable,
144+
);
145+
final buildResult = await buildRunner.build(
146+
buildMode: BuildModeImpl.release,
147+
linkModePreference: linkModePreference,
148+
target: target ?? Target.current,
149+
workingDirectory: packageUri,
150+
cCompilerConfig: cCompilerConfig,
151+
includeParentEnvironment: includeParentEnvironment,
152+
packageLayout: packageLayout,
153+
runPackageName: runPackageName,
154+
targetIOSSdk: targetIOSSdk,
155+
targetIOSVersion: targetIOSVersion,
156+
targetMacOSVersion: targetMacOSVersion,
157+
targetAndroidNdkApi: targetAndroidNdkApi,
158+
);
159+
160+
if (!buildResult.success) {
161+
return (buildResult, HookResult());
162+
}
163+
164+
await expectAssetsExist(buildResult.assets);
165+
for (final assetsForLinking in buildResult.assetsForLinking.values) {
166+
await expectAssetsExist(assetsForLinking);
167+
}
168+
169+
final linkResult = await buildRunner.link(
170+
linkModePreference: linkModePreference,
171+
buildMode: BuildModeImpl.release,
172+
target: target ?? Target.current,
173+
workingDirectory: packageUri,
174+
cCompilerConfig: cCompilerConfig,
175+
includeParentEnvironment: includeParentEnvironment,
176+
packageLayout: packageLayout,
177+
buildResult: buildResult,
178+
resourceIdentifiers: resourceIdentifiers,
179+
targetIOSSdk: targetIOSSdk,
180+
targetIOSVersion: targetIOSVersion,
181+
targetMacOSVersion: targetMacOSVersion,
182+
targetAndroidNdkApi: targetAndroidNdkApi,
183+
);
184+
185+
if (linkResult.success) {
186+
await expectAssetsExist(buildResult.assets);
187+
}
188+
189+
return (buildResult, linkResult);
190+
});
191+
101192
Future<T> runWithLog<T>(
102193
List<String>? capturedLogs,
103194
Future<T> Function() f,

0 commit comments

Comments
 (0)