Skip to content

Commit

Permalink
feat: experimental SPM support (#5721)
Browse files Browse the repository at this point in the history
  • Loading branch information
rigor789 committed Mar 25, 2023
1 parent 083311b commit 1443240
Show file tree
Hide file tree
Showing 12 changed files with 10,802 additions and 7,761 deletions.
1 change: 1 addition & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ injector.require("iOSProjectService", "./services/ios-project-service");
injector.require("iOSProvisionService", "./services/ios-provision-service");
injector.require("xcconfigService", "./services/xcconfig-service");
injector.require("iOSSigningService", "./services/ios/ios-signing-service");
injector.require("spmService", "./services/ios/spm-service");
injector.require(
"xcodebuildArgsService",
"./services/ios/xcodebuild-args-service"
Expand Down
29 changes: 18 additions & 11 deletions lib/commands/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,24 @@ export class TypingsCommand implements ICommand {
path.resolve(this.$projectData.projectDir, "typings", "ios")
);

await this.$childProcess.spawnFromEvent("ns", ["build", "ios"], "exit", {
env: {
...process.env,
TNS_TYPESCRIPT_DECLARATIONS_PATH: path.resolve(
this.$projectData.projectDir,
"typings",
"ios"
),
},
stdio: "inherit",
});
const nsPath = path.resolve(__dirname, "../../bin/nativescript.js");

await this.$childProcess.spawnFromEvent(
"node",
[nsPath, "build", "ios"],
"exit",
{
env: {
...process.env,
TNS_TYPESCRIPT_DECLARATIONS_PATH: path.resolve(
this.$projectData.projectDir,
"typings",
"ios"
),
},
stdio: "inherit",
}
);
}
}

Expand Down
8 changes: 8 additions & 0 deletions lib/definitions/ios.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ declare global {
): Promise<string>;
}

interface ISPMService {
applySPMPackages(platformData: IPlatformData, projectData: IProjectData);
}

interface IXcodebuildArgsService {
getBuildForSimulatorArgs(
platformData: IPlatformData,
Expand All @@ -52,6 +56,10 @@ declare global {
projectData: IProjectData,
buildConfig: IBuildConfig
): Promise<string[]>;
getXcodeProjectArgs(
projectRoot: string,
projectData: IProjectData
): string[];
}

interface IXcodebuildCommandService {
Expand Down
5 changes: 4 additions & 1 deletion lib/services/ios-project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
private $iOSWatchAppService: IIOSWatchAppService,
private $iOSNativeTargetService: IIOSNativeTargetService,
private $sysInfo: ISysInfo,
private $tempService: ITempService
private $tempService: ITempService,
private $spmService: ISPMService
) {
super($fs, $projectDataService);
}
Expand Down Expand Up @@ -981,6 +982,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
);
}

await this.$spmService.applySPMPackages(platformData, projectData);

const pbxProjPath = this.getPbxProjPath(projectData);
this.$iOSExtensionsService.removeExtensions({ pbxProjPath });
await this.addExtensions(projectData, pluginsData);
Expand Down
88 changes: 88 additions & 0 deletions lib/services/ios/spm-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { injector } from "../../common/yok";
import { IProjectConfigService, IProjectData } from "../../definitions/project";
import {
MobileProject,
IosSPMPackageDefinition,
} from "@rigor789/trapezedev-project";
import { IPlatformData } from "../../definitions/platform";

export class SPMService implements ISPMService {
constructor(
private $logger: ILogger,
private $projectConfigService: IProjectConfigService,
private $xcodebuildCommandService: IXcodebuildCommandService,
private $xcodebuildArgsService: IXcodebuildArgsService
) {}

public getSPMPackages(projectData: IProjectData): IosSPMPackageDefinition[] {
const spmPackages = this.$projectConfigService.getValue(
"ios.SPMPackages",
[]
);

return spmPackages;
}

public hasSPMPackages(projectData: IProjectData): boolean {
return this.getSPMPackages(projectData).length > 0;
}

public async applySPMPackages(
platformData: IPlatformData,
projectData: IProjectData
) {
try {
const spmPackages = this.getSPMPackages(projectData);

if (!spmPackages.length) {
this.$logger.trace("SPM: no SPM packages to apply.");
return;
}

const project = new MobileProject(platformData.projectRoot, {
ios: {
path: ".",
},
enableAndroid: false,
});
await project.load();

if (!project.ios) {
this.$logger.trace("SPM: no iOS project found via trapeze.");
return;
}

// todo: handle removing packages? Or just warn and require a clean?
for (const pkg of spmPackages) {
this.$logger.trace(`SPM: adding package ${pkg.name} to project.`, pkg);
await project.ios.addSPMPackage(projectData.projectName, pkg);
}
await project.commit();

// finally resolve the dependencies
await this.resolveSPMDependencies(platformData, projectData);
} catch (err) {
this.$logger.trace("SPM: error applying SPM packages: ", err);
}
}

public async resolveSPMDependencies(
platformData: IPlatformData,
projectData: IProjectData
) {
await this.$xcodebuildCommandService.executeCommand(
this.$xcodebuildArgsService
.getXcodeProjectArgs(platformData.projectRoot, projectData)
.concat([
"-destination",
"generic/platform=iOS",
"-resolvePackageDependencies",
]),
{
cwd: projectData.projectDir,
message: "Resolving SPM dependencies...",
}
);
}
}
injector.register("spmService", SPMService);
34 changes: 5 additions & 29 deletions lib/services/ios/xcodebuild-args-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ import * as _ from "lodash";

const DevicePlatformSdkName = "iphoneos";
const SimulatorPlatformSdkName = "iphonesimulator";
enum ProductArgs {
target = "target",
scheme = "scheme",
}

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

let productType: ProductArgs;
if (this.$iOSWatchAppService.hasWatchApp(platformData, projectData)) {
productType = ProductArgs.scheme;
args = args.concat(["CODE_SIGNING_ALLOWED=NO"]);
} else {
args = args.concat(["CODE_SIGN_IDENTITY="]);
Expand All @@ -59,13 +53,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
)
)
.concat(this.getBuildLoggingArgs())
.concat(
this.getXcodeProjectArgs(
platformData.projectRoot,
projectData,
productType
)
);
.concat(this.getXcodeProjectArgs(platformData.projectRoot, projectData));

return args;
}
Expand All @@ -90,13 +78,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
buildConfig.release ? Configurations.Release : Configurations.Debug,
"-allowProvisioningUpdates",
]
.concat(
this.getXcodeProjectArgs(
platformData.projectRoot,
projectData,
ProductArgs.scheme
)
)
.concat(this.getXcodeProjectArgs(platformData.projectRoot, projectData))
.concat(architectures)
.concat(
this.getBuildCommonArgs(
Expand Down Expand Up @@ -125,10 +107,9 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
return args;
}

private getXcodeProjectArgs(
public getXcodeProjectArgs(
projectRoot: string,
projectData: IProjectData,
product?: ProductArgs
projectData: IProjectData
): string[] {
const xcworkspacePath = path.join(
projectRoot,
Expand All @@ -147,12 +128,7 @@ export class XcodebuildArgsService implements IXcodebuildArgsService {
projectRoot,
`${projectData.projectName}.xcodeproj`
);
return [
"-project",
xcodeprojPath,
product ? "-" + product : "-target",
projectData.projectName,
];
return ["-project", xcodeprojPath, "-scheme", projectData.projectName];
}

private getBuildLoggingArgs(): string[] {
Expand Down
10 changes: 9 additions & 1 deletion lib/services/project-changes-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@ export class ProjectChangesService implements IProjectChangesService {
): string {
const projectFilePath = path.join(projectDir, PACKAGE_JSON_FILE_NAME);
const projectFileContents = this.$fs.readJson(projectFilePath);

const relevantProperties = ["dependencies"];

const projectFileStrippedContents = _.pick(
projectFileContents,
relevantProperties
);

// _(this.$devicePlatformsConstants)
// .keys()
// .map(k => k.toLowerCase())
Expand All @@ -329,7 +337,7 @@ export class ProjectChangesService implements IProjectChangesService {
// delete projectFileContents.nativescript[`tns-${otherPlatform}`];
// });

return getHash(JSON.stringify(projectFileContents));
return getHash(JSON.stringify(projectFileStrippedContents));
}

private isProjectFileChanged(
Expand Down
Loading

0 comments on commit 1443240

Please sign in to comment.