Skip to content

Commit 1443240

Browse files
authored
feat: experimental SPM support (#5721)
1 parent 083311b commit 1443240

12 files changed

+10802
-7761
lines changed

lib/bootstrap.ts

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ injector.require("iOSProjectService", "./services/ios-project-service");
5858
injector.require("iOSProvisionService", "./services/ios-provision-service");
5959
injector.require("xcconfigService", "./services/xcconfig-service");
6060
injector.require("iOSSigningService", "./services/ios/ios-signing-service");
61+
injector.require("spmService", "./services/ios/spm-service");
6162
injector.require(
6263
"xcodebuildArgsService",
6364
"./services/ios/xcodebuild-args-service"

lib/commands/typings.ts

+18-11
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,24 @@ export class TypingsCommand implements ICommand {
122122
path.resolve(this.$projectData.projectDir, "typings", "ios")
123123
);
124124

125-
await this.$childProcess.spawnFromEvent("ns", ["build", "ios"], "exit", {
126-
env: {
127-
...process.env,
128-
TNS_TYPESCRIPT_DECLARATIONS_PATH: path.resolve(
129-
this.$projectData.projectDir,
130-
"typings",
131-
"ios"
132-
),
133-
},
134-
stdio: "inherit",
135-
});
125+
const nsPath = path.resolve(__dirname, "../../bin/nativescript.js");
126+
127+
await this.$childProcess.spawnFromEvent(
128+
"node",
129+
[nsPath, "build", "ios"],
130+
"exit",
131+
{
132+
env: {
133+
...process.env,
134+
TNS_TYPESCRIPT_DECLARATIONS_PATH: path.resolve(
135+
this.$projectData.projectDir,
136+
"typings",
137+
"ios"
138+
),
139+
},
140+
stdio: "inherit",
141+
}
142+
);
136143
}
137144
}
138145

lib/definitions/ios.d.ts

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ declare global {
4141
): Promise<string>;
4242
}
4343

44+
interface ISPMService {
45+
applySPMPackages(platformData: IPlatformData, projectData: IProjectData);
46+
}
47+
4448
interface IXcodebuildArgsService {
4549
getBuildForSimulatorArgs(
4650
platformData: IPlatformData,
@@ -52,6 +56,10 @@ declare global {
5256
projectData: IProjectData,
5357
buildConfig: IBuildConfig
5458
): Promise<string[]>;
59+
getXcodeProjectArgs(
60+
projectRoot: string,
61+
projectData: IProjectData
62+
): string[];
5563
}
5664

5765
interface IXcodebuildCommandService {

lib/services/ios-project-service.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
100100
private $iOSWatchAppService: IIOSWatchAppService,
101101
private $iOSNativeTargetService: IIOSNativeTargetService,
102102
private $sysInfo: ISysInfo,
103-
private $tempService: ITempService
103+
private $tempService: ITempService,
104+
private $spmService: ISPMService
104105
) {
105106
super($fs, $projectDataService);
106107
}
@@ -981,6 +982,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
981982
);
982983
}
983984

985+
await this.$spmService.applySPMPackages(platformData, projectData);
986+
984987
const pbxProjPath = this.getPbxProjPath(projectData);
985988
this.$iOSExtensionsService.removeExtensions({ pbxProjPath });
986989
await this.addExtensions(projectData, pluginsData);

lib/services/ios/spm-service.ts

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { injector } from "../../common/yok";
2+
import { IProjectConfigService, IProjectData } from "../../definitions/project";
3+
import {
4+
MobileProject,
5+
IosSPMPackageDefinition,
6+
} from "@rigor789/trapezedev-project";
7+
import { IPlatformData } from "../../definitions/platform";
8+
9+
export class SPMService implements ISPMService {
10+
constructor(
11+
private $logger: ILogger,
12+
private $projectConfigService: IProjectConfigService,
13+
private $xcodebuildCommandService: IXcodebuildCommandService,
14+
private $xcodebuildArgsService: IXcodebuildArgsService
15+
) {}
16+
17+
public getSPMPackages(projectData: IProjectData): IosSPMPackageDefinition[] {
18+
const spmPackages = this.$projectConfigService.getValue(
19+
"ios.SPMPackages",
20+
[]
21+
);
22+
23+
return spmPackages;
24+
}
25+
26+
public hasSPMPackages(projectData: IProjectData): boolean {
27+
return this.getSPMPackages(projectData).length > 0;
28+
}
29+
30+
public async applySPMPackages(
31+
platformData: IPlatformData,
32+
projectData: IProjectData
33+
) {
34+
try {
35+
const spmPackages = this.getSPMPackages(projectData);
36+
37+
if (!spmPackages.length) {
38+
this.$logger.trace("SPM: no SPM packages to apply.");
39+
return;
40+
}
41+
42+
const project = new MobileProject(platformData.projectRoot, {
43+
ios: {
44+
path: ".",
45+
},
46+
enableAndroid: false,
47+
});
48+
await project.load();
49+
50+
if (!project.ios) {
51+
this.$logger.trace("SPM: no iOS project found via trapeze.");
52+
return;
53+
}
54+
55+
// todo: handle removing packages? Or just warn and require a clean?
56+
for (const pkg of spmPackages) {
57+
this.$logger.trace(`SPM: adding package ${pkg.name} to project.`, pkg);
58+
await project.ios.addSPMPackage(projectData.projectName, pkg);
59+
}
60+
await project.commit();
61+
62+
// finally resolve the dependencies
63+
await this.resolveSPMDependencies(platformData, projectData);
64+
} catch (err) {
65+
this.$logger.trace("SPM: error applying SPM packages: ", err);
66+
}
67+
}
68+
69+
public async resolveSPMDependencies(
70+
platformData: IPlatformData,
71+
projectData: IProjectData
72+
) {
73+
await this.$xcodebuildCommandService.executeCommand(
74+
this.$xcodebuildArgsService
75+
.getXcodeProjectArgs(platformData.projectRoot, projectData)
76+
.concat([
77+
"-destination",
78+
"generic/platform=iOS",
79+
"-resolvePackageDependencies",
80+
]),
81+
{
82+
cwd: projectData.projectDir,
83+
message: "Resolving SPM dependencies...",
84+
}
85+
);
86+
}
87+
}
88+
injector.register("spmService", SPMService);

lib/services/ios/xcodebuild-args-service.ts

+5-29
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ import * as _ from "lodash";
1414

1515
const DevicePlatformSdkName = "iphoneos";
1616
const SimulatorPlatformSdkName = "iphonesimulator";
17-
enum ProductArgs {
18-
target = "target",
19-
scheme = "scheme",
20-
}
2117

2218
export class XcodebuildArgsService implements IXcodebuildArgsService {
2319
constructor(
@@ -35,9 +31,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
3531
): Promise<string[]> {
3632
let args = await this.getArchitecturesArgs(buildConfig);
3733

38-
let productType: ProductArgs;
3934
if (this.$iOSWatchAppService.hasWatchApp(platformData, projectData)) {
40-
productType = ProductArgs.scheme;
4135
args = args.concat(["CODE_SIGNING_ALLOWED=NO"]);
4236
} else {
4337
args = args.concat(["CODE_SIGN_IDENTITY="]);
@@ -59,13 +53,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
5953
)
6054
)
6155
.concat(this.getBuildLoggingArgs())
62-
.concat(
63-
this.getXcodeProjectArgs(
64-
platformData.projectRoot,
65-
projectData,
66-
productType
67-
)
68-
);
56+
.concat(this.getXcodeProjectArgs(platformData.projectRoot, projectData));
6957

7058
return args;
7159
}
@@ -90,13 +78,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
9078
buildConfig.release ? Configurations.Release : Configurations.Debug,
9179
"-allowProvisioningUpdates",
9280
]
93-
.concat(
94-
this.getXcodeProjectArgs(
95-
platformData.projectRoot,
96-
projectData,
97-
ProductArgs.scheme
98-
)
99-
)
81+
.concat(this.getXcodeProjectArgs(platformData.projectRoot, projectData))
10082
.concat(architectures)
10183
.concat(
10284
this.getBuildCommonArgs(
@@ -125,10 +107,9 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
125107
return args;
126108
}
127109

128-
private getXcodeProjectArgs(
110+
public getXcodeProjectArgs(
129111
projectRoot: string,
130-
projectData: IProjectData,
131-
product?: ProductArgs
112+
projectData: IProjectData
132113
): string[] {
133114
const xcworkspacePath = path.join(
134115
projectRoot,
@@ -147,12 +128,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
147128
projectRoot,
148129
`${projectData.projectName}.xcodeproj`
149130
);
150-
return [
151-
"-project",
152-
xcodeprojPath,
153-
product ? "-" + product : "-target",
154-
projectData.projectName,
155-
];
131+
return ["-project", xcodeprojPath, "-scheme", projectData.projectName];
156132
}
157133

158134
private getBuildLoggingArgs(): string[] {

lib/services/project-changes-service.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,14 @@ export class ProjectChangesService implements IProjectChangesService {
321321
): string {
322322
const projectFilePath = path.join(projectDir, PACKAGE_JSON_FILE_NAME);
323323
const projectFileContents = this.$fs.readJson(projectFilePath);
324+
325+
const relevantProperties = ["dependencies"];
326+
327+
const projectFileStrippedContents = _.pick(
328+
projectFileContents,
329+
relevantProperties
330+
);
331+
324332
// _(this.$devicePlatformsConstants)
325333
// .keys()
326334
// .map(k => k.toLowerCase())
@@ -329,7 +337,7 @@ export class ProjectChangesService implements IProjectChangesService {
329337
// delete projectFileContents.nativescript[`tns-${otherPlatform}`];
330338
// });
331339

332-
return getHash(JSON.stringify(projectFileContents));
340+
return getHash(JSON.stringify(projectFileStrippedContents));
333341
}
334342

335343
private isProjectFileChanged(

0 commit comments

Comments
 (0)