Skip to content

fix: bundle indentifier warning in Xcode11 #5013

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 1 commit into from
Sep 11, 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
1 change: 1 addition & 0 deletions lib/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ $injector.require("gradleCommandService", "./services/android/gradle-command-ser
$injector.require("gradleBuildService", "./services/android/gradle-build-service");
$injector.require("gradleBuildArgsService", "./services/android/gradle-build-args-service");
$injector.require("iOSEntitlementsService", "./services/ios-entitlements-service");
$injector.require("iOSNativeTargetService", "./services/ios-native-target-service");
$injector.require("iOSExtensionsService", "./services/ios-extensions-service");
$injector.require("iOSWatchAppService", "./services/ios-watch-app-service");
$injector.require("iOSProjectService", "./services/ios-project-service");
Expand Down
20 changes: 17 additions & 3 deletions lib/definitions/project.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,12 +458,26 @@ interface ICocoaPodsPlatformManager {
replacePlatformRow(podfileContent: string, podfilePath: string): { replacedContent: string, podfilePlatformData: IPodfilePlatformData };
}

declare const enum BuildNames {
debug = "Debug",
release = "Release"
}

interface IXcodeTargetBuildConfigurationProperty {
name: string;
value: any;
buildNames?: BuildNames[];
}

/**
* Describes a service used to add and remove iOS extension
*/
interface IIOSExtensionsService {
addExtensionsFromPath(options: IAddExtensionsFromPathOptions): Promise<boolean>;
removeExtensions(options: IRemoveExtensionsOptions): void;
interface IIOSNativeTargetService {
addTargetToProject(targetRootPath: string, targetFolder: string, targetType: string, project: IXcode.project, platformData: IPlatformData, parentTarget?: string): IXcode.target;
prepareSigning(targetUuids: string[], projectData:IProjectData, projectPath: string): void;
getTargetDirectories(folderPath: string): string[];
setXcodeTargetBuildConfigurationProperties(properties: IXcodeTargetBuildConfigurationProperty[], targetName: string, project: IXcode.project): void
setConfigurationsFromJsonFile(jsonPath: string, targetUuid: string, targetName: string, project: IXcode.project): void
}

/**
Expand Down
17 changes: 8 additions & 9 deletions lib/services/ios-extensions-service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import * as path from "path";
import { NativeTargetServiceBase } from "./ios-native-target-service-base";
import { IOSNativeTargetProductTypes, IOSNativeTargetTypes } from "../constants";

export class IOSExtensionsService extends NativeTargetServiceBase implements IIOSExtensionsService {
export class IOSExtensionsService implements IIOSExtensionsService {
constructor(protected $fs: IFileSystem,
protected $pbxprojDomXcode: IPbxprojDomXcode,
protected $xcode: IXcode) {
super($fs, $pbxprojDomXcode, $xcode);
protected $xcode: IXcode,
private $iOSNativeTargetService: IIOSNativeTargetService) {
}

public async addExtensionsFromPath({extensionsFolderPath, projectData, platformData, pbxProjPath}: IAddExtensionsFromPathOptions): Promise<boolean> {
Expand All @@ -17,29 +16,29 @@ export class IOSExtensionsService extends NativeTargetServiceBase implements IIO
}
const project = new this.$xcode.project(pbxProjPath);
project.parseSync();
this.getTargetDirectories(extensionsFolderPath)
this.$iOSNativeTargetService.getTargetDirectories(extensionsFolderPath)
.forEach(extensionFolder => {
const target = this.addTargetToProject(extensionsFolderPath, extensionFolder, IOSNativeTargetTypes.appExtension, project, platformData);
const target = this.$iOSNativeTargetService.addTargetToProject(extensionsFolderPath, extensionFolder, IOSNativeTargetTypes.appExtension, project, platformData);
this.configureTarget(extensionFolder, path.join(extensionsFolderPath, extensionFolder), target, project, projectData);
targetUuids.push(target.uuid);
addedExtensions = true;
});

this.$fs.writeFile(pbxProjPath, project.writeSync({omitEmptyValues: true}));
this.prepareSigning(targetUuids, projectData, pbxProjPath);
this.$iOSNativeTargetService.prepareSigning(targetUuids, projectData, pbxProjPath);

return addedExtensions;
}

private configureTarget(extensionName: string, extensionPath: string, target: IXcode.target, project: IXcode.project, projectData: IProjectData) {
const extJsonPath = path.join(extensionPath, "extension.json");

this.setXcodeTargetBuildConfigurationProperties(
this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties(
[{name: "PRODUCT_BUNDLE_IDENTIFIER", value: `${projectData.projectIdentifiers.ios}.${extensionName}`}],
extensionName,
project);

this.setConfigurationsFromJsonFile(extJsonPath, target.uuid, extensionName, project);
this.$iOSNativeTargetService.setConfigurationsFromJsonFile(extJsonPath, target.uuid, extensionName, project);
}

public removeExtensions({pbxProjPath}: IRemoveExtensionsOptions): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,27 @@
import * as path from "path";

export enum BuildNames {
debug = "Debug",
release = "Release"
}

export interface IXcodeTargetBuildConfigurationProperty {
name: string;
value: any;
buildNames?: BuildNames[];
}

export abstract class NativeTargetServiceBase {
export class IOSNativeTargetService implements IIOSNativeTargetService {
constructor(protected $fs: IFileSystem,
protected $pbxprojDomXcode: IPbxprojDomXcode,
protected $xcode: IXcode) {
protected $pbxprojDomXcode: IPbxprojDomXcode) {
}

protected addTargetToProject(extensionsFolderPath: string, extensionFolder: string, targetType: string, project: IXcode.project, platformData: IPlatformData, parentTarget?: string): IXcode.target {
const extensionPath = path.join(extensionsFolderPath, extensionFolder);
const extensionRelativePath = path.relative(platformData.projectRoot, extensionPath);
const files = this.$fs.readDirectory(extensionPath)
public addTargetToProject(targetRootPath: string, targetFolder: string, targetType: string, project: IXcode.project, platformData: IPlatformData, parentTarget?: string): IXcode.target {
const targetPath = path.join(targetRootPath, targetFolder);
const targetRelativePath = path.relative(platformData.projectRoot, targetPath);
const files = this.$fs.readDirectory(targetPath)
.filter(filePath => !filePath.startsWith("."))
.map(filePath => path.join(extensionPath, filePath));
const target = project.addTarget(extensionFolder, targetType, extensionRelativePath, parentTarget);
.map(filePath => path.join(targetPath, filePath));
const target = project.addTarget(targetFolder, targetType, targetRelativePath, parentTarget);
project.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid);
project.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid);
project.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', target.uuid);

project.addPbxGroup(files, extensionFolder, extensionPath, null, { isMain: true, target: target.uuid, filesRelativeToProject: true });
project.addToHeaderSearchPaths(extensionPath, target.pbxNativeTarget.productName);
project.addPbxGroup(files, targetFolder, targetPath, null, { isMain: true, target: target.uuid, filesRelativeToProject: true });
project.addToHeaderSearchPaths(targetPath, target.pbxNativeTarget.productName);
return target;
}

protected prepareSigning(targetUuids: string[], projectData:IProjectData, projectPath: string) {
public prepareSigning(targetUuids: string[], projectData: IProjectData, projectPath: string): void {
const xcode = this.$pbxprojDomXcode.Xcode.open(projectPath);
const signing = xcode.getSigning(projectData.projectName);
if (signing !== undefined) {
Expand All @@ -52,7 +40,7 @@ export abstract class NativeTargetServiceBase {
xcode.save();
}

protected getTargetDirectories(folderPath: string): string[] {
public getTargetDirectories(folderPath: string): string[] {
return this.$fs.readDirectory(folderPath)
.filter(fileName => {
const filePath = path.join(folderPath, fileName);
Expand All @@ -62,7 +50,7 @@ export abstract class NativeTargetServiceBase {
});
}

protected setXcodeTargetBuildConfigurationProperties(properties: IXcodeTargetBuildConfigurationProperty[], targetName: string, project: IXcode.project): void {
public setXcodeTargetBuildConfigurationProperties(properties: IXcodeTargetBuildConfigurationProperty[], targetName: string, project: IXcode.project): void {
properties.forEach(property => {
const buildNames = property.buildNames || [BuildNames.debug, BuildNames.release];
buildNames.forEach((buildName) => {
Expand All @@ -71,7 +59,7 @@ export abstract class NativeTargetServiceBase {
});
}

protected setConfigurationsFromJsonFile(jsonPath: string, targetUuid: string, targetName: string, project: IXcode.project) {
public setConfigurationsFromJsonFile(jsonPath: string, targetUuid: string, targetName: string, project: IXcode.project): void {
if (this.$fs.exists(jsonPath)) {
const configurationJson = this.$fs.readJson(jsonPath) || {};

Expand All @@ -94,3 +82,5 @@ export abstract class NativeTargetServiceBase {
}
}
}

$injector.register("iOSNativeTargetService", IOSNativeTargetService);
18 changes: 16 additions & 2 deletions lib/services/ios-project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
private $xcconfigService: IXcconfigService,
private $xcodebuildService: IXcodebuildService,
private $iOSExtensionsService: IIOSExtensionsService,
private $iOSWatchAppService: IIOSWatchAppService) {
private $iOSWatchAppService: IIOSWatchAppService,
private $iOSNativeTargetService: IIOSNativeTargetService) {
super($fs, $projectDataService);
}

Expand Down Expand Up @@ -432,7 +433,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>${projectData.projectIdentifiers.ios}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</dict>
</plist>`
});
Expand Down Expand Up @@ -529,6 +530,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ

public async handleNativeDependenciesChange(projectData: IProjectData, opts: IRelease): Promise<void> {
const platformData = this.getPlatformData(projectData);

this.setProductBundleIdentifier(projectData);
await this.$cocoapodsService.applyPodfileFromAppResources(projectData, platformData);

const projectPodfilePath = this.$cocoapodsService.getProjectPodfilePath(platformData.projectRoot);
Expand Down Expand Up @@ -603,6 +606,17 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
return target;
}

private setProductBundleIdentifier(projectData: IProjectData): void {
const project = this.createPbxProj(projectData);
this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties([
{
name: "PRODUCT_BUNDLE_IDENTIFIER",
value: `"${projectData.projectIdentifiers.ios}"`
}
], projectData.projectName, project);
this.savePbxProj(project, projectData);
}

private getAllLibsForPluginWithFileExtension(pluginData: IPluginData, fileExtension: string | string[]): string[] {
const fileExtensions = _.isArray(fileExtension) ? fileExtension : [fileExtension];
const filterCallback = (fileName: string, pluginPlatformsFolderPath: string) =>
Expand Down
21 changes: 10 additions & 11 deletions lib/services/ios-watch-app-service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import * as path from "path";
import { NativeTargetServiceBase } from "./ios-native-target-service-base";
import { IOSDeviceTargets, IOS_WATCHAPP_FOLDER, IOS_WATCHAPP_EXTENSION_FOLDER, IOSNativeTargetProductTypes, IOSNativeTargetTypes } from "../constants";

export class IOSWatchAppService extends NativeTargetServiceBase implements IIOSWatchAppService {
export class IOSWatchAppService implements IIOSWatchAppService {
private static WATCH_APP_IDENTIFIER = "watchkitapp";
private static WACTCH_EXTENSION_IDENTIFIER = "watchkitextension";
constructor(protected $fs: IFileSystem,
protected $pbxprojDomXcode: IPbxprojDomXcode,
protected $xcode: IXcode) {
super($fs, $pbxprojDomXcode, $xcode);
protected $xcode: IXcode,
private $iOSNativeTargetService: IIOSNativeTargetService) {
}

public async addWatchAppFromPath({watchAppFolderPath, projectData, platformData, pbxProjPath}: IAddWatchAppFromPathOptions): Promise<boolean> {
Expand All @@ -20,13 +19,13 @@ export class IOSWatchAppService extends NativeTargetServiceBase implements IIOSW
return false;
}

const appFolder = this.getTargetDirectories(appPath)[0];
const extensionFolder = this.getTargetDirectories(extensionPath)[0];
const appFolder = this.$iOSNativeTargetService.getTargetDirectories(appPath)[0];
const extensionFolder = this.$iOSNativeTargetService.getTargetDirectories(extensionPath)[0];

const project = new this.$xcode.project(pbxProjPath);
project.parseSync();

const watchApptarget = this.addTargetToProject(appPath, appFolder, IOSNativeTargetTypes.watchApp, project, platformData, project.getFirstTarget().uuid);
const watchApptarget = this.$iOSNativeTargetService.addTargetToProject(appPath, appFolder, IOSNativeTargetTypes.watchApp, project, platformData, project.getFirstTarget().uuid);
this.configureTarget(
appFolder,
path.join(appPath, appFolder),
Expand All @@ -37,7 +36,7 @@ export class IOSWatchAppService extends NativeTargetServiceBase implements IIOSW
);
targetUuids.push(watchApptarget.uuid);

const watchExtensionTarget = this.addTargetToProject(extensionPath, extensionFolder, IOSNativeTargetTypes.watchExtension, project, platformData, watchApptarget.uuid);
const watchExtensionTarget = this.$iOSNativeTargetService.addTargetToProject(extensionPath, extensionFolder, IOSNativeTargetTypes.watchExtension, project, platformData, watchApptarget.uuid);
this.configureTarget(
extensionFolder,
path.join(extensionPath, extensionFolder),
Expand All @@ -48,7 +47,7 @@ export class IOSWatchAppService extends NativeTargetServiceBase implements IIOSW
targetUuids.push(watchExtensionTarget.uuid);

this.$fs.writeFile(pbxProjPath, project.writeSync({omitEmptyValues: true}));
this.prepareSigning(targetUuids, projectData, pbxProjPath);
this.$iOSNativeTargetService.prepareSigning(targetUuids, projectData, pbxProjPath);

return true;
}
Expand Down Expand Up @@ -78,15 +77,15 @@ export class IOSWatchAppService extends NativeTargetServiceBase implements IIOSW
identifierParts.pop();
const wkAppBundleIdentifier = identifierParts.join(".");

this.setXcodeTargetBuildConfigurationProperties([
this.$iOSNativeTargetService.setXcodeTargetBuildConfigurationProperties([
{name: "PRODUCT_BUNDLE_IDENTIFIER", value: identifier},
{name: "SDKROOT", value: "watchos"},
{name: "TARGETED_DEVICE_FAMILY", value: IOSDeviceTargets.watchos},
{name: "WATCHOS_DEPLOYMENT_TARGET", value: 5.2},
{name: "WK_APP_BUNDLE_IDENTIFIER", value: wkAppBundleIdentifier}
], targetName, project);

this.setConfigurationsFromJsonFile(targetConfigurationJsonPath, target.uuid, targetName, project);
this.$iOSNativeTargetService.setConfigurationsFromJsonFile(targetConfigurationJsonPath, target.uuid, targetName, project);
project.addToHeaderSearchPaths(targetPath, target.pbxNativeTarget.productName);
}
}
Expand Down
3 changes: 3 additions & 0 deletions test/ios-project-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ function createTestInjector(projectPath: string, projectName: string, xCode?: IX
testInjector.register("logSourceMapService", {
replaceWithOriginalFileLocations: (platform: string, message: string) => message
});
testInjector.register("iOSNativeTargetService", {
setXcodeTargetBuildConfigurationProperties: () => { /* */ }
});
return testInjector;
}

Expand Down