diff --git a/packages/platform-ios/src/config/__tests__/findPodfilePath.test.ts b/packages/platform-ios/src/config/__tests__/findPodfilePath.test.ts deleted file mode 100644 index f3da6da8e..000000000 --- a/packages/platform-ios/src/config/__tests__/findPodfilePath.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import findPodfilePath from '../findPodfilePath'; -import * as projects from '../__fixtures__/projects'; - -jest.mock('path'); -jest.mock('fs'); - -const fs = require('fs'); - -describe('ios::findPodfilePath', () => { - it('returns null if there is no Podfile', () => { - fs.__setMockFilesystem(projects.withoutPods); - expect(findPodfilePath('')).toBeNull(); - }); - - it('returns Podfile path if it exists', () => { - fs.__setMockFilesystem(projects.withPods); - expect(findPodfilePath('/ios')).toContain('Podfile'); - }); -}); diff --git a/packages/platform-ios/src/config/__tests__/findProject.test.ts b/packages/platform-ios/src/config/__tests__/findProject.test.ts index bdcf9106a..43aafdf66 100644 --- a/packages/platform-ios/src/config/__tests__/findProject.test.ts +++ b/packages/platform-ios/src/config/__tests__/findProject.test.ts @@ -6,7 +6,7 @@ * */ -import findProject from '../findProject'; +import {findXcodeProject as findProject} from '../findProject'; import * as projects from '../__fixtures__/projects'; jest.mock('path'); diff --git a/packages/platform-ios/src/config/findPodfilePath.ts b/packages/platform-ios/src/config/findPodfilePath.ts deleted file mode 100644 index 695be0888..000000000 --- a/packages/platform-ios/src/config/findPodfilePath.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -import fs from 'fs'; -import path from 'path'; - -export default function findPodfilePath(projectFolder: string) { - const podFilePath = path.join(projectFolder, '..', 'Podfile'); - const podFileExists = fs.existsSync(podFilePath); - - return podFileExists ? podFilePath : null; -} diff --git a/packages/platform-ios/src/config/findProject.ts b/packages/platform-ios/src/config/findProject.ts index fb28c436a..2612b4d9e 100644 --- a/packages/platform-ios/src/config/findProject.ts +++ b/packages/platform-ios/src/config/findProject.ts @@ -8,11 +8,12 @@ import glob from 'glob'; import path from 'path'; +import isXcodeProject from './isXcodeProject'; /** * Glob pattern to look for xcodeproj */ -const GLOB_PATTERN = '**/*.xcodeproj'; +const GLOB_PATTERN = '**/*.{xcodeproj,xcworkspace}'; /** * Regexp matching all test projects @@ -29,17 +30,9 @@ const IOS_BASE = 'ios'; */ const GLOB_EXCLUDE_PATTERN = ['**/@(Pods|node_modules|Carthage)/**']; -/** - * Finds iOS project by looking for all .xcodeproj files - * in given folder. - * - * Returns first match if files are found or null - * - * Note: `./ios/*.xcodeproj` are returned regardless of the name - */ -export default function findProject(folder: string): string | null { - const projects = glob - .sync(GLOB_PATTERN, { +function findProject(folder: string, pattern: string): string[] { + return glob + .sync(pattern, { cwd: folder, ignore: GLOB_EXCLUDE_PATTERN, }) @@ -48,10 +41,37 @@ export default function findProject(folder: string): string | null { path.dirname(project) === IOS_BASE || !TEST_PROJECTS.test(project), ) .sort((project) => (path.dirname(project) === IOS_BASE ? -1 : 1)); +} +/** + * Finds a `Podfile` in given folder. + * + * Returns first match if files are found or null + * + * Note: `./ios/Podfile` are returned regardless of the name + */ +export function findPodfile(folder: string): string | null { + const projects = findProject(folder, '**/Podfile'); if (projects.length === 0) { return null; } return projects[0]; } + +/** + * Finds iOS project by looking for all .xcodeproj files + * in given folder. + * + * Returns first match if files are found or null + * + * Note: `./ios/*.xcodeproj` are returned regardless of the name + */ +export function findXcodeProject(folder: string): string | null { + const projects = findProject(folder, GLOB_PATTERN); + if (projects.length === 0) { + return null; + } + + return projects.find(isXcodeProject) || projects[0]; +} diff --git a/packages/platform-ios/src/config/index.ts b/packages/platform-ios/src/config/index.ts index 965f397be..bf383914b 100644 --- a/packages/platform-ios/src/config/index.ts +++ b/packages/platform-ios/src/config/index.ts @@ -8,15 +8,16 @@ import path from 'path'; import {memoize} from 'lodash'; -import findProject from './findProject'; -import findPodfilePath from './findPodfilePath'; +import {findPodfile, findXcodeProject} from './findProject'; import findPodspec from './findPodspec'; +import isXcodeProject from './isXcodeProject'; import { IOSProjectParams, IOSDependencyParams, } from '@react-native-community/cli-types'; -const memoizedFindProject = memoize(findProject); +const memoizedFindPodfile = memoize(findPodfile); +const memoizedFindProject = memoize(findXcodeProject); /** * For libraries specified without an extension, add '.tbd' for those that @@ -38,23 +39,33 @@ export function projectConfig(folder: string, userConfig: IOSProjectParams) { if (!userConfig) { return; } + + const podfile = memoizedFindPodfile(folder); const project = userConfig.project || memoizedFindProject(folder); /** * No iOS config found here */ - if (!project) { + if (!project && !podfile) { return null; } - const projectPath = path.join(folder, project); - const sourceDir = path.dirname(projectPath); + const projectPath = project && path.join(folder, project); + + // Source files may be referenced from anywhere in a `.xcodeproj`. CocoaPods, + // on the other hand, is a lot stricter because files cannot live outside the + // folder in which `Podfile` resides. If we found a `Podfile`, it's a strong + // indication that source files are in that directory. + const sourceDir = path.resolve(path.dirname(podfile || projectPath || '')); return { sourceDir, folder, - pbxprojPath: path.join(projectPath, 'project.pbxproj'), - podfile: findPodfilePath(projectPath), + pbxprojPath: + projectPath && isXcodeProject(projectPath) + ? path.join(projectPath, 'project.pbxproj') + : null, + podfile: podfile && path.resolve(podfile), podspecPath: userConfig.podspecPath || // podspecs are usually placed in the root dir of the library or in the @@ -62,7 +73,7 @@ export function projectConfig(folder: string, userConfig: IOSProjectParams) { findPodspec(folder) || findPodspec(sourceDir), projectPath, - projectName: path.basename(projectPath), + projectName: projectPath && path.basename(projectPath), libraryFolder: userConfig.libraryFolder || 'Libraries', sharedLibraries: mapSharedLibaries(userConfig.sharedLibraries || []), plist: userConfig.plist || [], diff --git a/packages/platform-ios/src/config/isXcodeProject.ts b/packages/platform-ios/src/config/isXcodeProject.ts new file mode 100644 index 000000000..efec949d9 --- /dev/null +++ b/packages/platform-ios/src/config/isXcodeProject.ts @@ -0,0 +1,10 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +export default function isXcodeProject(projectPath: string): boolean { + return projectPath.endsWith('.xcodeproj'); +} diff --git a/packages/platform-ios/src/link/warnAboutManuallyLinkedLibs.ts b/packages/platform-ios/src/link/warnAboutManuallyLinkedLibs.ts index 9aac5d0d8..df7d523e5 100644 --- a/packages/platform-ios/src/link/warnAboutManuallyLinkedLibs.ts +++ b/packages/platform-ios/src/link/warnAboutManuallyLinkedLibs.ts @@ -12,8 +12,12 @@ export default function warnAboutManuallyLinkedLibs( Config['platforms']['ios']['linkConfig'] > = getLinkConfig(), ) { - let deps: Array = []; const projectConfig = config.project[platform]; + if (projectConfig.pbxprojPath === null) { + return; + } + + let deps: Array = []; for (let key in config.dependencies) { const dependency = config.dependencies[key];