2019-06-04 16:50:29 +00:00
#
2019-08-06 16:16:51 +00:00
# This script prepares a finalized version of node_modules,
# as well as a local version of the Maven repository required by Gradle scripts
2019-06-04 16:50:29 +00:00
#
{ stdenv , stdenvNoCC , lib , callPackage ,
2019-08-06 16:16:51 +00:00
gradle , bash , file , nodejs , zlib ,
projectNodePackage , localMavenRepoBuilder , mkFilter } :
2019-06-04 16:50:29 +00:00
let
mavenLocalRepo = callPackage ./maven { inherit localMavenRepoBuilder ; stdenv = if stdenv . isLinux then stdenv else stdenvNoCC ; } ;
# Import the native dependencies for React Native Android builds
2019-08-06 16:16:51 +00:00
react-native-deps = callPackage ./maven/reactnative-android-native-deps.nix { inherit stdenvNoCC ; } ;
2019-06-04 16:50:29 +00:00
createMobileFilesSymlinks = root : ''
2019-09-12 12:38:16 +00:00
ln - sf $ { root } /mobile_files/package.json $ { root } /package.json
2019-06-04 16:50:29 +00:00
ln - sf $ { root } /mobile_files/metro.config.js $ { root } /metro.config.js
ln - sf $ { root } /mobile_files/yarn.lock $ { root } /yarn.lock
'' ;
# fake build to pre-download deps into fixed-output derivation
deps =
let
# Place build target directories in NIX_BUILD_TOP (normally represents /build)
2019-08-14 07:05:32 +00:00
projectBuildDir = " $ N I X _ B U I L D _ T O P / p r o j e c t " ;
2019-06-04 16:50:29 +00:00
mavenRepoDir = " $ N I X _ B U I L D _ T O P / . m 2 / r e p o s i t o r y " ;
reactNativeDepsDir = " $ N I X _ B U I L D _ T O P / d e p s " ; # Use local writable deps, otherwise (probably due to some interaction between Nix sandboxing and Java) gradle will fail copying directly from the nix store
in
stdenv . mkDerivation {
2019-08-06 16:16:51 +00:00
name = " p a t c h e d - a n d r o i d - g r a d l e - a n d - n p m - m o d u l e s " ;
2019-06-04 16:50:29 +00:00
src =
let path = ./../../../.. ; # Import the root /android and /mobile_files folders clean of any build artifacts
in builtins . path { # We use builtins.path so that we can name the resulting derivation, otherwise the name would be taken from the checkout directory, which is outside of our control
inherit path ;
2019-07-15 16:34:33 +00:00
name = " s t a t u s - r e a c t - s o u r c e - g r a d l e - i n s t a l l " ;
2019-06-04 16:50:29 +00:00
filter =
# Keep this filter as restrictive as possible in order to avoid unnecessary rebuilds and limit closure size
mkFilter {
dirRootsToInclude = [
2019-08-26 12:57:26 +00:00
" a n d r o i d " " m o b i l e _ f i l e s " " r e s o u r c e s "
2019-06-04 16:50:29 +00:00
" t r a n s l a t i o n s " " s t a t u s - m o d u l e s "
] ;
dirsToExclude = [ " . g i t " " . s v n " " C V S " " . h g " " . g r a d l e " " b u i l d " " i n t e r m e d i a t e s " " l i b s " " o b j " ] ;
filesToInclude = [ " . b a b e l r c " ] ;
filesToExclude = [ " a n d r o i d / g r a d l e w " ] ;
root = path ;
} ;
} ;
2019-08-06 16:16:51 +00:00
phases = [ " u n p a c k P h a s e " " p a t c h P h a s e " " i n s t a l l P h a s e " " f i x u p P h a s e " ] ;
2019-06-04 16:50:29 +00:00
nativeBuildInputs = [ projectNodePackage ] ;
2019-08-01 10:49:46 +00:00
buildInputs = [ gradle nodejs bash file zlib mavenLocalRepo ] ;
2019-08-06 16:16:51 +00:00
propagatedBuildInputs = [ react-native-deps ] ;
2019-06-04 16:50:29 +00:00
unpackPhase = ''
runHook preUnpack
# Copy project directory
2019-08-14 07:05:32 +00:00
mkdir - p $ { projectBuildDir }
cp - a $ src/. $ { projectBuildDir }
chmod u + w $ { projectBuildDir }
cd $ { projectBuildDir }
2019-06-04 16:50:29 +00:00
# Copy RN maven dependencies and make them writable, otherwise Gradle copy fails (since the top-level directory is read-only, Java isn't smart enough to copy the child files/folders into that target directory)
mkdir - p $ { mavenRepoDir }
cp - a $ { mavenLocalRepo } /. $ { mavenRepoDir }
cp - a $ { react-native-deps } /deps $ { reactNativeDepsDir }
for d in ` find $ { reactNativeDepsDir } - mindepth 1 - maxdepth 1 - type d ` ; do
chmod - R u + w $ d
done
# Copy node_modules from Nix store
2019-08-14 07:05:32 +00:00
rm - rf $ { projectBuildDir } /node_modules
mkdir - p $ { projectBuildDir } /node_modules
cp - a $ { projectNodePackage } /node_modules/. $ { projectBuildDir } /node_modules /
2019-06-04 16:50:29 +00:00
2019-08-22 16:36:59 +00:00
# Ensure that module was correctly installed
[ - d $ { projectBuildDir } /node_modules/jsc-android/dist ] || exit 1
2019-06-04 16:50:29 +00:00
# Adjust permissions
2019-08-14 07:05:32 +00:00
chmod - R u + w $ { projectBuildDir }
2019-06-04 16:50:29 +00:00
2019-08-14 07:05:32 +00:00
cp - R $ { projectBuildDir } /status-modules / $ { projectBuildDir } /node_modules/status-modules /
cp - R $ { projectBuildDir } /translations / $ { projectBuildDir } /node_modules/status-modules/translations /
2019-06-04 16:50:29 +00:00
# Set up symlinks to mobile enviroment in project root
2019-08-14 07:05:32 +00:00
$ { createMobileFilesSymlinks projectBuildDir }
2019-06-04 16:50:29 +00:00
# Create a dummy VERSION, since we don't want this expression to be invalidated just because the version changed
2019-08-14 07:05:32 +00:00
echo ' 0 .0 . 1 ' > $ { projectBuildDir } /VERSION
2019-06-04 16:50:29 +00:00
runHook postUnpack
'' ;
patchPhase = ''
runHook prePatch
prevSet = $ -
set - e
2019-08-14 07:05:32 +00:00
patchShebangs $ { projectBuildDir }
2019-06-04 16:50:29 +00:00
function patchMavenSource ( ) {
set + e
local targetGradleFile = " $ 1 "
local source = " $ 2 "
local deriv = " $ 3 "
grep " $ s o u r c e " $ targetGradleFile > /dev/null && \
substituteInPlace $ targetGradleFile - - replace " $ s o u r c e " " $ d e r i v "
}
function patchMavenSources ( ) {
set + e
local targetGradleFile = " $ 1 "
local deriv = " $ 2 "
patchMavenSource $ targetGradleFile ' mavenCentral ( ) ' ' mavenLocal ( ) '
patchMavenSource $ targetGradleFile ' google ( ) ' ' mavenLocal ( ) '
patchMavenSource $ targetGradleFile ' jcenter ( ) ' ' mavenLocal ( ) '
grep ' https://maven.google.com' $ targetGradleFile > /dev/null && \
substituteInPlace $ targetGradleFile - - replace ' https://maven.google.com' " $ d e r i v "
grep ' https://jitpack.io' $ targetGradleFile > /dev/null && \
substituteInPlace $ targetGradleFile - - replace ' https://jitpack.io' " $ d e r i v "
}
# Patch maven and google central repositories with our own local directories. This prevents the builder from downloading Maven artifacts
patchMavenSources ' android/build.gradle ' ' $ { mavenLocalRepo } '
2019-08-14 07:05:32 +00:00
for f in ` find $ { projectBuildDir } /node_modules / - name build . gradle ` ; do
2019-06-04 16:50:29 +00:00
patchMavenSources $ f ' $ { mavenLocalRepo } '
done
# Do not add a BuildId to the generated libraries, for reproducibility
2019-08-14 07:05:32 +00:00
substituteInPlace $ { projectBuildDir } /node_modules/react-native/ReactAndroid/src/main/jni/Application.mk \
- - replace \
' - Wl , - - build-id' \
' - Wl , - - build-id = none'
2019-06-04 16:50:29 +00:00
# Disable Gradle daemon and caching, since that causes rebuilds (and subsequently errors) anyway due to cache being considered stale
2019-08-14 07:05:32 +00:00
substituteInPlace $ { projectBuildDir } /android/gradle.properties \
- - replace \
' org . gradle . jvmargs = - Xmx8704M' \
' org . gradle . jvmargs = - Xmx8704M
2019-06-04 16:50:29 +00:00
org . gradle . daemon = false
org . gradle . caching = false'
# Patch the path to nodejs in project.ext.react
2019-08-14 07:05:32 +00:00
substituteInPlace $ { projectBuildDir } /android/app/build.gradle \
- - replace \
' nodeExecutableAndArgs : [ " n o d e " ' \
' nodeExecutableAndArgs : [ " ${ nodejs } / b i n / n o d e " '
2019-06-04 16:50:29 +00:00
2019-08-22 16:36:59 +00:00
# Fix bugs in Hermes usage (https://github.com/facebook/react-native/issues/25601#issuecomment-510856047)
# - Make script always include release Hermes VM, as the debug version is currently way too slow in npm package <= 0.1.1 (https://github.com/facebook/hermes/issues/73)
# - Make PR builds also count as release builds
# - Fix issue where hermes command is being called with same input/output file
substituteInPlace $ { projectBuildDir } /node_modules/react-native/react.gradle \
- - replace \
' def isRelease = targetName . toLowerCase ( ) . contains ( " r e l e a s e " ) ' \
' def isRelease = true' \
- - replace \
' targetName . toLowerCase ( ) . contains ( " r e l e a s e " ) ' \
' ! targetName . toLowerCase ( ) . contains ( " d e b u g " ) ' \
- - replace \
' commandLine ( getHermesCommand ( ) , " - e m i t - b i n a r y " , " - o u t " , jsBundleFile , jsBundleFile , * hermesFlags ) ' \
' def jsBundleFileIn = File . createTempFile ( " i n d e x . a n d r o i d " , " . t m p " )
jsBundleFileIn . deleteOnExit ( )
ant . move (
file : jsBundleFile ,
tofile : jsBundleFileIn
) ;
commandLine ( getHermesCommand ( ) , " - e m i t - b i n a r y " , " - o u t " , jsBundleFile , jsBundleFileIn , * hermesFlags )
' \
|| exit
2019-08-07 13:08:22 +00:00
# Patch dependencies which are not yet ported to AndroidX
npx jetify
2019-06-04 16:50:29 +00:00
set $ prevSet
runHook postPatch
'' ;
installPhase = ''
rm - rf $ out
2019-08-14 07:05:32 +00:00
mkdir - p $ out / { project , .m2/repository }
2019-06-04 16:50:29 +00:00
# TODO: maybe node_modules/react-native/ReactAndroid/build/{tmp,generated} can be discarded?
cp - R $ { mavenRepoDir } $ out/.m2 /
2019-08-14 07:05:32 +00:00
cp - R $ { projectBuildDir } / { android , node_modules } / $ out/project
2019-06-04 16:50:29 +00:00
'' ;
fixupPhase = ''
# Patch prepareJSC so that it doesn't subsequently try to build NDK libs
substituteInPlace $ out/project/node_modules/react-native/ReactAndroid/build.gradle \
2019-08-14 07:05:32 +00:00
- - replace \
' packageReactNdkLibs ( dependsOn : buildReactNdkLib , ' \
' packageReactNdkLibs ( '
2019-06-04 16:50:29 +00:00
'' ;
# The ELF types are incompatible with the host platform, so let's not even try
# TODO: Use Android NDK to strip binaries manually
dontPatchELF = true ;
dontStripHost = true ;
# Take whole sources into consideration when calculating sha
outputHashMode = " r e c u r s i v e " ;
outputHashAlgo = " s h a 2 5 6 " ;
} ;
in {
deriv = deps ;
shellHook = ''
$ { createMobileFilesSymlinks " $ S T A T U S _ R E A C T _ H O M E " }
export STATUSREACT_NIX_MAVEN_REPO = " ${ deps } / . m 2 / r e p o s i t o r y "
'' ;
}