diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 36bc30909..0e236eeba 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,6 +3,9 @@ on: pull_request: { } push: branches: [ develop, master ] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: windows: strategy: @@ -67,7 +70,13 @@ jobs: run: "yarn build --publish never -w ${{ matrix.build-args }}" linux: - name: Linux + strategy: + matrix: + include: + - sqlcipher: system + - sqlcipher: static + static: 1 + name: 'Linux (sqlcipher: ${{ matrix.sqlcipher }})' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -84,6 +93,10 @@ jobs: with: toolchain: stable + - name: Install libsqlcipher-dev + if: matrix.sqlcipher == 'system' + run: sudo apt-get install -y libsqlcipher-dev + - uses: actions/setup-node@v3 with: cache: "yarn" @@ -94,6 +107,8 @@ jobs: - name: Build Natives run: "yarn build:native" + env: + SQLCIPHER_STATIC: ${{ matrix.static }} - name: Build App run: "yarn build --publish never" diff --git a/dockerbuild/Dockerfile b/dockerbuild/Dockerfile index 41d1901a9..d7d07061c 100644 --- a/dockerbuild/Dockerfile +++ b/dockerbuild/Dockerfile @@ -13,7 +13,9 @@ RUN apt-get -qq update && apt-get -qq dist-upgrade && \ # libsecret-1-dev and libgnome-keyring-dev are required even for prebuild keytar apt-get -qq install --no-install-recommends qtbase5-dev bsdtar build-essential autoconf libssl-dev gcc-multilib g++-multilib lzip rpm python libcurl4 git git-lfs ssh unzip tcl \ libsecret-1-dev libgnome-keyring-dev \ - libopenjp2-tools && \ + libopenjp2-tools \ + # Used by seshat (when not SQLCIPHER_STATIC) \ + libsqlcipher-dev && \ # git-lfs git lfs install && \ apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/* diff --git a/docs/native-node-modules.md b/docs/native-node-modules.md index a36a5fde3..0da6f4a8a 100644 --- a/docs/native-node-modules.md +++ b/docs/native-node-modules.md @@ -47,7 +47,7 @@ using yarn at the root of this project: yarn add matrix-seshat -You will have to rebuild the native libraries against electron's version of +You will have to rebuild the native libraries against electron's version of node rather than your system node, using the `electron-build-env` tool. This is also needed to when pulling in changes to Seshat using `yarn link`. @@ -66,6 +66,17 @@ as usual using: yarn start +### Statically linking libsqlcipher + +On Windows & macOS we always statically link libsqlcipher for it is not generally available. +On Linux by default we will use a system package, on debian & ubuntu this is `libsqlcipher0`, +but this is problematic for some other packages. +By including `SQLCIPHER_STATIC=1` in the build environment, the build scripts will statically link sqlcipher, +note that this will want a `libcrypto1.1` shared library available in the system. + +More info can be found at https://github.com/matrix-org/seshat/issues/102 +and https://github.com/vector-im/element-web/issues/20926. + ## Compiling for specific architectures ### macOS diff --git a/element.io/nightly/control.template b/element.io/nightly/control.template index aa29aa64c..a4b50f303 100644 --- a/element.io/nightly/control.template +++ b/element.io/nightly/control.template @@ -4,9 +4,9 @@ Vendor: support@element.io Architecture: amd64 Maintainer: support@element.io Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0 -Recommends: libappindicator3-1 +Recommends: libappindicator3-1, libsqlcipher0 Section: net Priority: extra Homepage: https://element.io/ -Description: +Description: riot.im A feature-rich client for Matrix.org (nightly unstable build). diff --git a/element.io/release/control.template b/element.io/release/control.template index 697466a0f..3c3bcc2fe 100644 --- a/element.io/release/control.template +++ b/element.io/release/control.template @@ -4,11 +4,11 @@ Vendor: support@element.io Architecture: amd64 Maintainer: support@element.io Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0 -Recommends: libappindicator3-1 +Recommends: libappindicator3-1, libsqlcipher0 Replaces: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0) Breaks: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0) Section: net Priority: extra Homepage: https://element.io/ -Description: +Description: A feature-rich client for Matrix.org diff --git a/hak/matrix-seshat/build.ts b/hak/matrix-seshat/build.ts index 3bd8601dc..a6e240bfd 100644 --- a/hak/matrix-seshat/build.ts +++ b/hak/matrix-seshat/build.ts @@ -26,7 +26,7 @@ export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promi if (hakEnv.isWin()) { await buildOpenSslWin(hakEnv, moduleInfo); await buildSqlCipherWin(hakEnv, moduleInfo); - } else { + } else if (hakEnv.wantsStaticSqlCipherUnix()) { await buildSqlCipherUnix(hakEnv, moduleInfo); } await buildMatrixSeshat(hakEnv, moduleInfo); @@ -186,8 +186,12 @@ async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo) { args.push('--with-crypto-lib=commoncrypto'); } - if (hakEnv.isLinux()) { - args.push('--with-pic=yes'); + if (hakEnv.wantsStaticSqlCipherUnix()) { + args.push('--enable-tcl=no'); + + if (hakEnv.isLinux()) { + args.push('--with-pic=yes'); + } } if (!hakEnv.isHost()) { @@ -210,7 +214,7 @@ async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo) { args.push(`CFLAGS=${cflags.join(' ')}`); } - const ldflags = []; + const ldflags: string[] = []; if (hakEnv.isMac()) { ldflags.push('-framework Security'); @@ -270,13 +274,15 @@ async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo) { // it for now: we should confirm how much of this it still actually needs. const env = hakEnv.makeGypEnv(); - Object.assign(env, { - SQLCIPHER_STATIC: 1, - SQLCIPHER_LIB_DIR: path.join(moduleInfo.depPrefix, 'lib'), - SQLCIPHER_INCLUDE_DIR: path.join(moduleInfo.depPrefix, 'include'), - }); + if (!hakEnv.isLinux() || hakEnv.wantsStaticSqlCipherUnix()) { + Object.assign(env, { + SQLCIPHER_STATIC: 1, + SQLCIPHER_LIB_DIR: path.join(moduleInfo.depPrefix, 'lib'), + SQLCIPHER_INCLUDE_DIR: path.join(moduleInfo.depPrefix, 'include'), + }); + } - if (hakEnv.isLinux()) { + if (hakEnv.isLinux() && hakEnv.wantsStaticSqlCipherUnix()) { // Ensure Element uses the statically-linked seshat build, and prevent other applications // from attempting to use this one. Detailed explanation: // diff --git a/hak/matrix-seshat/check.ts b/hak/matrix-seshat/check.ts index 14794187e..86e1112ab 100644 --- a/hak/matrix-seshat/check.ts +++ b/hak/matrix-seshat/check.ts @@ -21,20 +21,22 @@ import HakEnv from '../../scripts/hak/hakEnv'; import { DependencyInfo } from '../../scripts/hak/dep'; export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise { - // of course tcl doesn't have a --version - await new Promise((resolve, reject) => { - const proc = childProcess.spawn('tclsh', [], { - stdio: ['pipe', 'ignore', 'ignore'], - }); - proc.on('exit', (code) => { - if (code !== 0) { - reject("Can't find tclsh - have you installed TCL?"); - } else { - resolve(); - } + if (hakEnv.wantsStaticSqlCipher()) { + // of course tcl doesn't have a --version + await new Promise((resolve, reject) => { + const proc = childProcess.spawn('tclsh', [], { + stdio: ['pipe', 'ignore', 'ignore'], + }); + proc.on('exit', (code) => { + if (code !== 0) { + reject("Can't find tclsh - have you installed TCL?"); + } else { + resolve(); + } + }); + proc.stdin.end(); }); - proc.stdin.end(); - }); + } const tools = [ ['rustc', '--version'], diff --git a/hak/matrix-seshat/fetchDeps.ts b/hak/matrix-seshat/fetchDeps.ts index 1ae1286bc..6edccaaba 100644 --- a/hak/matrix-seshat/fetchDeps.ts +++ b/hak/matrix-seshat/fetchDeps.ts @@ -25,7 +25,9 @@ import HakEnv from '../../scripts/hak/hakEnv'; import { DependencyInfo } from '../../scripts/hak/dep'; export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise { - await getSqlCipher(hakEnv, moduleInfo); + if (hakEnv.wantsStaticSqlCipher()) { + await getSqlCipher(hakEnv, moduleInfo); + } if (hakEnv.isWin()) { await getOpenSsl(hakEnv, moduleInfo); @@ -36,7 +38,7 @@ async function getSqlCipher(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise const version = moduleInfo.cfg.dependencies.sqlcipher; const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`); - let haveSqlcipher; + let haveSqlcipher: boolean; try { await fsProm.stat(sqlCipherDir); haveSqlcipher = true; @@ -47,7 +49,7 @@ async function getSqlCipher(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise if (haveSqlcipher) return; const sqlCipherTarball = path.join(moduleInfo.moduleDotHakDir, `sqlcipher-${version}.tar.gz`); - let haveSqlcipherTar; + let haveSqlcipherTar: boolean; try { await fsProm.stat(sqlCipherTarball); haveSqlcipherTar = true; @@ -97,7 +99,7 @@ async function getOpenSsl(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise { + public makeGypEnv(): Record { return Object.assign({}, process.env, { npm_config_arch: this.target.arch, npm_config_target_arch: this.target.arch, @@ -107,7 +107,15 @@ export default class HakEnv { }); } - getNodeModuleBin(name: string): string { + public getNodeModuleBin(name: string): string { return path.join(this.projectRoot, 'node_modules', '.bin', name); } + + public wantsStaticSqlCipherUnix(): boolean { + return this.isMac() || process.env.SQLCIPHER_STATIC == '1'; + } + + public wantsStaticSqlCipher(): boolean { + return this.isWin() || this.wantsStaticSqlCipherUnix(); + } }