Skip to content

Commit

Permalink
Update iOS container generator for RN61+ support
Browse files Browse the repository at this point in the history
  • Loading branch information
belemaire committed Apr 10, 2020
1 parent 9da9c79 commit 1755cf1
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 16 deletions.
3 changes: 2 additions & 1 deletion ern-container-gen-ios/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"fs-extra": "^8.1.0",
"fs-readdir-recursive": "^1.1.0",
"lodash": "^4.17.14",
"xcode-ern": "^1.0.12"
"xcode-ern": "^1.0.12",
"semver": "^5.5.0"
},
"devDependencies": {
"copyfiles": "^2.0.0",
Expand Down
129 changes: 129 additions & 0 deletions ern-container-gen-ios/src/IosGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
childProcess,
manifest,
iosUtil,
injectReactNativeVersionKeysInObject,
Expand All @@ -9,6 +10,9 @@ import {
NativePlatform,
kax,
PluginConfig,
readPackageJson,
writePackageJson,
yarn,
} from 'ern-core'
import {
ContainerGenerator,
Expand All @@ -25,6 +29,7 @@ import xcode from 'xcode-ern'
import _ from 'lodash'
import readDir from 'fs-readdir-recursive'
import { Composite } from 'ern-composite-gen'
import semver from 'semver'

const ROOT_DIR = process.cwd()
const PATH_TO_HULL_DIR = path.join(__dirname, 'hull')
Expand Down Expand Up @@ -134,6 +139,130 @@ export default class IosGenerator implements ContainerGenerator {
)

fs.writeFileSync(projectPath, iosProject.writeSync())

if (semver.gte(reactNativePlugin.version!, '0.61.0')) {
//
// Add all native dependencies to package.json dependencies so that
// !use_native_modules can detect them to add their pod to the Podfile
const dependencies = await config.composite.getNativeDependencies({})
const resDependencies = [
...dependencies.thirdPartyInManifest,
...dependencies.thirdPartyNotInManifest,
]
const addDependencies: any = {}
resDependencies.forEach(p => {
addDependencies[p.name!] = p.version
})

//
// Create package.json in container directory root
// so that native modules pods can be resolved
// by use_native_modules! RN ruby script
const pjsonObj = {
dependencies: addDependencies,
name: 'container',
}
await writePackageJson(config.outDir, pjsonObj)

//
// Copy all native dependencies from composite node_modules
// to container node_modules so that pods can be found local
// to the container directory
const containerNodeModulesPath = path.join(config.outDir, 'node_modules')
shell.mkdir('-p', containerNodeModulesPath)
resDependencies.forEach(p => {
shell.cp('-rf', p.basePath!, containerNodeModulesPath)
})
// Add @react-native-community/cli-platform-ios because
// it contains the scripts needed for native modules pods linking
// look in composite to match proper version
const compositeNodeModulesPath = path.join(
config.composite.path,
'node_modules'
)
const cliPlatformIosPkg = '@react-native-community/cli-platform-ios'
const cliPlatformIosPkgVersion = (
await readPackageJson(
path.join(compositeNodeModulesPath, cliPlatformIosPkg)
)
).version
shell.pushd(config.outDir)
try {
await yarn.add(
PackagePath.fromString(
`${cliPlatformIosPkg}@${cliPlatformIosPkgVersion}`
)
)
} finally {
shell.popd()
}

//
// Run pod install
shell.pushd(config.outDir)
try {
await kax
.task('Running pod install')
.run(childProcess.spawnp('pod', ['install']))
} finally {
shell.popd()
}

//
// Clean node_modules by only keeping the directories that are
// needed for proper container build.
shell.pushd(config.outDir)
try {
//
// Look in the Pods pbxproj for any references to some files
// kepts in some node_module subdirectory (basically react-native
// as well as all native modules)
const f = fs.readFileSync('Pods/Pods.xcodeproj/project.pbxproj', {
encoding: 'utf8',
})

//
// Build an array of these directories
const re = RegExp('"../node_modules/([^"]+)"', 'g')
const matches = []
let match = re.exec(f)
while (match !== null) {
matches.push(match[1])
match = re.exec(f)
}
const res = matches
.map(r => r.split('/'))
.filter(x => x[0] !== 'react-native')
.map(x => x.join('/'))
.concat('react-native')

//
// Copy all retained directories from 'node_modules'
// to a new directory 'node_modules_light'
const nodeModulesLightDir = 'node_modules_light'
const nodeModulesDir = 'node_modules'
shell.mkdir('-p', nodeModulesLightDir)
for (const b of res) {
shell.mkdir('-p', path.join(nodeModulesLightDir, b))
shell.cp(
'-Rf',
path.join(nodeModulesDir, b, '{.*,*}'),
path.join(nodeModulesLightDir, b)
)
}
//
// Replace the huge 'node_modules' directory with the skimmed one
shell.rm('-rf', nodeModulesDir)
shell.mv(nodeModulesLightDir, nodeModulesDir)
//
// Finally get rid of all android directories to further reduce
// overall 'node_modules' directory size, as they are not needed
// for iOS container builds.
shell.rm('-rf', path.join(nodeModulesDir, '**/android'))
} finally {
shell.popd()
}
}
}

// Code to keep backward compatibility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
// https://github.com/dempseyatgithub/BuildSettingExtractor
//

{{#RN_VERSION_GTE_61}}
#include "Pods/Target Support Files/Pods-ElectrodeContainer/Pods-ElectrodeContainer.debug.xcconfig"
{{/RN_VERSION_GTE_61}}

{{#RN_VERSION_LT_61}}
HEADER_SEARCH_PATHS =
OTHER_LDFLAGS = -ObjC -lc++ -lz
{{/RN_VERSION_LT_61}}

ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES
CLANG_ENABLE_MODULES = YES
Expand All @@ -15,12 +24,10 @@ DYLIB_COMPATIBILITY_VERSION = 1
DYLIB_CURRENT_VERSION = 1
DYLIB_INSTALL_NAME_BASE = @rpath
FRAMEWORK_SEARCH_PATHS = $(inherited) $(SRCROOT)/ElectrodeContainer/Frameworks
HEADER_SEARCH_PATHS =
INFOPLIST_FILE = ElectrodeContainer/Info.plist
INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
IPHONEOS_DEPLOYMENT_TARGET = 10.0
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
OTHER_LDFLAGS = -ObjC -lc++ -lz
PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ern.ElectrodeContainer
PRODUCT_NAME = $(TARGET_NAME)
SKIP_INSTALL = YES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@
// https://github.com/dempseyatgithub/BuildSettingExtractor
//

{{#RN_VERSION_GTE_61}}
#include "Pods/Target Support Files/Pods-ElectrodeContainer/Pods-ElectrodeContainer.qadeployment.xcconfig"
{{/RN_VERSION_GTE_61}}

{{#RN_VERSION_LT_61}}
HEADER_SEARCH_PATHS =
OTHER_LDFLAGS = -ObjC -lc++ -lz
{{/RN_VERSION_LT_61}}

ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES
CLANG_ENABLE_MODULES = YES
Expand All @@ -17,12 +26,10 @@ DYLIB_INSTALL_NAME_BASE = @rpath
ENABLE_ON_DEMAND_RESOURCES = NO
ENABLE_TESTABILITY = YES
FRAMEWORK_SEARCH_PATHS = $(inherited) $(SRCROOT)/ElectrodeContainer/Frameworks
HEADER_SEARCH_PATHS =
INFOPLIST_FILE = ElectrodeContainer/Info.plist
INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
ONLY_ACTIVE_ARCH = NO
OTHER_LDFLAGS = -ObjC -lc++ -lz
PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ern.ElectrodeContainer
PRODUCT_NAME = $(TARGET_NAME)
SKIP_INSTALL = YES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@
// https://github.com/dempseyatgithub/BuildSettingExtractor
//

{{#RN_VERSION_GTE_61}}
#include "Pods/Target Support Files/Pods-ElectrodeContainer/Pods-ElectrodeContainer.release.xcconfig"
{{/RN_VERSION_GTE_61}}

{{#RN_VERSION_LT_61}}
HEADER_SEARCH_PATHS =
OTHER_LDFLAGS = -ObjC -lc++ -lz
{{/RN_VERSION_LT_61}}

CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES
CODE_SIGN_IDENTITY =
DEFINES_MODULE = YES
DYLIB_COMPATIBILITY_VERSION = 1
DYLIB_CURRENT_VERSION = 1
DYLIB_INSTALL_NAME_BASE = @rpath
FRAMEWORK_SEARCH_PATHS = $(inherited) $(SRCROOT)/ElectrodeContainer/Frameworks
HEADER_SEARCH_PATHS =
INFOPLIST_FILE = ElectrodeContainer/Info.plist
INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
IPHONEOS_DEPLOYMENT_TARGET = 10.0
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
OTHER_LDFLAGS = -ObjC -lc++ -lz
PRODUCT_BUNDLE_IDENTIFIER = com.walmartlabs.ern.ElectrodeContainer
PRODUCT_NAME = $(TARGET_NAME)
SKIP_INSTALL = YES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES
CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer
COPY_PHASE_STRIP = NO
CURRENT_PROJECT_VERSION = 1
DEBUG_INFORMATION_FORMAT = dwarf
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
ENABLE_STRICT_OBJC_MSGSEND = YES
ENABLE_TESTABILITY = YES
GCC_C_LANGUAGE_STANDARD = gnu99
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "NO">
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "NO">
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
Expand Down
2 changes: 2 additions & 0 deletions ern-core/src/injectReactNativeVersionKeysInObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ export function injectReactNativeVersionKeysInObject(
RN_VERSION_GTE_54: semver.gte(reactNativeVersion, '0.54.0'),
RN_VERSION_GTE_59: semver.gte(reactNativeVersion, '0.59.0'),
RN_VERSION_GTE_60_1: semver.gte(reactNativeVersion, '0.60.1'),
RN_VERSION_GTE_61: semver.gte(reactNativeVersion, '0.61.0'),
RN_VERSION_LT_54: semver.lt(reactNativeVersion, '0.54.0'),
RN_VERSION_LT_58: semver.lt(reactNativeVersion, '0.58.0-rc.2'),
RN_VERSION_LT_59: semver.lt(reactNativeVersion, '0.59.0'),
RN_VERSION_LT_61: semver.lt(reactNativeVersion, '0.61.0'),
reactNativeVersion,
})
}
20 changes: 14 additions & 6 deletions ern-core/src/iosUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import shell from './shell'
import { manifest, PluginConfig } from './Manifest'
import handleCopyDirective from './handleCopyDirective'
import log from './log'
import { isDependencyJsApiImpl } from './utils'
import { isDependencyJsApiImpl, extractJsApiImplementations } from './utils'
import path from 'path'
import xcode from 'xcode-ern'
import fs from 'fs-extra'
Expand Down Expand Up @@ -40,14 +40,22 @@ export async function fillProjectHull(

if (mustacheView) {
log.debug(`iOS: reading template files to be rendered for plugins`)
const files = readDir(pathSpec.outputDir)
const a = path.join(pathSpec.outputDir, 'ElectrodeContainer')
const b = path.join(pathSpec.outputDir, 'config')
const files = [
...readDir(a).map(x => path.join(a, x)),
...readDir(b).map(x => path.join(b, x)),
]
for (const file of files) {
if (file.endsWith('.h') || file.endsWith('.m')) {
const pathToOutputFile = path.join(pathSpec.outputDir, file)
if (
file.endsWith('.h') ||
file.endsWith('.m') ||
file.endsWith('.xcconfig')
) {
await mustacheUtils.mustacheRenderToOutputFileUsingTemplateFile(
pathToOutputFile,
file,
mustacheView,
pathToOutputFile
file
)
}
}
Expand Down

0 comments on commit 1755cf1

Please sign in to comment.