diff --git a/.envrc b/.envrc new file mode 100644 index 00000000000..14d7e94da69 --- /dev/null +++ b/.envrc @@ -0,0 +1,5 @@ +if ! has nix_direnv_version || ! nix_direnv_version 3.0.6; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.6/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM=" +fi + +use flake --impure diff --git a/AppRun b/AppRun index 87a2f47c8d1..573cde9aa93 100755 --- a/AppRun +++ b/AppRun @@ -2,14 +2,15 @@ APPDIR="$(dirname "$(readlink -f "${0}")")" export GST_PLUGIN_SCANNER="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner" export GST_PLUGIN_PATH="${APPDIR}/usr/lib/gstreamer-1.0" -export GST_PLUGIN_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0" -export GST_PLUGIN_SYSTEM_PATH="${APPDIR}/usr/lib/gstreamer-1.0" -export GST_PLUGIN_SYSTEM_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0" +export GST_PLUGIN_PATH_1_0="${GST_PLUGIN_PATH}" +export GST_PLUGIN_SYSTEM_PATH="${GST_PLUGIN_PATH}" +export GST_PLUGIN_SYSTEM_PATH_1_0="${GST_PLUGIN_PATH}" export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${APPDIR}/usr/lib/nss:${LD_LIBRARY_PATH}" export QT_QPA_PLATFORM="xcb" # TODO: Remove once qt 5.15.2 support is dropped # Fixing bug: https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1944468 export QTWEBENGINE_CHROMIUM_FLAGS="${QTWEBENGINE_CHROMIUM_FLAGS} --disable-seccomp-filter-sandbox" +export QTWEBENGINEPROCESS_PATH="${APPDIR}/usr/bin/QtWebEngineProcess" DEFAULT_LANG=en_US.UTF-8 if [[ "$LANG" == "C.UTF-8" ]] diff --git a/AppRun-cpp b/AppRun-cpp index 9b3a2c589ad..15d36b6b837 100755 --- a/AppRun-cpp +++ b/AppRun-cpp @@ -2,11 +2,15 @@ APPDIR="$(dirname "$(readlink -f "${0}")")" export GST_PLUGIN_SCANNER="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner" export GST_PLUGIN_PATH="${APPDIR}/usr/lib/gstreamer-1.0" -export GST_PLUGIN_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0" -export GST_PLUGIN_SYSTEM_PATH="${APPDIR}/usr/lib/gstreamer-1.0" -export GST_PLUGIN_SYSTEM_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0" -export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${LD_LIBRARY_PATH}" +export GST_PLUGIN_PATH_1_0="${GST_PLUGIN_PATH}" +export GST_PLUGIN_SYSTEM_PATH="${GST_PLUGIN_PATH}" +export GST_PLUGIN_SYSTEM_PATH_1_0="${GST_PLUGIN_PATH}" +export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${APPDIR}/usr/lib/nss:${LD_LIBRARY_PATH}" export QT_QPA_PLATFORM="xcb" +# TODO: Remove once qt 5.15.2 support is dropped +# Fixing bug: https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1944468 +export QTWEBENGINE_CHROMIUM_FLAGS="${QTWEBENGINE_CHROMIUM_FLAGS} --disable-seccomp-filter-sandbox" +export QTWEBENGINEPROCESS_PATH="${APPDIR}/usr/bin/QtWebEngineProcess" DEFAULT_LANG=en_US.UTF-8 if [[ "$LANG" == "C.UTF-8" ]] diff --git a/Makefile b/Makefile index 8f94537279d..6803074b18c 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system all \ nix-shell \ bottles \ + check-nix-shell \ check-qt-dir \ check-pkg-target-linux \ check-pkg-target-macos \ @@ -48,6 +49,31 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system run-storybook-tests \ update +# This is a code for automatic help generator. +# It supports ANSI colors and categories. +# To add new item into help output, simply add comments +# starting with '##'. To add category, use @category. +GREEN := $(shell echo "\e[32m") +WHITE := $(shell echo "\e[37m") +YELLOW := $(shell echo "\e[33m") +RESET := $(shell echo "\e[0m") +HELP_FUN = \ + %help; \ + while(<>) { push @{$$help{$$2 // 'options'}}, [$$1, $$3] if /^([a-zA-Z0-9\-]+)\s*:.*\#\#(?:@([a-zA-Z\-]+))?\s(.*)$$/ }; \ + print "Usage: make [target]\n\n"; \ + for (sort keys %help) { \ + print "${WHITE}$$_:${RESET}\n"; \ + for (@{$$help{$$_}}) { \ + $$sep = " " x (32 - length $$_->[0]); \ + print " ${YELLOW}$$_->[0]${RESET}$$sep${GREEN}$$_->[1]${RESET}\n"; \ + }; \ + print "\n"; \ + } + +help: SHELL := /bin/sh +help: ##@other Show this help + @perl -e '$(HELP_FUN)' $(MAKEFILE_LIST) + ifeq ($(NIM_PARAMS),) # "variables.mk" was not included, so we update the submodules. GIT_SUBMODULE_UPDATE := git submodule update --init --recursive @@ -65,9 +91,14 @@ else # "variables.mk" was included. Business as usual until the end of this file all: nim_status_client -nix-shell: export NIX_USER_CONF_FILES := $(PWD)/nix/nix.conf -nix-shell: - nix-shell +shell: export NIX_USER_CONF_FILES := $(shell pwd)/nix/nix.conf +shell: ##@prepare Enter into a pre-configured shell +shell: +ifndef IN_NIX_SHELL + nix develop --impure # nixGL needs currentTime +else + @echo "${YELLOW}Nix shell is already active$(RESET)" +endif # must be included after the default target -include $(BUILD_SYSTEM_DIR)/makefiles/targets.mk @@ -104,6 +135,13 @@ else RUN_TARGET := run-linux endif +check-nix-shell: +ifeq ($(detected_OS),Linux) + ifndef IN_NIX_SHELL + $(error Running outside of Nix shell is not supported) + endif +endif + check-qt-dir: ifeq ($(shell qmake -v 2>/dev/null),) $(error Cannot find your Qt5 installation. Please make sure to export correct Qt installation binaries path to PATH env) @@ -333,7 +371,7 @@ statusq-tests: run-statusq-tests: export QTWEBENGINE_CHROMIUM_FLAGS := "${QTWEBENGINE_CHROMIUM_FLAGS} --disable-seccomp-filter-sandbox" run-statusq-tests: statusq-tests echo -e "\033[92mRunning:\033[39m StatusQ Unit Tests" - ctest -V --test-dir $(STATUSQ_BUILD_PATH) ${ARGS} + cd $(STATUSQ_BUILD_PATH) && nixGL ctest -V ${ARGS} ## ## Storybook @@ -363,18 +401,21 @@ storybook-build: | storybook-configure --config $(COMMON_CMAKE_BUILD_TYPE) \ $(HANDLE_OUTPUT) +# This will fix the issue on Ubuntu: +# (nim_status_client:11556): GLib-GIO-ERROR **: 14:15:07.064: Settings schema 'org.gnome.settings-daemon.plugins.xsettings' does not contain a key named 'antialiasing' +run-storybook: export GDK_BACKEND := x11 run-storybook: storybook-build echo -e "\033[92mRunning:\033[39m Storybook" - $(STORYBOOK_BUILD_PATH)/bin/Storybook + nixGL $(STORYBOOK_BUILD_PATH)/bin/Storybook run-storybook-tests: storybook-build echo -e "\033[92mRunning:\033[39m Storybook Tests" - ctest -V --test-dir $(STORYBOOK_BUILD_PATH) -E PagesValidator + cd $(STORYBOOK_BUILD_PATH) && nixGL ctest -V -E PagesValidator # repeat because of https://bugreports.qt.io/browse/QTBUG-92236 (Qt < 5.15.4) run-storybook-pages-validator: storybook-build echo -e "\033[92mRunning:\033[39m Storybook Pages Validator" - ctest -V --test-dir $(STORYBOOK_BUILD_PATH) -R PagesValidator --repeat until-pass:3 + cd $(STORYBOOK_BUILD_PATH) && nixGL ctest -V -R PagesValidator --repeat until-pass:3 storybook-clean: echo -e "\033[92mCleaning:\033[39m Storybook" @@ -453,7 +494,7 @@ status-go-clean: rm -f $(STATUSGO) export STATUSKEYCARDGO := vendor/status-keycard-go/build/libkeycard/libkeycard.$(LIBSTATUS_EXT) -export STATUSKEYCARDGO_LIBDIR := "$(shell pwd)/$(shell dirname "$(STATUSKEYCARDGO)")" +export STATUSKEYCARDGO_LIBDIR := $(shell pwd)/$(shell dirname "$(STATUSKEYCARDGO)") status-keycard-go: $(STATUSKEYCARDGO) $(STATUSKEYCARDGO): | deps @@ -578,7 +619,7 @@ ifeq ($(detected_OS),Darwin) bin/nim_status_client endif -nim_status_client: force-rebuild-status-go $(NIM_STATUS_CLIENT) +nim_status_client: check-nix-shell force-rebuild-status-go $(NIM_STATUS_CLIENT) ifdef IN_NIX_SHELL APPIMAGE_TOOL := appimagetool @@ -825,15 +866,21 @@ ICON_TOOL := node_modules/.bin/fileicon # STATUS_PORT ?= 30306 # WAKUV2_PORT ?= 30307 +# This will fix the issue on Ubuntu: +# (nim_status_client:11556): GLib-GIO-ERROR **: 14:15:07.064: Settings schema 'org.gnome.settings-daemon.plugins.xsettings' does not contain a key named 'antialiasing' +run-linux: export GDK_BACKEND := x11 +run-linux: export LD_LIBRARY_PATH := $(QT5_LIBDIR):$(STATUSGO_LIBDIR):$(STATUSKEYCARDGO_LIBDIR):$(LD_LIBRARY_PATH) run-linux: nim_status_client echo -e "\033[92mRunning:\033[39m bin/nim_status_client" - LD_LIBRARY_PATH="$(QT5_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR):$(LD_LIBRARY_PATH)" \ - ./bin/nim_status_client $(ARGS) + nixGL ./bin/nim_status_client $(ARGS) +# This will fix the issue on Ubuntu: +# (nim_status_client:11556): GLib-GIO-ERROR **: 14:15:07.064: Settings schema 'org.gnome.settings-daemon.plugins.xsettings' does not contain a key named 'antialiasing' +run-linux: export GDK_BACKEND := x11 +run-linux-gdb: export LD_LIBRARY_PATH := $(QT5_LIBDIR):$(STATUSGO_LIBDIR):$(STATUSKEYCARDGO_LIBDIR):$(LD_LIBRARY_PATH) run-linux-gdb: nim_status_client echo -e "\033[92mRunning:\033[39m bin/nim_status_client" - LD_LIBRARY_PATH="$(QT5_LIBDIR)":"$(STATUSGO_LIBDIR)":"$(STATUSKEYCARDGO_LIBDIR):$(LD_LIBRARY_PATH)" \ - gdb -ex=r ./bin/nim_status_client $(ARGS) + nixGL gdb -ex=r ./bin/nim_status_client $(ARGS) run-macos: nim_status_client mkdir -p bin/StatusDev.app/Contents/{MacOS,Resources} diff --git a/ci/Jenkinsfile.linux b/ci/Jenkinsfile.linux index 26dc7571951..76c250daa25 100644 --- a/ci/Jenkinsfile.linux +++ b/ci/Jenkinsfile.linux @@ -6,15 +6,7 @@ def isPRBuild = utils.isPRBuild() def isNightlyBuild = utils.isNightlyBuild() pipeline { - agent { - /* Necessary image with Ubuntu 20.04 for older Glibc. */ - docker { - label 'linux' - image 'statusteam/nim-status-client-build:1.5.0-qt5.15.2' - /* allows jenkins use cat and mounts '/dev/fuse' for linuxdeployqt */ - args '--entrypoint="" --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse' - } - } + agent { label 'linux && x86_64 && nix-2.19' } parameters { booleanParam( @@ -77,21 +69,22 @@ pipeline { stages { stage('Deps') { - steps { - sh 'make update' - sh 'make deps' - } + steps { script { + nix.shell('make update', pure: true) + nix.shell('make deps', pure: true) + } } } stage('status-go') { - steps { - sh 'make status-go' - } + steps { script { + nix.shell('make status-go', pure: true) + } } } stage('Package') { steps { script { - linux.bundle('tgz-linux') + //linux.bundle('tgz-linux', nixShell=true) + linux.bundle('tgz-linux', 0, true) } } } diff --git a/ci/Jenkinsfile.linux-nix b/ci/Jenkinsfile.linux-nix deleted file mode 100644 index 93530de41b9..00000000000 --- a/ci/Jenkinsfile.linux-nix +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env groovy -library 'status-jenkins-lib@v1.9.7' - -/* Options section can't access functions in objects. */ -def isPRBuild = utils.isPRBuild() -def isNightlyBuild = utils.isNightlyBuild() - -pipeline { - agent { label 'linux && x86_64 && nix-2.14' } - - parameters { - booleanParam( - name: 'RELEASE', - description: 'Decides whether release credentials are used.', - defaultValue: params.RELEASE ?: false - ) - booleanParam( - name: 'INCLUDE_DEBUG_SYMBOLS', - description: 'Decides whether binaries are built with debug symbols.', - defaultValue: params.INCLUDE_DEBUG_SYMBOLS ?: false - ) - choice( - name: 'VERBOSE', - description: 'Level of verbosity based on nimbus-build-system setup.', - choices: ['0', '1', '2'] - ) - string( - name: 'NIMFLAGS', - description: 'Extra Nim flags. Examples: --verbosity:2 --passL:"-v" --passC:"-v"', - defaultValue: '--colors:off' - ) - booleanParam( - name: 'USE_MOCKED_KEYCARD_LIB', - description: 'Decides whether the mocked status-keycard-go library is built.', - defaultValue: false - ) - } - - options { - timestamps() - /* Prevent Jenkins jobs from running forever */ - timeout(time: 25, unit: 'MINUTES') - /* manage how many builds we keep */ - buildDiscarder(logRotator( - numToKeepStr: '10', - daysToKeepStr: '30', - artifactNumToKeepStr: '1', - )) - /* Allows combined build to copy */ - copyArtifactPermission('/status-desktop/*') - /* Abort old PR builds. */ - disableConcurrentBuilds( - abortPrevious: isPRBuild - ) - } - - environment { - PLATFORM = "linux-nix/${getArch()}" - /* Improve make performance */ - MAKEFLAGS = "-j4 V=${params.VERBOSE}" - /* Avoid weird bugs caused by stale cache. */ - QML_DISABLE_DISK_CACHE = "true" - /* Control output the filename */ - STATUS_CLIENT_APPIMAGE = "pkg/${utils.pkgFilename(ext: 'nix.AppImage', arch: getArch())}" - STATUS_CLIENT_TARBALL = "pkg/${utils.pkgFilename(ext: 'nix.tar.gz', arch: getArch())}" - /* prevent sharing cache dir across different jobs */ - GO_GENERATE_FAST_DIR = "${env.WORKSPACE_TMP}/go-generate-fast" - } - - stages { - stage('Deps') { - steps { script { - nix.shell('make update', pure: true) - nix.shell('make deps', pure: true) - } } - } - - stage('status-go') { - steps { script { - nix.shell('make status-go', pure: true) - } } - } - - stage('Package') { - steps { script { - linux.bundle('tgz-linux', 0, true) - } } - } - - stage('Parallel Upload') { - parallel { - stage('Upload') { - steps { script { - env.PKG_URL = s3.uploadArtifact(env.STATUS_CLIENT_TARBALL) - jenkins.setBuildDesc(AppImage: env.PKG_URL) - } } - } - stage('Archive') { - steps { script { - archiveArtifacts("${env.STATUS_CLIENT_TARBALL}*") - } } - } - } - } - } - - post { - success { script { github.notifyPR(true) } } - failure { script { github.notifyPR(false) } } - cleanup { sh './scripts/clean-git.sh' } - } -} - -def getArch() { - def tokens = Thread.currentThread().getName().split('/') - for (def arch in ['x86_64', 'aarch64']) { - if (tokens.contains(arch)) { return arch } - } -} diff --git a/ci/Jenkinsfile.tests-ui b/ci/Jenkinsfile.tests-ui index d84473c96b2..dd6f14bcc7b 100644 --- a/ci/Jenkinsfile.tests-ui +++ b/ci/Jenkinsfile.tests-ui @@ -5,9 +5,7 @@ library 'status-jenkins-lib@v1.9.7' def isPRBuild = utils.isPRBuild() pipeline { - agent { - label 'linux && x86_64 && qt-5.15.2' - } + agent { label 'linux && x86_64 && nix-2.19' } parameters { choice( @@ -37,28 +35,26 @@ pipeline { PLATFORM = 'tests/ui' /* Improve make performance */ MAKEFLAGS = "-j4 V=${params.VERBOSE}" - /* Makefile assumes the compiler folder is included */ - QTDIR = "/opt/qt/5.15.2/gcc_64" PATH = "${env.QTDIR}/bin:${env.PATH}" } stages { stage('Build StatusQ Tests') { - steps { - sh 'make statusq-tests' - } + steps { script { + nix.shell('make statusq-tests', pure: true) + } } } stage('Build StatusQ Sanity Checker') { - steps { - sh 'make statusq-sanity-checker' - } + steps { script { + nix.shell('make statusq-sanity-checker', pure: true) + } } } stage('Build Storybook') { - steps { - sh 'make storybook-build' - } + steps { script { + nix.shell('make storybook-build', pure: true) + } } } stage('Check StatusQ Tests') { @@ -70,7 +66,7 @@ pipeline { parallelBuild: true, screen: '2560x1440x24', ]) { - sh('make run-statusq-tests') + nix.shell('make run-statusq-tests', pure: true) } } } } @@ -84,7 +80,7 @@ pipeline { parallelBuild: true, screen: '2560x1440x24', ]) { - sh('make run-statusq-sanity-checker') + nix.shell('make run-statusq-sanity-checker', pure: true) } } } } @@ -98,7 +94,7 @@ pipeline { parallelBuild: true, screen: '2560x1440x24', ]) { - sh('make run-storybook-tests') + nix.shell('make run-storybook-tests', pure: true) } } } } @@ -112,7 +108,7 @@ pipeline { parallelBuild: true, screen: '2560x1440x24', ]) { - sh('make run-storybook-pages-validator') + nix.shell('make run-storybook-pages-validator', pure: true) } } } } diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000000..610c444a108 --- /dev/null +++ b/flake.lock @@ -0,0 +1,80 @@ +{ + "nodes": { + "flake-compat": { + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "revCount": 57, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixgl": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1672992692, + "narHash": "sha256-/eLQLSNIa22ARTZbk+x8i0iE8khe1eiHWkuxgTVXZ7g=", + "owner": "nix-community", + "repo": "nixGL", + "rev": "643e730efb981ffaf8478f441ec9b9aeea1c89f5", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixGL", + "rev": "643e730efb981ffaf8478f441ec9b9aeea1c89f5", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1651477912, + "narHash": "sha256-YDFgJElf0ZL977+fo6ueQAmpb6lwrw1lzDlxLEINVXE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "66b0db71f463164486a36dded50bedee185e45c2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-20.09", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "nixgl": "nixgl", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000000..c9d23e9aadb --- /dev/null +++ b/flake.nix @@ -0,0 +1,24 @@ +{ + description = "Status Desktop"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-20.09"; + # for nix-shell support + inputs.flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"; + + # pinned last commit which works with nixpkgs 20.09 + inputs.nixgl = { + inputs.nixpkgs.follows = "nixpkgs"; + url = "github:nix-community/nixGL/643e730efb981ffaf8478f441ec9b9aeea1c89f5"; + }; + + outputs = { self, nixpkgs, nixgl, flake-compat }: + let + flake = import "${self}/flake.nix"; + pkgs = import nixpkgs { + system = "x86_64-linux"; + overlays = [ (import ./nix/overlay.nix) nixgl.overlay ]; + }; + in { + devShells.x86_64-linux.default = pkgs.callPackage ./nix/shell.nix { inherit flake; }; + }; +} diff --git a/nix/pkgs.nix b/nix/pkgs.nix deleted file mode 100644 index 68786b857ba..00000000000 --- a/nix/pkgs.nix +++ /dev/null @@ -1,18 +0,0 @@ -# This file controls the pinned version of nixpkgs we use for our Nix environment -# as well as which versions of package we use, including their overrides. -let - # For testing local version of nixpkgs - #nixpkgsSrc = (import { }).lib.cleanSource "/home/jakubgs/work/nixpkgs"; - - # We follow the release-20.09 branch of official nixpkgs. - nixpkgsSrc = builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/66b0db71f463164486a36dded50bedee185e45c2.tar.gz"; - sha256 = "sha256:0wam1m12qw9rrijhvbvhm5psj2a0ksms77xzxzyr5laz94j60cb0"; - }; - - # Override some packages and utilities - pkgsOverlay = import ./overlay.nix; -in - (import nixpkgsSrc) { - overlays = [ pkgsOverlay ]; - } diff --git a/nix/scripts/lib.sh b/nix/scripts/lib.sh new file mode 100755 index 00000000000..74a550f3fc7 --- /dev/null +++ b/nix/scripts/lib.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -eo pipefail +GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel) + +# Checking group ownership to identify installation type. +file_group() { + UNAME=$(uname -s) + if [[ "${UNAME}" == "Linux" ]]; then + stat -Lc "%G" "${1}" 2>/dev/null + elif [[ "${UNAME}" == "Darwin" ]]; then + # Avoid using Nix GNU stat when in Nix shell. + /usr/bin/stat -Lf "%Sg" "${1}" 2>/dev/null + fi +} + +os_name() { + source /etc/os-release 2>/dev/null + echo "${NAME}" +} + +is_arch_linux() { + [[ -f /etc/arch-release ]] +} + +nix_install_type() { + NIX_STORE_DIR_GROUP=$(file_group /nix/store) + if [[ "$(os_name)" =~ NixOS ]]; then + echo "nixos" + else + case "${NIX_STORE_DIR_GROUP}" in + "nixbld") echo "multi";; + "30000") echo "multi";; + "(30000)") echo "multi";; + "wheel") echo "single";; + "users") echo "single";; + "${USER}") echo "single";; + "${UID}") echo "single";; + "(${UID})") echo "single";; + "") echo "none"; + echo "No Nix installtion detected!" >&2;; + *) echo "Unknown Nix installtion type!" >&2; exit 1;; + esac + fi +} + +nix_root() { + NIX_ROOT="/nix" + if [[ $(uname -s) == "Darwin" ]]; then + # Special case due to read-only root on MacOS Catalina + NIX_ROOT="/opt/nix" + fi + echo "${NIX_ROOT}" +} + +nix_current_version() { + nix-env --version | awk '{print $3}' +} + +nix_get_local_setting() { + local NIX_LOCAL_CONFIG="${GIT_ROOT}/nix/nix.conf" + local KEY="${1}" + awk -F' = ' "/^${KEY} *=/{print \$2}" nix/nix.conf +} + +nix_set_global_setting() { + local NIX_GLOBAL_CONFIG="/etc/nix/nix.conf" + local KEY="${1}" + local VAL="${2}" + if grep "${KEY}" "${NIX_GLOBAL_CONFIG}" 2>/dev/null; then + sed -i "s/${KEY} = \(.*\)$/${KEY} = ${VAL}/" "${NIX_GLOBAL_CONFIG}" + else + echo "${KEY} = ${VAL}" | sudo tee -a "${NIX_GLOBAL_CONFIG}" >/dev/null + fi +} + +nix_daemon_restart() { + # Restarting Nix Daemon makes sense only on a multi-user install. + [[ $(nix_install_type) != "multi" ]] && return + if [[ "$(uname -s)" == "Darwin" ]]; then + echo "Restarting Nix daemon Launchd service..." >&2 + sudo launchctl unload /Library/LaunchDaemons/org.nixos.nix-daemon.plist + sudo launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist + elif [[ "$(uname -s)" == "Linux" ]] && [[ "$(nix_install_type)" == "multi" ]]; then + echo "Restarting Nix daemon Systemd service..." >&2 + sudo systemctl daemon-reload + sudo systemctl restart nix-daemon + else + echo "Unknown platform! Unable to restart daemon!" >&2 + exit 1 + fi +} diff --git a/nix/scripts/setup.sh b/nix/scripts/setup.sh new file mode 100755 index 00000000000..00843d6b060 --- /dev/null +++ b/nix/scripts/setup.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# This script installs a specific version of Nix. +set -eo pipefail + +GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel) +source "${GIT_ROOT}/scripts/colors.sh" +source "${GIT_ROOT}/nix/scripts/lib.sh" +source "${GIT_ROOT}/nix/scripts/version.sh" + +nix_install() { + # Download installer and verify SHA256> + curl -sSf "${NIX_INSTALL_URL}" -o "${NIX_INSTALL_PATH}" + echo "${NIX_INSTALL_SHA256} ${NIX_INSTALL_PATH}" | sha256sum -c + chmod +x "${NIX_INSTALL_PATH}" + + # Identify installation type. + if [[ -z "${NIX_INSTALL_OPTS}" ]]; then + if [[ "$(uname -r)" =~ microsoft ]]; then + # Systemd is not started by default on WSL. + NIX_INSTALL_OPTS="--no-daemon" + elif [[ "$(uname -s)" == "Darwin" ]]; then + # Single-user not supported on Darwin. + NIX_INSTALL_OPTS="--daemon" + elif [[ "$(uname -s)" == "Linux" ]]; then + # Open file limit issues on Linux. + # https://github.com/NixOS/nix/issues/6007 + # Alson known issues with nix-daemon.socket on Arch. + NIX_INSTALL_OPTS="--no-daemon" + fi + fi + + # Run the installer + "${NIX_INSTALL_PATH}" "${NIX_INSTALL_OPTS}" + if [[ $? -eq 0 ]]; then + echo -e "${GRN}The Nix package manager was successfully installed.${RST}" + else + echo -e "${RED}Failed to install Nix package manager!${RST}" >&2 + echo "Please see: https://nixos.org/nix/manual/#chap-installation" >&2 + exit 1 + fi + + # Additional fixes + nix_add_extra_cache + nix_daemon_restart +} + +# Adding directly to global config to avoid warnings like this: +# "ignoring untrusted substituter 'https://nix-cache.status.im/', you are not a trusted user." +nix_add_extra_cache() { + # Single-user installations do not have this issue. + [[ ! -f /etc/nix/nix.conf ]] && return + echo -e 'Adding our cache to Nix daemon config...' >&2 + local NIX_SETTINGS=('substituters' 'trusted-substituters' 'trusted-public-keys') + for NIX_SETTING in "${NIX_SETTINGS[@]}"; do + nix_set_global_setting "${NIX_SETTING}" "$(nix_get_local_setting "${NIX_SETTING}")" + done +} + +if [[ ! -x "$(command -v sha256sum)" ]]; then + echo -e "${RED}The 'sha256sum' utility is required for Nix installation.${RST}" >&2 + echo -e "${YLW}Install 'coreutils' package on your system.${RST}" >&2 + exit 1 +fi + +if [[ ! -x "$(command -v curl)" ]]; then + echo -e "${RED}The 'curl' utility is required for Nix installation.${RST}" >&2 + exit 1 +fi + +if [[ "$(source /etc/os-release 2>/dev/null && echo "${NAME}")" == *NixOS* ]]; then + echo -e "${GRN}Already running NixOS.${RST}" + exit +fi + +if [[ -x "$(command -v nix)" ]]; then + echo -e "${GRN}Nix package manager already installed.${RST}" + exit +fi + +if [[ "${IN_NIX_SHELL}" == 'pure' ]]; then + echo -e "${GRN}Already in a pure Nix shell.${RST}" + exit +fi + +# If none of the checks before succeeded we need to install Nix +echo -e "${GRN}Setting up Nix package manager...${RST}" +nix_install +echo -e "${YLW}See STARTING_GUIDE.md if you're new here.${RST}" diff --git a/nix/scripts/version.sh b/nix/scripts/version.sh new file mode 100755 index 00000000000..a58158a0c3d --- /dev/null +++ b/nix/scripts/version.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +export NIX_VERSION="2.19.3" +export NIX_PACKAGE="nixVersions.nix_2_19" +export NIX_INSTALL_URL="https://nixos.org/releases/nix/nix-${NIX_VERSION}/install" +export NIX_INSTALL_SHA256="73d47b0ab783fddca1b2d44a03d52a74c97c28a1fc8ff5a29419079302ef9c3d" +export NIX_INSTALL_PATH="/tmp/nix-install-${NIX_VERSION}" diff --git a/nix/shell.nix b/nix/shell.nix new file mode 100644 index 00000000000..2ff4bc1a394 --- /dev/null +++ b/nix/shell.nix @@ -0,0 +1,108 @@ +{ + pkgs, + flake +}: + +let + qtCustom = (with pkgs.qt515_8; + # TODO:check the required modules + env "qt-custom-${qtbase.version}" ([ + qtbase + qtdeclarative + qtquickcontrols + qtquickcontrols2 + qtsvg + qtmultimedia + qtwebview + qttools + qtwebchannel + qtgraphicaleffects + qtwebengine + qtlocation + ])); + +in pkgs.mkShell { + name = "status-desktop-build-shell"; + + # TODO:check the required packages + buildInputs = with pkgs; [ + # dev and CI + bash curl wget git file unzip jq lsb-release which cacert gnupg + linuxdeployqt appimagekit + libglvnd # TODO: Qt 5.15.2 fix, review after upgrade + cmake_3_19 gnumake pkg-config gnugrep qtCustom + go_1_21 go-bindata mockgen protobuf3_20 protoc-gen-go + pcre nss pcsclite extra-cmake-modules + xorg.libxcb xorg.libX11 libxkbcommon + # dev machine only + nixUnstable # for flake support TODO: remove with nixpkgs upgrade + nixgl.auto.nixGLDefault + gdb figlet + ] ++ (with gst_all_1; [ + gst-libav gstreamer + gst-plugins-bad gst-plugins-base + gst-plugins-good gst-plugins-ugly + ]); + + # Avoid terminal issues. + TERM = "xterm"; + LANG = "en_US.UTF-8"; + LANGUAGE = "en_US.UTF-8"; + + QTDIR = qtCustom; + # TODO: still needed? + # https://github.com/NixOS/nixpkgs/pull/109649 + QT_INSTALL_PLUGINS = "${qtCustom}/${pkgs.qt515_8.qtbase.qtPluginPrefix}"; + + shellHook = '' + export MAKEFLAGS="-j$NIX_BUILD_CORES" + export PATH="${pkgs.lddWrapped}/bin:$PATH" + figlet -t "${flake.description}" + ''; + + LIBKRB5_PATH = pkgs.libkrb5; + QTWEBENGINE_PATH = pkgs.qt515_8.qtwebengine.out; + GSTREAMER_PATH = pkgs.gst_all_1.gstreamer; + NSS_PATH = pkgs.nss; + + # Used for linuxdeployqt + # TODO:check which deps are needed + LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath ( + [ + libudev0-shim # this only needed to run, not build + alsaLib + expat + fontconfig + freetype + gcc-unwrapped + glib + gmp + harfbuzz + libglvnd + libkrb5 + libpng + libpulseaudio + libxkbcommon + openexr + openssl + p11-kit + zlib + ] ++ (with xorg; [ + libICE + libSM + libX11 + libXrender + libxcb + xcbutil + xcbutilimage + xcbutilkeysyms + xcbutilrenderutil + xcbutilwm + ]) ++ (with gst_all_1; [ + gst-plugins-base + gst-plugins-good + gst-plugins-bad + gst-plugins-ugly + gstreamer + ])); +} diff --git a/scripts/colors.sh b/scripts/colors.sh new file mode 100644 index 00000000000..6b19a153f67 --- /dev/null +++ b/scripts/colors.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Colors +export YLW='\033[1;33m' +export RED='\033[0;31m' +export GRN='\033[0;32m' +export BLU='\033[0;34m' +export BLD='\033[1m' +export RST='\033[0m' + +# Clear line +export CLR='\033[2K' diff --git a/scripts/fix_app_dir.sh b/scripts/fix_app_dir.sh index 5d32089e0fa..80352722d9e 100755 --- a/scripts/fix_app_dir.sh +++ b/scripts/fix_app_dir.sh @@ -18,11 +18,11 @@ if [[ ! -z "${IN_NIX_SHELL}" ]]; then patchelf --set-rpath '$ORIGIN/../../' "${APP_DIR}"/usr/lib/gstreamer1.0/gstreamer-1.0/* - patchelf --set-rpath '$ORIGIN/../lib' "${APP_DIR}/usr/libexec/QtWebEngineProcess" + patchelf --set-rpath '$ORIGIN/../lib' "${APP_DIR}/usr/bin/QtWebEngineProcess" patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 \ "${APP_DIR}/usr/bin/nim_status_client" \ - "${APP_DIR}/usr/libexec/QtWebEngineProcess" \ + "${APP_DIR}/usr/bin/QtWebEngineProcess" \ "${APP_DIR}/usr/lib/libQt5Core.so.5" \ "${APP_DIR}"/usr/lib/gstreamer1.0/gstreamer-1.0/* fi diff --git a/scripts/init_app_dir.sh b/scripts/init_app_dir.sh index 4c3e6fa0ef7..f2c587f588a 100755 --- a/scripts/init_app_dir.sh +++ b/scripts/init_app_dir.sh @@ -33,15 +33,14 @@ if [[ -z "${IN_NIX_SHELL}" ]]; then cp -r /usr/lib/x86_64-linux-gnu/gstreamer1.0 "${APP_DIR}/usr/lib/" else mkdir -p "${APP_DIR}"/usr/lib/{gstreamer1.0,gstreamer-1.0,nss} - mkdir -p "${APP_DIR}"/usr/libexec echo "${GST_PLUGIN_SYSTEM_PATH_1_0}" | tr ':' '\n' | sort -u | xargs -I {} find {} -name "*.so" | xargs -I {} cp {} "${APP_DIR}/usr/lib/gstreamer-1.0/" cp -r "${GSTREAMER_PATH}/libexec/gstreamer-1.0" "${APP_DIR}/usr/lib/gstreamer1.0/" cp "${LIBKRB5_PATH}/lib/libcom_err.so.3" "${APP_DIR}/usr/lib/libcom_err.so.3" cp "${NSS_PATH}"/lib/{libfreebl3,libfreeblpriv3,libnssckbi,libnssdbm3,libsoftokn3}.{chk,so} "${APP_DIR}/usr/lib/nss/" || true - cp "${QTWEBENGINE_PATH}/libexec/QtWebEngineProcess" "${APP_DIR}/usr/libexec/QtWebEngineProcess" - cp "${QTWEBENGINE_PATH}"/resources/* "${APP_DIR}/usr/libexec/" - cp -r "${QTWEBENGINE_PATH}/translations/qtwebengine_locales" "${APP_DIR}/usr/libexec/" + cp "${QTWEBENGINE_PATH}/libexec/QtWebEngineProcess" "${APP_DIR}/usr/bin/QtWebEngineProcess" + cp "${QTWEBENGINE_PATH}"/resources/* "${APP_DIR}/usr/bin/" + cp -r "${QTWEBENGINE_PATH}/translations/qtwebengine_locales" "${APP_DIR}/usr/bin/" chmod -R u+w "${APP_DIR}/usr" fi diff --git a/shell.nix b/shell.nix index d93290803b2..942ce016ac5 100644 --- a/shell.nix +++ b/shell.nix @@ -1,100 +1,10 @@ -{ - pkgs ? import ./nix/pkgs.nix -}: - -let - qtCustom = (with pkgs.qt515_8; - # TODO:check the required modules - env "qt-custom-${qtbase.version}" ([ - qtbase - qtdeclarative - qtquickcontrols - qtquickcontrols2 - qtsvg - qtmultimedia - qtwebview - qttools - qtwebchannel - qtgraphicaleffects - qtwebengine - qtlocation - ])); - -in pkgs.mkShell { - name = "status-desktop-build-shell"; - - # TODO:check the required packages - buildInputs = with pkgs; [ - bash curl wget git file unzip jq lsb-release which cacert gnupg - linuxdeployqt appimagekit - libglvnd # TODO: Qt 5.15.2 fix, review after upgrade - cmake_3_19 gnumake pkg-config gnugrep qtCustom - go_1_21 go-bindata mockgen protobuf3_20 protoc-gen-go - pcre nss pcsclite extra-cmake-modules - xorg.libxcb xorg.libX11 libxkbcommon - ] ++ (with gst_all_1; [ - gst-libav gstreamer - gst-plugins-bad gst-plugins-base - gst-plugins-good gst-plugins-ugly - ]); - - # Avoid terminal issues. - TERM = "xterm"; - LANG = "en_US.UTF-8"; - LANGUAGE = "en_US.UTF-8"; - - QTDIR = qtCustom; - # TODO: still needed? - # https://github.com/NixOS/nixpkgs/pull/109649 - QT_INSTALL_PLUGINS = "${qtCustom}/${pkgs.qt515_8.qtbase.qtPluginPrefix}"; - - shellHook = '' - export MAKEFLAGS="-j$NIX_BUILD_CORES" - export PATH="${pkgs.lddWrapped}/bin:$PATH" - ''; - - LIBKRB5_PATH = pkgs.libkrb5; - QTWEBENGINE_PATH = pkgs.qt515_8.qtwebengine.out; - GSTREAMER_PATH = pkgs.gst_all_1.gstreamer; - NSS_PATH = pkgs.nss; - - # Used for linuxdeployqt - # TODO:check which deps are needed - LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath ( - [ - alsaLib - expat - fontconfig - freetype - gcc-unwrapped - glib - gmp - harfbuzz - libglvnd - libkrb5 - libpng - libpulseaudio - libxkbcommon - openexr - openssl - p11-kit - zlib - ] ++ (with xorg; [ - libICE - libSM - libX11 - libXrender - libxcb - xcbutil - xcbutilimage - xcbutilkeysyms - xcbutilrenderutil - xcbutilwm - ]) ++ (with gst_all_1; [ - gst-plugins-base - gst-plugins-good - gst-plugins-bad - gst-plugins-ugly - gstreamer - ])); -} +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).shellNix