2019-11-29 10:20:08 +00:00
{ stdenv , lib , config , callPackage ,
2019-09-10 09:50:09 +00:00
mkFilter , bash , file , gnumake , watchmanFactory , gradle ,
2019-07-15 16:34:33 +00:00
androidEnvShellHook , mavenAndNpmDeps ,
2019-08-06 16:16:51 +00:00
nodejs , openjdk , jsbundle , status-go , unzip , zlib } :
2019-06-04 16:50:29 +00:00
2020-01-13 14:28:40 +00:00
{ secrets-file ? " " , # Path to the file containing secret environment variables
2019-09-10 09:50:09 +00:00
watchmanSockPath ? " " , # Path to the socket file exposed by an external watchman instance (workaround needed for building Android on macOS)
2019-11-13 13:12:02 +00:00
env ? { } # Attribute set containing environment variables to expose to the build script
2019-06-04 16:50:29 +00:00
} :
2019-09-10 09:50:09 +00:00
assert ( builtins . stringLength watchmanSockPath ) > 0 -> stdenv . isDarwin ;
2019-06-04 16:50:29 +00:00
let
2020-01-13 14:28:40 +00:00
inherit ( lib ) attrByPath hasAttrByPath optionalAttrs ;
env' = env // optionalAttrs ( hasAttrByPath [ " s t a t u s - i m " " s t a t u s - g o " " s r c - o v e r r i d e " ] config ) {
STATUS_GO_SRC_OVERRIDE = config . status-im . status-go . src-override ;
2020-01-21 07:19:49 +00:00
} // optionalAttrs ( hasAttrByPath [ " s t a t u s - i m " " n i m b u s " " s r c - o v e r r i d e " ] config ) {
NIMBUS_SRC_OVERRIDE = config . status-im . nimbus . src-override ;
2019-11-13 13:12:02 +00:00
} ;
2020-01-13 14:28:40 +00:00
inherit ( config . status-im ) build-type ;
inherit ( config . status-im . status-react ) build-number ;
gradle-opts = ( attrByPath [ " s t a t u s - i m " " s t a t u s - r e a c t " " g r a d l e - o p t s " ] " " config ) ;
2020-03-02 11:18:01 +00:00
# Path to the .keystore file used to sign the Android APK
keystore-file = ( attrByPath [ " s t a t u s - i m " " s t a t u s - r e a c t " " k e y s t o r e - f i l e " ] " " config ) ;
2019-11-29 10:20:08 +00:00
baseName = " r e l e a s e - a n d r o i d " ;
2019-07-15 16:34:33 +00:00
name = " s t a t u s - r e a c t - b u i l d - ${ baseName } " ;
2019-06-04 16:50:29 +00:00
gradleHome = " $ N I X _ B U I L D _ T O P / . g r a d l e " ;
2019-11-29 10:20:08 +00:00
localMavenRepo = " ${ mavenAndNpmDeps . drv } / . m 2 / r e p o s i t o r y " ;
sourceProjectDir = " ${ mavenAndNpmDeps . drv } / p r o j e c t " ;
2019-06-04 16:50:29 +00:00
envFileName =
if ( build-type == " r e l e a s e " || build-type == " n i g h t l y " || build-type == " e 2 e " ) then " . e n v . ${ build-type } " else
if build-type != " " then " . e n v . j e n k i n s " else " . e n v " ;
2019-09-13 17:16:13 +00:00
buildType = if ( build-type == " p r " || build-type == " e 2 e " ) then " p r " else " r e l e a s e " ; /* P R b u i l d s s h o u l d n ' t r e p l a c e n o r m a l r e l e a s e s */
apksPath = " $ s o u r c e R o o t / a n d r o i d / a p p / b u i l d / o u t p u t s / a p k / ${ buildType } " ;
2019-09-10 09:50:09 +00:00
patchedWatchman = watchmanFactory watchmanSockPath ;
2019-06-04 16:50:29 +00:00
in stdenv . mkDerivation {
inherit name ;
src =
let path = ./../../../.. ;
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 - ${ baseName } " ;
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 {
2020-03-30 07:45:25 +00:00
root = path ;
include = [
2020-04-06 15:30:41 +00:00
" m o b i l e / j s _ f i l e s . * " " r e s o u r c e s / . * "
2020-03-30 07:45:25 +00:00
" m o d u l e s / r e a c t - n a t i v e - s t a t u s / a n d r o i d . * "
2020-03-02 11:18:01 +00:00
envFileName " V E R S I O N " " . w a t c h m a n c o n f i g "
" s t a t u s - g o - v e r s i o n . j s o n " " r e a c t - n a t i v e . c o n f i g . j s "
] ;
2019-06-04 16:50:29 +00:00
} ;
} ;
2019-09-10 09:50:09 +00:00
nativeBuildInputs = [ bash gradle unzip ] ++ lib . optionals stdenv . isDarwin [ file gnumake patchedWatchman ] ;
2019-06-04 16:50:29 +00:00
buildInputs = [ nodejs openjdk ] ;
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 " " b u i l d P h a s e " " c h e c k P h a s e " " i n s t a l l P h a s e " ] ;
unpackPhase = ''
runHook preUnpack
cp - r $ src ./project
chmod u + w - R ./project
export sourceRoot = $ PWD/project
runHook postUnpack
'' ;
2019-06-04 16:50:29 +00:00
postUnpack = ''
mkdir - p $ { gradleHome }
2020-03-02 11:18:01 +00:00
$ { if keystore-file != " " then " c p - a - - n o - p r e s e r v e = o w n e r s h i p ${ keystore-file } ${ gradleHome } / ; e x p o r t K E Y S T O R E _ P A T H = ${ gradleHome } / $ ( b a s e n a m e ${ keystore-file } ) " else " " }
2019-06-04 16:50:29 +00:00
# Ensure we have the right .env file
cp - f $ sourceRoot / $ { envFileName } $ sourceRoot/.env
# Copy index.*.js input file
2019-07-23 20:54:17 +00:00
cp - a - - no-preserve = ownership $ { jsbundle } /index * . js $ sourceRoot /
2019-06-04 16:50:29 +00:00
# Copy android/ directory
cp - a - - no-preserve = ownership $ { sourceProjectDir } /android / $ sourceRoot /
chmod u + w $ sourceRoot/android
chmod u + w $ sourceRoot/android/app
mkdir $ sourceRoot/android/build && chmod - R u + w $ sourceRoot/android/build
# Copy node_modules/ directory
cp - a - - no-preserve = ownership $ { sourceProjectDir } /node_modules / $ sourceRoot /
# Make android/build directories writable under node_modules
2019-09-03 10:51:53 +00:00
for d in ` find $ sourceRoot/node_modules - type f - name build . gradle | xargs dirname ` ; do
2019-06-04 16:50:29 +00:00
chmod - R u + w $ d
done
'' ;
patchPhase = ''
prevSet = $ -
set - e
2019-08-06 16:16:51 +00:00
substituteInPlace $ sourceRoot/android/gradlew \
2019-08-14 07:05:32 +00:00
- - replace \
' exec gradle' \
" e x e c g r a d l e - D m a v e n . r e p o . l o c a l = ' ${ localMavenRepo } ' - - o f f l i n e ${ gradle-opts } "
2019-06-04 16:50:29 +00:00
set $ prevSet
'' ;
buildPhase =
let
inherit ( lib ) catAttrs concatStrings concatStringsSep mapAttrsToList makeLibraryPath optionalString substring toUpper ;
# Take the env attribute set and build a couple of scripts
# (one to export the environment variables, and another to unset them)
2019-11-13 13:12:02 +00:00
exportEnvVars = concatStringsSep " ; " ( mapAttrsToList ( name : value : " e x p o r t ${ name } = ' ${ value } ' " ) env' ) ;
unsetEnvVars = concatStringsSep " ; " ( mapAttrsToList ( name : value : " u n s e t ${ name } " ) env' ) ;
2019-06-04 16:50:29 +00:00
adhocEnvVars = optionalString stdenv . isLinux " L D _ L I B R A R Y _ P A T H = $ L D _ L I B R A R Y _ P A T H : ${ makeLibraryPath [ zlib ] } " ;
2019-09-13 17:16:13 +00:00
capitalizedBuildType = toUpper ( substring 0 1 buildType ) + substring 1 ( -1 ) buildType ;
2019-06-04 16:50:29 +00:00
in ''
export STATUS_REACT_HOME = $ PWD
2019-08-06 16:16:51 +00:00
export HOME = $ sourceRoot
2019-06-04 16:50:29 +00:00
$ { exportEnvVars }
$ { if secrets-file != " " then " s o u r c e ${ secrets-file } " else " " }
$ { androidEnvShellHook }
2019-11-29 10:20:08 +00:00
$ { concatStrings ( catAttrs " s h e l l H o o k " [ mavenAndNpmDeps . shell status-go . shell ] ) }
2019-06-04 16:50:29 +00:00
2019-08-06 16:16:51 +00:00
pushd $ sourceRoot/android
2020-01-13 14:28:40 +00:00
$ { adhocEnvVars } ./gradlew - PversionCode = $ { assert build-number != " " ; build-number } assemble $ { capitalizedBuildType } || exit
2019-06-04 16:50:29 +00:00
popd > /dev/null
$ { unsetEnvVars }
'' ;
2019-08-06 16:16:51 +00:00
doCheck = true ;
checkPhase = ''
2019-09-13 17:16:13 +00:00
ls $ { apksPath } /* . a p k | x a r g s - n 1 u n z i p - q q l | g r e p ' a s s e t s / i n d e x . a n d r o i d . b u n d l e '
2019-08-06 16:16:51 +00:00
'' ;
2019-06-04 16:50:29 +00:00
installPhase = ''
mkdir - p $ out
2019-09-13 17:16:13 +00:00
cp $ { apksPath } /* . a p k $ o u t /
2019-06-04 16:50:29 +00:00
'' ;
}