nix: simplify android release build

Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
Jakub Sokołowski 2020-05-06 15:33:54 +02:00
parent df25f09159
commit 45f1d58832
No known key found for this signature in database
GPG Key ID: 4EF064D0E6D63020
10 changed files with 128 additions and 136 deletions

1
.gitignore vendored
View File

@ -129,6 +129,7 @@ fastlane/README.md
.dir-locals.el .dir-locals.el
#ignore platform-specific files in the root since they are only symlinks to files in folders 'desktop/js_files' and 'mobile/js_files' #ignore platform-specific files in the root since they are only symlinks to files in folders 'desktop/js_files' and 'mobile/js_files'
/DEPENDENCIES.md
/package-lock.json /package-lock.json
/package.json /package.json
/metro.config.js /metro.config.js

View File

@ -0,0 +1,29 @@
{ stdenvNoCC, fetchurl }:
let
inherit (builtins) map baseNameOf;
deps = import ./deps.nix;
fetchTarball = dep: with dep;
fetchurl {
inherit url sha256;
name = "${name}-${baseNameOf url}";
};
in stdenvNoCC.mkDerivation {
name = "reactnative-android-deps";
phases = [ "unpackPhase" ];
srcs = map fetchTarball deps;
unpackPhase = ''
# Unpack all source archives.
mkdir -p $out/deps
cd $out/deps
for tarball in $srcs; do
unpackFile "$tarball" 2>/dev/null
done
cd ..
export sourceRoot=$out/deps
echo $sourceRoot
'';
}

View File

@ -0,0 +1,29 @@
# These versions should match values in:
# node_modules/react-native/ReactAndroid/gradle.properties
# Currently this is done manually.
[
rec {
name = "boost";
version = "1.63.0";
url = "https://github.com/react-native-community/boost-for-react-native/releases/download/v${version}-0/${name}_${builtins.replaceStrings ["."] ["_"] version}.tar.gz";
sha256 = "1hq5h6wzcr3sk1kccfk769d59swwxy1kvfhqd6p7786a1zsavdr6";
}
rec {
name = "double-conversion";
version = "1.1.6";
url = "https://github.com/google/${name}/archive/v${version}.tar.gz";
sha256 = "0ynnckpyyhpwisb976knk9gr8jklfwr9flic8xj5flc8iv6hm1bb";
}
rec {
name = "folly";
version = "2018.10.22.00";
url = "https://github.com/facebook/${name}/archive/v${version}.tar.gz";
sha256 = "08cxc8hw34vnyyq45d04spy4dilrgqrv374lwxhg3sx60ww640y4";
}
rec {
name = "glog";
version = "0.3.5";
url = "https://github.com/google/${name}/archive/v${version}.tar.gz";
sha256 = "1q6ihk2asbx95a56kmyqwysq1x3grrw9jwqllafaidf0l84f903m";
}
]

View File

@ -29,7 +29,8 @@ in {
shell = mkShell { shell = mkShell {
buildInputs = with pkgs; [ buildInputs = with pkgs; [
mavenAndNpmDeps.drv openjdk gradle openjdk
gradle
lsof # used in start-react-native.sh lsof # used in start-react-native.sh
flock # used in reset-node_modules.sh flock # used in reset-node_modules.sh
]; ];

View File

@ -3,21 +3,12 @@
# as well as a local version of the Maven repository required by Gradle scripts # as well as a local version of the Maven repository required by Gradle scripts
# #
{ stdenv, lib, callPackage, deps, mkShell, { stdenv, lib, callPackage, pkgs, deps, mkShell
gradle, bash, file, nodejs, zlib, localMavenRepoBuilder }: , localMavenRepoBuilder }:
let let
mavenLocalRepo = callPackage ./maven { inherit localMavenRepoBuilder stdenv; }; mavenLocalRepo = callPackage ./maven { inherit localMavenRepoBuilder stdenv; };
# Import the native dependencies for React Native Android builds
react-native-deps = callPackage ./maven/reactnative-android-native-deps.nix { };
createMobileFilesSymlinks = root: ''
ln -sf ${root}/mobile/js_files/package.json ${root}/package.json
ln -sf ${root}/mobile/js_files/metro.config.js ${root}/metro.config.js
ln -sf ${root}/mobile/js_files/yarn.lock ${root}/yarn.lock
'';
# fake build to pre-download deps into fixed-output derivation # fake build to pre-download deps into fixed-output derivation
drv = drv =
let let
@ -48,8 +39,8 @@ let
}; };
phases = [ "unpackPhase" "patchPhase" "installPhase" "fixupPhase" ]; phases = [ "unpackPhase" "patchPhase" "installPhase" "fixupPhase" ];
nativeBuildInputs = [ deps.nodejs ]; nativeBuildInputs = [ deps.nodejs ];
buildInputs = [ gradle nodejs bash file zlib mavenLocalRepo ]; buildInputs = with pkgs; [ gradle nodejs file zlib mavenLocalRepo ];
propagatedBuildInputs = [ react-native-deps ]; propagatedBuildInputs = [ deps.react-native ];
unpackPhase = '' unpackPhase = ''
runHook preUnpack runHook preUnpack
@ -62,10 +53,8 @@ let
# 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) # 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} mkdir -p ${mavenRepoDir}
cp -a ${mavenLocalRepo}/. ${mavenRepoDir} cp -a ${mavenLocalRepo}/. ${mavenRepoDir}
cp -a ${react-native-deps}/deps ${reactNativeDepsDir} cp -a ${deps.react-native}/deps ${reactNativeDepsDir}
for d in `find ${reactNativeDepsDir} -mindepth 1 -maxdepth 1 -type d`; do find ${reactNativeDepsDir} -maxdepth 1 -type d -exec chmod -R u+w {} \;
chmod -R u+w $d
done
# Copy node_modules from Nix store # Copy node_modules from Nix store
rm -rf ${projectBuildDir}/node_modules rm -rf ${projectBuildDir}/node_modules
@ -80,9 +69,6 @@ let
cp -R ${projectBuildDir}/status-modules/ ${projectBuildDir}/node_modules/status-modules/ cp -R ${projectBuildDir}/status-modules/ ${projectBuildDir}/node_modules/status-modules/
# Set up symlinks to mobile enviroment in project root
${createMobileFilesSymlinks projectBuildDir}
# Create a dummy VERSION, since we don't want this expression to be invalidated just because the version changed # Create a dummy VERSION, since we don't want this expression to be invalidated just because the version changed
echo '0.0.1' > ${projectBuildDir}/VERSION echo '0.0.1' > ${projectBuildDir}/VERSION
@ -144,7 +130,7 @@ let
substituteInPlace ${projectBuildDir}/android/app/build.gradle \ substituteInPlace ${projectBuildDir}/android/app/build.gradle \
--replace \ --replace \
'nodeExecutableAndArgs: ["node"' \ 'nodeExecutableAndArgs: ["node"' \
'nodeExecutableAndArgs: ["${nodejs}/bin/node"' 'nodeExecutableAndArgs: ["${pkgs.nodejs}/bin/node"'
# Fix bugs in Hermes usage (https://github.com/facebook/react-native/issues/25601#issuecomment-510856047) # Fix bugs in Hermes usage (https://github.com/facebook/react-native/issues/25601#issuecomment-510856047)
# - Make PR builds also count as release builds # - Make PR builds also count as release builds
@ -191,8 +177,6 @@ in {
inherit drv; inherit drv;
shell = mkShell { shell = mkShell {
shellHook = '' shellHook = ''
${createMobileFilesSymlinks "$STATUS_REACT_HOME"}
export STATUSREACT_NIX_MAVEN_REPO="${drv}/.m2/repository" export STATUSREACT_NIX_MAVEN_REPO="${drv}/.m2/repository"
''; '';
}; };

View File

@ -1,48 +0,0 @@
{ stdenvNoCC, fetchurl }:
let
# These versions should match node_modules/react-native/ReactAndroid/gradle.properties
react-native-deps-sources = [
rec {
name = "boost";
version = "1.63.0";
url = "https://github.com/react-native-community/boost-for-react-native/releases/download/v${version}-0/${name}_${builtins.replaceStrings ["."] ["_"] version}.tar.gz";
sha256 = "1hq5h6wzcr3sk1kccfk769d59swwxy1kvfhqd6p7786a1zsavdr6";
}
rec {
name = "double-conversion";
version = "1.1.6";
url = "https://github.com/google/${name}/archive/v${version}.tar.gz";
sha256 = "0ynnckpyyhpwisb976knk9gr8jklfwr9flic8xj5flc8iv6hm1bb";
}
rec {
name = "folly";
version = "2018.10.22.00";
url = "https://github.com/facebook/${name}/archive/v${version}.tar.gz";
sha256 = "08cxc8hw34vnyyq45d04spy4dilrgqrv374lwxhg3sx60ww640y4";
}
rec {
name = "glog";
version = "0.3.5";
url = "https://github.com/google/${name}/archive/v${version}.tar.gz";
sha256 = "1q6ihk2asbx95a56kmyqwysq1x3grrw9jwqllafaidf0l84f903m";
}
];
in stdenvNoCC.mkDerivation {
name = "reactnative-android-native-deps";
srcs = builtins.map (d: (fetchurl { inherit (d) url sha256; })) react-native-deps-sources;
phases = [ "unpackPhase" ];
unpackPhase = ''
# Unpack all source archives.
mkdir -p $out/deps
cd $out/deps
for i in $srcs; do
unpackFile "$i"
done
cd ..
export sourceRoot=$out/deps
echo $sourceRoot
'';
}

View File

@ -12,23 +12,13 @@
assert (lib.stringLength watchmanSockPath) > 0 -> stdenv.isDarwin; assert (lib.stringLength watchmanSockPath) > 0 -> stdenv.isDarwin;
let let
inherit (lib) toLower optionalString getConfig; inherit (lib) toLower optionalString stringLength getConfig makeLibraryPath;
# custom env variables derived from config
env = {
ANDROID_ABI_SPLIT = getConfig "android.abi-split" "false";
ANDROID_ABI_INCLUDE = getConfig "android.abi-include" "armeabi-v7a;arm64-v8a;x86";
STATUS_GO_SRC_OVERRIDE = getConfig "nimbus.src-override" null;
};
buildType = getConfig "build-type" "prod"; buildType = getConfig "build-type" "prod";
buildNumber = getConfig "build-number" 9999; buildNumber = getConfig "build-number" 9999;
gradleOpts = getConfig "android.gradle-opts" null; gradleOpts = getConfig "android.gradle-opts" null;
keystorePath = getConfig "android.keystore-path" null; keystorePath = getConfig "android.keystore-path" null;
# Keep the same keystore path for determinism
keystoreLocal = "${gradleHome}/status-im.keystore";
baseName = "release-android"; baseName = "release-android";
name = "status-react-build-${baseName}"; name = "status-react-build-${baseName}";
@ -45,7 +35,7 @@ let
then "Pr" then "Pr"
else "Release"; # PR builds shouldn't replace normal releases else "Release"; # PR builds shouldn't replace normal releases
apksPath = "$sourceRoot/android/app/build/outputs/apk/${toLower gradleBuildType}"; apksPath = "$PROJECT/android/app/build/outputs/apk/${toLower gradleBuildType}";
patchedWatchman = watchmanFactory watchmanSockPath; patchedWatchman = watchmanFactory watchmanSockPath;
in stdenv.mkDerivation rec { in stdenv.mkDerivation rec {
@ -74,41 +64,56 @@ in stdenv.mkDerivation rec {
# Used by Clojure at compile time to include JS modules # Used by Clojure at compile time to include JS modules
BUILD_ENV = buildEnv; BUILD_ENV = buildEnv;
phases = [ "unpackPhase" "patchPhase" "buildPhase" "checkPhase" "installPhase" ]; # custom env variables derived from config
STATUS_GO_SRC_OVERRIDE = getConfig "nimbus.src-override" null;
ANDROID_ABI_SPLIT = getConfig "android.abi-split" "false";
ANDROID_ABI_INCLUDE = getConfig "android.abi-include" "armeabi-v7a;arm64-v8a;x86";
ANDROID_SDK_ROOT = "${androidPkgs}";
ANDROID_NDK_ROOT = "${androidPkgs}/ndk-bundle";
# Used by the Android Gradle build script in android/build.gradle
STATUS_GO_ANDROID_LIBDIR = "${status-go}";
# Used by the Android Gradle wrapper in android/gradlew
STATUSREACT_NIX_MAVEN_REPO = "${mavenAndNpmDeps.drv}/.m2/repository";
phases = [
"unpackPhase" "patchPhase" "secretPhase" "buildPhase" "checkPhase" "installPhase"
];
unpackPhase = '' unpackPhase = ''
runHook preUnpack
cp -r $src ./project cp -r $src ./project
chmod u+w -R ./project chmod u+w -R ./project
export PROJECT=$PWD/project
export sourceRoot=$PWD/project
runHook postUnpack runHook postUnpack
''; '';
postUnpack = assert lib.assertMsg (keystorePath != null) "keystore-file has to be set!"; '' postUnpack = assert lib.assertMsg (keystorePath != null) "keystore-file has to be set!"; ''
mkdir -p ${gradleHome} mkdir -p ${gradleHome}
# WARNING: Renaming the keystore will cause 'Keystore was tampered with' error # Keep the same keystore path for determinism
cp -a --no-preserve=ownership "${keystorePath}" "${keystoreLocal}" export KEYSTORE_PATH="${gradleHome}/status-im.keystore"
cp -a --no-preserve=ownership "${keystorePath}" "$KEYSTORE_PATH"
# Ensure we have the right .env file # Ensure we have the right .env file
cp -f $sourceRoot/${envFileName} $sourceRoot/.env cp -f $PROJECT/${envFileName} $PROJECT/.env
# Copy index.js and app/ input files # Copy index.js and app/ input files
cp -ra --no-preserve=ownership ${jsbundle}/* $sourceRoot/ cp -ra --no-preserve=ownership ${jsbundle}/* $PROJECT/
# Copy android/ directory # Copy android/ directory
cp -a --no-preserve=ownership ${sourceProjectDir}/android/ $sourceRoot/ cp -a --no-preserve=ownership ${sourceProjectDir}/android/ $PROJECT/
chmod u+w $sourceRoot/android chmod u+w $PROJECT/android
chmod u+w $sourceRoot/android/app chmod u+w $PROJECT/android/app
mkdir -p $sourceRoot/android/build mkdir -p $PROJECT/android/build
chmod -R u+w $sourceRoot/android/build chmod -R u+w $PROJECT/android/build
# Copy node_modules/ directory # Copy node_modules/ directory
cp -a --no-preserve=ownership ${sourceProjectDir}/node_modules/ $sourceRoot/ cp -a --no-preserve=ownership ${sourceProjectDir}/node_modules/ $PROJECT/
# Make android/build directories writable under node_modules # Make android/build directories writable under node_modules
for d in `find $sourceRoot/node_modules -type f -name build.gradle | xargs dirname`; do for d in `find $PROJECT/node_modules -type f -name build.gradle | xargs dirname`; do
chmod -R u+w $d chmod -R u+w $d
done done
''; '';
@ -116,50 +121,38 @@ in stdenv.mkDerivation rec {
prevSet=$- prevSet=$-
set -e set -e
substituteInPlace $sourceRoot/android/gradlew \ substituteInPlace $PROJECT/android/gradlew \
--replace \ --replace \
'exec gradle' \ 'exec gradle' \
"exec gradle -Dmaven.repo.local='${localMavenRepo}' --offline ${toString gradleOpts}" "exec gradle -Dmaven.repo.local='${localMavenRepo}' --offline ${toString gradleOpts}"
set $prevSet set $prevSet
''; '';
secretPhase = optionalString (secretsFile != "") ''
source "${secretsFile}"
'';
buildPhase = let buildPhase = let
inherit (lib)
stringLength optionalString substring
toInt concatStrings concatStringsSep
catAttrs mapAttrsToList makeLibraryPath;
# Take the env attribute set and build a couple of scripts
# (one to export the environment variables, and another to unset them)
exportEnvVars = concatStringsSep ";"
(mapAttrsToList (name: value: "export ${name}='${toString value}'") env);
adhocEnvVars = optionalString stdenv.isLinux adhocEnvVars = optionalString stdenv.isLinux
"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${makeLibraryPath [ zlib ]}"; "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${makeLibraryPath [ zlib ]}";
in in
assert env.ANDROID_ABI_SPLIT != null && env.ANDROID_ABI_SPLIT != ""; assert ANDROID_ABI_SPLIT != null && ANDROID_ABI_SPLIT != "";
assert stringLength env.ANDROID_ABI_INCLUDE > 0; assert stringLength ANDROID_ABI_INCLUDE > 0;
'' ''
export ANDROID_SDK_ROOT="${androidPkgs}"
export ANDROID_NDK_ROOT="${androidPkgs}/ndk-bundle"
export KEYSTORE_PATH="${keystoreLocal}"
export STATUS_REACT_HOME=$PWD export STATUS_REACT_HOME=$PWD
export HOME=$sourceRoot export HOME=$PROJECT
# Used by the Android Gradle build script in android/build.gradle # create mobile node/yarn symlinks
export STATUS_GO_ANDROID_LIBDIR=${status-go} ln -sf $PROJECT/mobile/js_files/* $PROJECT/
${exportEnvVars}
${optionalString (secretsFile != "") "source ${secretsFile}"}
${concatStrings (catAttrs "shellHook" [ mavenAndNpmDeps.shell ])}
# fix permissions so gradle can create directories # fix permissions so gradle can create directories
chmod -R +w $sourceRoot/android chmod -R +w $PROJECT/android
pushd $sourceRoot/android pushd $PROJECT/android
${adhocEnvVars} ./gradlew -PversionCode=${toString buildNumber} assemble${gradleBuildType} || exit ${adhocEnvVars} ./gradlew \
--stacktrace \
-PversionCode=${toString buildNumber} \
assemble${gradleBuildType} \
|| exit 1
popd > /dev/null popd > /dev/null
''; '';
doCheck = true; doCheck = true;

View File

@ -1,5 +1,4 @@
{ config, lib, stdenvNoCC, callPackage, mkShell, { config, lib, stdenvNoCC, callPackage, mkShell, status-go }:
status-go, xcodeWrapper }:
let let
inherit (lib) catAttrs concatStrings optional unique; inherit (lib) catAttrs concatStrings optional unique;
@ -14,7 +13,7 @@ let
}; };
ios = callPackage ./ios { ios = callPackage ./ios {
inherit xcodeWrapper fastlane; inherit fastlane;
status-go = status-go.mobile.ios; status-go = status-go.mobile.ios;
}; };
@ -29,6 +28,10 @@ let
in { in {
shell = mkShell { shell = mkShell {
inputsFrom = (catAttrs "shell" selectedSources); inputsFrom = (catAttrs "shell" selectedSources);
shellHooks = ''
# create mobile node/yarn symlinks
ln -sf $STATUS_REACT_HOME/mobile/js_files/* $STATUS_REACT_HOME/
'';
}; };
# TARGETS # TARGETS

View File

@ -1,6 +1,5 @@
{ callPackage, lib, mkShell, { callPackage, lib, mkShell, deps, pkgs
xcodeWrapper, projectNodePackage, status-go, , status-go, fastlane }:
flock, procps, watchman, bundler, fastlane }:
let let
inherit (lib) catAttrs unique; inherit (lib) catAttrs unique;
@ -12,7 +11,7 @@ in {
inherit pod-shell status-go-shell; inherit pod-shell status-go-shell;
shell = mkShell { shell = mkShell {
buildInputs = [ buildInputs = with pkgs; [
xcodeWrapper watchman bundler procps xcodeWrapper watchman bundler procps
flock # used in reset-node_modules.sh flock # used in reset-node_modules.sh
]; ];
@ -32,7 +31,7 @@ in {
ln -sf ./mobile/js_files/yarn.lock ./yarn.lock ln -sf ./mobile/js_files/yarn.lock ./yarn.lock
# check if node modules changed and if so install them # check if node modules changed and if so install them
./nix/mobile/reset-node_modules.sh "${projectNodePackage}" ./nix/mobile/reset-node_modules.sh "${deps.nodejs}"
} }
popd > /dev/null popd > /dev/null
''; '';

View File

@ -24,6 +24,7 @@ in {
deps = { deps = {
clojure = callPackage ./deps/clojure { }; clojure = callPackage ./deps/clojure { };
nodejs = callPackage ./deps/nodejs { }; nodejs = callPackage ./deps/nodejs { };
react-native = callPackage ./deps/react-native { };
}; };
# Android environement # Android environement