@bacons/apple-targets 0.0.10 → 0.1.0
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/README.md +3 -1
- package/build/index.js +1 -0
- package/build/withWidget.d.ts +1 -0
- package/build/withWidget.js +1 -0
- package/build/withXcodeChanges.d.ts +2 -0
- package/build/withXcodeChanges.js +99 -338
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,11 +9,13 @@ An experimental Expo Config Plugin that generates native Apple Targets like Widg
|
|
|
9
9
|
|
|
10
10
|
## 🚀 How to use
|
|
11
11
|
|
|
12
|
+
> This plugin requires at least CocoaPods 1.16.2 and Xcode 16.
|
|
13
|
+
|
|
12
14
|
- Add targets to `targets/` directory with an `expo-target.config.json` file.
|
|
13
15
|
- Currently, if you don't have an `Info.plist`, it'll be generated on `npx expo prebuild`. This may be changed in the future so if you have an `Info.plist` it'll be used, otherwise, it'll be generated.
|
|
14
16
|
- Any files in a top-level `target/*/assets` directory will be linked as resources of the target. This was added to support Safari Extensions.
|
|
15
17
|
- A single top-level `*.entitlements` file will be linked as the entitlements of the target. This is not currently used in EAS Capability signing, but may be in the future.
|
|
16
|
-
- All
|
|
18
|
+
- All Swift files will be linked as build sources of the target. There is currently no support for storyboard or `.xib` files because I can't be bothered.
|
|
17
19
|
- All top-level `*.xcassets` will be linked as resources, and accessible in the targets. If you add files outside of Xcode, you'll need to re-run `npx expo prebuild` to link them.
|
|
18
20
|
- In Expo SDK +52, set the `ios.appleTeamId`, for SDK 51 and below, set the `appleTeamId` prop in the Config Plugin in `app.config.js`:
|
|
19
21
|
|
package/build/index.js
CHANGED
|
@@ -26,6 +26,7 @@ const withTargetsDir = (config, _props) => {
|
|
|
26
26
|
appleTeamId,
|
|
27
27
|
...require(configPath),
|
|
28
28
|
directory: path_1.default.relative(projectRoot, path_1.default.dirname(configPath)),
|
|
29
|
+
configPath,
|
|
29
30
|
});
|
|
30
31
|
});
|
|
31
32
|
(0, withPodTargetExtension_1.withPodTargetExtension)(config);
|
package/build/withWidget.d.ts
CHANGED
package/build/withWidget.js
CHANGED
|
@@ -113,6 +113,7 @@ const withWidget = (config, props) => {
|
|
|
113
113
|
const targetName = (_c = props.name) !== null && _c !== void 0 ? _c : widget;
|
|
114
114
|
const bundleId = config.ios.bundleIdentifier + "." + widget;
|
|
115
115
|
(0, withXcodeChanges_1.withXcodeChanges)(config, {
|
|
116
|
+
configPath: props.configPath,
|
|
116
117
|
name: targetName,
|
|
117
118
|
cwd: "../" +
|
|
118
119
|
path_1.default.relative(config._internal.projectRoot, path_1.default.resolve(props.directory)),
|
|
@@ -5,7 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.withXcodeChanges = void 0;
|
|
7
7
|
const xcode_1 = require("@bacons/xcode");
|
|
8
|
-
const json_1 = require("@bacons/xcode/json");
|
|
9
8
|
const fs_1 = __importDefault(require("fs"));
|
|
10
9
|
const glob_1 = require("glob");
|
|
11
10
|
const path_1 = __importDefault(require("path"));
|
|
@@ -40,14 +39,19 @@ function createNotificationContentConfigurationList(project, { name, cwd, bundle
|
|
|
40
39
|
INFOPLIST_KEY_CFBundleDisplayName: name,
|
|
41
40
|
INFOPLIST_KEY_NSHumanReadableCopyright: "",
|
|
42
41
|
IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
|
|
43
|
-
LD_RUNPATH_SEARCH_PATHS:
|
|
42
|
+
LD_RUNPATH_SEARCH_PATHS: [
|
|
43
|
+
"$(inherited)",
|
|
44
|
+
"@executable_path/Frameworks",
|
|
45
|
+
"@executable_path/../../Frameworks",
|
|
46
|
+
],
|
|
44
47
|
MARKETING_VERSION: "1.0",
|
|
45
48
|
MTL_FAST_MATH: "YES",
|
|
46
49
|
PRODUCT_BUNDLE_IDENTIFIER: bundleId,
|
|
47
50
|
PRODUCT_NAME: "$(TARGET_NAME)",
|
|
48
51
|
SKIP_INSTALL: "YES",
|
|
49
52
|
SWIFT_EMIT_LOC_STRINGS: "YES",
|
|
50
|
-
|
|
53
|
+
SWIFT_COMPILATION_MODE: "wholemodule",
|
|
54
|
+
SWIFT_OPTIMIZATION_LEVEL: "-O",
|
|
51
55
|
SWIFT_VERSION: "5.0",
|
|
52
56
|
TARGETED_DEVICE_FAMILY: "1,2",
|
|
53
57
|
};
|
|
@@ -135,7 +139,11 @@ function createShareConfigurationList(project, { name, cwd, bundleId, deployment
|
|
|
135
139
|
INFOPLIST_KEY_CFBundleDisplayName: name,
|
|
136
140
|
INFOPLIST_KEY_NSHumanReadableCopyright: "",
|
|
137
141
|
IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
|
|
138
|
-
LD_RUNPATH_SEARCH_PATHS:
|
|
142
|
+
LD_RUNPATH_SEARCH_PATHS: [
|
|
143
|
+
"$(inherited)",
|
|
144
|
+
"@executable_path/Frameworks",
|
|
145
|
+
"@executable_path/../../Frameworks",
|
|
146
|
+
],
|
|
139
147
|
MARKETING_VERSION: "1.0",
|
|
140
148
|
MTL_FAST_MATH: "YES",
|
|
141
149
|
PRODUCT_BUNDLE_IDENTIFIER: bundleId,
|
|
@@ -202,7 +210,11 @@ function createIMessageConfigurationList(project, { name, cwd, bundleId, deploym
|
|
|
202
210
|
INFOPLIST_KEY_CFBundleDisplayName: name,
|
|
203
211
|
INFOPLIST_KEY_NSHumanReadableCopyright: "",
|
|
204
212
|
IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
|
|
205
|
-
LD_RUNPATH_SEARCH_PATHS:
|
|
213
|
+
LD_RUNPATH_SEARCH_PATHS: [
|
|
214
|
+
"$(inherited)",
|
|
215
|
+
"@executable_path/Frameworks",
|
|
216
|
+
"@executable_path/../../Frameworks",
|
|
217
|
+
],
|
|
206
218
|
MARKETING_VERSION: "1.0",
|
|
207
219
|
MTL_FAST_MATH: "YES",
|
|
208
220
|
PRODUCT_BUNDLE_IDENTIFIER: bundleId,
|
|
@@ -260,7 +272,7 @@ function createWatchAppConfigurationList(project, { name, cwd, bundleId, deploym
|
|
|
260
272
|
INFOPLIST_KEY_WKCompanionAppBundleIdentifier: mainAppTarget.props.buildSettings.PRODUCT_BUNDLE_IDENTIFIER,
|
|
261
273
|
// INFOPLIST_KEY_WKCompanionAppBundleIdentifier: "$(BUNDLE_IDENTIFIER)",
|
|
262
274
|
// INFOPLIST_KEY_WKCompanionAppBundleIdentifier: rootBundleId,
|
|
263
|
-
LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks",
|
|
275
|
+
LD_RUNPATH_SEARCH_PATHS: ["$(inherited)", "@executable_path/Frameworks"],
|
|
264
276
|
MARKETING_VERSION: "1.0",
|
|
265
277
|
MTL_FAST_MATH: "YES",
|
|
266
278
|
PRODUCT_BUNDLE_IDENTIFIER: bundleId,
|
|
@@ -292,7 +304,8 @@ function createWatchAppConfigurationList(project, { name, cwd, bundleId, deploym
|
|
|
292
304
|
buildSettings: {
|
|
293
305
|
...common,
|
|
294
306
|
// Diff
|
|
295
|
-
|
|
307
|
+
SWIFT_COMPILATION_MODE: "wholemodule",
|
|
308
|
+
SWIFT_OPTIMIZATION_LEVEL: "-O",
|
|
296
309
|
COPY_PHASE_STRIP: "NO",
|
|
297
310
|
DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
|
|
298
311
|
},
|
|
@@ -321,7 +334,11 @@ function createSafariConfigurationList(project, { name, cwd, bundleId, deploymen
|
|
|
321
334
|
INFOPLIST_KEY_CFBundleDisplayName: name,
|
|
322
335
|
INFOPLIST_KEY_NSHumanReadableCopyright: "",
|
|
323
336
|
IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
|
|
324
|
-
LD_RUNPATH_SEARCH_PATHS:
|
|
337
|
+
LD_RUNPATH_SEARCH_PATHS: [
|
|
338
|
+
"$(inherited)",
|
|
339
|
+
"@executable_path/Frameworks",
|
|
340
|
+
"@executable_path/../../Frameworks",
|
|
341
|
+
],
|
|
325
342
|
MARKETING_VERSION: "1.0",
|
|
326
343
|
MTL_FAST_MATH: "YES",
|
|
327
344
|
PRODUCT_BUNDLE_IDENTIFIER: bundleId,
|
|
@@ -348,7 +365,8 @@ function createSafariConfigurationList(project, { name, cwd, bundleId, deploymen
|
|
|
348
365
|
buildSettings: {
|
|
349
366
|
...common,
|
|
350
367
|
// Diff
|
|
351
|
-
|
|
368
|
+
SWIFT_COMPILATION_MODE: "wholemodule",
|
|
369
|
+
SWIFT_OPTIMIZATION_LEVEL: "-O",
|
|
352
370
|
COPY_PHASE_STRIP: "NO",
|
|
353
371
|
DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
|
|
354
372
|
},
|
|
@@ -404,7 +422,7 @@ function createAppClipConfigurationList(project, { name, cwd, bundleId, deployme
|
|
|
404
422
|
...infoPlist,
|
|
405
423
|
...superCommon,
|
|
406
424
|
ASSETCATALOG_COMPILER_APPICON_NAME: "AppIcon",
|
|
407
|
-
LD_RUNPATH_SEARCH_PATHS: "$(inherited) @executable_path/Frameworks",
|
|
425
|
+
LD_RUNPATH_SEARCH_PATHS: ["$(inherited)", "@executable_path/Frameworks"],
|
|
408
426
|
MTL_FAST_MATH: "YES",
|
|
409
427
|
ENABLE_PREVIEWS: "YES",
|
|
410
428
|
};
|
|
@@ -424,7 +442,8 @@ function createAppClipConfigurationList(project, { name, cwd, bundleId, deployme
|
|
|
424
442
|
buildSettings: {
|
|
425
443
|
...common,
|
|
426
444
|
// Diff
|
|
427
|
-
|
|
445
|
+
SWIFT_COMPILATION_MODE: "wholemodule",
|
|
446
|
+
SWIFT_OPTIMIZATION_LEVEL: "-O",
|
|
428
447
|
COPY_PHASE_STRIP: "NO",
|
|
429
448
|
DEBUG_INFORMATION_FORMAT: "dwarf-with-dsym",
|
|
430
449
|
},
|
|
@@ -458,7 +477,11 @@ function createConfigurationList(project, { name, cwd, bundleId, deploymentTarge
|
|
|
458
477
|
INFOPLIST_KEY_CFBundleDisplayName: name,
|
|
459
478
|
INFOPLIST_KEY_NSHumanReadableCopyright: "",
|
|
460
479
|
IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
|
|
461
|
-
LD_RUNPATH_SEARCH_PATHS:
|
|
480
|
+
LD_RUNPATH_SEARCH_PATHS: [
|
|
481
|
+
"$(inherited)",
|
|
482
|
+
"@executable_path/Frameworks",
|
|
483
|
+
"@executable_path/../../Frameworks",
|
|
484
|
+
],
|
|
462
485
|
MARKETING_VERSION: "1.0",
|
|
463
486
|
MTL_ENABLE_DEBUG_INFO: "INCLUDE_SOURCE",
|
|
464
487
|
MTL_FAST_MATH: "YES",
|
|
@@ -494,14 +517,19 @@ function createConfigurationList(project, { name, cwd, bundleId, deploymentTarge
|
|
|
494
517
|
INFOPLIST_KEY_CFBundleDisplayName: name,
|
|
495
518
|
INFOPLIST_KEY_NSHumanReadableCopyright: "",
|
|
496
519
|
IPHONEOS_DEPLOYMENT_TARGET: deploymentTarget,
|
|
497
|
-
LD_RUNPATH_SEARCH_PATHS:
|
|
520
|
+
LD_RUNPATH_SEARCH_PATHS: [
|
|
521
|
+
"$(inherited)",
|
|
522
|
+
"@executable_path/Frameworks",
|
|
523
|
+
"@executable_path/../../Frameworks",
|
|
524
|
+
],
|
|
498
525
|
MARKETING_VERSION: "1.0",
|
|
499
526
|
MTL_FAST_MATH: "YES",
|
|
500
527
|
PRODUCT_BUNDLE_IDENTIFIER: bundleId,
|
|
501
528
|
PRODUCT_NAME: "$(TARGET_NAME)",
|
|
502
529
|
SKIP_INSTALL: "YES",
|
|
503
530
|
SWIFT_EMIT_LOC_STRINGS: "YES",
|
|
504
|
-
|
|
531
|
+
SWIFT_COMPILATION_MODE: "wholemodule",
|
|
532
|
+
SWIFT_OPTIMIZATION_LEVEL: "-O",
|
|
505
533
|
SWIFT_VERSION: "5",
|
|
506
534
|
TARGETED_DEVICE_FAMILY: "1,2",
|
|
507
535
|
},
|
|
@@ -540,37 +568,6 @@ function createConfigurationListForType(project, props) {
|
|
|
540
568
|
return createNotificationContentConfigurationList(project, props);
|
|
541
569
|
}
|
|
542
570
|
}
|
|
543
|
-
/** It's common for all frameworks to exist in the top-level "Frameworks" folder that shows in Xcode. */
|
|
544
|
-
function addFrameworksToDisplayFolder(project, frameworks) {
|
|
545
|
-
var _a;
|
|
546
|
-
const mainFrameworksGroup = (_a = project.rootObject.props.mainGroup
|
|
547
|
-
.getChildGroups()
|
|
548
|
-
.find((group) => group.getDisplayName() === "Frameworks")) !== null && _a !== void 0 ? _a :
|
|
549
|
-
// If this happens, there's a big problem. But just in case...
|
|
550
|
-
project.rootObject.props.mainGroup.createGroup({
|
|
551
|
-
name: "Frameworks",
|
|
552
|
-
sourceTree: "<group>",
|
|
553
|
-
});
|
|
554
|
-
frameworks.forEach((file) => {
|
|
555
|
-
if (!mainFrameworksGroup.props.children.find((child) => child.uuid === file.uuid)) {
|
|
556
|
-
mainFrameworksGroup.props.children.push(file);
|
|
557
|
-
}
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
function getFramework(project, name) {
|
|
561
|
-
const frameworkName = name + ".framework";
|
|
562
|
-
for (const [, entry] of project.entries()) {
|
|
563
|
-
if (xcode_1.PBXFileReference.is(entry) &&
|
|
564
|
-
entry.props.lastKnownFileType === "wrapper.framework" &&
|
|
565
|
-
entry.props.sourceTree === "SDKROOT" &&
|
|
566
|
-
entry.props.name === frameworkName) {
|
|
567
|
-
return entry;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
return xcode_1.PBXFileReference.create(project, {
|
|
571
|
-
path: "System/Library/Frameworks/" + frameworkName,
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
571
|
async function applyXcodeChanges(config, project, props) {
|
|
575
572
|
var _a, _b;
|
|
576
573
|
const mainAppTarget = (0, target_1.getMainAppTarget)(project);
|
|
@@ -592,18 +589,6 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
592
589
|
console.log(`Target "${targetToUpdate.props.productName}" already exists, updating instead of creating a new one`);
|
|
593
590
|
}
|
|
594
591
|
const magicCwd = path_1.default.join(config._internal.projectRoot, "ios", props.cwd);
|
|
595
|
-
function getOrCreateBuildFile(file) {
|
|
596
|
-
for (const entry of file.getReferrers()) {
|
|
597
|
-
if (xcode_1.PBXBuildFile.is(entry) && entry.props.fileRef.uuid === file.uuid) {
|
|
598
|
-
return entry;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
return xcode_1.PBXBuildFile.create(project, {
|
|
602
|
-
fileRef: file,
|
|
603
|
-
});
|
|
604
|
-
}
|
|
605
|
-
// Add the widget target to the display folder (cosmetic)
|
|
606
|
-
addFrameworksToDisplayFolder(project, props.frameworks.map((framework) => getFramework(project, framework)));
|
|
607
592
|
const developmentTeamId = (_b = props.teamId) !== null && _b !== void 0 ? _b : mainAppTarget.getDefaultBuildSetting("DEVELOPMENT_TEAM");
|
|
608
593
|
if (!developmentTeamId) {
|
|
609
594
|
throw new Error("Couldn't find DEVELOPMENT_TEAM in Xcode project and none were provided in the Expo config.");
|
|
@@ -646,19 +631,11 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
646
631
|
}
|
|
647
632
|
function configureTargetWithEntitlements(target) {
|
|
648
633
|
const entitlements = (0, glob_1.sync)("*.entitlements", {
|
|
649
|
-
absolute:
|
|
634
|
+
absolute: false,
|
|
650
635
|
cwd: magicCwd,
|
|
651
|
-
}).map((file) => {
|
|
652
|
-
return xcode_1.PBXBuildFile.create(project, {
|
|
653
|
-
fileRef: xcode_1.PBXFileReference.create(project, {
|
|
654
|
-
path: path_1.default.basename(file),
|
|
655
|
-
explicitFileType: "text.plist.entitlements",
|
|
656
|
-
sourceTree: "<group>",
|
|
657
|
-
}),
|
|
658
|
-
});
|
|
659
636
|
});
|
|
660
637
|
if (entitlements.length > 0) {
|
|
661
|
-
target.setBuildSetting("CODE_SIGN_ENTITLEMENTS", props.cwd + "/" + entitlements[0]
|
|
638
|
+
target.setBuildSetting("CODE_SIGN_ENTITLEMENTS", props.cwd + "/" + entitlements[0]);
|
|
662
639
|
}
|
|
663
640
|
else {
|
|
664
641
|
target.removeBuildSetting("CODE_SIGN_ENTITLEMENTS");
|
|
@@ -674,50 +651,6 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
674
651
|
}
|
|
675
652
|
});
|
|
676
653
|
}
|
|
677
|
-
function buildFileGroupHierarchy(files) {
|
|
678
|
-
const root = [];
|
|
679
|
-
function getOrCreateGroup(name, segment, group) {
|
|
680
|
-
const fullPath = path_1.default.join(magicCwd, name);
|
|
681
|
-
let newGroup = group.find((child) => child.props.isa === json_1.ISA.PBXGroup && child.props.path === fullPath);
|
|
682
|
-
if (!newGroup) {
|
|
683
|
-
newGroup = xcode_1.PBXGroup.create(project, {
|
|
684
|
-
name: segment,
|
|
685
|
-
path: fullPath,
|
|
686
|
-
children: [],
|
|
687
|
-
});
|
|
688
|
-
group.push(newGroup);
|
|
689
|
-
}
|
|
690
|
-
return newGroup;
|
|
691
|
-
}
|
|
692
|
-
files.forEach((filePath) => {
|
|
693
|
-
const pathSegments = filePath.split(path_1.default.sep);
|
|
694
|
-
let currentLevel = root;
|
|
695
|
-
pathSegments.forEach((part, index) => {
|
|
696
|
-
const isRoot = part === ".";
|
|
697
|
-
const currentPath = pathSegments.slice(0, index + 1).join(path_1.default.sep);
|
|
698
|
-
currentLevel = isRoot ? currentLevel : getOrCreateGroup(currentPath, part, currentLevel).props.children;
|
|
699
|
-
const isFinalPart = index === pathSegments.length - 1;
|
|
700
|
-
if (swiftBuildFiles[filePath] && isFinalPart) {
|
|
701
|
-
const filex = swiftBuildFiles[filePath];
|
|
702
|
-
currentLevel.push(...filex);
|
|
703
|
-
}
|
|
704
|
-
});
|
|
705
|
-
});
|
|
706
|
-
return root;
|
|
707
|
-
}
|
|
708
|
-
function generateProjectGroups(project, structure, magicCwd) {
|
|
709
|
-
return structure.map((item) => {
|
|
710
|
-
if (item.props.isa === json_1.ISA.PBXGroup) {
|
|
711
|
-
// @ts-ignore
|
|
712
|
-
const childGroups = generateProjectGroups(project, item.props.children, path_1.default.join(magicCwd, item.props.name));
|
|
713
|
-
item.props.children = childGroups;
|
|
714
|
-
return item;
|
|
715
|
-
}
|
|
716
|
-
else if (item.props.isa === json_1.ISA.PBXBuildFile) {
|
|
717
|
-
return item.props.fileRef;
|
|
718
|
-
}
|
|
719
|
-
});
|
|
720
|
-
}
|
|
721
654
|
function configureTargetWithPreview(target) {
|
|
722
655
|
const assets = (0, glob_1.sync)("preview/*.xcassets", {
|
|
723
656
|
absolute: true,
|
|
@@ -736,7 +669,9 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
736
669
|
const shellScript = mainAppTarget.props.buildPhases.find((phase) => xcode_1.PBXShellScriptBuildPhase.is(phase) &&
|
|
737
670
|
phase.props.name === "Bundle React Native code and images");
|
|
738
671
|
if (!shellScript) {
|
|
739
|
-
|
|
672
|
+
console.warn('Failed to find the "Bundle React Native code and images" build phase in the main app target. Will not be able to configure: ' +
|
|
673
|
+
props.type);
|
|
674
|
+
return;
|
|
740
675
|
}
|
|
741
676
|
const currentShellScript = target.props.buildPhases.find((phase) => xcode_1.PBXShellScriptBuildPhase.is(phase) &&
|
|
742
677
|
phase.props.name === "Bundle React Native code and images");
|
|
@@ -777,7 +712,8 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
777
712
|
});
|
|
778
713
|
targetToUpdate.props.buildConfigurationList.removeFromProject();
|
|
779
714
|
// Create new build phases
|
|
780
|
-
targetToUpdate.props.buildConfigurationList =
|
|
715
|
+
targetToUpdate.props.buildConfigurationList =
|
|
716
|
+
createConfigurationListForType(project, props);
|
|
781
717
|
configureTargetWithEntitlements(targetToUpdate);
|
|
782
718
|
configureTargetWithPreview(targetToUpdate);
|
|
783
719
|
configureTargetWithKnownSettings(targetToUpdate);
|
|
@@ -786,126 +722,7 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
786
722
|
syncMarketingVersions();
|
|
787
723
|
return project;
|
|
788
724
|
}
|
|
789
|
-
|
|
790
|
-
const swiftBuildFiles = {};
|
|
791
|
-
(0, glob_1.sync)("**/*.swift", {
|
|
792
|
-
absolute: true,
|
|
793
|
-
cwd: magicCwd,
|
|
794
|
-
}).forEach((file) => {
|
|
795
|
-
const fileDir = path_1.default.dirname(path_1.default.relative(magicCwd, file));
|
|
796
|
-
const pbxFile = xcode_1.PBXBuildFile.create(project, {
|
|
797
|
-
fileRef: xcode_1.PBXFileReference.create(project, {
|
|
798
|
-
path: file,
|
|
799
|
-
sourceTree: "<group>",
|
|
800
|
-
}),
|
|
801
|
-
});
|
|
802
|
-
if (!swiftBuildFiles[fileDir]) {
|
|
803
|
-
swiftBuildFiles[fileDir] = [];
|
|
804
|
-
}
|
|
805
|
-
swiftBuildFiles[fileDir].push(pbxFile);
|
|
806
|
-
return undefined;
|
|
807
|
-
});
|
|
808
|
-
const swiftStructure = buildFileGroupHierarchy(Object.keys(swiftBuildFiles));
|
|
809
|
-
const swiftGroups = generateProjectGroups(project, swiftStructure, magicCwd);
|
|
810
|
-
// NOTE: Single-level only
|
|
811
|
-
const intentFiles = (0, glob_1.sync)("*.intentdefinition", {
|
|
812
|
-
absolute: true,
|
|
813
|
-
cwd: magicCwd,
|
|
814
|
-
}).map((file) => {
|
|
815
|
-
return xcode_1.PBXFileReference.create(project, {
|
|
816
|
-
lastKnownFileType: "file.intentdefinition",
|
|
817
|
-
path: path_1.default.basename(file),
|
|
818
|
-
sourceTree: "<group>",
|
|
819
|
-
});
|
|
820
|
-
});
|
|
821
|
-
const intentBuildFiles = [0, 1].map((_) => intentFiles.map((file) => {
|
|
822
|
-
return xcode_1.PBXBuildFile.create(project, {
|
|
823
|
-
fileRef: file,
|
|
824
|
-
});
|
|
825
|
-
}));
|
|
826
|
-
let assetFiles = [
|
|
827
|
-
// All assets`
|
|
828
|
-
// "assets/*",
|
|
829
|
-
// NOTE: Single-level only
|
|
830
|
-
"*.xcassets",
|
|
831
|
-
]
|
|
832
|
-
.map((glob) => (0, glob_1.sync)(glob, {
|
|
833
|
-
absolute: true,
|
|
834
|
-
cwd: magicCwd,
|
|
835
|
-
}).map((file) => {
|
|
836
|
-
return xcode_1.PBXBuildFile.create(project, {
|
|
837
|
-
fileRef: xcode_1.PBXFileReference.create(project, {
|
|
838
|
-
path: path_1.default.basename(file),
|
|
839
|
-
sourceTree: "<group>",
|
|
840
|
-
}),
|
|
841
|
-
});
|
|
842
|
-
}))
|
|
843
|
-
.flat();
|
|
844
|
-
const resAssets = [];
|
|
845
|
-
// Support for LaunchScreen files
|
|
846
|
-
const baseProj = path_1.default.join(magicCwd, "Base.lproj");
|
|
847
|
-
if (fs_1.default.existsSync(baseProj)) {
|
|
848
|
-
// Link LaunchScreen.storyboard
|
|
849
|
-
fs_1.default.readdirSync(baseProj).forEach((file) => {
|
|
850
|
-
if (file === ".DS_Store")
|
|
851
|
-
return;
|
|
852
|
-
const stat = fs_1.default.statSync(path_1.default.join(baseProj, file));
|
|
853
|
-
if (stat.isFile()) {
|
|
854
|
-
if (file.endsWith(".storyboard")) {
|
|
855
|
-
assetFiles.push(xcode_1.PBXBuildFile.create(project, {
|
|
856
|
-
fileRef: xcode_1.PBXVariantGroup.create(project, {
|
|
857
|
-
name: file,
|
|
858
|
-
sourceTree: "<group>",
|
|
859
|
-
children: [
|
|
860
|
-
xcode_1.PBXFileReference.create(project, {
|
|
861
|
-
lastKnownFileType: "file.storyboard",
|
|
862
|
-
name: "Base",
|
|
863
|
-
path: path_1.default.join("Base.lproj", file),
|
|
864
|
-
sourceTree: "<group>",
|
|
865
|
-
}),
|
|
866
|
-
],
|
|
867
|
-
}),
|
|
868
|
-
}));
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
// TODO: Maybe just limit this to Safari?
|
|
874
|
-
if (fs_1.default.existsSync(path_1.default.join(magicCwd, "assets"))) {
|
|
875
|
-
// get top-level directories in `assets/` and append them to assetFiles as folder types
|
|
876
|
-
fs_1.default.readdirSync(path_1.default.join(magicCwd, "assets")).forEach((file) => {
|
|
877
|
-
if (file === ".DS_Store")
|
|
878
|
-
return;
|
|
879
|
-
const stat = fs_1.default.statSync(path_1.default.join(magicCwd, "assets", file));
|
|
880
|
-
if (stat.isDirectory()) {
|
|
881
|
-
resAssets.push(xcode_1.PBXBuildFile.create(project, {
|
|
882
|
-
fileRef: xcode_1.PBXFileReference.create(project, {
|
|
883
|
-
path: file,
|
|
884
|
-
sourceTree: "<group>",
|
|
885
|
-
lastKnownFileType: "folder",
|
|
886
|
-
}),
|
|
887
|
-
}));
|
|
888
|
-
}
|
|
889
|
-
else if (stat.isFile()) {
|
|
890
|
-
resAssets.push(xcode_1.PBXBuildFile.create(project, {
|
|
891
|
-
fileRef: xcode_1.PBXFileReference.create(project, {
|
|
892
|
-
path: file,
|
|
893
|
-
explicitFileType: file.endsWith(".js")
|
|
894
|
-
? "sourcecode.javascript"
|
|
895
|
-
: file.endsWith(".json")
|
|
896
|
-
? "text.json"
|
|
897
|
-
: file.endsWith(".html")
|
|
898
|
-
? "text.html"
|
|
899
|
-
: file.endsWith(".css")
|
|
900
|
-
? "text.css"
|
|
901
|
-
: "text",
|
|
902
|
-
sourceTree: "<group>",
|
|
903
|
-
}),
|
|
904
|
-
}));
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
}
|
|
908
|
-
const alphaExtensionAppexBf = xcode_1.PBXBuildFile.create(project, {
|
|
725
|
+
const appExtensionBuildFile = xcode_1.PBXBuildFile.create(project, {
|
|
909
726
|
fileRef: xcode_1.PBXFileReference.create(project, {
|
|
910
727
|
explicitFileType: "wrapper.app-extension",
|
|
911
728
|
includeInIndex: 0,
|
|
@@ -918,44 +735,30 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
918
735
|
});
|
|
919
736
|
project.rootObject.ensureProductGroup().props.children.push(
|
|
920
737
|
// @ts-expect-error
|
|
921
|
-
|
|
922
|
-
const
|
|
738
|
+
appExtensionBuildFile.props.fileRef);
|
|
739
|
+
const extensionTarget = project.rootObject.createNativeTarget({
|
|
923
740
|
buildConfigurationList: createConfigurationListForType(project, props),
|
|
924
741
|
name: productName,
|
|
925
742
|
productName,
|
|
926
743
|
// @ts-expect-error
|
|
927
|
-
productReference:
|
|
744
|
+
productReference: appExtensionBuildFile.props.fileRef /* alphaExtension.appex */,
|
|
928
745
|
productType: (0, target_1.productTypeForType)(props.type),
|
|
929
746
|
});
|
|
930
|
-
configureTargetWithKnownSettings(
|
|
931
|
-
|
|
932
|
-
configureTargetWithPreview(
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
// ...entitlementFiles
|
|
938
|
-
],
|
|
939
|
-
// CD0706152A2EBE2E009C1192 /* index.swift in Sources */,
|
|
940
|
-
// CD07061A2A2EBE2F009C1192 /* alpha.intentdefinition in Sources */,
|
|
941
|
-
// CD0706112A2EBE2E009C1192 /* alphaBundle.swift in Sources */,
|
|
942
|
-
// CD0706132A2EBE2E009C1192 /* alphaLiveActivity.swift in Sources */,
|
|
943
|
-
});
|
|
944
|
-
widgetTarget.createBuildPhase(xcode_1.PBXFrameworksBuildPhase, {
|
|
945
|
-
files: props.frameworks.map((framework) => getOrCreateBuildFile(getFramework(project, framework))),
|
|
946
|
-
});
|
|
947
|
-
widgetTarget.createBuildPhase(xcode_1.PBXResourcesBuildPhase, {
|
|
948
|
-
files: [...assetFiles, ...resAssets],
|
|
949
|
-
});
|
|
950
|
-
configureJsExport(widgetTarget);
|
|
747
|
+
configureTargetWithKnownSettings(extensionTarget);
|
|
748
|
+
configureTargetWithEntitlements(extensionTarget);
|
|
749
|
+
configureTargetWithPreview(extensionTarget);
|
|
750
|
+
extensionTarget.ensureFrameworks(props.frameworks);
|
|
751
|
+
extensionTarget.getSourcesBuildPhase();
|
|
752
|
+
extensionTarget.getResourcesBuildPhase();
|
|
753
|
+
configureJsExport(extensionTarget);
|
|
951
754
|
const containerItemProxy = xcode_1.PBXContainerItemProxy.create(project, {
|
|
952
755
|
containerPortal: project.rootObject,
|
|
953
756
|
proxyType: 1,
|
|
954
|
-
remoteGlobalIDString:
|
|
757
|
+
remoteGlobalIDString: extensionTarget.uuid,
|
|
955
758
|
remoteInfo: productName,
|
|
956
759
|
});
|
|
957
760
|
const targetDependency = xcode_1.PBXTargetDependency.create(project, {
|
|
958
|
-
target:
|
|
761
|
+
target: extensionTarget,
|
|
959
762
|
targetProxy: containerItemProxy,
|
|
960
763
|
});
|
|
961
764
|
// Add the target dependency to the main app, should be only one.
|
|
@@ -974,105 +777,63 @@ async function applyXcodeChanges(config, project, props) {
|
|
|
974
777
|
});
|
|
975
778
|
if (copyFilesBuildPhase) {
|
|
976
779
|
// Assume that this is the first run if there is no matching target that we identified from a previous run.
|
|
977
|
-
copyFilesBuildPhase.props.files.push(
|
|
780
|
+
copyFilesBuildPhase.props.files.push(appExtensionBuildFile);
|
|
978
781
|
}
|
|
979
782
|
else {
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
dstPath: "$(CONTENTS_FOLDER_PATH)/" + dstPath,
|
|
984
|
-
dstSubfolderSpec: 16,
|
|
985
|
-
buildActionMask: 2147483647,
|
|
986
|
-
files: [alphaExtensionAppexBf],
|
|
987
|
-
name: WELL_KNOWN_COPY_EXTENSIONS_NAME,
|
|
988
|
-
runOnlyForDeploymentPostprocessing: 0,
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
else {
|
|
992
|
-
mainAppTarget.createBuildPhase(xcode_1.PBXCopyFilesBuildPhase, {
|
|
993
|
-
dstSubfolderSpec: 13,
|
|
994
|
-
buildActionMask: 2147483647,
|
|
995
|
-
files: [alphaExtensionAppexBf],
|
|
996
|
-
name: WELL_KNOWN_COPY_EXTENSIONS_NAME,
|
|
997
|
-
runOnlyForDeploymentPostprocessing: 0,
|
|
998
|
-
});
|
|
999
|
-
}
|
|
783
|
+
mainAppTarget.createBuildPhase(xcode_1.PBXCopyFilesBuildPhase, {
|
|
784
|
+
files: [appExtensionBuildFile],
|
|
785
|
+
});
|
|
1000
786
|
}
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
// Like `../alpha`
|
|
1009
|
-
path: props.cwd,
|
|
1010
|
-
sourceTree: "<group>",
|
|
1011
|
-
children: [
|
|
1012
|
-
...swiftGroups,
|
|
1013
|
-
...intentFiles.sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
|
|
1014
|
-
...assetFiles
|
|
1015
|
-
.map((buildFile) => buildFile.props.fileRef)
|
|
1016
|
-
.sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
|
|
1017
|
-
...entitlementFiles
|
|
1018
|
-
.map((buildFile) => buildFile.props.fileRef)
|
|
1019
|
-
.sort((a, b) => a.getDisplayName().localeCompare(b.getDisplayName())),
|
|
1020
|
-
// CD0706192A2EBE2F009C1192 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
|
1021
|
-
xcode_1.PBXFileReference.create(project, {
|
|
1022
|
-
path: "Info.plist",
|
|
1023
|
-
sourceTree: "<group>",
|
|
1024
|
-
}),
|
|
787
|
+
const syncException = xcode_1.PBXFileSystemSynchronizedBuildFileExceptionSet.create(project, {
|
|
788
|
+
target: extensionTarget,
|
|
789
|
+
membershipExceptions: [
|
|
790
|
+
// TODO: What other files belong here, why is this here?
|
|
791
|
+
"Info.plist",
|
|
792
|
+
// Exclude the config path
|
|
793
|
+
path_1.default.relative(magicCwd, props.configPath),
|
|
1025
794
|
],
|
|
1026
|
-
// children = (
|
|
1027
|
-
// CD0706102A2EBE2E009C1192 /* alphaBundle.swift */,
|
|
1028
|
-
// CD0706122A2EBE2E009C1192 /* alphaLiveActivity.swift */,
|
|
1029
|
-
// CD0706142A2EBE2E009C1192 /* index.swift */,
|
|
1030
|
-
// CD0706162A2EBE2E009C1192 /* alpha.intentdefinition */,
|
|
1031
|
-
// CD0706172A2EBE2F009C1192 /* Assets.xcassets */,
|
|
1032
|
-
// CD0706192A2EBE2F009C1192 /* Info.plist */,
|
|
1033
|
-
// );
|
|
1034
|
-
// name = "expo:alpha";
|
|
1035
|
-
// path = "../alpha";
|
|
1036
|
-
// sourceTree = "<group>";
|
|
1037
795
|
});
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
796
|
+
const assetsDir = path_1.default.join(magicCwd, "assets");
|
|
797
|
+
// TODO: Maybe just limit this to Safari extensions?
|
|
798
|
+
const explicitFolders = !fs_1.default.existsSync(assetsDir)
|
|
799
|
+
? []
|
|
800
|
+
: fs_1.default
|
|
801
|
+
.readdirSync(assetsDir)
|
|
802
|
+
.filter((file) => file !== ".DS_Store" &&
|
|
803
|
+
fs_1.default.statSync(path_1.default.join(assetsDir, file)).isDirectory())
|
|
804
|
+
.map((file) => path_1.default.join("assets", file));
|
|
805
|
+
const syncRootGroup = xcode_1.PBXFileSystemSynchronizedRootGroup.create(project, {
|
|
806
|
+
path: path_1.default.basename(props.cwd),
|
|
807
|
+
exceptions: [syncException],
|
|
808
|
+
explicitFileTypes: {},
|
|
809
|
+
explicitFolders: [
|
|
810
|
+
// Replaces the previous `lastKnownFileType: "folder",` system that's used in things like Safari extensions to include folders of assets.
|
|
811
|
+
// ex: `"Resources/_locales", "Resources/images"`
|
|
812
|
+
...explicitFolders,
|
|
813
|
+
],
|
|
814
|
+
sourceTree: "<group>",
|
|
815
|
+
});
|
|
816
|
+
if (!extensionTarget.props.fileSystemSynchronizedGroups) {
|
|
817
|
+
extensionTarget.props.fileSystemSynchronizedGroups = [];
|
|
1048
818
|
}
|
|
819
|
+
extensionTarget.props.fileSystemSynchronizedGroups.push(syncRootGroup);
|
|
820
|
+
ensureProtectedGroup(project, path_1.default.dirname(props.cwd)).props.children.push(syncRootGroup);
|
|
1049
821
|
applyDevelopmentTeamIdToTargets();
|
|
1050
822
|
syncMarketingVersions();
|
|
1051
823
|
return project;
|
|
1052
824
|
}
|
|
1053
825
|
const PROTECTED_GROUP_NAME = "expo:targets";
|
|
1054
|
-
function ensureProtectedGroup(project) {
|
|
826
|
+
function ensureProtectedGroup(project, relativePath = "../targets") {
|
|
1055
827
|
const hasProtectedGroup = project.rootObject.props.mainGroup
|
|
1056
828
|
.getChildGroups()
|
|
1057
829
|
.find((group) => group.getDisplayName() === PROTECTED_GROUP_NAME);
|
|
1058
830
|
const protectedGroup = hasProtectedGroup !== null && hasProtectedGroup !== void 0 ? hasProtectedGroup : xcode_1.PBXGroup.create(project, {
|
|
1059
831
|
name: PROTECTED_GROUP_NAME,
|
|
832
|
+
path: relativePath,
|
|
1060
833
|
sourceTree: "<group>",
|
|
1061
834
|
});
|
|
1062
835
|
if (!hasProtectedGroup) {
|
|
1063
836
|
project.rootObject.props.mainGroup.props.children.unshift(protectedGroup);
|
|
1064
|
-
// let libIndex = project.rootObject.props.mainGroup
|
|
1065
|
-
// .getChildGroups()
|
|
1066
|
-
// .findIndex((group) => group.getDisplayName() === "Libraries");
|
|
1067
|
-
// if (libIndex === -1) {
|
|
1068
|
-
// libIndex = 0;
|
|
1069
|
-
// }
|
|
1070
|
-
// add above the group named "Libraries"
|
|
1071
|
-
// project.rootObject.props.mainGroup.props.children.splice(
|
|
1072
|
-
// libIndex,
|
|
1073
|
-
// 0,
|
|
1074
|
-
// protectedGroup
|
|
1075
|
-
// );
|
|
1076
837
|
}
|
|
1077
838
|
return protectedGroup;
|
|
1078
839
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bacons/apple-targets",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Generate Apple Targets with Expo Prebuild",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"files": [
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@react-native/normalize-colors": "^0.76.1",
|
|
32
32
|
"glob": "^10.2.6",
|
|
33
|
-
"@bacons/xcode": "^1.0.0-alpha.
|
|
33
|
+
"@bacons/xcode": "^1.0.0-alpha.21",
|
|
34
34
|
"fs-extra": "^11.2.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|