Skip to content

Commit 73d1460

Browse files
fix: Project's Podfile is regenerated incorrectly
In case multiple plugins have Podfile with post_install hook, CLI modifies the hook of each of them by renaming the hook's function and calling it in the single post_install that is allowed for Podfile (placed at the bottom of the project's Podfile). However, when some change in node_modules is detected, CLI processes all Podfiles again and tries to apply them to project's Podfile. The "apply" is check if the plugin's Podfile is already added to project's one and in case not - adding it again. Whenever all Podfiles are processed, the "afterPrepareAllPlugins" method checks the final project's Podfile and replaces the post_install hooks from all plugins with a new functions (by adding index to the name) and calls them inside a newly added post_install function. This is not working as when CLI checks if a plugin's Podfile is already added to the project's one, it uses the original content of the plugin's Podfile, where the post_install hook is called `post_install`, while in the project's one it is renamed. So CLI always thinks that plugin's Podfile, which has post_install hook is not added to the project. CLI tries to add it again and messes the whole structure. In order to fix the issue, apply the following logic: 1. When a plugin has a Podfile, during prepare of the plugin read the content of this file. After that apply modifications over the file by replacing the post_install with a well known name - `post_install<plugin_name>_<index>`. 2. Check if the replaced content is part of the project's Podfile. In case yes - do nothing. 3. In case the replaced content is not part of the project's Podfile, it means that either we have never added this Podfile or its content has been changed. In order to handle both cases first remove the plugin's Podfile from the project's one - this includes removing the whole content between `# Begin Podfile <podfile>` and `# End Podfile` for this Podfile to be removed from the project's one and all post_install hooks with name that would have been used for this plugin to be removed. After that add the replaced content in the project's Podfile and call all post_install replaced functions in the project's Podfile's post_install hook. 4. On `afterPrepareAllPlugins` do nothing with the Podfile, it is already processed. This solution ensures the Podfile is correct after processing each plugin. The previous one relyed on the `afterPrepareAllPlugins` to fix the project's Podfile. Also, by using well known pattern for generating the post_install hooks, we ensure we can remove them from the final Podfile whenever is required.
1 parent 76ff072 commit 73d1460

File tree

7 files changed

+581
-147
lines changed

7 files changed

+581
-147
lines changed

lib/common

lib/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,10 @@ export class AddPlaformErrors {
215215

216216
export const PLUGIN_BUILD_DATA_FILENAME = "plugin-data.json";
217217
export const PLUGINS_BUILD_DATA_FILENAME = ".ns-plugins-build-data.json";
218+
219+
export class PluginNativeDirNames {
220+
public static iOS = "ios";
221+
public static Android = "android";
222+
}
223+
224+
export const PODFILE_NAME = "Podfile";

lib/definitions/project.d.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,32 @@ interface ICocoaPodsService {
464464
getPodfileFooter(): string;
465465

466466
/**
467-
* Merges the content of hooks with the provided name if there are more than one hooks with this name in the Podfile.
468-
* @param {string} hookName The name of the hook.
469-
* @param {string} pathToPodfile The path to the Podfile.
470-
* @return {void}
467+
* Prepares the Podfile content of a plugin and merges it in the project's Podfile.
468+
* @param {IPluginData} pluginData Information about the plugin.
469+
* @param {IProjectData} projectData Information about the project.
470+
* @param {string} nativeProjectPath Path to the native Xcode project.
471+
* @returns {Promise<void>}
472+
*/
473+
applyPluginPodfileToProject(pluginData: IPluginData, projectData: IProjectData, nativeProjectPath: string): Promise<void>;
474+
475+
/**
476+
* Removes plugins Podfile content from the project.
477+
* @param {IPluginData} pluginData Information about the plugin.
478+
* @param {IProjectData} projectData Information about the project.
479+
* @param {string} nativeProjectPath Path to the native Xcode project.
480+
* @returns {void}
471481
*/
472-
mergePodfileHookContent(sectionName: string, pathToPodfile: string): void
482+
removePluginPodfileFromProject(pluginData: IPluginData, projectData: IProjectData, nativeProjectPath: string): void;
483+
484+
/**
485+
* Gives the path to project's Podfile.
486+
* @param {string} nativeProjectPath Path to the native Xcode project.
487+
* @returns {string} Path to project's Podfile.
488+
*/
489+
getProjectPodfilePath(nativeProjectPath: string): string;
490+
}
491+
492+
interface IRubyFunction {
493+
functionName: string;
494+
functionParameters?: string;
473495
}

lib/services/cocoapods-service.ts

Lines changed: 138 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { EOL } from "os";
2-
3-
interface IRubyFunction {
4-
functionName: string;
5-
functionParameters?: string;
6-
}
2+
import * as path from "path";
3+
import { PluginNativeDirNames, PODFILE_NAME } from "../constants";
74

85
export class CocoaPodsService implements ICocoaPodsService {
6+
private static PODFILE_POST_INSTALL_SECTION_NAME = "post_install";
7+
98
constructor(private $fs: IFileSystem) { }
109

1110
public getPodfileHeader(targetName: string): string {
@@ -16,20 +15,132 @@ export class CocoaPodsService implements ICocoaPodsService {
1615
return `${EOL}end`;
1716
}
1817

19-
public mergePodfileHookContent(hookName: string, pathToPodfile: string): void {
20-
if (!this.$fs.exists(pathToPodfile)) {
21-
throw new Error(`The Podfile ${pathToPodfile} does not exist.`);
18+
public getProjectPodfilePath(projectRoot: string): string {
19+
return path.join(projectRoot, PODFILE_NAME);
20+
}
21+
22+
public async applyPluginPodfileToProject(pluginData: IPluginData, projectData: IProjectData, nativeProjectPath: string): Promise<void> {
23+
const pluginPodFilePath = this.getPathToPluginPodfile(pluginData);
24+
if (!this.$fs.exists(pluginPodFilePath)) {
25+
return;
26+
}
27+
28+
const { pluginPodFileContent, replacedFunctions } = this.buildPodfileContent(pluginPodFilePath, pluginData.name);
29+
const pathToProjectPodfile = this.getProjectPodfilePath(nativeProjectPath);
30+
const projectPodfileContent = this.$fs.exists(pathToProjectPodfile) ? this.$fs.readText(pathToProjectPodfile) : "";
31+
32+
if (projectPodfileContent.indexOf(pluginPodFileContent) === -1) {
33+
// Remove old occurences of the plugin from the project's Podfile.
34+
this.removePluginPodfileFromProject(pluginData, projectData, nativeProjectPath);
35+
let finalPodfileContent = this.$fs.exists(pathToProjectPodfile) ? this.getPodfileContentWithoutTarget(projectData, this.$fs.readText(pathToProjectPodfile)) : "";
36+
37+
if (pluginPodFileContent.indexOf(CocoaPodsService.PODFILE_POST_INSTALL_SECTION_NAME) !== -1) {
38+
finalPodfileContent = this.addPostInstallHook(replacedFunctions, finalPodfileContent, pluginPodFileContent);
39+
}
40+
41+
finalPodfileContent = `${pluginPodFileContent}${EOL}${finalPodfileContent}`;
42+
this.saveProjectPodfile(projectData, finalPodfileContent, nativeProjectPath);
2243
}
44+
}
2345

24-
const podfileContent = this.$fs.readText(pathToPodfile);
46+
public removePluginPodfileFromProject(pluginData: IPluginData, projectData: IProjectData, projectRoot: string): void {
47+
const pluginPodFilePath = this.getPathToPluginPodfile(pluginData);
48+
49+
if (this.$fs.exists(pluginPodFilePath) && this.$fs.exists(this.getProjectPodfilePath(projectRoot))) {
50+
let projectPodFileContent = this.$fs.readText(this.getProjectPodfilePath(projectRoot));
51+
// Remove the data between #Begin Podfile and #EndPodfile
52+
const regExpToRemove = new RegExp(`${this.getPluginPodfileHeader(pluginPodFilePath)}[\\s\\S]*?${this.getPluginPodfileEnd()}`, "mg");
53+
projectPodFileContent = projectPodFileContent.replace(regExpToRemove, "");
54+
projectPodFileContent = this.removePostInstallHook(pluginData, projectPodFileContent);
55+
56+
const defaultPodfileBeginning = `use_frameworks!${EOL}${EOL}target "${projectData.projectName}" do${EOL}`;
57+
const defaultContentWithPostInstallHook = `${defaultPodfileBeginning}${EOL}post_install do |installer|${EOL}end${EOL}end`;
58+
const defaultContentWithoutPostInstallHooke = `${defaultPodfileBeginning}end`;
59+
const trimmedProjectPodFileContent = projectPodFileContent.trim();
60+
if (!trimmedProjectPodFileContent || trimmedProjectPodFileContent === defaultContentWithPostInstallHook || trimmedProjectPodFileContent === defaultContentWithoutPostInstallHooke) {
61+
this.$fs.deleteFile(this.getProjectPodfilePath(projectRoot));
62+
} else {
63+
this.$fs.writeFile(this.getProjectPodfilePath(projectRoot), projectPodFileContent);
64+
}
65+
}
66+
}
67+
68+
private getPathToPluginPodfile(pluginData: IPluginData): string {
69+
const pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(PluginNativeDirNames.iOS);
70+
const pluginPodFilePath = path.join(pluginPlatformsFolderPath, PODFILE_NAME);
71+
return pluginPodFilePath;
72+
}
73+
74+
private addPostInstallHook(replacedFunctions: IRubyFunction[], finalPodfileContent: string, pluginPodFileContent: string): string {
75+
const hookStart = `${CocoaPodsService.PODFILE_POST_INSTALL_SECTION_NAME} do`;
76+
const blokParameterName = "installer";
77+
const postInstallHookStart = `${hookStart} |${blokParameterName}|${EOL}`;
78+
let postInstallHookContent = "";
79+
_.each(replacedFunctions, rubyFunction => {
80+
let functionExecution = rubyFunction.functionName;
81+
if (rubyFunction.functionParameters && rubyFunction.functionParameters.length) {
82+
functionExecution = `${functionExecution} ${blokParameterName}`;
83+
}
84+
85+
postInstallHookContent += ` ${functionExecution}${EOL}`;
86+
});
87+
88+
if (postInstallHookContent) {
89+
const index = finalPodfileContent.indexOf(postInstallHookStart);
90+
if (index !== -1) {
91+
finalPodfileContent = finalPodfileContent.replace(postInstallHookStart, `${postInstallHookStart}${postInstallHookContent}`);
92+
} else {
93+
const postInstallHook = `${postInstallHookStart}${postInstallHookContent}end`;
94+
finalPodfileContent = `${finalPodfileContent}${postInstallHook}`;
95+
}
96+
}
97+
98+
return finalPodfileContent;
99+
}
100+
101+
private getPodfileContentWithoutTarget(projectData: IProjectData, projectPodfileContent: string): string {
102+
const podFileHeader = this.getPodfileHeader(projectData.projectName);
103+
104+
if (_.startsWith(projectPodfileContent, podFileHeader)) {
105+
projectPodfileContent = projectPodfileContent.substr(podFileHeader.length);
106+
107+
const podFileFooter = this.getPodfileFooter();
108+
// Only remove the final end in case the file starts with the podFileHeader
109+
if (_.endsWith(projectPodfileContent, podFileFooter)) {
110+
projectPodfileContent = projectPodfileContent.substr(0, projectPodfileContent.length - podFileFooter.length);
111+
}
112+
}
113+
114+
return projectPodfileContent.trim();
115+
}
116+
117+
private saveProjectPodfile(projectData: IProjectData, projectPodfileContent: string, projectRoot: string): void {
118+
projectPodfileContent = this.getPodfileContentWithoutTarget(projectData, projectPodfileContent);
119+
const podFileHeader = this.getPodfileHeader(projectData.projectName);
120+
const podFileFooter = this.getPodfileFooter();
121+
const contentToWrite = `${podFileHeader}${projectPodfileContent}${podFileFooter}`;
122+
const projectPodfilePath = this.getProjectPodfilePath(projectRoot);
123+
this.$fs.writeFile(projectPodfilePath, contentToWrite);
124+
}
125+
126+
private removePostInstallHook(pluginData: IPluginData, projectPodFileContent: string): string {
127+
const regExp = new RegExp(`^.*?${this.getHookBasicFuncNameForPlugin(CocoaPodsService.PODFILE_POST_INSTALL_SECTION_NAME, pluginData.name)}.*?$\\r?\\n`, "gm");
128+
projectPodFileContent = projectPodFileContent.replace(regExp, "");
129+
return projectPodFileContent;
130+
}
131+
132+
private getHookBasicFuncNameForPlugin(hookName: string, pluginName: string): string {
133+
return `${hookName}${pluginName.replace(/[^A-Za-z0-9]/g, "")}`;
134+
}
135+
136+
private replaceHookContent(hookName: string, podfileContent: string, pluginName: string): { replacedContent: string, newFunctions: IRubyFunction[] } {
25137
const hookStart = `${hookName} do`;
26138

27139
const hookDefinitionRegExp = new RegExp(`${hookStart} *(\\|(\\w+)\\|)?`, "g");
28-
let newFunctionNameIndex = 1;
29140
const newFunctions: IRubyFunction[] = [];
30141

31142
const replacedContent = podfileContent.replace(hookDefinitionRegExp, (substring: string, firstGroup: string, secondGroup: string, index: number): string => {
32-
const newFunctionName = `${hookName}${newFunctionNameIndex++}`;
143+
const newFunctionName = `${this.getHookBasicFuncNameForPlugin(hookName, pluginName)}_${newFunctions.length}`;
33144
let newDefinition = `def ${newFunctionName}`;
34145

35146
const rubyFunction: IRubyFunction = { functionName: newFunctionName };
@@ -43,26 +154,27 @@ export class CocoaPodsService implements ICocoaPodsService {
43154
return newDefinition;
44155
});
45156

46-
if (newFunctions.length > 1) {
47-
// Execute all methods in the hook and pass the parameter to them.
48-
const blokParameterName = "installer";
49-
let mergedHookContent = `${hookStart} |${blokParameterName}|${EOL}`;
157+
return { replacedContent, newFunctions };
158+
}
50159

51-
_.each(newFunctions, (rubyFunction: IRubyFunction) => {
52-
let functionExecution = rubyFunction.functionName;
53-
if (rubyFunction.functionParameters && rubyFunction.functionParameters.length) {
54-
functionExecution = `${functionExecution} ${blokParameterName}`;
55-
}
160+
private getPluginPodfileHeader(pluginPodFilePath: string): string {
161+
return `# Begin Podfile - ${pluginPodFilePath}`;
162+
}
56163

57-
mergedHookContent = `${mergedHookContent} ${functionExecution}${EOL}`;
58-
});
164+
private getPluginPodfileEnd(): string {
165+
return `# End Podfile${EOL}`;
166+
}
59167

60-
mergedHookContent = `${mergedHookContent}end`;
168+
private buildPodfileContent(pluginPodFilePath: string, pluginName: string): { pluginPodFileContent: string, replacedFunctions: IRubyFunction[] } {
169+
const pluginPodFileContent = this.$fs.readText(pluginPodFilePath);
170+
const { replacedContent, newFunctions: replacedFunctions } = this.replaceHookContent(CocoaPodsService.PODFILE_POST_INSTALL_SECTION_NAME, pluginPodFileContent, pluginName);
61171

62-
const newPodfileContent = `${replacedContent}${EOL}${mergedHookContent}`;
63-
this.$fs.writeFile(pathToPodfile, newPodfileContent);
64-
}
172+
return {
173+
pluginPodFileContent: `${this.getPluginPodfileHeader(pluginPodFilePath)}${EOL}${replacedContent}${EOL}${this.getPluginPodfileEnd()}`,
174+
replacedFunctions
175+
};
65176
}
177+
66178
}
67179

68180
$injector.register("cocoapodsService", CocoaPodsService);

lib/services/ios-project-service.ts

Lines changed: 9 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as path from "path";
22
import * as shell from "shelljs";
3-
import * as os from "os";
43
import * as semver from "semver";
54
import * as constants from "../constants";
65
import * as helpers from "../common/helpers";
@@ -28,11 +27,6 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
2827
private static XCODEBUILD_MIN_VERSION = "6.0";
2928
private static IOS_PROJECT_NAME_PLACEHOLDER = "__PROJECT_NAME__";
3029
private static IOS_PLATFORM_NAME = "ios";
31-
private static PODFILE_POST_INSTALL_SECTION_NAME = "post_install";
32-
33-
private get $npmInstallationManager(): INpmInstallationManager {
34-
return this.$injector.resolve("npmInstallationManager");
35-
}
3630

3731
constructor($fs: IFileSystem,
3832
private $childProcess: IChildProcess,
@@ -900,10 +894,6 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
900894
return path.join(this.getPlatformData(projectData).projectRoot, projectData.projectName + IOSProjectService.XCODE_PROJECT_EXT_NAME);
901895
}
902896

903-
private getProjectPodFilePath(projectData: IProjectData): string {
904-
return path.join(this.getPlatformData(projectData).projectRoot, "Podfile");
905-
}
906-
907897
private getPluginsDebugXcconfigFilePath(projectData: IProjectData): string {
908898
return path.join(this.getPlatformData(projectData).projectRoot, "plugins-debug.xcconfig");
909899
}
@@ -951,7 +941,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
951941
await this.prepareResources(pluginPlatformsFolderPath, pluginData, projectData);
952942
await this.prepareFrameworks(pluginPlatformsFolderPath, pluginData, projectData);
953943
await this.prepareStaticLibs(pluginPlatformsFolderPath, pluginData, projectData);
954-
await this.prepareCocoapods(pluginPlatformsFolderPath, projectData);
944+
await this.prepareCocoapods(pluginPlatformsFolderPath, pluginData, projectData);
955945
}
956946

957947
public async removePluginNativeCode(pluginData: IPluginData, projectData: IProjectData): Promise<void> {
@@ -960,20 +950,14 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
960950
this.removeNativeSourceCode(pluginPlatformsFolderPath, pluginData, projectData);
961951
this.removeFrameworks(pluginPlatformsFolderPath, pluginData, projectData);
962952
this.removeStaticLibs(pluginPlatformsFolderPath, pluginData, projectData);
963-
this.removeCocoapods(pluginPlatformsFolderPath, projectData);
953+
const projectRoot = this.getPlatformData(projectData).projectRoot;
954+
955+
this.$cocoapodsService.removePluginPodfileFromProject(pluginData, projectData, projectRoot);
964956
}
965957

966958
public async afterPrepareAllPlugins(projectData: IProjectData): Promise<void> {
967-
if (this.$fs.exists(this.getProjectPodFilePath(projectData))) {
968-
const projectPodfileContent = this.$fs.readText(this.getProjectPodFilePath(projectData));
969-
this.$logger.trace("Project Podfile content");
970-
this.$logger.trace(projectPodfileContent);
971-
972-
const firstPostInstallIndex = projectPodfileContent.indexOf(IOSProjectService.PODFILE_POST_INSTALL_SECTION_NAME);
973-
if (firstPostInstallIndex !== -1 && firstPostInstallIndex !== projectPodfileContent.lastIndexOf(IOSProjectService.PODFILE_POST_INSTALL_SECTION_NAME)) {
974-
this.$cocoapodsService.mergePodfileHookContent(IOSProjectService.PODFILE_POST_INSTALL_SECTION_NAME, this.getProjectPodFilePath(projectData));
975-
}
976-
959+
const projectRoot = this.getPlatformData(projectData).projectRoot;
960+
if (this.$fs.exists(this.$cocoapodsService.getProjectPodfilePath(projectRoot))) {
977961
const xcuserDataPath = path.join(this.getXcodeprojPath(projectData), "xcuserdata");
978962
const sharedDataPath = path.join(this.getXcodeprojPath(projectData), "xcshareddata");
979963

@@ -1169,38 +1153,15 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
11691153
}
11701154
}
11711155

1172-
private async prepareCocoapods(pluginPlatformsFolderPath: string, projectData: IProjectData, opts?: any): Promise<void> {
1156+
private async prepareCocoapods(pluginPlatformsFolderPath: string, pluginData: IPluginData, projectData: IProjectData, opts?: any): Promise<void> {
1157+
const projectRoot = this.getPlatformData(projectData).projectRoot;
1158+
await this.$cocoapodsService.applyPluginPodfileToProject(pluginData, projectData, projectRoot);
11731159
const pluginPodFilePath = path.join(pluginPlatformsFolderPath, "Podfile");
1174-
if (this.$fs.exists(pluginPodFilePath)) {
1175-
const pluginPodFileContent = this.$fs.readText(pluginPodFilePath);
1176-
const pluginPodFilePreparedContent = this.buildPodfileContent(pluginPodFilePath, pluginPodFileContent);
1177-
let projectPodFileContent = this.$fs.exists(this.getProjectPodFilePath(projectData)) ? this.$fs.readText(this.getProjectPodFilePath(projectData)) : "";
1178-
1179-
if (!~projectPodFileContent.indexOf(pluginPodFilePreparedContent)) {
1180-
const podFileHeader = this.$cocoapodsService.getPodfileHeader(projectData.projectName),
1181-
podFileFooter = this.$cocoapodsService.getPodfileFooter();
1182-
1183-
if (_.startsWith(projectPodFileContent, podFileHeader)) {
1184-
projectPodFileContent = projectPodFileContent.substr(podFileHeader.length);
1185-
}
1186-
1187-
if (_.endsWith(projectPodFileContent, podFileFooter)) {
1188-
projectPodFileContent = projectPodFileContent.substr(0, projectPodFileContent.length - podFileFooter.length);
1189-
}
1190-
1191-
const contentToWrite = `${podFileHeader}${projectPodFileContent}${pluginPodFilePreparedContent}${podFileFooter}`;
1192-
this.$fs.writeFile(this.getProjectPodFilePath(projectData), contentToWrite);
1193-
1194-
const project = this.createPbxProj(projectData);
1195-
this.savePbxProj(project, projectData);
1196-
}
1197-
}
11981160

11991161
if (opts && opts.executePodInstall && this.$fs.exists(pluginPodFilePath)) {
12001162
await this.executePodInstall(projectData);
12011163
}
12021164
}
1203-
12041165
private removeNativeSourceCode(pluginPlatformsFolderPath: string, pluginData: IPluginData, projectData: IProjectData): void {
12051166
const project = this.createPbxProj(projectData);
12061167
const group = this.getRootGroup(pluginData.name, pluginPlatformsFolderPath);
@@ -1235,26 +1196,6 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
12351196
this.savePbxProj(project, projectData);
12361197
}
12371198

1238-
private removeCocoapods(pluginPlatformsFolderPath: string, projectData: IProjectData): void {
1239-
const pluginPodFilePath = path.join(pluginPlatformsFolderPath, "Podfile");
1240-
1241-
if (this.$fs.exists(pluginPodFilePath) && this.$fs.exists(this.getProjectPodFilePath(projectData))) {
1242-
const pluginPodFileContent = this.$fs.readText(pluginPodFilePath);
1243-
let projectPodFileContent = this.$fs.readText(this.getProjectPodFilePath(projectData));
1244-
const contentToRemove = this.buildPodfileContent(pluginPodFilePath, pluginPodFileContent);
1245-
projectPodFileContent = helpers.stringReplaceAll(projectPodFileContent, contentToRemove, "");
1246-
if (projectPodFileContent.trim() === `use_frameworks!${os.EOL}${os.EOL}target "${projectData.projectName}" do${os.EOL}${os.EOL}end`) {
1247-
this.$fs.deleteFile(this.getProjectPodFilePath(projectData));
1248-
} else {
1249-
this.$fs.writeFile(this.getProjectPodFilePath(projectData), projectPodFileContent);
1250-
}
1251-
}
1252-
}
1253-
1254-
private buildPodfileContent(pluginPodFilePath: string, pluginPodFileContent: string): string {
1255-
return `# Begin Podfile - ${pluginPodFilePath} ${os.EOL} ${pluginPodFileContent} ${os.EOL} # End Podfile ${os.EOL}`;
1256-
}
1257-
12581199
private generateModulemap(headersFolderPath: string, libraryName: string): void {
12591200
const headersFilter = (fileName: string, containingFolderPath: string) => (path.extname(fileName) === ".h" && this.$fs.getFsStats(path.join(containingFolderPath, fileName)).isFile());
12601201
const headersFolderContents = this.$fs.readDirectory(headersFolderPath);

0 commit comments

Comments
 (0)