From 2ac5ee019eca72be2bee060a2af6b02f7caa2a88 Mon Sep 17 00:00:00 2001 From: Pedro Pombeiro Date: Fri, 15 Feb 2019 09:04:03 +0100 Subject: [PATCH] Migrate Desktop build environment to leverage Nix - Add Conan to default.nix - Integrate Qt5 Nix package (with forked repo for new QtWebView module) - Fix rpaths in macOS and Linux - Add Nix expressions to install nsis, appimagekit and linuxdeployqt --- .TOOLVERSIONS | 4 +- default.nix | 99 ++--- desktop/CMakeLists.txt | 5 +- desktop/run-app.sh.in | 7 +- desktop_files/package.json.orig | 2 +- desktop_files/yarn.lock | 4 +- .../desktop/CMakeLists.txt | 15 +- .../desktop/build-status-go.sh | 8 +- scripts/build-desktop.sh | 345 +++++++++++++----- scripts/lib/setup/installers.sh | 11 - .../setup/nix/desktop/appimagekit/default.nix | 117 ++++++ .../setup/nix/desktop/appimagekit/nix.patch | 197 ++++++++++ scripts/lib/setup/nix/desktop/default.nix | 26 ++ .../nix/desktop/linuxdeployqt/default.nix | 43 +++ .../lib/setup/nix/desktop/windows/default.nix | 8 + scripts/lib/setup/packages.sh | 76 ---- scripts/run-environment-check.sh | 22 +- scripts/setup | 3 - 18 files changed, 731 insertions(+), 261 deletions(-) create mode 100644 scripts/lib/setup/nix/desktop/appimagekit/default.nix create mode 100644 scripts/lib/setup/nix/desktop/appimagekit/nix.patch create mode 100644 scripts/lib/setup/nix/desktop/default.nix create mode 100644 scripts/lib/setup/nix/desktop/linuxdeployqt/default.nix create mode 100644 scripts/lib/setup/nix/desktop/windows/default.nix diff --git a/.TOOLVERSIONS b/.TOOLVERSIONS index 75adc3f564..ba491dd847 100644 --- a/.TOOLVERSIONS +++ b/.TOOLVERSIONS @@ -5,8 +5,8 @@ android-sdk;4333796;aa190cfd7299cd6a1c687355bb2764e4 bundler;1.17.2;bundler clojure_cli;1.9.0.391; cmake;3.11.2; -conan;1.9.0; -golang;1.10.8; +conan;1.12.0; +golang;1.11.5; leiningen;2.8.1; maven;3.5.4; nix;2.2.1; diff --git a/default.nix b/default.nix index c70ca135e2..1f76f2b29a 100644 --- a/default.nix +++ b/default.nix @@ -1,52 +1,59 @@ let pkgs = import ((import { }).fetchFromGitHub { - owner = "NixOS"; + owner = "status-im"; repo = "nixpkgs"; - rev = "168cbb39691cca2822ce1fdb3e8c0183af5c6d0d"; - sha256 = "0fqasswfqrz2rbag9bz17j8y7615s0p9l23cw4sk2f384gk0zf6c"; + rev = "15623aac6e8cbfa24d4268195bc8eda7303ea2ff"; + sha256 = "0crjmspk65rbpkl3kqcj7433355i9fy530lhc48g2cz75xjk4sxh"; }) { config = { }; }; - nodejs = pkgs."nodejs-10_x"; - nodeInputs = import ./scripts/lib/setup/nix/global-node-packages/output { - # The remaining dependencies come from Nixpkgs - inherit pkgs; - inherit nodejs; - }; - nodePkgs = (map (x: nodeInputs."${x}") (builtins.attrNames nodeInputs)); -in pkgs.stdenv.mkDerivation rec { - name = "env"; - env = pkgs.buildEnv { name = name; paths = buildInputs; }; - statusDesktopBuildInputs = with pkgs; [ - cmake - extra-cmake-modules - go_1_10 - ] ++ stdenv.lib.optional stdenv.isLinux python37; # for Conan - buildInputs = with pkgs; [ - clojure - jq - leiningen - lsof # used in scripts/start-react-native.sh - maven - nodejs - openjdk - python27 # for e.g. gyp - watchman - unzip - wget - yarn - ] ++ nodePkgs - ++ statusDesktopBuildInputs - ++ stdenv.lib.optional stdenv.isDarwin cocoapods; - shellHook = with pkgs; '' - local toolversion="$(git rev-parse --show-toplevel)/scripts/toolversion" - export JAVA_HOME="${openjdk}" - export ANDROID_HOME=~/.status/Android/Sdk - export ANDROID_SDK_ROOT="$ANDROID_HOME" - export ANDROID_NDK_ROOT="$ANDROID_SDK_ROOT/android-ndk-$($toolversion android-ndk)" - 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" +in with pkgs; + let + _stdenv = stdenvNoCC; # TODO: Try to use stdenv for Darwin + statusDesktop = callPackage ./scripts/lib/setup/nix/desktop { stdenv = _stdenv; }; + nodeInputs = import ./scripts/lib/setup/nix/global-node-packages/output { + # The remaining dependencies come from Nixpkgs + inherit pkgs; + inherit nodejs; + }; + nodePkgs = [ + nodejs + python27 # for e.g. gyp + yarn + ] ++ (map (x: nodeInputs."${x}") (builtins.attrNames nodeInputs)); - [ -d "$ANDROID_NDK_ROOT" ] || ./scripts/setup # we assume that if the NDK dir does not exist, make setup needs to be run - ''; -} \ No newline at end of file + in _stdenv.mkDerivation rec { + name = "env"; + env = buildEnv { name = name; paths = buildInputs; }; + buildInputs = with _stdenv; [ + clojure + curl + jq + leiningen + lsof # used in scripts/start-react-native.sh + maven + ncurses + ps # used in scripts/start-react-native.sh + openjdk + statusDesktop.buildInputs + watchman + unzip + wget + ] ++ nodePkgs + ++ lib.optional isDarwin cocoapods + ++ lib.optional isLinux gcc7; + shellHook = '' + ${statusDesktop.shellHook} + + local toolversion="$(git rev-parse --show-toplevel)/scripts/toolversion" + + export JAVA_HOME="${openjdk}" + export ANDROID_HOME=~/.status/Android/Sdk + export ANDROID_SDK_ROOT="$ANDROID_HOME" + export ANDROID_NDK_ROOT="$ANDROID_SDK_ROOT/android-ndk-$($toolversion android-ndk)" + 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" + + [ -d "$ANDROID_NDK_ROOT" ] || ./scripts/setup # we assume that if the Android NDK dir does not exist, make setup needs to be run + ''; + } \ No newline at end of file diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 17df70f0fd..7922accd0c 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -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) @@ -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") diff --git a/desktop/run-app.sh.in b/desktop/run-app.sh.in index 401251ea87..e4547fad15 100755 --- a/desktop/run-app.sh.in +++ b/desktop/run-app.sh.in @@ -13,8 +13,6 @@ plugins_path="" asset_path="share" executor="" -react_host=`hostname -I` - # Parse args for arg in "$@" do @@ -65,9 +63,12 @@ if [[ $on_device == 1 ]]; then # adb reverse --no-rebind tcp:8081 tcp:808 # Run app on device + react_host=`hostname -I` + adb shell "cd $app_path && REACT_SERVER_HOST=$react_host ./@APP_NAME@ --host $react_host $args -- --desktop_file_hint=/usr/share/applications/webbrowser-app.desktop" else # Run app locally - @CMAKE_BINARY_DIR@/bin/@APP_NAME@ $args + # Note: Needed to add QT_XCB_GL_INTEGRATION=none when migrating to Nix, since running the app in debug mode inside Nix shell was failing at run time with "qt.glx: qglx_findConfig: Failed to finding matching FBConfig (1 1 1 0)\nCould not initialize GLX" + QT_XCB_GL_INTEGRATION=none @CMAKE_BINARY_DIR@/bin/@APP_NAME@ $args fi diff --git a/desktop_files/package.json.orig b/desktop_files/package.json.orig index e2fef18c23..2101d81924 100644 --- a/desktop_files/package.json.orig +++ b/desktop_files/package.json.orig @@ -81,7 +81,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#v.3.0.0-3-status", "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", diff --git a/desktop_files/yarn.lock b/desktop_files/yarn.lock index 88e22d2354..dc06021f5f 100644 --- a/desktop_files/yarn.lock +++ b/desktop_files/yarn.lock @@ -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#v.3.0.0-3-status": 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#25a76813def48ba9bf0fd1b3dd1e915d002b55dd" "react-native-languages@git+https://github.com/status-im/react-native-languages.git#v0.1.1-status": version "3.0.2" diff --git a/modules/react-native-desktop-notification/desktop/CMakeLists.txt b/modules/react-native-desktop-notification/desktop/CMakeLists.txt index 58c6299f9a..770f666a54 100755 --- a/modules/react-native-desktop-notification/desktop/CMakeLists.txt +++ b/modules/react-native-desktop-notification/desktop/CMakeLists.txt @@ -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}" @@ -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}" diff --git a/modules/react-native-status/desktop/build-status-go.sh b/modules/react-native-status/desktop/build-status-go.sh index 9fd826d267..6e63e205a9 100755 --- a/modules/react-native-status/desktop/build-status-go.sh +++ b/modules/react-native-status/desktop/build-status-go.sh @@ -7,11 +7,11 @@ if [ "$1" = 'Windows' ]; then export GOOS=windows export GOARCH=amd64 export CGO_ENABLED=1 - export CC=$5 - export CC_FOR_TARGET=$5 - export CXX_FOR_TARGET=$6 fi - +export CC=$5 +export CC_FOR_TARGET=$5 +export CXX_FOR_TARGET=$6 + cd $4/lib go get ./ cd .. diff --git a/scripts/build-desktop.sh b/scripts/build-desktop.sh index 020e066b63..6b975411dc 100755 --- a/scripts/build-desktop.sh +++ b/scripts/build-desktop.sh @@ -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' \ @@ -76,20 +70,21 @@ 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" +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' -APPIMAGETOOLFNAME='appimagetool-x86_64_20190221.AppImage' -DEPLOYQT=$(joinPath . "$DEPLOYQTFNAME") -APPIMAGETOOL=$(joinPath . "$APPIMAGETOOLFNAME") STATUSIM_APPIMAGE_ARCHIVE="StatusImAppImage_20181208.zip" -APPIMAGE_OPTIONS="" -if [[ ! -c /dev/fuse ]]; then # doesn't exist when run under docker - # We extract it to avoid having to use fuse and privileged mode in docker - APPIMAGE_OPTIONS="--appimage-extract-and-run" -fi - function init() { if [ -z $STATUSREACTPATH ]; then echo "${RED}STATUSREACTPATH environment variable is not defined!${NC}" @@ -103,36 +98,14 @@ function init() { fi fi - if is_macos; then - if [ -z $MACDEPLOYQT ]; then - set +e - MACDEPLOYQT=$(which macdeployqt) - if [ -z $MACDEPLOYQT ]; then - echo "${RED}MACDEPLOYQT environment variable is not defined and macdeployqt executable not found in path!${NC}" - exit 1 - fi - set -e - fi - - DEPLOYQT="$MACDEPLOYQT" - elif is_linux; then + if is_linux; then rm -rf ./desktop/toolchain/ # TODO: Use Conan for Linux and MacOS builds too if is_windows_target; then - if ! program_exists 'python3'; then - echo "${RED}python3 prerequisite is missing. Exiting.${NC}" - exit 1 - fi - export PATH=$STATUSREACTPATH:$PATH if ! program_exists 'conan'; then - if ! program_exists 'pip3'; then - echo "${RED}pip3 package manager not found. Exiting.${NC}" - exit 1 - fi - - echo "${RED}Conan package manager not found. Installing...${NC}" - pip3 install conan==$(toolversion conan) + echo "${RED}Conan package manager not found. Exiting...${NC}" + exit 1 fi conan remote add --insert 0 -f status-im https://conan.status.im @@ -197,24 +170,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 } @@ -268,6 +230,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 @@ -292,24 +290,14 @@ 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 - fi - - if [ ! -f $APPIMAGETOOL ]; then - wget --output-document="$APPIMAGETOOL" --show-progress "https://desktop-app-files.ams3.digitaloceanspaces.com/$APPIMAGETOOLFNAME" # Versioned from https://github.com/AppImage/AppImageKit/releases/download/10/appimagetool-x86_64.AppImage - chmod a+x $APPIMAGETOOL - fi 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 @@ -317,7 +305,17 @@ function bundleLinux() { rm -f $usrBinPath/Status.AppImage popd - $DEPLOYQT $APPIMAGE_OPTIONS \ + # 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[@]})" \ + linuxdeployqt \ $desktopFilePath \ -verbose=$VERBOSE_LEVEL -always-overwrite -no-strip \ -no-translations -bundle-non-qt-libs \ @@ -330,7 +328,11 @@ function bundleLinux() { pushd $WORKFOLDER rm -f $usrBinPath/Status.AppImage - $APPIMAGETOOL $APPIMAGE_OPTIONS ./AppDir + appimagetool ./AppDir + if [ ${#unique_folders[@]} -gt 0 ]; then + # Ensure the AppImage isn't using the interpreter in Nix's store + patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 ./Status-x86_64.AppImage + fi [ $VERBOSE_LEVEL -ge 1 ] && ldd $usrBinPath/Status rm -rf Status.AppImage popd @@ -339,36 +341,191 @@ function bundleLinux() { echo "" } -function bundleMacOS() { - # download prepared package with mac bundle files (it contains qt libraries, icon) - echo "Downloading skeleton of mac bundle..." +if is_macos; then + function getQtFullOutPathFromNixStore() { + local qtFullDerivationPath=$(nix show-derivation -f $STATUSREACTPATH/default.nix | jq -r '.[] | .inputDrvs | 'keys' | .[]' | grep qt-full) + echo $(nix show-derivation $qtFullDerivationPath | jq -r '.[] | .outputs.out.path') + } + + 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 copyDylibNixDependenciesToPackage() { + local dylib="$1" + local contentsDir="$2" + local frameworksDir="$contentsDir/Frameworks" + local exeDir="$contentsDir/MacOS" + + # Walk through the dependencies of $dylib + local dependencies=$(otool -L "$dylib" | grep -E "\s+/nix/" | awk -F "(" '{print $1}' | xargs) + local moduleDirPath=$(basename $dylib) + for depDylib in $dependencies; do + local targetDepDylib=$(joinPath "$frameworksDir" "$(basename $depDylib)") + # Copy any dependencies that: are not in the Frameworks directory, do not already exist in /usr/lib and are not a Qt5 module (will be handled by macdeployqt anyway) + if [ ! -f "$targetDepDylib" ] && [[ "$(basename $targetDepDylib)" != "libQt5"* ]] && [ ! -f "/usr/lib/$(basename $depDylib)" ]; then + [ $VERBOSE_LEVEL -ge 1 ] && echo " Copying $depDylib to $frameworksDir..." + cp -a -L "$depDylib" "$frameworksDir" + chmod 0755 "$targetDepDylib" + + copyDylibNixDependenciesToPackage "$depDylib" "$contentsDir" + fi + done + } + + function copyQtPlugInToPackage() { + local qtPath="$1" + local pluginName="$2" + local contentsPath="$3" + local filter="" + local targetPath="$contentsPath/PlugIns" + local pluginTargetPath="$targetPath/$pluginName" + + [ "$pluginName" == 'platforms' ] && filter='libqcocoa.dylib' + + mkdir -p $pluginTargetPath + local qtLibPath=$(find $qtPath/lib -maxdepth 1 -name qt-*) + local srcPath=$(readlink -f "$qtLibPath/plugins/$pluginName") + echo "Copying $srcPath to $targetPath" + if [ -z "$filter" ]; then + cp -a -f -L "$srcPath" "$targetPath" + else + cp -f $(readlink -f "$srcPath/$filter") "$pluginTargetPath" + fi + chmod 755 $pluginTargetPath + chmod 755 $pluginTargetPath/* + + for dylib in `find $pluginTargetPath -name *.dylib`; do + copyDylibNixDependenciesToPackage "$dylib" "$contentsPath" + done + } + + function fixupRPathsInDylib() { + local dylib="$1" + local contentsDir="$2" + local frameworksDir="$contentsDir/Frameworks" + local exeDir="$contentsDir/MacOS" + + [ $VERBOSE_LEVEL -ge 1 ] && echo "Checking rpaths in ${dylib}" + + # Walk through the dependencies of $dylib + local dependencies=$(otool -L "$dylib" | grep -E "\s+/nix/" | sed "s|@executable_path|$exeDir|" | awk -F "(" '{print $1}' | xargs) + local moduleDirPath=$(dirname $dylib) + for depDylib in $dependencies; do + # Fix rpath and copy library to target + local replacementTargetPath="" + local framework=$(echo $depDylib | sed -E "s|^\/nix\/.+\/Library\/Frameworks\/(.+)\.framework\/\1$|\1|" 2> /dev/null) + if [ -n "$framework" ] && [ "$framework" != "$depDylib" ]; then + # Handle macOS framework + local targetDepDylib=$(joinExistingPath "/System/Library/Frameworks" "${framework}.framework/${framework}") + + if [ ! -f "$targetDepDylib" ]; then + echo -e "${RED}FATAL: system framework not found: ${targetDepDylib}${NC}" + exit 1 + fi + + # Change dependency rpath in $dylib to point to $targetDepDylib + replacementTargetPath=$targetDepDylib + else + # Handle other libraries + local targetDepDylib=$(joinPath "$frameworksDir" "$(basename $depDylib)") + + if [ ! -f "$targetDepDylib" ]; then + echo -e "${RED}FATAL: macdeployqt should have copied the dependency to ${targetDepDylib}${NC}" + exit 1 + fi + + # Change dependency rpath in $dylib to point to $replacementTargetPath + local replacementPath="" + local targetDepModuleDirPath=$(dirname $targetDepDylib) + if [[ $targetDepModuleDirPath -ef $moduleDirPath ]]; then + replacementPath="@loader_path" + else + replacementPath="@executable_path/$(realpath --relative-to="$exeDir" "$targetDepModuleDirPath")" + fi + local modulePathRegExp="($(pwd)/)?$moduleDirPath" + replacementTargetPath=$(echo $targetDepDylib | sed -E "s|$modulePathRegExp|$replacementPath|") + fi + + if [ -n "$replacementTargetPath" ]; then + [ $VERBOSE_LEVEL -ge 1 ] && echo "Updating $dylib to point to $replacementTargetPath" + install_name_tool -change "$depDylib" "$replacementTargetPath" "$dylib" + fi + done + } + + function fixupRemainingRPaths() { + local searchRootPath="$1" + local contentsDir="$2" + + for dylib in `find $searchRootPath -name *.dylib`; do + fixupRPathsInDylib "$dylib" "$contentsDir" + + # Sanity check for absolute paths + local dependencies=$(otool -L "$dylib" | grep -E "\s+${STATUSREACTPATH}") + if [ -n "$dependencies" ]; then + echo "Absolute path detected in dependencies of $dylib. Aborting..." + echo "${dependencies[@]}" + exit 1 + fi + done + } +fi + +function bundleMacOS() { pushd $WORKFOLDER + # download prepared package with mac bundle files (it contains qt libraries, icon) + echo "Downloading skeleton of mac bundle..." + rm -rf Status.app # TODO this needs to be fixed: status-react/issues/5378 [ -f ./Status.app.zip ] || curl -L -o Status.app.zip https://desktop-app-files.ams3.digitaloceanspaces.com/Status_20181113.app.zip 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' + local usrBinPath=$(joinExistingPath "$WORKFOLDER" "$contentsPath/MacOS") + + cp -r assets/share/assets $contentsPath/Resources + ln -sf ../Resources/assets ../Resources/ubuntu-server ../Resources/node_modules $usrBinPath + chmod +x $contentsPath/Resources/ubuntu-server + cp ../desktop/bin/Status $usrBinPath/Status + cp ../desktop/bin/reportApp $usrBinPath + cp ../.env $contentsPath/Resources + ln -sf ../Resources/.env $usrBinPath/.env + cp -f ../deployment/macos/qt-reportApp.conf $contentsPath/Resources + ln -sf ../Resources/qt-reportApp.conf $usrBinPath/qt.conf + cp -f ../deployment/macos/Info.plist $contentsPath + cp -f ../deployment/macos/status-icon.icns $contentsPath/Resources + + local qtbaseplugins=(bearer platforms printsupport styles) + local qtfullplugins=(iconengines imageformats webview) + 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) + local qtfullOutPath=$(getQtFullOutPathFromNixStore) + mkdir -p "$contentsPath/PlugIns" + for plugin in ${qtbaseplugins[@]}; do copyQtPlugInToPackage "$qtbaseBinPath" "$plugin" "$contentsPath"; done + for plugin in ${qtfullplugins[@]}; do copyQtPlugInToPackage "$qtfullOutPath" "$plugin" "$contentsPath"; done + fi + + macdeployqt Status.app \ + -verbose=$VERBOSE_LEVEL \ + -executable="$(joinExistingPath "$usrBinPath" 'reportApp')" \ + -qmldir="$(joinExistingPath "$STATUSREACTPATH" 'node_modules/react-native')" \ + -qmldir="$(joinExistingPath "$STATUSREACTPATH" 'desktop/reportApp')" + + # macdeployqt doesn't fix rpaths for all the libraries (although it copies them all), so we'll just walk through them and update rpaths to not point to /nix + echo "Fixing remaining rpaths in modules..." + fixupRemainingRPaths "$contentsPath/Frameworks" "$contentsPath" + fixupRemainingRPaths "$contentsPath/PlugIns" "$contentsPath" + echo "Done fixing rpaths in modules" rm -f Status.app.zip popd diff --git a/scripts/lib/setup/installers.sh b/scripts/lib/setup/installers.sh index 9650a17c36..4fc4b1d128 100755 --- a/scripts/lib/setup/installers.sh +++ b/scripts/lib/setup/installers.sh @@ -38,17 +38,6 @@ function install_nix() { fi } -function install_nsis() { - ! is_linux && return 0 - - # NSIS (Nullsoft Scriptable Install System) is a professional open source system to create Windows installers. It is designed to be as small and flexible as possible and is therefore very suitable for internet distribution. - if program_exists "apt"; then - apt_install "nsis" - else - echo "nsis is not supported in this Linux distro. Generating Windows setup executables will not be possible" - fi -} - function install_android_sdk() { if [ -d "$ANDROID_SDK_ROOT" ]; then cecho "@green[[Android SDK already installed.]]" diff --git a/scripts/lib/setup/nix/desktop/appimagekit/default.nix b/scripts/lib/setup/nix/desktop/appimagekit/default.nix new file mode 100644 index 0000000000..b8cc0184db --- /dev/null +++ b/scripts/lib/setup/nix/desktop/appimagekit/default.nix @@ -0,0 +1,117 @@ +{ stdenv, fetchFromGitHub +, pkgconfig, cmake, autoconf, automake, libtool +, wget, xxd, desktop-file-utils, file +, glib, zlib, cairo, openssl, fuse, xz, squashfuse, inotify-tools, libarchive +, squashfsTools +, gtest +}: + +let + + appimagekit_src = fetchFromGitHub { + owner = "AppImage"; + repo = "AppImageKit"; + rev = "b0859501df61cde198b54a317c03b41dbafc98b1"; + sha256 = "0qqg79jw9w9rs8c2w3lla4kz62ihafrf7jm370pp1dl8y2i81jzg"; + }; + + # squashfuse adapted to nix from cmake experession in "${appimagekit_src}/cmake/dependencies.cmake" + appimagekit_squashfuse = squashfuse.overrideAttrs (attrs: rec { + name = "squashfuse-${version}"; + version = "20161009"; + + src = fetchFromGitHub { + owner = "vasi"; + repo = "squashfuse"; + rev = "1f980303b89c779eabfd0a0fdd36d6a7a311bf92"; + sha256 = "0lrw9ff8k15l34wjwyllw3i35hl0cms97jj2hpnr2q8ipgxpb5q5"; + }; + + patches = [ + "${appimagekit_src}/squashfuse.patch" + "${appimagekit_src}/squashfuse_dlopen.patch" + ]; + + postPatch = '' + cp -v ${appimagekit_src}/squashfuse_dlopen.[hc] . + ''; + + preConfigure = '' + sed -i "/PKG_CHECK_MODULES.*/,/,:./d" configure + sed -i "s/typedef off_t sqfs_off_t/typedef int64_t sqfs_off_t/g" common.h + ''; + + configureFlags = [ + "--disable-demo" "--disable-high-level" "--without-lzo" "--without-lz4" + ]; + + postConfigure = '' + sed -i "s|XZ_LIBS = -llzma |XZ_LIBS = -Bstatic -llzma/|g" Makefile + ''; + + # only static libs and header files + installPhase = '' + mkdir -p $out/lib $out/include + cp -v ./.libs/*.a $out/lib + cp -v ./*.h $out/include + ''; + }); + +in stdenv.mkDerivation rec { + name = "appimagekit-20180727"; + + src = appimagekit_src; + + patches = [ ./nix.patch ]; + + nativeBuildInputs = [ + pkgconfig cmake autoconf automake libtool wget xxd + desktop-file-utils + ]; + + buildInputs = [ + glib zlib cairo openssl fuse + xz inotify-tools libarchive + squashfsTools + ]; + + preConfigure = '' + export HOME=$(pwd) + ''; + + cmakeFlags = [ + "-DUSE_SYSTEM_XZ=ON" + "-DUSE_SYSTEM_SQUASHFUSE=ON" + "-DSQUASHFUSE=${appimagekit_squashfuse}" + "-DUSE_SYSTEM_INOTIFY_TOOLS=ON" + "-DUSE_SYSTEM_LIBARCHIVE=ON" + "-DUSE_SYSTEM_GTEST=ON" + "-DUSE_SYSTEM_MKSQUASHFS=ON" + "-DBUILD_TESTING=${if doCheck then "ON" else "OFF"}" + ]; + + postInstall = '' + cp "${stdenv.lib.makeBinPath [ squashfsTools ]}/mksquashfs" "$out/lib/appimagekit/" + cp "${stdenv.lib.makeBinPath [ desktop-file-utils ]}/desktop-file-validate" "$out/bin" + ''; + + checkInputs = [ gtest ]; + doCheck = false; # fails 1 out of 4 tests, I'm too lazy to debug why + + # for debugging + passthru = { + squashfuse = appimagekit_squashfuse; + }; + + meta = with stdenv.lib; { + description = "A tool to package desktop applications as AppImages"; + longDescription = '' + AppImageKit is an implementation of the AppImage format that + provides tools such as appimagetool and appimaged for handling + AppImages. + ''; + license = licenses.mit; + homepage = src.meta.homepage; + platforms = platforms.linux; + }; +} diff --git a/scripts/lib/setup/nix/desktop/appimagekit/nix.patch b/scripts/lib/setup/nix/desktop/appimagekit/nix.patch new file mode 100644 index 0000000000..4162e698c7 --- /dev/null +++ b/scripts/lib/setup/nix/desktop/appimagekit/nix.patch @@ -0,0 +1,197 @@ +diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake +index ea133a3..916606c 100644 +--- a/cmake/dependencies.cmake ++++ b/cmake/dependencies.cmake +@@ -224,21 +224,23 @@ if(NOT USE_SYSTEM_XZ) + LIBRARY_DIRS /lib/ + LIBRARIES "/lib/liblzma.a" + INCLUDE_DIRS "/src/liblzma/api/" + ) + else() + message(STATUS "Using system xz") + + import_pkgconfig_target(TARGET_NAME xz PKGCONFIG_TARGET liblzma STATIC) + endif() + ++set(USE_SYSTEM_SQUASHFUSE OFF CACHE BOOL "Use system squashfuse instead of building our own") + ++if(NOT USE_SYSTEM_SQUASHFUSE) + # as distros don't provide suitable squashfuse and squashfs-tools, those dependencies are bundled in, can, and should + # be used from this repository + # TODO: implement out-of-source builds for squashfuse, as for the other dependencies + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/patch-squashfuse.sh.in + ${CMAKE_CURRENT_BINARY_DIR}/patch-squashfuse.sh + @ONLY + ) + + ExternalProject_Add(squashfuse-EXTERNAL +@@ -259,20 +261,34 @@ ExternalProject_Add(squashfuse-EXTERNAL + BUILD_IN_SOURCE ON + INSTALL_COMMAND ${MAKE} install + ) + + import_external_project( + TARGET_NAME squashfuse + EXT_PROJECT_NAME squashfuse-EXTERNAL + LIBRARIES "/.libs/libsquashfuse.a;/.libs/libsquashfuse_ll.a;/.libs/libfuseprivate.a" + INCLUDE_DIRS "" + ) ++else() ++ message(STATUS "Using system squashfsfuse from ${SQUASHFUSE}") ++ ++ add_library(squashfuse INTERFACE IMPORTED GLOBAL) ++ ++ set(squashfuse_INCLUDE_DIRS "${SQUASHFUSE}/include") ++ set(squashfuse_LIBRARIES "${SQUASHFUSE}/lib/libsquashfuse.a;${SQUASHFUSE}/lib/libsquashfuse_ll.a;${SQUASHFUSE}/lib/libfuseprivate.a") ++ ++ set_property( ++ TARGET squashfuse ++ PROPERTY INTERFACE_LINK_LIBRARIES ${squashfuse_LIBRARIES} ++ ) ++ include_directories(${squashfuse_INCLUDE_DIRS}) ++endif() + + + set(USE_SYSTEM_INOTIFY_TOOLS OFF CACHE BOOL "Use system libinotifytools instead of building our own") + + if(NOT USE_SYSTEM_INOTIFY_TOOLS) + message(STATUS "Downloading and building inotify-tools") + + # TODO: build out of source + ExternalProject_Add(inotify-tools-EXTERNAL + URL https://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz +@@ -345,20 +361,23 @@ if(NOT USE_SYSTEM_GTEST) + INCLUDE_DIRS "/include/" + ) + else() + message(STATUS "Using system GTest") + + import_find_pkg_target(gtest GTest GTEST) + endif() + endif() + + ++set(USE_SYSTEM_MKSQUASHFS OFF CACHE BOOL "Use system mksquashfs instead of downloading and building our own") ++ ++if(NOT USE_SYSTEM_MKSQUASHFS) + # TODO: allow using system wide mksquashfs + set(mksquashfs_cflags "-DXZ_SUPPORT ${CFLAGS}") + + if(xz_LIBRARIES MATCHES "\\.a$") + set(mksquashfs_ldflags "${xz_LIBRARIES}") + else() + set(mksquashfs_ldflags "-l${xz_LIBRARIES}") + endif() + + if(xz_INCLUDE_DIRS) +@@ -385,20 +404,25 @@ ExternalProject_Add(mksquashfs + INSTALL_COMMAND ${MAKE} -C squashfs-tools/ install INSTALL_DIR= + ) + + ExternalProject_Get_Property(mksquashfs INSTALL_DIR) + set(mksquashfs_INSTALL_DIR "${INSTALL_DIR}") + mark_as_advanced(mksquashfs_INSTALL_DIR) + + # for later use when packaging as an AppImage + set(mksquashfs_BINARY "${mksquashfs_INSTALL_DIR}/mksquashfs") + mark_as_advanced(mksquashfs_BINARY) ++else() ++ message(STATUS "Using system mksquashfs") ++ ++ set(mksquashfs_BINARY "mksquashfs") ++endif() + + + #### build dependency configuration #### + + # only have to build custom xz when not using system libxz + if(TARGET xz-EXTERNAL) + if(TARGET squashfuse-EXTERNAL) + ExternalProject_Add_StepDependencies(squashfuse-EXTERNAL configure xz-EXTERNAL) + endif() + if(TARGET mksquashfs) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 3f25442..974ed0e 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -197,27 +197,27 @@ target_include_directories(digest_md5 + + target_link_libraries(digest_md5 + PRIVATE + libglib + ) + + + # install binaries + if(AUXILIARY_FILES_DESTINATION) + install( +- PROGRAMS ${mksquashfs_INSTALL_DIR}/mksquashfs ${CMAKE_CURRENT_BINARY_DIR}/runtime ++ PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/runtime + DESTINATION ${AUXILIARY_FILES_DESTINATION} + COMPONENT applications + ) + else() + install( +- PROGRAMS ${mksquashfs_INSTALL_DIR}/mksquashfs ${CMAKE_CURRENT_BINARY_DIR}/runtime ++ PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/runtime + DESTINATION bin + COMPONENT applications + ) + endif() + + install( + TARGETS AppRun appimagetool digest validate + RUNTIME DESTINATION bin COMPONENT applications + LIBRARY DESTINATION lib COMPONENT applications + ARCHIVE DESTINATION lib/static COMPONENT applications +diff --git a/src/shared.c b/src/shared.c +index cf5fd5c..4f48dbc 100644 +--- a/src/shared.c ++++ b/src/shared.c +@@ -34,21 +34,21 @@ + #include + #include + #include + #include + + #include + #include + #include + #include + +-#include "squashfuse.h" ++#include + #include + #include "getsection.h" + #include "elf.h" + + #include "xdg-basedir.h" + + // own header + #include "shared.h" + + #if HAVE_LIBARCHIVE3 == 1 // CentOS +diff --git a/src/appimagetool.c b/src/appimagetool.c +index 69beaa1..c55d6b1 100644 +--- a/src/appimagetool.c ++++ b/src/appimagetool.c +@@ -200,9 +200,6 @@ int sfs_mksquashfs(char *source, char *destination, int offset) { + args[i++] = exclude_file; + } + +- args[i++] = "-mkfs-fixed-time"; +- args[i++] = "0"; +- + args[i++] = 0; + + if (verbose) { +@@ -348,7 +345,7 @@ void extract_arch_from_text(gchar *archname, const gchar* sourcename, bool* arch + void guess_arch_of_file(const gchar *archfile, bool* archs) { + char line[PATH_MAX]; + char command[PATH_MAX]; +- sprintf(command, "/usr/bin/file -L -N -b %s", archfile); ++ sprintf(command, "file -L -N -b %s", archfile); + FILE* fp = popen(command, "r"); + if (fp == NULL) + die("Failed to run file command"); diff --git a/scripts/lib/setup/nix/desktop/default.nix b/scripts/lib/setup/nix/desktop/default.nix new file mode 100644 index 0000000000..7d344f5ae2 --- /dev/null +++ b/scripts/lib/setup/nix/desktop/default.nix @@ -0,0 +1,26 @@ +{ stdenv, pkgs }: + +with pkgs; +with stdenv; + +let + windowsPlatform = callPackage ./windows { }; + appimagekit = callPackage ./appimagekit { }; + linuxdeployqt = callPackage ./linuxdeployqt { inherit appimagekit; }; + +in + { + buildInputs = [ + cmake + extra-cmake-modules + file + gnupg # Used by appimagetool + go + qt5.full + ] ++ lib.optional isLinux [ appimagekit linuxdeployqt patchelf ] + ++ lib.optional isLinux windowsPlatform.buildInputs; + shellHook = '' + export QT_PATH="${qt5.full}" + export PATH="${stdenv.lib.makeBinPath [ qt5.full ]}:$PATH" + ''; + } diff --git a/scripts/lib/setup/nix/desktop/linuxdeployqt/default.nix b/scripts/lib/setup/nix/desktop/linuxdeployqt/default.nix new file mode 100644 index 0000000000..7662f17202 --- /dev/null +++ b/scripts/lib/setup/nix/desktop/linuxdeployqt/default.nix @@ -0,0 +1,43 @@ +{ pkgs, stdenv, fetchFromGitHub, appimagekit }: + +with pkgs; + +stdenv.mkDerivation rec { + name = "linuxdeployqt"; + version = "20181215"; + + src = + if stdenv.hostPlatform.system == "x86_64-linux" then + fetchFromGitHub { + owner = "probonopd"; + repo = "linuxdeployqt"; + rev = "600fc20ea73ee937a402a2bb6b3663d93fcc1d4b"; + sha256 = "05kvkfbhsyadlcggl63rhrw5s36d8qxs8gyihrjn2cjk42xx8r7j"; + } + else throw "${name} is not supported on ${stdenv.hostPlatform.system}"; + + buildInputs = [ qt5.qtbase appimagekit ]; + nativeBuildInputs = [ wget ]; + + buildPhase = '' + qmake + make + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp -r bin/linuxdeployqt $out/bin/ + + runHook postInstall + ''; + + meta = { + description = "Makes Linux applications self-contained by copying in the libraries and plugins that the application uses, and optionally generates an AppImage. Can be used for Qt and other applications"; + homepage = https://github.com/probonopd/linuxdeployqt/; + license = stdenv.lib.licenses.gpl3; + maintainers = [ stdenv.lib.maintainers.pombeirp ]; + platforms = stdenv.lib.platforms.linux; + }; +} diff --git a/scripts/lib/setup/nix/desktop/windows/default.nix b/scripts/lib/setup/nix/desktop/windows/default.nix new file mode 100644 index 0000000000..ea9cdba738 --- /dev/null +++ b/scripts/lib/setup/nix/desktop/windows/default.nix @@ -0,0 +1,8 @@ +{ stdenv, pkgs }: + +with pkgs; +with stdenv; + +{ + buildInputs = lib.optional isLinux [ conan nsis ]; +} diff --git a/scripts/lib/setup/packages.sh b/scripts/lib/setup/packages.sh index ec77820a7a..f49e0a53d5 100755 --- a/scripts/lib/setup/packages.sh +++ b/scripts/lib/setup/packages.sh @@ -29,79 +29,3 @@ function program_version_exists() { function toolversion() { ${GIT_ROOT}/scripts/toolversion "${1}" } - -############### -# Linux -############### - -# FIXME This command assumes that package names in different package managers (apt, pacman) are same. -# At this moment, it works as expected because we only call it for installing maven and nodejs. -# If this list grows, please consider adding some sort of mapping mechanism. -function linux_install() { - ! is_linux && return 0 - - if program_exists "apt"; then - apt_install "$@" - elif program_exists "pacman"; then - pacman_install "$@" - else - echo "Unsupported Linux distro." - exit 1; - fi -} - - -############### -# Aptitude -############### - -function apt_update() { - sudo apt update -} - -function apt_is_installed() { - local package=$1 - - dpkg -s "$package" >/dev/null 2>&1 -} - -function apt_install() { - local package=$1 - - if apt_is_installed "$package"; then - cecho "+ $package already installed... skipping." - else - sudo apt install -y "$package" || exit 1 - fi -} - -############### -# Pacman -############### - -function pacman_update() { - sudo pacman -Syu -} - -function pacman_is_installed() { - local package=$1 - pacman -Qs $package >/dev/null 2>&1 -} - -function pacman_install() { - local package=$1 - - if pacman_is_installed "$package"; then - cecho "+ $package already installed... skipping." - else - sudo pacman -S --noconfirm "$package" || exit 1 - fi -} - -############### -# RVM -############### - -function load_rvm_if_available() { - [ -f ~/.rvm/scripts/rvm ] && source ~/.rvm/scripts/rvm -} diff --git a/scripts/run-environment-check.sh b/scripts/run-environment-check.sh index c228a3d72f..97ac21f10b 100755 --- a/scripts/run-environment-check.sh +++ b/scripts/run-environment-check.sh @@ -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}********************************************************************************************" +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 "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 + echo -e "**********************************************************************************************${NC}" + exit 1 + fi fi if [[ $PLATFORM == 'android' ]]; then diff --git a/scripts/setup b/scripts/setup index 450983f84e..2b32515a53 100755 --- a/scripts/setup +++ b/scripts/setup @@ -20,8 +20,6 @@ source_lib "installers.sh" exit_unless_os_supported -load_rvm_if_available - #### setup_header "Checking prerequisites..." @@ -64,7 +62,6 @@ fi setup_header "Installing requirements..." install_nix && \ -install_nsis && \ install_android_sdk && \ install_android_ndk || \ exit $?