xgem-cli 2.0.0-alpha.3 → 2.0.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/doctor.sh +13 -2
- package/lib/flutter.sh +8 -3
- package/lib/ios.sh +82 -41
- package/lib/version.sh +1 -1
- package/package.json +1 -1
package/lib/doctor.sh
CHANGED
|
@@ -26,7 +26,10 @@ flutter_supports_flag() {
|
|
|
26
26
|
flutter_config_spm_enabled() {
|
|
27
27
|
has_cmd flutter || { echo "unknown (flutter not found)"; return; }
|
|
28
28
|
local line
|
|
29
|
-
|
|
29
|
+
# Anchored to "enable-swift-package-manager:" (the current-value line)
|
|
30
|
+
# so this doesn't instead match the "--[no-]enable-swift-package-manager"
|
|
31
|
+
# flag-syntax help line that `flutter config` also prints.
|
|
32
|
+
line=$(flutter config 2>/dev/null | grep -im1 -E '^[[:space:]]*enable-swift-package-manager:')
|
|
30
33
|
if [ -z "$line" ]; then
|
|
31
34
|
echo "unknown (not reported by this Flutter version)"
|
|
32
35
|
else
|
|
@@ -86,7 +89,7 @@ doctor_print_ios() {
|
|
|
86
89
|
echo "Deployment target [$cfg]: ${t:-unknown}"
|
|
87
90
|
done
|
|
88
91
|
|
|
89
|
-
local required
|
|
92
|
+
local required generated
|
|
90
93
|
required=$(ios_required_spm_deployment_target "$project_dir" 2>/dev/null)
|
|
91
94
|
if [ -n "$required" ]; then
|
|
92
95
|
echo "Required by resolved SwiftPM plugins: $required"
|
|
@@ -94,6 +97,14 @@ doctor_print_ios() {
|
|
|
94
97
|
echo "Required by resolved SwiftPM plugins: unable to determine (run 'flutter pub get' first, or no SPM plugins declare an explicit floor)"
|
|
95
98
|
fi
|
|
96
99
|
|
|
100
|
+
if [ "$uses_spm" = "yes" ]; then
|
|
101
|
+
generated=$(ios_generated_package_target "$project_dir" 2>/dev/null)
|
|
102
|
+
echo "FlutterGeneratedPluginSwiftPackage declares: ${generated:-unknown}"
|
|
103
|
+
if [ -n "$required" ] && [ -n "$generated" ] && _ios_ver_lt "$generated" "$required"; then
|
|
104
|
+
log_warn "This is stale — it declares iOS $generated but plugins need $required. This can happen even when your app's own deployment target is already high enough; 'xgem run flutter build' will detect and fix this."
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
|
|
97
108
|
if [ "$uses_spm" = "yes" ]; then
|
|
98
109
|
ios_known_issue_check
|
|
99
110
|
fi
|
package/lib/flutter.sh
CHANGED
|
@@ -66,14 +66,19 @@ _flutter_build_ios() {
|
|
|
66
66
|
|
|
67
67
|
require_cmd xcodebuild "iOS builds require Xcode's command-line tools."
|
|
68
68
|
|
|
69
|
+
# Must run pub get BEFORE reconciling: the required-deployment-target
|
|
70
|
+
# check reads .dart_tool/package_config.json, and that file only
|
|
71
|
+
# reflects the plugin versions actually in use after a fresh pub get.
|
|
72
|
+
# Reconciling against a stale package_config.json can silently pass a
|
|
73
|
+
# check that the real, just-resolved dependency graph would fail.
|
|
74
|
+
log_info "Regenerating dependencies..."
|
|
75
|
+
flutter pub get
|
|
76
|
+
|
|
69
77
|
log_info "Reconciling iOS deployment target against resolved SwiftPM plugins..."
|
|
70
78
|
if ! ios_reconcile_deployment_target "."; then
|
|
71
79
|
die "iOS deployment target could not be reconciled; aborting before build."
|
|
72
80
|
fi
|
|
73
81
|
|
|
74
|
-
log_info "Regenerating dependencies..."
|
|
75
|
-
flutter pub get
|
|
76
|
-
|
|
77
82
|
if ios_project_uses_pods "."; then
|
|
78
83
|
log_info "CocoaPods detected - installing pods..."
|
|
79
84
|
( cd ios || exit 1; pod install )
|
package/lib/ios.sh
CHANGED
|
@@ -60,8 +60,13 @@ ios_deployment_target_for_config() {
|
|
|
60
60
|
|
|
61
61
|
if has_cmd xcodebuild; then
|
|
62
62
|
local value
|
|
63
|
+
# Anchored: newer Xcode also emits DEPLOYMENT_TARGET_SETTING_NAME =
|
|
64
|
+
# IPHONEOS_DEPLOYMENT_TARGET (a meta-setting whose *value* is that
|
|
65
|
+
# string), which an unanchored grep matches before the real
|
|
66
|
+
# "IPHONEOS_DEPLOYMENT_TARGET = 15.6" line — anchoring to the key
|
|
67
|
+
# position avoids grabbing that decoy.
|
|
63
68
|
value=$(xcodebuild -showBuildSettings "${xcb_args[@]}" -configuration "$config" 2>/dev/null \
|
|
64
|
-
| grep -m1 'IPHONEOS_DEPLOYMENT_TARGET' | awk '{print $NF}')
|
|
69
|
+
| grep -m1 -E '^[[:space:]]*IPHONEOS_DEPLOYMENT_TARGET[[:space:]]*=' | awk '{print $NF}')
|
|
65
70
|
[ -n "$value" ] && { echo "$value"; return 0; }
|
|
66
71
|
fi
|
|
67
72
|
|
|
@@ -80,15 +85,34 @@ ios_pbxproj_current_max_target() {
|
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
# ios_required_spm_deployment_target [project_dir]
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
+
# Returns the highest .iOS(.vNN) platform floor declared across every
|
|
89
|
+
# resolved SwiftPM plugin, instead of hardcoding a guessed value.
|
|
90
|
+
#
|
|
91
|
+
# Primary source: ios/Flutter/ephemeral/Packages/.packages/<name>-<version>/,
|
|
92
|
+
# which `flutter pub get` itself populates with each SPM-enabled plugin as
|
|
93
|
+
# part of dependency resolution — this is the actual, already-resolved
|
|
94
|
+
# location Xcode/SPM uses, not a path we have to reconstruct. Scanning it
|
|
95
|
+
# directly sidesteps having to guess each plugin's on-disk manifest layout
|
|
96
|
+
# (which varies — not every plugin puts Package.swift at <root>/ios/).
|
|
97
|
+
#
|
|
98
|
+
# Falls back to parsing .dart_tool/package_config.json's rootUri entries
|
|
99
|
+
# (assuming the common <root>/ios/Package.swift convention) only if that
|
|
100
|
+
# ephemeral directory doesn't exist yet — e.g. before any pub get has run.
|
|
88
101
|
ios_required_spm_deployment_target() {
|
|
89
102
|
local project_dir=${1:-.}
|
|
90
|
-
local
|
|
103
|
+
local packages_dir="$project_dir/ios/Flutter/ephemeral/Packages/.packages"
|
|
104
|
+
|
|
105
|
+
if [ -d "$packages_dir" ]; then
|
|
106
|
+
find "$packages_dir" -maxdepth 4 -name "Package.swift" -print0 2>/dev/null \
|
|
107
|
+
| xargs -0 grep -ohE '\.iOS\(\.v[0-9_]+\)' 2>/dev/null \
|
|
108
|
+
| grep -oE '[0-9]+(_[0-9]+)?' | tr '_' '.' \
|
|
109
|
+
| sort -g | tail -1
|
|
110
|
+
return 0
|
|
111
|
+
fi
|
|
91
112
|
|
|
113
|
+
log_debug "No resolved SwiftPM packages directory at $packages_dir yet; falling back to package_config.json."
|
|
114
|
+
|
|
115
|
+
local pkg_config="$project_dir/.dart_tool/package_config.json"
|
|
92
116
|
[ -f "$pkg_config" ] || { log_debug "No .dart_tool/package_config.json — run flutter pub get first."; return 1; }
|
|
93
117
|
has_cmd python3 || { log_debug "python3 not found; cannot parse package_config.json."; return 1; }
|
|
94
118
|
|
|
@@ -206,13 +230,23 @@ ios_regenerate_generated_package() {
|
|
|
206
230
|
}
|
|
207
231
|
|
|
208
232
|
ios_known_issue_check() {
|
|
209
|
-
log_warn "Known upstream issue (flutter/flutter#186804, #189422, #162072): FlutterGeneratedPluginSwiftPackage's deployment target can desync from your app's IPHONEOS_DEPLOYMENT_TARGET. Currently open — xgem detects and works around it automatically below."
|
|
233
|
+
log_warn "Known upstream issue (flutter/flutter#186804, #189422, #162072): FlutterGeneratedPluginSwiftPackage's deployment target can desync from your app's IPHONEOS_DEPLOYMENT_TARGET — independently, even when the app's own target is already high enough. Currently open — xgem detects and works around it automatically below."
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
# _ios_ver_lt a b -> true if a < b, numeric comparison (not string equality,
|
|
237
|
+
# since "15" and "15.0" are the same version but different strings).
|
|
238
|
+
_ios_ver_lt() {
|
|
239
|
+
awk -v a="$1" -v b="$2" 'BEGIN{exit !(a<b)}'
|
|
210
240
|
}
|
|
211
241
|
|
|
212
242
|
# ios_reconcile_deployment_target [project_dir]
|
|
213
|
-
# The core "self-healing" step
|
|
214
|
-
#
|
|
215
|
-
#
|
|
243
|
+
# The core "self-healing" step. Checks TWO independent things against the
|
|
244
|
+
# required version — the app's own pbxproj target, AND
|
|
245
|
+
# FlutterGeneratedPluginSwiftPackage's own declared platform — because the
|
|
246
|
+
# upstream bug is exactly that these two can desync from each other. A
|
|
247
|
+
# project whose pbxproj is already at (say) 15.6 can still have a generated
|
|
248
|
+
# package stuck at 13.0; checking only the pbxproj target (as an earlier
|
|
249
|
+
# version of this function did) misses that case entirely.
|
|
216
250
|
# Returns 0 if no action was needed or the fix succeeded; 1 if it couldn't
|
|
217
251
|
# reconcile and the caller should stop before attempting a build.
|
|
218
252
|
ios_reconcile_deployment_target() {
|
|
@@ -220,46 +254,53 @@ ios_reconcile_deployment_target() {
|
|
|
220
254
|
|
|
221
255
|
ios_project_uses_spm "$project_dir" || { log_debug "Project does not use SwiftPM; skipping deployment-target reconciliation."; return 0; }
|
|
222
256
|
|
|
223
|
-
local required
|
|
257
|
+
local required
|
|
224
258
|
required=$(ios_required_spm_deployment_target "$project_dir")
|
|
225
|
-
current=$(ios_deployment_target_for_config "Release" "$project_dir")
|
|
226
|
-
|
|
227
259
|
if [ -z "$required" ]; then
|
|
228
260
|
log_debug "Could not determine a required deployment target from resolved SPM plugins; skipping reconciliation."
|
|
229
261
|
return 0
|
|
230
262
|
fi
|
|
231
|
-
|
|
232
|
-
|
|
263
|
+
|
|
264
|
+
ios_known_issue_check
|
|
265
|
+
|
|
266
|
+
local current generated
|
|
267
|
+
current=$(ios_deployment_target_for_config "Release" "$project_dir")
|
|
268
|
+
generated=$(ios_generated_package_target "$project_dir")
|
|
269
|
+
|
|
270
|
+
local pbxproj_needs_bump=0 generated_needs_fix=0
|
|
271
|
+
[ -n "$current" ] && _ios_ver_lt "$current" "$required" && pbxproj_needs_bump=1
|
|
272
|
+
if [ -z "$generated" ] || _ios_ver_lt "$generated" "$required"; then
|
|
273
|
+
generated_needs_fix=1
|
|
274
|
+
fi
|
|
275
|
+
|
|
276
|
+
if [ "$pbxproj_needs_bump" = 0 ] && [ "$generated_needs_fix" = 0 ]; then
|
|
277
|
+
log_debug "Deployment target ($current) and generated package ($generated) already satisfy SwiftPM requirement ($required)."
|
|
233
278
|
return 0
|
|
234
279
|
fi
|
|
235
280
|
|
|
236
|
-
|
|
281
|
+
log_warn "Resolved SwiftPM plugins require iOS $required."
|
|
282
|
+
[ "$pbxproj_needs_bump" = 1 ] && echo " - project.pbxproj currently targets iOS $current"
|
|
283
|
+
[ "$generated_needs_fix" = 1 ] && echo " - FlutterGeneratedPluginSwiftPackage currently declares iOS ${generated:-unknown}"
|
|
284
|
+
echo "Plan:"
|
|
285
|
+
[ "$pbxproj_needs_bump" = 1 ] && echo " 1. Set IPHONEOS_DEPLOYMENT_TARGET = $required across every build configuration in project.pbxproj"
|
|
286
|
+
echo " 2. Clear ios/Flutter/ephemeral and re-run 'flutter pub get' to regenerate FlutterGeneratedPluginSwiftPackage"
|
|
287
|
+
echo " 3. Verify the regenerated package declares iOS $required; if it still doesn't (known upstream bug), patch it directly"
|
|
288
|
+
|
|
289
|
+
if ! confirm "Apply this fix?"; then
|
|
290
|
+
log_warn "Skipped. The build will likely fail SwiftPM resolution until this is reconciled manually."
|
|
291
|
+
return 1
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
[ "$pbxproj_needs_bump" = 1 ] && ios_pbxproj_patch_deployment_target "$required" "$project_dir"
|
|
295
|
+
ios_regenerate_generated_package "$project_dir"
|
|
237
296
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
echo " 2. Clear ios/Flutter/ephemeral and re-run 'flutter pub get' to regenerate FlutterGeneratedPluginSwiftPackage"
|
|
243
|
-
echo " 3. Verify the regenerated package declares iOS $required; if it still doesn't (known upstream bug), patch it directly"
|
|
244
|
-
|
|
245
|
-
if ! confirm "Apply this fix?"; then
|
|
246
|
-
log_warn "Skipped. The build will likely fail SwiftPM resolution until the deployment target is reconciled manually."
|
|
247
|
-
return 1
|
|
248
|
-
fi
|
|
249
|
-
|
|
250
|
-
ios_pbxproj_patch_deployment_target "$required" "$project_dir"
|
|
251
|
-
ios_regenerate_generated_package "$project_dir"
|
|
252
|
-
|
|
253
|
-
local regenerated
|
|
254
|
-
regenerated=$(ios_generated_package_target "$project_dir")
|
|
255
|
-
if [ "$regenerated" = "$required" ]; then
|
|
256
|
-
log_success "Generated package now correctly declares iOS $regenerated."
|
|
257
|
-
else
|
|
258
|
-
log_warn "Generated package declares '${regenerated:-unknown}' after regeneration, not $required."
|
|
259
|
-
ios_patch_generated_package_target "$required" "$project_dir"
|
|
260
|
-
fi
|
|
297
|
+
local regenerated
|
|
298
|
+
regenerated=$(ios_generated_package_target "$project_dir")
|
|
299
|
+
if [ -n "$regenerated" ] && ! _ios_ver_lt "$regenerated" "$required"; then
|
|
300
|
+
log_success "Generated package now correctly declares iOS $regenerated."
|
|
261
301
|
else
|
|
262
|
-
|
|
302
|
+
log_warn "Generated package declares '${regenerated:-unknown}' after regeneration, still below $required."
|
|
303
|
+
ios_patch_generated_package_target "$required" "$project_dir"
|
|
263
304
|
fi
|
|
264
305
|
|
|
265
306
|
return 0
|
package/lib/version.sh
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xgem-cli",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.5",
|
|
4
4
|
"description": "Framework-aware automation CLI: scaffolds and runs clean/build/dev scripts per project type, an environment doctor, a SwiftPM-aware iOS build engine, and a git workflow helper. Runs natively on macOS, Linux, and Windows.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"xgem": "bin/xgem.js"
|