Skip to content

Commit

Permalink
Integrate Qt5 Nix package (with forked repo for new QtWebView module)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Pombeiro committed Feb 28, 2019
1 parent cb62ee1 commit 07cf170
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 79 deletions.
26 changes: 16 additions & 10 deletions default.nix
@@ -1,10 +1,12 @@
let
pkgs = import ((import <nixpkgs> { }).fetchFromGitHub {
owner = "NixOS";
owner = "status-im";
repo = "nixpkgs";
rev = "168cbb39691cca2822ce1fdb3e8c0183af5c6d0d";
sha256 = "0fqasswfqrz2rbag9bz17j8y7615s0p9l23cw4sk2f384gk0zf6c";
rev = "3bd9966672d76e790e56cda234f0c34e5205a267";
sha256 = "12ggprababkdr37s8q3wz2n6idd9p6wpzj8nsx7vcmdl6940p5y9";
}) { config = { }; };

derivation = if pkgs.stdenv.isLinux then pkgs.stdenvNoCC.mkDerivation else pkgs.stdenv.mkDerivation;
nodejs = pkgs."nodejs-10_x";
conan = with pkgs; import ./scripts/lib/setup/nix/conan {
# Import a newer version of the Conan package to fix pylint issues with pinned one
Expand All @@ -19,15 +21,17 @@ let
inherit nodejs;
};
nodePkgs = (map (x: nodeInputs."${x}") (builtins.attrNames nodeInputs));
in pkgs.stdenv.mkDerivation rec {

in with pkgs; derivation rec {
name = "env";
env = pkgs.buildEnv { name = name; paths = buildInputs; };
statusDesktopBuildInputs = with pkgs; [
env = buildEnv { name = name; paths = buildInputs; };
statusDesktopBuildInputs = with stdenv; [
cmake
extra-cmake-modules
go_1_10
] ++ stdenv.lib.optional stdenv.isLinux conan;
buildInputs = with pkgs; [
qt5.full # Status Desktop, cannot be installed on macOS https://github.com/NixOS/nixpkgs/issues/55892
] ++ lib.optional isLinux [conan patchelf];
buildInputs = with stdenv; [
clojure
jq
leiningen
Expand All @@ -41,8 +45,9 @@ in pkgs.stdenv.mkDerivation rec {
yarn
] ++ nodePkgs
++ statusDesktopBuildInputs
++ stdenv.lib.optional stdenv.isDarwin cocoapods;
shellHook = with pkgs; ''
++ lib.optional isDarwin cocoapods
++ lib.optional isLinux gcc7;
shellHook = ''
local toolversion="$(git rev-parse --show-toplevel)/scripts/toolversion"
export JAVA_HOME="${openjdk}"
Expand All @@ -52,6 +57,7 @@ in pkgs.stdenv.mkDerivation rec {
export ANDROID_NDK_HOME="$ANDROID_NDK_ROOT"
export ANDROID_NDK="$ANDROID_NDK_ROOT"
export PATH="$ANDROID_HOME/bin:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools:$PATH"
export QT_PATH="${qt5.full}"
[ -d "$ANDROID_NDK_ROOT" ] || ./scripts/setup # we assume that if the NDK dir does not exist, make setup needs to be run
'';
Expand Down
5 changes: 3 additions & 2 deletions desktop/CMakeLists.txt
Expand Up @@ -11,7 +11,6 @@ cmake_minimum_required(VERSION 2.8.11)
set(APP_NAME Status)
set(JS_APP_NAME StatusIm)
set(REACT_BUILD_STATIC_LIB ON)
project(${APP_NAME} CXX)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUNICODE -std=c++11")
if(STATUS_NO_LOGGING)
Expand All @@ -26,7 +25,9 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")

set(USED_QT_MODULES Core Qml Quick WebSockets Svg)
project(${APP_NAME} C CXX)

set(USED_QT_MODULES Core Concurrent Qml Quick WebSockets Svg)
include(QtConfiguration)

set(ICON_PNG_RESOURCE_PATH "${CMAKE_SOURCE_DIR}/../deployment/status-icon.png")
Expand Down
2 changes: 1 addition & 1 deletion desktop_files/package.json.orig
Expand Up @@ -66,7 +66,7 @@
"react-native-image-crop-picker": "0.18.1",
"react-native-image-resizer": "1.0.0",
"react-native-invertible-scroll-view": "1.1.0",
"react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#v.3.0.0-2-status",
"react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#feature/nix",
"react-native-languages": "git+https://github.com/status-im/react-native-languages.git#v0.1.1-status",
"react-native-os": "1.1.0",
"react-native-qrcode": "0.2.6",
Expand Down
4 changes: 2 additions & 2 deletions desktop_files/yarn.lock
Expand Up @@ -7071,9 +7071,9 @@ react-native-invertible-scroll-view@1.1.0:
react-clone-referenced-element "^1.0.1"
react-native-scrollable-mixin "^1.0.1"

"react-native-keychain@git+https://github.com/status-im/react-native-keychain.git#v.3.0.0-2-status":
"react-native-keychain@git+https://github.com/status-im/react-native-keychain.git#feature/nix":
version "3.0.0-rc.3"
resolved "git+https://github.com/status-im/react-native-keychain.git#ce6cec62222713f2cec7798b69c4fae6b493832f"
resolved "git+https://github.com/status-im/react-native-keychain.git#1fe61ddc4d5817e8b76eafd318e24ec904bd92a1"

"react-native-languages@git+https://github.com/status-im/react-native-languages.git#v0.1.1-status":
version "3.0.2"
Expand Down
15 changes: 8 additions & 7 deletions modules/react-native-desktop-notification/desktop/CMakeLists.txt
Expand Up @@ -42,6 +42,14 @@ set(SnoreNotifyBackendSettings_STATIC_LIB ${SN_PREFIX}/lib${SN_LIBPATHSUFFIX}/${
set(SnoreNotifySettings_STATIC_LIB ${SN_PREFIX}/lib${SN_LIBPATHSUFFIX}/${CMAKE_STATIC_LIBRARY_PREFIX}snoresettings-qt5${CMAKE_STATIC_LIBRARY_SUFFIX})
set(SnoreNotify_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${SN_PREFIX} -DSNORE_STATIC=ON -DBUILD_daemon=OFF -DBUILD_settings=OFF
-DBUILD_snoresend=OFF ${SnoreNotify_CMAKE_ARGS})
set(SnoreNotify_CMAKE_ARGS ${SnoreNotify_CMAKE_ARGS}
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
"-DCMAKE_C_COMPILER_AR=${CMAKE_C_COMPILER_AR}"
"-DCMAKE_C_COMPILER_RANLIB=${CMAKE_C_COMPILER_RANLIB}"
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_COMPILER_AR=${CMAKE_CXX_COMPILER_AR}"
"-DCMAKE_CXX_COMPILER_RANLIB=${CMAKE_CXX_COMPILER_RANLIB}"
"-DCMAKE_LINKER=${CMAKE_LINKER}")
if (CMAKE_CROSSCOMPILING)
set(SnoreNotify_CMAKE_ARGS ${SnoreNotify_CMAKE_ARGS}
"-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
Expand All @@ -53,13 +61,6 @@ if (CMAKE_CROSSCOMPILING)
"-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}"
"-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}"
"-DCMAKE_AR=${CMAKE_AR}"
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
"-DCMAKE_C_COMPILER_AR=${CMAKE_C_COMPILER_AR}"
"-DCMAKE_C_COMPILER_RANLIB=${CMAKE_C_COMPILER_RANLIB}"
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_CXX_COMPILER_AR=${CMAKE_CXX_COMPILER_AR}"
"-DCMAKE_CXX_COMPILER_RANLIB=${CMAKE_CXX_COMPILER_RANLIB}"
"-DCMAKE_LINKER=${CMAKE_LINKER}"
"-DCMAKE_RC_COMPILER=${CMAKE_RC_COMPILER}"
"-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}"
"-DCMAKE_COMPILER_PREFIX=${CMAKE_COMPILER_PREFIX}"
Expand Down
156 changes: 111 additions & 45 deletions scripts/build-desktop.sh
Expand Up @@ -15,12 +15,6 @@ if [ -z $TARGET_SYSTEM_NAME ]; then
fi
WINDOWS_CROSSTOOLCHAIN_PKG_NAME='mxetoolchain-x86_64-w64-mingw32'

if [ -z $STATUS_NO_LOGGING ]; then
COMPILE_FLAGS="-DCMAKE_CXX_FLAGS:='-DBUILD_FOR_BUNDLE=1'"
else
COMPILE_FLAGS="-DCMAKE_CXX_FLAGS:=-DBUILD_FOR_BUNDLE=1 -DSTATUS_NO_LOGGING=1"
fi

external_modules_dir=( \
'node_modules/react-native-languages/desktop' \
'node_modules/react-native-config/desktop' \
Expand Down Expand Up @@ -76,6 +70,18 @@ function joinExistingPath() {
fi
}

function join { local IFS="$1"; shift; echo "$*"; }

CMAKE_EXTRA_FLAGS=$'-DCMAKE_CXX_FLAGS:=\'-DBUILD_FOR_BUNDLE=1\''
[ -n $STATUS_NO_LOGGING ] && CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DSTATUS_NO_LOGGING=1"
is_macos && CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DCMAKE_CXX_COMPILER=g++"
if is_windows_target; then
CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DCMAKE_TOOLCHAIN_FILE='Toolchain-Ubuntu-mingw64.cmake'"
CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DCMAKE_C_COMPILER='x86_64-w64-mingw32.shared-gcc'"
CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DCMAKE_CXX_COMPILER='x86_64-w64-mingw32.shared-g++'"
CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DCMAKE_RC_COMPILER='x86_64-w64-mingw32.shared-windres'"
fi

STATUSREACTPATH="$(cd "$SCRIPTPATH" && cd '..' && pwd)"
WORKFOLDER="$(joinExistingPath "$STATUSREACTPATH" 'StatusImPackage')"
DEPLOYQTFNAME='linuxdeployqt-continuous-x86_64_20181215.AppImage'
Expand Down Expand Up @@ -187,24 +193,13 @@ function compile() {
fi
export PATH=$bin_dir:$PATH
done <<< "$bin_dirs"
cmake -Wno-dev \
-DCMAKE_TOOLCHAIN_FILE='Toolchain-Ubuntu-mingw64.cmake' \
-DCMAKE_C_COMPILER='x86_64-w64-mingw32.shared-gcc' \
-DCMAKE_CXX_COMPILER='x86_64-w64-mingw32.shared-g++' \
-DCMAKE_RC_COMPILER='x86_64-w64-mingw32.shared-windres' \
-DCMAKE_BUILD_TYPE=Release \
-DEXTERNAL_MODULES_DIR="$EXTERNAL_MODULES_DIR" \
-DDESKTOP_FONTS="$DESKTOP_FONTS" \
-DJS_BUNDLE_PATH="$JS_BUNDLE_PATH" \
$COMPILE_FLAGS || exit 1
else
cmake -Wno-dev \
-DCMAKE_BUILD_TYPE=Release \
-DEXTERNAL_MODULES_DIR="$EXTERNAL_MODULES_DIR" \
-DDESKTOP_FONTS="$DESKTOP_FONTS" \
-DJS_BUNDLE_PATH="$JS_BUNDLE_PATH" \
$COMPILE_FLAGS || exit 1
fi
cmake -Wno-dev \
-DCMAKE_BUILD_TYPE=Release \
-DEXTERNAL_MODULES_DIR="$EXTERNAL_MODULES_DIR" \
-DDESKTOP_FONTS="$DESKTOP_FONTS" \
-DJS_BUNDLE_PATH="$JS_BUNDLE_PATH" \
$CMAKE_EXTRA_FLAGS || exit 1
make -S -j5 || exit 1
popd
}
Expand Down Expand Up @@ -258,6 +253,42 @@ function bundleWindows() {
./deployment/windows/nsis/setup.nsi
}

if is_linux; then
#
# getRecursiveDependencies will use ldd to go through the dependencies of a library,
# and output those which are ELF binaries
#
declare -A treated_libs=()
declare -A treated_package_dirs=()
function getRecursiveDependencies() {
local args=("$@")
local root_lib=(${args[0]})
treated_libs["$root_lib"]=1
if program_exists 'realpath'; then
root_lib=$(realpath -m "$root_lib" 2> /dev/null)
fi
echo $root_lib

[ -x $root_lib ] || return

local nix_package_dep_libs=($(ldd $root_lib | grep '=>' | awk -F'=>' -F ' ' "/^.*/{print \$3}"))
[ ${#nix_package_dep_libs[@]} -eq 0 ] && return

local nix_package_dep_libs_dirs=$(echo ${nix_package_dep_libs[@]} | xargs dirname | xargs realpath | sort -u | uniq | grep "^/nix")
for packageLibDir in $nix_package_dep_libs_dirs; do
if ! [ ${treated_package_dirs[$packageLibDir]} ]; then
treated_package_dirs["$packageLibDir"]=1
for lib in $(ls $packageLibDir/*.so* | xargs realpath | sort | uniq); do
local type=$(file $lib | awk -F':' "/^.*/{print \$2}" | awk -F' ' "/^.*/{print \$1}")
if [ $type == 'ELF' ]; then
[ ${treated_libs[$lib]} ] || getRecursiveDependencies "$lib"
fi
done
fi
done
}
fi

function bundleLinux() {
local QTBIN=$(joinExistingPath "$QT_PATH" 'gcc_64/bin')
if [ ! -d "$QTBIN" ]; then
Expand All @@ -282,11 +313,11 @@ function bundleLinux() {
popd

qmakePath="$(joinExistingPath "${QTBIN}" 'qmake')"
usrBinPath=$(joinPath "$WORKFOLDER" "AppDir/usr/bin")
usrBinPath="$(joinPath "$WORKFOLDER" "AppDir/usr/bin")"
cp -r ./deployment/linux/usr $WORKFOLDER/AppDir
cp ./.env $usrBinPath
cp ./desktop/bin/Status ./desktop/bin/reportApp $usrBinPath

if [ ! -f $DEPLOYQT ]; then
wget --output-document="$DEPLOYQT" --show-progress "https://desktop-app-files.ams3.digitaloceanspaces.com/$DEPLOYQTFNAME" # Versioned from https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
chmod a+x $DEPLOYQT
Expand All @@ -299,14 +330,22 @@ function bundleLinux() {

rm -f Application-x86_64.AppImage Status-x86_64.AppImage

[ $VERBOSE_LEVEL -ge 1 ] && ldd $(joinExistingPath "$usrBinPath" 'Status')
[ $VERBOSE_LEVEL -ge 1 ] && ldd $(joinExistingPath "$usrBinPath" 'Status')
desktopFilePath="$(joinExistingPath "$WORKFOLDER" 'AppDir/usr/share/applications/Status.desktop')"
pushd $WORKFOLDER
cp -r assets/share/assets $usrBinPath
cp -rf StatusImAppImage/* $usrBinPath
rm -f $usrBinPath/Status.AppImage
popd

# Tell linuxdeployqt about all the different lib folders in Nix's store
local all_deps=($(getRecursiveDependencies "$usrBinPath/Status"))
local unique_folders=($(echo "${all_deps[@]}" | xargs dirname | sort -u -r | uniq | grep "/nix"))
if [ ${#unique_folders[@]} -gt 0 ]; then
# Ensure the binary isn't using the interpreter in Nix's store
patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 "$usrBinPath/Status"
fi
LD_LIBRARY_PATH="$(join : ${unique_folders[@]})" \
$DEPLOYQT $APPIMAGE_OPTIONS \
$desktopFilePath \
-verbose=$VERBOSE_LEVEL -always-overwrite -no-strip \
Expand All @@ -329,6 +368,27 @@ function bundleLinux() {
echo ""
}

if is_macos; then
function getQtBaseBinPathFromNixStore() {
local qtFullDerivationPath=$(nix show-derivation -f $STATUSREACTPATH/default.nix | jq -r '.[] | .inputDrvs | 'keys' | .[]' | grep qt-full)
local qtBaseDerivationPath=$(nix show-derivation $qtFullDerivationPath | jq -r '.[] | .inputDrvs | 'keys' | .[]' | grep qtbase)

echo $(nix show-derivation $qtBaseDerivationPath | jq -r '.[] | .outputs.bin.path')
}

function copyVersionedQtLibToPackage() {
local qtbaseBinPath="$1"
local fileName="$2"
local targetPath="$3"

mkdir -p $targetPath
local srcPath=$(find $qtbaseBinPath/lib -name $fileName)
echo "Copying $srcPath to $targetPath"
cp -f "$srcPath" "$targetPath/$fileName"
chmod +w "$targetPath/$fileName"
}
fi

function bundleMacOS() {
# download prepared package with mac bundle files (it contains qt libraries, icon)
echo "Downloading skeleton of mac bundle..."
Expand All @@ -340,25 +400,31 @@ function bundleMacOS() {
echo -e "${GREEN}Downloading done.${NC}"
echo ""
unzip ./Status.app.zip
cp -r assets/share/assets Status.app/Contents/Resources
ln -sf ../Resources/assets ../Resources/ubuntu-server ../Resources/node_modules Status.app/Contents/MacOS
chmod +x Status.app/Contents/Resources/ubuntu-server
cp ../desktop/bin/Status Status.app/Contents/MacOS/Status
cp ../desktop/bin/reportApp Status.app/Contents/MacOS
cp ../.env Status.app/Contents/Resources
ln -sf ../Resources/.env Status.app/Contents/MacOS/.env
cp -f ../deployment/macos/qt-reportApp.conf Status.app/Contents/Resources
ln -sf ../Resources/qt-reportApp.conf Status.app/Contents/MacOS/qt.conf
install_name_tool -add_rpath "@executable_path/../Frameworks" \
-delete_rpath "${QT_PATH}/lib" \
'Status.app/Contents/MacOS/reportApp'
install_name_tool -add_rpath "@executable_path/../Frameworks" \
-delete_rpath "${QT_PATH}/lib" \
'Status.app/Contents/MacOS/Status'
cp -f ../deployment/macos/Info.plist Status.app/Contents
cp -f ../deployment/macos/status-icon.icns Status.app/Contents/Resources
$DEPLOYQT Status.app -verbose=$VERBOSE_LEVEL \
-qmldir="$STATUSREACTPATH/node_modules/react-native/ReactQt/runtime/src/qml/"
local contentsPath='Status.app/Contents'
cp -r assets/share/assets $contentsPath/Resources
ln -sf ../Resources/assets ../Resources/ubuntu-server ../Resources/node_modules $contentsPath/MacOS
chmod +x $contentsPath/Resources/ubuntu-server
cp ../desktop/bin/Status $contentsPath/MacOS/Status
cp ../desktop/bin/reportApp $contentsPath/MacOS
cp ../.env $contentsPath/Resources
ln -sf ../Resources/.env $contentsPath/MacOS/.env
cp -f ../deployment/macos/qt-reportApp.conf $contentsPath/Resources
ln -sf ../Resources/qt-reportApp.conf $contentsPath/MacOS/qt.conf
cp -f ../deployment/macos/Info.plist $contentsPath
cp -f ../deployment/macos/status-icon.icns $contentsPath/Resources

if program_exists nix && [ -n "$IN_NIX_SHELL" ]; then
# Since in the Nix qt.full package the different Qt modules are spread across several directories,
# macdeployqt cannot find some qtbase plugins, so we copy them in its place
local qtbaseBinPath=$(getQtBaseBinPathFromNixStore)
copyVersionedQtLibToPackage $qtbaseBinPath libqcocoa.dylib "$contentsPath/PlugIns/platforms/"
copyVersionedQtLibToPackage $qtbaseBinPath libcocoaprintersupport.dylib "$contentsPath/PlugIns/printsupport/"
fi

$DEPLOYQT Status.app \
-verbose=$VERBOSE_LEVEL \
-qmldir="$(joinExistingPath "$STATUSREACTPATH" 'node_modules/react-native')" \
-qmldir="$(joinExistingPath "$STATUSREACTPATH" 'desktop/reportApp')"
rm -f Status.app.zip
popd

Expand Down
26 changes: 14 additions & 12 deletions scripts/run-environment-check.sh
Expand Up @@ -22,18 +22,20 @@ else
PLATFORM=$1
fi

if ! program_version_exists node $EXPECTED_NODE_VERSION || ! program_version_exists yarn $EXPECTED_YARN_VERSION; then
echo -e "${YELLOW}********************************************************************************************"

echo -e "The current environment doesn't contain the expected versions of node and/or yarn"
echo -e " - node:\texpected\t${EXPECTED_NODE_VERSION}"
echo -e " \t\tfound\t\t$(node -v) ($(which node))"
echo -e " - yarn:\texpected\t${EXPECTED_YARN_VERSION}"
echo -e " \t\tfound\t\t$(yarn -v) ($(which yarn))"
echo -e "Please open another console to reload the environment, and then run 'make setup' if necessary."

echo -e "**********************************************************************************************${NC}"
exit 1
if [ -z "$IN_NIX_SHELL" ]; then
if ! program_version_exists node $EXPECTED_NODE_VERSION || ! program_version_exists yarn $EXPECTED_YARN_VERSION; then
echo -e "${YELLOW}********************************************************************************************"

echo -e "The current environment doesn't contain the expected versions of node and/or yarn"
echo -e " - node:\texpected\t${EXPECTED_NODE_VERSION}"
echo -e " \t\tfound\t\t$(node -v) ($(which node))"
echo -e " - yarn:\texpected\t${EXPECTED_YARN_VERSION}"
echo -e " \t\tfound\t\t$(yarn -v) ($(which yarn))"
echo -e "Please open another console to reload the environment, and then run 'make setup' if necessary."

echo -e "**********************************************************************************************${NC}"
exit 1
fi
fi

if [[ $PLATFORM == 'android' ]]; then
Expand Down

0 comments on commit 07cf170

Please sign in to comment.