diff --git a/lib/create.js b/lib/create.js index bb3189248..2c4ea38d3 100755 --- a/lib/create.js +++ b/lib/create.js @@ -71,9 +71,8 @@ class ProjectCreator { create () { this.provideProjectTemplate(); this.provideCordovaJs(); - this.provideCordovaLib(); this.provideBuildScripts(); - this.updateBundleSettings(); + this.updateProjectSettings(); } provideProjectTemplate () { @@ -92,18 +91,13 @@ class ProjectCreator { ); } - provideCordovaLib () { - this.copyOrLinkCordovaLib(); - this.configureCordovaLibPath(); - } - provideBuildScripts () { const srcScriptsDir = path.join(ROOT, 'templates', 'cordova'); const destScriptsDir = this.projectPath('cordova'); fs.cpSync(srcScriptsDir, destScriptsDir, { recursive: true }); } - updateBundleSettings () { + updateProjectSettings () { const projectPath = this.projectPath('App.xcodeproj', 'project.pbxproj'); const xcodeproj = xcode.project(projectPath); xcodeproj.parseSync(); @@ -111,66 +105,26 @@ class ProjectCreator { xcodeproj.updateBuildProperty('PRODUCT_NAME', `"${this.project.name}"`, null, 'App'); xcodeproj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', `"${this.project.id}"`, null, 'App'); - fs.writeFileSync(projectPath, xcodeproj.writeSync()); - } - - copyOrLinkCordovaLib () { - const cordovaLibPathSrc = path.join(ROOT, 'CordovaLib'); - const cordovaLibPathDest = this.projectPath('CordovaLib'); - - if (this.options.linkLib) { - // Symlink not used in project file, but is currently required for plugman because - // it reads the VERSION file from it (instead of using the cordova/version script - // like it should). - fs.symlinkSync(cordovaLibPathSrc, cordovaLibPathDest); - } else { - fs.cpSync(cordovaLibPathSrc, cordovaLibPathDest, { recursive: true }); - } - } - - configureCordovaLibPath () { - // CordovaLib could be a symlink, so we resolve it - const cdvLibRealPath = fs.realpathSync(this.projectPath('CordovaLib')); - - const cdvLibXcodeAbsPath = path.join(cdvLibRealPath, 'CordovaLib.xcodeproj'); - let cdvLibXcodePath = path.relative(this.project.path, cdvLibXcodeAbsPath); - - if (path.sep !== path.posix.sep) { - // If the Cordova project is being created on Windows, we need to - // make sure the Xcode project file uses POSIX-style paths or else - // Xcode considers it invalid - cdvLibXcodePath = cdvLibXcodePath.replace(path.sep, path.posix.sep); - } - - // Replace magic line in project.pbxproj - const pbxprojPath = this.projectPath('App.xcodeproj', 'project.pbxproj'); - transformFileContents(pbxprojPath, contents => { - const regex = /(.+CordovaLib.xcodeproj.+PBXFileReference.+wrapper.pb-project.+)(path = .+?;)(.*)(sourceTree.+;)(.+)/; - const line = contents.split(/\r?\n/) - .find(l => regex.test(l)); - - if (!line) { - throw new Error(`Entry not found in project file for sub-project: ${cdvLibXcodePath}`); - } - - let newLine = line - .replace(/path = .+?;/, `path = ${cdvLibXcodePath};`) - .replace(/sourceTree.+?;/, 'sourceTree = "";'); - - if (!newLine.match('name')) { - newLine = newLine.replace('path = ', 'name = CordovaLib.xcodeproj; path = '); + // Update the CordovaLib Swift package reference path + const pkgRefs = xcodeproj.hash.project.objects.XCLocalSwiftPackageReference; + if (pkgRefs) { + for (const [key, ref] of Object.entries(pkgRefs)) { + /* istanbul ignore if */ + if (key.endsWith('_comment')) { + continue; + } + + if (ref.relativePath?.match(/\/cordova-ios/)) { + ref.relativePath = `"${path.relative(this.project.path, ROOT).replaceAll(path.sep, path.posix.sep)}"`; + break; + } } + } - return contents.replace(line, newLine); - }); + fs.writeFileSync(projectPath, xcodeproj.writeSync()); } projectPath (...projectRelativePaths) { return path.join(this.project.path, ...projectRelativePaths); } } - -function transformFileContents (file, transform) { - const contents = fs.readFileSync(file, 'utf-8'); - fs.writeFileSync(file, transform(contents)); -} diff --git a/templates/project/App.xcodeproj/project.pbxproj b/templates/project/App.xcodeproj/project.pbxproj index 778b69acf..eb99b980f 100755 --- a/templates/project/App.xcodeproj/project.pbxproj +++ b/templates/project/App.xcodeproj/project.pbxproj @@ -25,10 +25,10 @@ objects = { /* Begin PBXBuildFile section */ - 902AE2142C6C059A0041150F /* Cordova.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 907F985F2C06B8DE00D2D242 /* Cordova.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 907F98562C06B87200D2D242 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 907F98552C06B87200D2D242 /* PrivacyInfo.xcprivacy */; }; 907F98662C06BC1B00D2D242 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 907F98652C06BC1B00D2D242 /* config.xml */; }; 907F986A2C06BCD300D2D242 /* www in Resources */ = {isa = PBXBuildFile; fileRef = 907F98692C06BCD300D2D242 /* www */; }; + 90A914592CA3D370003DB979 /* CordovaLib in Frameworks */ = {isa = PBXBuildFile; productRef = 90A914582CA3D370003DB979 /* CordovaLib */; }; 90BD9B7A2C06907D000DEBAB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 90BD9B792C06907D000DEBAB /* Base */; }; 90BD9B7C2C06907E000DEBAB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90BD9B7B2C06907E000DEBAB /* Assets.xcassets */; }; 90BD9B7F2C06907E000DEBAB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 90BD9B7E2C06907E000DEBAB /* Base */; }; @@ -37,23 +37,6 @@ 90CBB52C2C06968500B805A2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90CBB52B2C06968500B805A2 /* ViewController.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 907F985C2C06B8DE00D2D242 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 68A32D7114102E1C006B237C; - remoteInfo = CordovaLib; - }; - 907F985E2C06B8DE00D2D242 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C0C01EB21E3911D50056E6CB; - remoteInfo = Cordova; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 902AE2152C6C059A0041150F /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -61,7 +44,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 902AE2142C6C059A0041150F /* Cordova.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -72,13 +54,12 @@ 9040B1872C6DD3EB00662C5D /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; 9040B1882C6DD41B00662C5D /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = ""; }; 907F98552C06B87200D2D242 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = CordovaLib/CordovaLib.xcodeproj; sourceTree = ""; }; 907F98622C06B97000D2D242 /* Entitlements-Debug.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Entitlements-Debug.plist"; sourceTree = ""; }; 907F98632C06B9C800D2D242 /* Entitlements-Release.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Entitlements-Release.plist"; sourceTree = ""; }; 907F98652C06BC1B00D2D242 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; 907F98692C06BCD300D2D242 /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = SOURCE_ROOT; }; 9080B40F2C6DD7EC00078F33 /* config.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = ""; }; - 90BD9B6C2C06907D000DEBAB /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 90BD9B6C2C06907D000DEBAB /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 90BD9B792C06907D000DEBAB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 90BD9B7B2C06907E000DEBAB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 90BD9B7E2C06907E000DEBAB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/CDVLaunchScreen.storyboard; sourceTree = ""; }; @@ -99,6 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 90A914592CA3D370003DB979 /* CordovaLib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -119,15 +101,6 @@ path = Plugins; sourceTree = ""; }; - 907F98582C06B8DE00D2D242 /* Products */ = { - isa = PBXGroup; - children = ( - 907F985D2C06B8DE00D2D242 /* libCordova.a */, - 907F985F2C06B8DE00D2D242 /* Cordova.framework */, - ); - name = Products; - sourceTree = ""; - }; 907F98602C06B8F000D2D242 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -158,7 +131,6 @@ 90BD9B632C06907D000DEBAB = { isa = PBXGroup; children = ( - 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */, 9080B40F2C6DD7EC00078F33 /* config.xml */, 9040B1882C6DD41B00662C5D /* www */, 90BD9B6E2C06907D000DEBAB /* App */, @@ -196,7 +168,7 @@ 9080B40D2C6DD79000078F33 /* config */, 9080B40E2C6DD7A100078F33 /* staging */, ); - path = "App"; + path = App; sourceTree = ""; }; /* End PBXGroup section */ @@ -215,10 +187,11 @@ ); dependencies = ( ); - name = "App"; + name = App; packageProductDependencies = ( + 90A914582CA3D370003DB979 /* CordovaLib */, ); - productName = "App"; + productName = App; productReference = 90BD9B6C2C06907D000DEBAB /* App.app */; productType = "com.apple.product-type.application"; }; @@ -247,15 +220,10 @@ ); mainGroup = 90BD9B632C06907D000DEBAB; packageReferences = ( + 90A914572CA3D370003DB979 /* XCLocalSwiftPackageReference "../../../cordova-ios" */, ); productRefGroup = 90BD9B6D2C06907D000DEBAB /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 907F98582C06B8DE00D2D242 /* Products */; - ProjectRef = 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */; - }, - ); projectRoot = ""; targets = ( 90BD9B6B2C06907D000DEBAB /* App */, @@ -263,23 +231,6 @@ }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 907F985D2C06B8DE00D2D242 /* libCordova.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libCordova.a; - remoteRef = 907F985C2C06B8DE00D2D242 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 907F985F2C06B8DE00D2D242 /* Cordova.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = Cordova.framework; - remoteRef = 907F985E2C06B8DE00D2D242 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 90BD9B6A2C06907D000DEBAB /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -551,6 +502,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 90A914572CA3D370003DB979 /* XCLocalSwiftPackageReference "../../../cordova-ios" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "../../../cordova-ios"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 90A914582CA3D370003DB979 /* CordovaLib */ = { + isa = XCSwiftPackageProductDependency; + productName = CordovaLib; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 90BD9B642C06907D000DEBAB /* Project object */; } diff --git a/tests/spec/createAndBuild.spec.js b/tests/spec/createAndBuild.spec.js index c82336019..2f6fe5172 100644 --- a/tests/spec/createAndBuild.spec.js +++ b/tests/spec/createAndBuild.spec.js @@ -39,7 +39,6 @@ function verifyProjectFiles (tmpDir, projectName) { expect(fs.existsSync(path.join(tmpDir, 'App'))).toBe(true); expect(fs.existsSync(path.join(tmpDir, 'App.xcodeproj'))).toBe(true); expect(fs.existsSync(path.join(tmpDir, 'App.xcworkspace'))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, 'CordovaLib'))).toBe(true); } /** diff --git a/tests/spec/unit/create.spec.js b/tests/spec/unit/create.spec.js index 820f8e585..f07c4bbe5 100644 --- a/tests/spec/unit/create.spec.js +++ b/tests/spec/unit/create.spec.js @@ -39,14 +39,28 @@ function verifyProjectFiles (tmpDir, projectName) { expect(fs.existsSync(path.join(tmpDir, 'App'))).toBe(true); expect(fs.existsSync(path.join(tmpDir, 'App.xcodeproj'))).toBe(true); expect(fs.existsSync(path.join(tmpDir, 'App.xcworkspace'))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, 'CordovaLib'))).toBe(true); const pbxproj = path.join(tmpDir, 'App.xcodeproj', 'project.pbxproj'); - const pbxcontents = fs.readFileSync(pbxproj, 'utf-8'); - const regex = /(.+CordovaLib.xcodeproj.+PBXFileReference.+wrapper.pb-project.+)(path = .+?;)(.*)(sourceTree.+;)(.+)/; - const line = pbxcontents.split(/\r?\n/).find(l => regex.test(l)); + const xcodeproj = xcode.project(pbxproj); + xcodeproj.parseSync(); - expect(line).toMatch(/path = CordovaLib\/CordovaLib.xcodeproj;/); + const packageLoc = path.dirname(require.resolve('../../../package.json')); + const relativePath = path.relative(tmpDir, packageLoc).replaceAll(path.sep, path.posix.sep); + + let foundRef = false; + const pkgRefs = xcodeproj.hash.project.objects.XCLocalSwiftPackageReference; + for (const [key, ref] of Object.entries(pkgRefs)) { + if (key.endsWith('_COMMENT')) { + continue; + } + + if (ref.relativePath.match(/\/cordova-ios/)) { + foundRef = true; + expect(ref.relativePath).toMatch(relativePath); + break; + } + } + expect(foundRef).toBeTruthy(); } /**