Skip to content

fix: prepare xcconfig files for all conigurations #4559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions lib/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -890,12 +890,11 @@ interface IXcprojInfo {

interface IXcconfigService {
/**
* Returns the path to the xcconfig file
* Returns the paths to the xcconfig files for build configuration (debug/release)
* @param projectRoot The path to root folder of native project (platforms/ios)
* @param opts
* @returns {string}
* @returns {IStringDictionary}
*/
getPluginsXcconfigFilePath(projectRoot: string, opts: IRelease): string;
getPluginsXcconfigFilePaths(projectRoot: string): IStringDictionary;

/**
* Returns the value of a property from a xcconfig file.
Expand Down
12 changes: 7 additions & 5 deletions lib/services/cocoapods-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ export class CocoaPodsService implements ICocoaPodsService {
return podInstallResult;
}

public async mergePodXcconfigFile(projectData: IProjectData, platformData: IPlatformData, opts: IRelease) {
public async mergePodXcconfigFile(projectData: IProjectData, platformData: IPlatformData): Promise<void> {
const podFilesRootDirName = path.join("Pods", "Target Support Files", `Pods-${projectData.projectName}`);
const podFolder = path.join(platformData.projectRoot, podFilesRootDirName);
if (this.$fs.exists(podFolder)) {
const podXcconfigFilePath = opts && opts.release ? path.join(podFolder, `Pods-${projectData.projectName}.release.xcconfig`)
: path.join(podFolder, `Pods-${projectData.projectName}.debug.xcconfig`);
const pluginsXcconfigFilePath = this.$xcconfigService.getPluginsXcconfigFilePath(platformData.projectRoot, opts);
await this.$xcconfigService.mergeFiles(podXcconfigFilePath, pluginsXcconfigFilePath);
const pluginsXcconfigFilePaths = this.$xcconfigService.getPluginsXcconfigFilePaths(platformData.projectRoot);
for (const configuration in pluginsXcconfigFilePaths) {
const pluginsXcconfigFilePath = pluginsXcconfigFilePaths[configuration];
const podXcconfigFilePath = path.join(podFolder, `Pods-${projectData.projectName}.${configuration}.xcconfig`);
await this.$xcconfigService.mergeFiles(podXcconfigFilePath, pluginsXcconfigFilePath);
}
}
}

Expand Down
53 changes: 32 additions & 21 deletions lib/services/ios-project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
public async processConfigurationFilesFromAppResources(projectData: IProjectData, opts: IRelease): Promise<void> {
await this.mergeInfoPlists(projectData, opts);
await this.$iOSEntitlementsService.merge(projectData);
await this.mergeProjectXcconfigFiles(projectData, opts);
await this.mergeProjectXcconfigFiles(projectData);
for (const pluginData of await this.getAllInstalledPlugins(projectData)) {
await this.$pluginVariablesService.interpolatePluginVariables(pluginData, this.getPlatformData(projectData).configurationFilePath, projectData.projectDir);
}
Expand Down Expand Up @@ -1216,43 +1216,54 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
this.$fs.writeFile(path.join(headersFolderPath, "module.modulemap"), modulemap);
}

private async mergeProjectXcconfigFiles(projectData: IProjectData, opts: IRelease): Promise<void> {
private async mergeProjectXcconfigFiles(projectData: IProjectData): Promise<void> {
const platformData = this.getPlatformData(projectData);
const pluginsXcconfigFilePath = this.$xcconfigService.getPluginsXcconfigFilePath(platformData.projectRoot, opts);
this.$fs.deleteFile(pluginsXcconfigFilePath);
const pluginsXcconfigFilePaths = _.values(this.$xcconfigService.getPluginsXcconfigFilePaths(platformData.projectRoot));

for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
this.$fs.deleteFile(pluginsXcconfigFilePath);
}

const pluginsService = <IPluginsService>this.$injector.resolve("pluginsService");
const allPlugins: IPluginData[] = await pluginsService.getAllInstalledPlugins(projectData);
for (const plugin of allPlugins) {
const pluginPlatformsFolderPath = plugin.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME);
const pluginXcconfigFilePath = path.join(pluginPlatformsFolderPath, BUILD_XCCONFIG_FILE_NAME);
if (this.$fs.exists(pluginXcconfigFilePath)) {
await this.$xcconfigService.mergeFiles(pluginXcconfigFilePath, pluginsXcconfigFilePath);
for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
await this.$xcconfigService.mergeFiles(pluginXcconfigFilePath, pluginsXcconfigFilePath);
}
}
}

const appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, BUILD_XCCONFIG_FILE_NAME);
if (this.$fs.exists(appResourcesXcconfigPath)) {
await this.$xcconfigService.mergeFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath);
for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
await this.$xcconfigService.mergeFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath);
}
}

if (!this.$fs.exists(pluginsXcconfigFilePath)) {
// We need the pluginsXcconfig file to exist in platforms dir as it is required in the native template:
// https://github.com/NativeScript/ios-runtime/blob/9c2b7b5f70b9bee8452b7a24aa6b646214c7d2be/build/project-template/__PROJECT_NAME__/build-debug.xcconfig#L3
// From Xcode 10 in case the file is missing, this include fails and the build itself fails (was a warning in previous Xcode versions).
this.$fs.writeFile(pluginsXcconfigFilePath, "");
for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
if (!this.$fs.exists(pluginsXcconfigFilePath)) {
// We need the pluginsXcconfig file to exist in platforms dir as it is required in the native template:
// https://github.com/NativeScript/ios-runtime/blob/9c2b7b5f70b9bee8452b7a24aa6b646214c7d2be/build/project-template/__PROJECT_NAME__/build-debug.xcconfig#L3
// From Xcode 10 in case the file is missing, this include fails and the build itself fails (was a warning in previous Xcode versions).
this.$fs.writeFile(pluginsXcconfigFilePath, "");
}
}

// Set Entitlements Property to point to default file if not set explicitly by the user.
const entitlementsPropertyValue = this.$xcconfigService.readPropertyValue(pluginsXcconfigFilePath, constants.CODE_SIGN_ENTITLEMENTS);
if (entitlementsPropertyValue === null && this.$fs.exists(this.$iOSEntitlementsService.getPlatformsEntitlementsPath(projectData))) {
temp.track();
const tempEntitlementsDir = temp.mkdirSync("entitlements");
const tempEntitlementsFilePath = path.join(tempEntitlementsDir, "set-entitlements.xcconfig");
const entitlementsRelativePath = this.$iOSEntitlementsService.getPlatformsEntitlementsRelativePath(projectData);
this.$fs.writeFile(tempEntitlementsFilePath, `CODE_SIGN_ENTITLEMENTS = ${entitlementsRelativePath}${EOL}`);

await this.$xcconfigService.mergeFiles(tempEntitlementsFilePath, pluginsXcconfigFilePath);
for (const pluginsXcconfigFilePath of pluginsXcconfigFilePaths) {
// Set Entitlements Property to point to default file if not set explicitly by the user.
const entitlementsPropertyValue = this.$xcconfigService.readPropertyValue(pluginsXcconfigFilePath, constants.CODE_SIGN_ENTITLEMENTS);
if (entitlementsPropertyValue === null && this.$fs.exists(this.$iOSEntitlementsService.getPlatformsEntitlementsPath(projectData))) {
temp.track();
const tempEntitlementsDir = temp.mkdirSync("entitlements");
const tempEntitlementsFilePath = path.join(tempEntitlementsDir, "set-entitlements.xcconfig");
const entitlementsRelativePath = this.$iOSEntitlementsService.getPlatformsEntitlementsRelativePath(projectData);
this.$fs.writeFile(tempEntitlementsFilePath, `CODE_SIGN_ENTITLEMENTS = ${entitlementsRelativePath}${EOL}`);

await this.$xcconfigService.mergeFiles(tempEntitlementsFilePath, pluginsXcconfigFilePath);
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions lib/services/xcconfig-service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as path from "path";
import { Configurations } from "../common/constants";

export class XcconfigService implements IXcconfigService {
constructor(
private $childProcess: IChildProcess,
private $fs: IFileSystem,
private $xcprojService: IXcprojService) { }

public getPluginsXcconfigFilePath(projectRoot: string, opts: IRelease): string {
if (opts && opts.release) {
return this.getPluginsReleaseXcconfigFilePath(projectRoot);
}

return this.getPluginsDebugXcconfigFilePath(projectRoot);
public getPluginsXcconfigFilePaths(projectRoot: string): IStringDictionary {
return {
[Configurations.Debug.toLowerCase()]: this.getPluginsDebugXcconfigFilePath(projectRoot),
[Configurations.Release.toLowerCase()]: this.getPluginsReleaseXcconfigFilePath(projectRoot)
};
}

private getPluginsDebugXcconfigFilePath(projectRoot: string): string {
Expand Down
2 changes: 1 addition & 1 deletion npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nativescript",
"preferGlobal": true,
"version": "5.3.3",
"version": "5.3.4",
"author": "Telerik <support@telerik.com>",
"description": "Command-line interface for building NativeScript projects",
"bin": {
Expand Down
56 changes: 29 additions & 27 deletions test/ios-project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1178,17 +1178,19 @@ describe("Merge Project XCConfig files", () => {

// run merge for all release: debug|release
for (const release in [true, false]) {
await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData, { release });
await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData);

const destinationFilePath = xcconfigService.getPluginsXcconfigFilePath(projectRoot, { release: !!release });
const destinationFilePaths = xcconfigService.getPluginsXcconfigFilePaths(projectRoot);

assert.isTrue(fs.exists(destinationFilePath), 'Target build xcconfig is missing for release: ' + release);
const expected = {
'ASSETCATALOG_COMPILER_APPICON_NAME': 'AppIcon',
'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME': 'LaunchImage',
'CODE_SIGN_IDENTITY': 'iPhone Distribution'
};
assertPropertyValues(expected, destinationFilePath, testInjector);
_.each(destinationFilePaths, destinationFilePath => {
assert.isTrue(fs.exists(destinationFilePath), 'Target build xcconfig is missing for release: ' + release);
const expected = {
'ASSETCATALOG_COMPILER_APPICON_NAME': 'AppIcon',
'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME': 'LaunchImage',
'CODE_SIGN_IDENTITY': 'iPhone Distribution'
};
assertPropertyValues(expected, destinationFilePath, testInjector);
});
}
});

Expand All @@ -1206,13 +1208,15 @@ describe("Merge Project XCConfig files", () => {

await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData, { release });

const destinationFilePath = xcconfigService.getPluginsXcconfigFilePath(projectRoot, { release: !!release });
const destinationFilePaths = xcconfigService.getPluginsXcconfigFilePaths(projectRoot);

assert.isTrue(fs.exists(destinationFilePath), 'Target build xcconfig is missing for release: ' + release);
const expected = {
'CODE_SIGN_ENTITLEMENTS': iOSEntitlementsService.getPlatformsEntitlementsRelativePath(projectData)
};
assertPropertyValues(expected, destinationFilePath, testInjector);
_.each(destinationFilePaths, destinationFilePath => {
assert.isTrue(fs.exists(destinationFilePath), 'Target build xcconfig is missing for release: ' + release);
const expected = {
'CODE_SIGN_ENTITLEMENTS': iOSEntitlementsService.getPlatformsEntitlementsRelativePath(projectData)
};
assertPropertyValues(expected, destinationFilePath, testInjector);
});
}
});

Expand All @@ -1222,34 +1226,32 @@ describe("Merge Project XCConfig files", () => {
const xcconfigEntitlements = appResourceXCConfigContent + `${EOL}CODE_SIGN_ENTITLEMENTS = ${expectedEntitlementsFile}`;
fs.writeFile(appResourcesXcconfigPath, xcconfigEntitlements);

// run merge for all release: debug|release
for (const release in [true, false]) {
await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData, { release });
await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData);

const destinationFilePath = xcconfigService.getPluginsXcconfigFilePath(projectRoot, { release: !!release });
const destinationFilePaths = xcconfigService.getPluginsXcconfigFilePaths(projectRoot);

assert.isTrue(fs.exists(destinationFilePath), 'Target build xcconfig is missing for release: ' + release);
_.each(destinationFilePaths, destinationFilePath => {
assert.isTrue(fs.exists(destinationFilePath), `Target build xcconfig ${destinationFilePath} is missing.`);
const expected = {
'ASSETCATALOG_COMPILER_APPICON_NAME': 'AppIcon',
'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME': 'LaunchImage',
'CODE_SIGN_IDENTITY': 'iPhone Distribution',
'CODE_SIGN_ENTITLEMENTS': expectedEntitlementsFile
};
assertPropertyValues(expected, destinationFilePath, testInjector);
}
});
});

it("creates empty plugins-<config>.xcconfig in case there are no build.xcconfig in App_Resources and in plugins", async () => {
// run merge for all release: debug|release
for (const release in [true, false]) {
await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData, { release });
await (<any>iOSProjectService).mergeProjectXcconfigFiles(projectData);

const destinationFilePath = xcconfigService.getPluginsXcconfigFilePath(projectRoot, { release: !!release });
const destinationFilePaths = xcconfigService.getPluginsXcconfigFilePaths(projectRoot);

assert.isTrue(fs.exists(destinationFilePath), 'Target build xcconfig is missing for release: ' + release);
_.each(destinationFilePaths, destinationFilePath => {
assert.isTrue(fs.exists(destinationFilePath), `Target build xcconfig ${destinationFilePath} is missing.` );
const content = fs.readFile(destinationFilePath).toString();
assert.equal(content, "");
}
});
});
});

Expand Down