forked from CringeStudios/element-desktop
Attempt to kill off hak
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
02c23e87b5
commit
9f00594ae3
22
.github/workflows/build_linux.yaml
vendored
22
.github/workflows/build_linux.yaml
vendored
@ -66,14 +66,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: webapp
|
name: webapp
|
||||||
|
|
||||||
- name: Cache .hak
|
|
||||||
id: cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}-${{ github.ref_name }}-${{ inputs.sqlcipher }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion', 'dockerbuild/*') }}
|
|
||||||
path: |
|
|
||||||
./.hak
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
@ -103,23 +95,11 @@ jobs:
|
|||||||
platforms: linux/${{ inputs.arch }}
|
platforms: linux/${{ inputs.arch }}
|
||||||
tags: ${{ env.HAK_DOCKER_IMAGE }}
|
tags: ${{ env.HAK_DOCKER_IMAGE }}
|
||||||
|
|
||||||
- name: Build Natives
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
docker run \
|
|
||||||
-v ${{ github.workspace }}:/work -w /work \
|
|
||||||
-e SQLCIPHER_BUNDLED \
|
|
||||||
$HAK_DOCKER_IMAGE \
|
|
||||||
yarn build:native
|
|
||||||
|
|
||||||
- name: Fix permissions on .hak
|
|
||||||
run: sudo chown -R $USER:$USER .hak
|
|
||||||
|
|
||||||
- name: Check native libraries in hak dependencies
|
- name: Check native libraries in hak dependencies
|
||||||
run: |
|
run: |
|
||||||
shopt -s globstar
|
shopt -s globstar
|
||||||
|
|
||||||
for filename in ./.hak/hakModules/**/*.node; do
|
for filename in ./node_modules/**/*.node; do
|
||||||
./scripts/glibc-check.sh $filename
|
./scripts/glibc-check.sh $filename
|
||||||
done
|
done
|
||||||
|
|
||||||
|
9
.github/workflows/build_macos.yaml
vendored
9
.github/workflows/build_macos.yaml
vendored
@ -39,14 +39,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: webapp
|
name: webapp
|
||||||
|
|
||||||
- name: Cache .hak
|
|
||||||
id: cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('hakHash', 'electronVersion') }}
|
|
||||||
path: |
|
|
||||||
./.hak
|
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
@ -73,7 +65,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Python 3.12 drops distutils which keytar relies on
|
# Python 3.12 drops distutils which keytar relies on
|
||||||
pip3 install setuptools
|
pip3 install setuptools
|
||||||
yarn build:native:universal
|
|
||||||
|
|
||||||
# We split these because electron-builder gets upset if we set CSC_LINK even to an empty string
|
# We split these because electron-builder gets upset if we set CSC_LINK even to an empty string
|
||||||
- name: "[Signed] Build App"
|
- name: "[Signed] Build App"
|
||||||
|
14
.github/workflows/build_windows.yaml
vendored
14
.github/workflows/build_windows.yaml
vendored
@ -66,14 +66,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: webapp
|
name: webapp
|
||||||
|
|
||||||
- name: Cache .hak
|
|
||||||
id: cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
key: ${{ runner.os }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion') }}
|
|
||||||
path: |
|
|
||||||
./.hak
|
|
||||||
|
|
||||||
# ActiveTCL package on choco is from 2015,
|
# ActiveTCL package on choco is from 2015,
|
||||||
# this one is newer but includes more than we need
|
# this one is newer but includes more than we need
|
||||||
- name: Choco install tclsh
|
- name: Choco install tclsh
|
||||||
@ -117,12 +109,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
arch: ${{ steps.config.outputs.arch || inputs.arch }}
|
arch: ${{ steps.config.outputs.arch || inputs.arch }}
|
||||||
|
|
||||||
- name: Build Natives
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
refreshenv
|
|
||||||
yarn build:native --target ${{ steps.config.outputs.target }}
|
|
||||||
|
|
||||||
- name: Install and configure eSigner CKA
|
- name: Install and configure eSigner CKA
|
||||||
run: |
|
run: |
|
||||||
Set-StrictMode -Version 'Latest'
|
Set-StrictMode -Version 'Latest'
|
||||||
|
@ -93,14 +93,7 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
|
|||||||
afterPack: async (context: AfterPackContext) => {
|
afterPack: async (context: AfterPackContext) => {
|
||||||
await injectAsarIntegrity(context);
|
await injectAsarIntegrity(context);
|
||||||
},
|
},
|
||||||
files: [
|
files: ["package.json", "lib/**"],
|
||||||
"package.json",
|
|
||||||
{
|
|
||||||
from: ".hak/hakModules",
|
|
||||||
to: "node_modules",
|
|
||||||
},
|
|
||||||
"lib/**",
|
|
||||||
],
|
|
||||||
extraResources: [
|
extraResources: [
|
||||||
{
|
{
|
||||||
from: "res/img",
|
from: "res/img",
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type HakEnv from "../../scripts/hak/hakEnv.js";
|
|
||||||
import type { DependencyInfo } from "../../scripts/hak/dep.js";
|
|
||||||
|
|
||||||
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
const env = hakEnv.makeGypEnv();
|
|
||||||
|
|
||||||
if (!hakEnv.isHost()) {
|
|
||||||
env.CARGO_BUILD_TARGET = hakEnv.getTargetId();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("Running yarn install");
|
|
||||||
await hakEnv.spawn("yarn", ["install"], {
|
|
||||||
cwd: moduleInfo.moduleBuildDir,
|
|
||||||
env,
|
|
||||||
shell: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const buildTarget = hakEnv.wantsStaticSqlCipher() ? "build-bundled" : "build";
|
|
||||||
|
|
||||||
console.log("Running yarn build");
|
|
||||||
await hakEnv.spawn("yarn", ["run", buildTarget], {
|
|
||||||
cwd: moduleInfo.moduleBuildDir,
|
|
||||||
env,
|
|
||||||
shell: true,
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import childProcess from "node:child_process";
|
|
||||||
import fsProm from "node:fs/promises";
|
|
||||||
|
|
||||||
import type HakEnv from "../../scripts/hak/hakEnv.js";
|
|
||||||
import type { Tool } from "../../scripts/hak/hakEnv.js";
|
|
||||||
import type { DependencyInfo } from "../../scripts/hak/dep.js";
|
|
||||||
|
|
||||||
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
const tools: Tool[] = [
|
|
||||||
["rustc", "--version"],
|
|
||||||
["python", "--version"], // node-gyp uses python for reasons beyond comprehension
|
|
||||||
];
|
|
||||||
if (hakEnv.isWin()) {
|
|
||||||
tools.push(["perl", "--version"]); // for openssl configure
|
|
||||||
tools.push(["nasm", "-v"]); // for openssl building
|
|
||||||
tools.push(["patch", "--version"]); // to patch sqlcipher Makefile.msc
|
|
||||||
tools.push(["nmake", "/?"]);
|
|
||||||
} else {
|
|
||||||
tools.push(["make", "--version"]);
|
|
||||||
}
|
|
||||||
await hakEnv.checkTools(tools);
|
|
||||||
|
|
||||||
// Ensure Rust target exists (nb. we avoid depending on rustup)
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
const rustc = childProcess.execFile(
|
|
||||||
"rustc",
|
|
||||||
["--target", hakEnv.getTargetId(), "--emit=obj", "-o", "tmp", "-"],
|
|
||||||
(err, out) => {
|
|
||||||
if (err) {
|
|
||||||
reject(
|
|
||||||
"rustc can't build for target " +
|
|
||||||
hakEnv.getTargetId() +
|
|
||||||
": ensure target is installed via `rustup target add " +
|
|
||||||
hakEnv.getTargetId() +
|
|
||||||
"` " +
|
|
||||||
"or your package manager if not using `rustup`",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
fsProm.unlink("tmp").then(resolve);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
rustc.stdin!.write("fn main() {}");
|
|
||||||
rustc.stdout!.pipe(process.stdout);
|
|
||||||
rustc.stderr!.pipe(process.stderr);
|
|
||||||
rustc.stdin!.end();
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"scripts": {
|
|
||||||
"check": "check.ts",
|
|
||||||
"build": "build.ts"
|
|
||||||
},
|
|
||||||
"copy": "index.node"
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"target": "es2022",
|
|
||||||
"sourceMap": false,
|
|
||||||
"strict": true,
|
|
||||||
"lib": ["es2022"]
|
|
||||||
},
|
|
||||||
"include": ["../scripts/@types/*.d.ts", "./**/*.ts"]
|
|
||||||
}
|
|
14
package.json
14
package.json
@ -27,17 +27,14 @@
|
|||||||
"asar-webapp": "asar p webapp webapp.asar",
|
"asar-webapp": "asar p webapp webapp.asar",
|
||||||
"start": "yarn run build:ts && yarn run build:res && electron .",
|
"start": "yarn run build:ts && yarn run build:res && electron .",
|
||||||
"lint": "yarn lint:types && yarn lint:js && yarn lint:workflows",
|
"lint": "yarn lint:types && yarn lint:js && yarn lint:workflows",
|
||||||
"lint:js": "eslint --max-warnings 0 src hak playwright scripts && prettier --check .",
|
"lint:js": "eslint --max-warnings 0 src playwright scripts && prettier --check .",
|
||||||
"lint:js-fix": "eslint --fix --max-warnings 0 src hak playwright scripts && prettier --log-level=warn --write .",
|
"lint:js-fix": "eslint --fix --max-warnings 0 src playwright scripts && prettier --log-level=warn --write .",
|
||||||
"lint:types": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts && yarn lint:types:hak",
|
"lint:types": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts",
|
||||||
"lint:types:src": "tsc --noEmit",
|
"lint:types:src": "tsc --noEmit",
|
||||||
"lint:types:test": "tsc --noEmit -p playwright/tsconfig.json",
|
"lint:types:test": "tsc --noEmit -p playwright/tsconfig.json",
|
||||||
"lint:types:scripts": "tsc --noEmit -p scripts/tsconfig.json",
|
"lint:types:scripts": "tsc --noEmit -p scripts/tsconfig.json",
|
||||||
"lint:types:hak": "tsc --noEmit -p hak/tsconfig.json",
|
|
||||||
"lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'",
|
"lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'",
|
||||||
"lint:knip": "knip",
|
"lint:knip": "knip",
|
||||||
"build:native": "yarn run hak",
|
|
||||||
"build:native:universal": "yarn run hak --target x86_64-apple-darwin fetchandbuild && yarn run hak --target aarch64-apple-darwin fetchandbuild && yarn run hak --target x86_64-apple-darwin --target aarch64-apple-darwin copyandlink",
|
|
||||||
"build:32": "yarn run build:ts && yarn run build:res && electron-builder --ia32",
|
"build:32": "yarn run build:ts && yarn run build:res && electron-builder --ia32",
|
||||||
"build:64": "yarn run build:ts && yarn run build:res && electron-builder --x64",
|
"build:64": "yarn run build:ts && yarn run build:res && electron-builder --x64",
|
||||||
"build:universal": "yarn run build:ts && yarn run build:res && electron-builder --universal",
|
"build:universal": "yarn run build:ts && yarn run build:res && electron-builder --universal",
|
||||||
@ -45,7 +42,6 @@
|
|||||||
"build:ts": "tsc",
|
"build:ts": "tsc",
|
||||||
"build:res": "tsx scripts/copy-res.ts",
|
"build:res": "tsx scripts/copy-res.ts",
|
||||||
"docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild -f dockerbuild/Dockerfile .",
|
"docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild -f dockerbuild/Dockerfile .",
|
||||||
"docker:build:native": "scripts/in-docker.sh yarn run hak",
|
|
||||||
"docker:build": "scripts/in-docker.sh yarn run build",
|
"docker:build": "scripts/in-docker.sh yarn run build",
|
||||||
"docker:install": "scripts/in-docker.sh yarn install",
|
"docker:install": "scripts/in-docker.sh yarn install",
|
||||||
"clean": "rimraf webapp.asar dist packages deploys lib",
|
"clean": "rimraf webapp.asar dist packages deploys lib",
|
||||||
@ -64,6 +60,7 @@
|
|||||||
"electron-store": "^10.0.0",
|
"electron-store": "^10.0.0",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"keytar-forked": "7.10.0",
|
"keytar-forked": "7.10.0",
|
||||||
|
"matrix-seshat": "https://gitpkg.vercel.app/matrix-org/seshat/seshat-node?t3chguy/binding-gyp",
|
||||||
"minimist": "^1.2.6",
|
"minimist": "^1.2.6",
|
||||||
"png-to-ico": "^2.1.1",
|
"png-to-ico": "^2.1.1",
|
||||||
"uuid": "^11.0.0"
|
"uuid": "^11.0.0"
|
||||||
@ -112,9 +109,6 @@
|
|||||||
"tsx": "^4.19.2",
|
"tsx": "^4.19.2",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
},
|
},
|
||||||
"hakDependencies": {
|
|
||||||
"matrix-seshat": "^4.0.1"
|
|
||||||
},
|
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "18.19.76",
|
"@types/node": "18.19.76",
|
||||||
"config-file-ts": "0.2.8-rc1"
|
"config-file-ts": "0.2.8-rc1"
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
# hak
|
|
||||||
|
|
||||||
This tool builds native dependencies for element-desktop. Here follows some very minimal
|
|
||||||
documentation for it.
|
|
||||||
|
|
||||||
Goals:
|
|
||||||
|
|
||||||
- Must build compiled native node modules in a shippable state
|
|
||||||
(ie. only dynamically linked against libraries that will be on the
|
|
||||||
target system, all unnecessary files removed).
|
|
||||||
- Must be able to build any native module, no matter what build system
|
|
||||||
it uses (electron-rebuild is supposed to do this job but only works
|
|
||||||
for modules that use gyp).
|
|
||||||
|
|
||||||
It's also loosely designed to be a general tool and agnostic to what it's
|
|
||||||
actually building. It's used here to build modules for the electron app
|
|
||||||
but should work equally well for building modules for normal node.
|
|
||||||
|
|
||||||
# Running
|
|
||||||
|
|
||||||
Hak is invoked with a command and a dependency, eg. `yarn run hak fetch matrix-seshat`.
|
|
||||||
If no dependencies are given, hak runs the command on all dependencies.
|
|
||||||
|
|
||||||
# Files
|
|
||||||
|
|
||||||
There are a lot of files involved:
|
|
||||||
|
|
||||||
- scripts/hak/... - The tool itself
|
|
||||||
- hak/[dependency] - Files provided by the app that tell hak how to build each of its native dependencies.
|
|
||||||
Contains a hak.json file and also some script files, each of which must be referenced in hak.json.
|
|
||||||
- .hak/ - Files generated by hak in the course of doing its job. Includes the dependency module itself and
|
|
||||||
any of the native dependency's native dependencies.
|
|
||||||
- .hak/[dependency]/build - An extracted copy of the dependency's node module used to build it.
|
|
||||||
- .hak/[dependency]/out - Another extracted copy of the dependency, this one contains only what will be shipped.
|
|
||||||
|
|
||||||
# Workings
|
|
||||||
|
|
||||||
Hak works around native node modules that try to fetch or build their native component in
|
|
||||||
the npm 'install' phase - modules that do this will typically end up with native components
|
|
||||||
targeted to the build platform and the node that npm/yarn is using, which is no good for an
|
|
||||||
electron app.
|
|
||||||
|
|
||||||
It does this by installing it with `--ignore-scripts` and then using `yarn link` to keep the
|
|
||||||
dependency module separate so yarn doesn't try to run its install / postinstall script
|
|
||||||
at other points (eg. whenever you `yarn add` a random other dependency).
|
|
||||||
|
|
||||||
This also means that the dependencies cannot be listed in `dependencies` or
|
|
||||||
`devDependencies` in the project, since this would cause npm / yarn to install them and
|
|
||||||
try to fetch their native parts. Instead, they are listed in `hakDependencies` which
|
|
||||||
hak reads to install them for you.
|
|
||||||
|
|
||||||
Hak will _not_ install dependencies for the copy of the module it links into your
|
|
||||||
project, so if your native module has javascript dependencies that are actually needed at
|
|
||||||
runtime (and not just to fetch / build the native parts), it won't work.
|
|
||||||
|
|
||||||
Hak will generate a `.yarnrc` in the project directory to set the link directory to its
|
|
||||||
own in the .hak directory (unless one already exists, in which case this is your problem).
|
|
||||||
|
|
||||||
# Lifecycle
|
|
||||||
|
|
||||||
Hak is divided into lifecycle stages, in order:
|
|
||||||
|
|
||||||
- fetch - Download and extract the source of the dependency
|
|
||||||
- link - Link the copy of the dependency into your node_modules directory
|
|
||||||
- build - The Good Stuff. Configure and build any native dependencies, then the module itself.
|
|
||||||
- copy - Copy the built artifact from the module build directory to the module output directory.
|
|
||||||
|
|
||||||
# hak.json
|
|
||||||
|
|
||||||
The scripts section contains scripts used for lifecycle stages that need them (fetch, fetchDeps, build).
|
|
||||||
It also contains 'prune' and 'copy' which are globs of files to delete from the output module directory
|
|
||||||
and copy over from the module build directory to the output module directory, respectively.
|
|
||||||
|
|
||||||
# Shortcomings
|
|
||||||
|
|
||||||
Hak doesn't know about dependencies between lifecycle stages, ie. it doesn't know that you need to
|
|
||||||
'fetch' and 'fetchDeps' before you can 'build', etc. You get to run each individually, and remember
|
|
||||||
the right order.
|
|
||||||
|
|
||||||
There is also a _lot_ of duplication in the command execution: we should abstract away
|
|
||||||
some of the boilerplate required to run commands & so forth.
|
|
@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
|
|
||||||
export default async function build(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
await moduleInfo.scripts.build(hakEnv, moduleInfo);
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
|
|
||||||
export default async function check(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
if (moduleInfo.scripts.check) {
|
|
||||||
await moduleInfo.scripts.check(hakEnv, moduleInfo);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import path from "node:path";
|
|
||||||
import { rimraf } from "rimraf";
|
|
||||||
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
|
|
||||||
export default async function clean(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
await rimraf(moduleInfo.moduleDotHakDir);
|
|
||||||
await rimraf(path.join(hakEnv.dotHakDir, "links", moduleInfo.name));
|
|
||||||
await rimraf(path.join(hakEnv.projectRoot, "node_modules", moduleInfo.name));
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import path from "node:path";
|
|
||||||
import fsProm from "node:fs/promises";
|
|
||||||
import childProcess from "node:child_process";
|
|
||||||
import { rimraf } from "rimraf";
|
|
||||||
import { glob } from "glob";
|
|
||||||
import { mkdirp } from "mkdirp";
|
|
||||||
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
|
|
||||||
export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
if (moduleInfo.cfg.prune) {
|
|
||||||
console.log("Removing " + moduleInfo.cfg.prune + " from " + moduleInfo.moduleOutDir);
|
|
||||||
// rimraf doesn't have a 'cwd' option: it always uses process.cwd()
|
|
||||||
// (and if you set glob.cwd it just breaks because it can't find the files)
|
|
||||||
const oldCwd = process.cwd();
|
|
||||||
try {
|
|
||||||
await mkdirp(moduleInfo.moduleOutDir);
|
|
||||||
process.chdir(moduleInfo.moduleOutDir);
|
|
||||||
await rimraf(moduleInfo.cfg.prune);
|
|
||||||
} finally {
|
|
||||||
process.chdir(oldCwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moduleInfo.cfg.copy) {
|
|
||||||
// If there are multiple moduleBuildDirs, singular moduleBuildDir
|
|
||||||
// is the same as moduleBuildDirs[0], so we're just listing the contents
|
|
||||||
// of the first one.
|
|
||||||
const files = await glob(moduleInfo.cfg.copy, {
|
|
||||||
cwd: moduleInfo.moduleBuildDir,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (moduleInfo.moduleBuildDirs.length > 1) {
|
|
||||||
if (!hakEnv.isMac()) {
|
|
||||||
console.error(
|
|
||||||
"You asked me to copy multiple targets but I've only been taught " + "how to do that on macOS.",
|
|
||||||
);
|
|
||||||
throw new Error("Can't copy multiple targets on this platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const f of files) {
|
|
||||||
const components = moduleInfo.moduleBuildDirs.map((dir) => path.join(dir, f));
|
|
||||||
const dst = path.join(moduleInfo.moduleOutDir, f);
|
|
||||||
|
|
||||||
await mkdirp(path.dirname(dst));
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
|
||||||
childProcess.execFile("lipo", ["-create", "-output", dst, ...components], (err) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log("Copying files from " + moduleInfo.moduleBuildDir + " to " + moduleInfo.moduleOutDir);
|
|
||||||
for (const f of files) {
|
|
||||||
console.log("\t" + f);
|
|
||||||
const src = path.join(moduleInfo.moduleBuildDir, f);
|
|
||||||
const dst = path.join(moduleInfo.moduleOutDir, f);
|
|
||||||
|
|
||||||
await mkdirp(path.dirname(dst));
|
|
||||||
await fsProm.copyFile(src, dst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
|
|
||||||
export interface DependencyInfo {
|
|
||||||
name: string;
|
|
||||||
version: string;
|
|
||||||
cfg: Record<string, any>;
|
|
||||||
moduleHakDir: string;
|
|
||||||
moduleDotHakDir: string;
|
|
||||||
moduleTargetDotHakDir: string;
|
|
||||||
moduleBuildDir: string;
|
|
||||||
moduleBuildDirs: string[];
|
|
||||||
moduleOutDir: string;
|
|
||||||
nodeModuleBinDir: string;
|
|
||||||
depPrefix: string;
|
|
||||||
scripts: Record<string, (hakEnv: HakEnv, moduleInfo: DependencyInfo) => Promise<void>>;
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fsProm from "node:fs/promises";
|
|
||||||
import pacote from "pacote";
|
|
||||||
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
|
|
||||||
export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
let haveModuleBuildDir;
|
|
||||||
try {
|
|
||||||
const stats = await fsProm.stat(moduleInfo.moduleBuildDir);
|
|
||||||
haveModuleBuildDir = stats.isDirectory();
|
|
||||||
} catch {
|
|
||||||
haveModuleBuildDir = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (haveModuleBuildDir) return;
|
|
||||||
|
|
||||||
console.log("Fetching " + moduleInfo.name + "@" + moduleInfo.version);
|
|
||||||
|
|
||||||
const packumentCache = new Map();
|
|
||||||
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleBuildDir, {
|
|
||||||
packumentCache,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Running yarn install in " + moduleInfo.moduleBuildDir);
|
|
||||||
await hakEnv.spawn("yarn", ["install", "--ignore-scripts"], {
|
|
||||||
cwd: moduleInfo.moduleBuildDir,
|
|
||||||
});
|
|
||||||
|
|
||||||
// also extract another copy to the output directory at this point
|
|
||||||
// nb. we do not yarn install in the output copy: we could install in
|
|
||||||
// production mode to get only runtime dependencies and not devDependencies,
|
|
||||||
// but usually native modules come with dependencies that are needed for
|
|
||||||
// building/fetching the native modules (eg. node-pre-gyp) rather than
|
|
||||||
// actually used at runtime: we do not want to bundle these into our app.
|
|
||||||
// We therefore just install no dependencies at all, and accept that any
|
|
||||||
// actual runtime dependencies will have to be added to the main app's
|
|
||||||
// dependencies. We can't tell what dependencies are real runtime deps
|
|
||||||
// and which are just used for native module building.
|
|
||||||
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleOutDir, {
|
|
||||||
packumentCache,
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { mkdirp } from "mkdirp";
|
|
||||||
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
|
|
||||||
export default async function fetchDeps(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
await mkdirp(moduleInfo.moduleDotHakDir);
|
|
||||||
if (moduleInfo.scripts.fetchDeps) {
|
|
||||||
await moduleInfo.scripts.fetchDeps(hakEnv, moduleInfo);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import path from "node:path";
|
|
||||||
import os from "node:os";
|
|
||||||
import { getElectronVersionFromInstalled } from "app-builder-lib/out/electron/electronVersion.js";
|
|
||||||
import childProcess, { type SpawnOptions } from "node:child_process";
|
|
||||||
|
|
||||||
import { type Arch, type Target, TARGETS, getHost, isHostId, type TargetId } from "./target.js";
|
|
||||||
|
|
||||||
async function getRuntimeVersion(projectRoot: string): Promise<string> {
|
|
||||||
const electronVersion = await getElectronVersionFromInstalled(projectRoot);
|
|
||||||
if (!electronVersion) {
|
|
||||||
throw new Error("Can't determine Electron version");
|
|
||||||
}
|
|
||||||
return electronVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Tool = [cmd: string, ...args: string[]];
|
|
||||||
|
|
||||||
export default class HakEnv {
|
|
||||||
public readonly target: Target;
|
|
||||||
public runtime: string = "electron";
|
|
||||||
public runtimeVersion?: string;
|
|
||||||
public dotHakDir: string;
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
public readonly projectRoot: string,
|
|
||||||
targetId: TargetId | null,
|
|
||||||
) {
|
|
||||||
const target = targetId ? TARGETS[targetId] : getHost();
|
|
||||||
|
|
||||||
if (!target) {
|
|
||||||
throw new Error(`Unknown target ${targetId}!`);
|
|
||||||
}
|
|
||||||
this.target = target;
|
|
||||||
this.dotHakDir = path.join(this.projectRoot, ".hak");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async init(): Promise<void> {
|
|
||||||
this.runtimeVersion = await getRuntimeVersion(this.projectRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getTargetId(): TargetId {
|
|
||||||
return this.target.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isWin(): boolean {
|
|
||||||
return this.target.platform === "win32";
|
|
||||||
}
|
|
||||||
|
|
||||||
public isMac(): boolean {
|
|
||||||
return this.target.platform === "darwin";
|
|
||||||
}
|
|
||||||
|
|
||||||
public isLinux(): boolean {
|
|
||||||
return this.target.platform === "linux";
|
|
||||||
}
|
|
||||||
|
|
||||||
public isFreeBSD(): boolean {
|
|
||||||
return this.target.platform === "freebsd";
|
|
||||||
}
|
|
||||||
|
|
||||||
public getTargetArch(): Arch {
|
|
||||||
return this.target.arch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isHost(): boolean {
|
|
||||||
return isHostId(this.target.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public makeGypEnv(): Record<string, string | undefined> {
|
|
||||||
return {
|
|
||||||
...process.env,
|
|
||||||
npm_config_arch: this.target.arch,
|
|
||||||
npm_config_target_arch: this.target.arch,
|
|
||||||
npm_config_disturl: "https://electronjs.org/headers",
|
|
||||||
npm_config_runtime: this.runtime,
|
|
||||||
npm_config_target: this.runtimeVersion,
|
|
||||||
npm_config_build_from_source: "true",
|
|
||||||
npm_config_devdir: path.join(os.homedir(), ".electron-gyp"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public wantsStaticSqlCipher(): boolean {
|
|
||||||
return !(this.isLinux() || this.isFreeBSD()) || process.env.SQLCIPHER_BUNDLED == "1";
|
|
||||||
}
|
|
||||||
|
|
||||||
public spawn(
|
|
||||||
cmd: string,
|
|
||||||
args: string[],
|
|
||||||
{ ignoreWinCmdlet, ...options }: SpawnOptions & { ignoreWinCmdlet?: boolean } = {},
|
|
||||||
): Promise<void> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const proc = childProcess.spawn(cmd + (!ignoreWinCmdlet && this.isWin() ? ".cmd" : ""), args, {
|
|
||||||
stdio: "inherit",
|
|
||||||
// We need shell mode on Windows to be able to launch `.cmd` executables
|
|
||||||
// See https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
|
|
||||||
shell: this.isWin(),
|
|
||||||
...options,
|
|
||||||
});
|
|
||||||
proc.on("exit", (code) => {
|
|
||||||
if (code) {
|
|
||||||
reject(code);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async checkTools(tools: Tool[]): Promise<void> {
|
|
||||||
for (const [tool, ...args] of tools) {
|
|
||||||
try {
|
|
||||||
await this.spawn(tool, args, {
|
|
||||||
ignoreWinCmdlet: true,
|
|
||||||
stdio: ["ignore"],
|
|
||||||
shell: false,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
throw new Error(`Can't find ${tool}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import path, { dirname } from "node:path";
|
|
||||||
import { fileURLToPath } from "node:url";
|
|
||||||
|
|
||||||
import HakEnv from "./hakEnv.js";
|
|
||||||
import type { TargetId } from "./target.js";
|
|
||||||
import type { DependencyInfo } from "./dep.js";
|
|
||||||
import { loadJsonFile } from "../../src/utils.js";
|
|
||||||
import packageJson from "../../package.json";
|
|
||||||
|
|
||||||
// These can only be run on specific modules
|
|
||||||
const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "clean"];
|
|
||||||
|
|
||||||
// Shortcuts for multiple commands at once (useful for building universal binaries
|
|
||||||
// because you can run the fetch/fetchDeps/build for each arch and then copy/link once)
|
|
||||||
const METACOMMANDS: Record<string, string[]> = {
|
|
||||||
fetchandbuild: ["check", "fetch", "build"],
|
|
||||||
copyandlink: ["copy", "link"],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Scripts valid in a hak.json 'scripts' section
|
|
||||||
const HAKSCRIPTS = ["check", "fetch", "build"];
|
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
|
||||||
const prefix = path.join(__dirname, "..", "..");
|
|
||||||
|
|
||||||
const targetIds: TargetId[] = [];
|
|
||||||
// Apply `--target <target>` option if specified
|
|
||||||
// Can be specified multiple times for the copy command to bundle
|
|
||||||
// multiple arches into a single universal output module)
|
|
||||||
for (;;) {
|
|
||||||
// eslint-disable-line no-constant-condition
|
|
||||||
const targetIndex = process.argv.indexOf("--target");
|
|
||||||
if (targetIndex === -1) break;
|
|
||||||
|
|
||||||
if (targetIndex + 1 >= process.argv.length) {
|
|
||||||
console.error("--target option specified without a target");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
// Extract target ID and remove from args
|
|
||||||
targetIds.push(process.argv.splice(targetIndex, 2)[1] as TargetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const hakEnvs = targetIds.map((tid) => new HakEnv(prefix, tid));
|
|
||||||
if (hakEnvs.length == 0) hakEnvs.push(new HakEnv(prefix, null));
|
|
||||||
for (const h of hakEnvs) {
|
|
||||||
await h.init();
|
|
||||||
}
|
|
||||||
const hakEnv = hakEnvs[0];
|
|
||||||
|
|
||||||
const deps: Record<string, DependencyInfo> = {};
|
|
||||||
|
|
||||||
const hakDepsCfg = packageJson.hakDependencies || {};
|
|
||||||
|
|
||||||
for (const dep in hakDepsCfg) {
|
|
||||||
const hakJsonPath = path.join(prefix, "hak", dep, "hak.json");
|
|
||||||
let hakJson: Record<string, any>;
|
|
||||||
try {
|
|
||||||
hakJson = loadJsonFile(hakJsonPath);
|
|
||||||
} catch {
|
|
||||||
console.error("No hak.json found for " + dep + ".");
|
|
||||||
console.log("Expecting " + hakJsonPath);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
deps[dep] = {
|
|
||||||
name: dep,
|
|
||||||
version: hakDepsCfg[dep as keyof typeof hakDepsCfg],
|
|
||||||
cfg: hakJson,
|
|
||||||
moduleHakDir: path.join(prefix, "hak", dep),
|
|
||||||
moduleDotHakDir: path.join(hakEnv.dotHakDir, dep),
|
|
||||||
moduleTargetDotHakDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId()),
|
|
||||||
moduleBuildDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "build"),
|
|
||||||
moduleBuildDirs: hakEnvs.map((h) => path.join(h.dotHakDir, dep, h.getTargetId(), "build")),
|
|
||||||
moduleOutDir: path.join(hakEnv.dotHakDir, "hakModules", dep),
|
|
||||||
nodeModuleBinDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "build", "node_modules", ".bin"),
|
|
||||||
depPrefix: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "opt"),
|
|
||||||
scripts: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const s of HAKSCRIPTS) {
|
|
||||||
if (hakJson.scripts?.[s]) {
|
|
||||||
// Shockingly, using path.join and backslashes here doesn't work on Windows
|
|
||||||
const scriptModule = await import(`../../hak/${dep}/${hakJson.scripts[s]}`);
|
|
||||||
if (scriptModule.default) {
|
|
||||||
deps[dep].scripts[s] = scriptModule.default;
|
|
||||||
} else {
|
|
||||||
deps[dep].scripts[s] = scriptModule;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cmds: string[];
|
|
||||||
if (process.argv.length < 3) {
|
|
||||||
cmds = ["check", "fetch", "build", "copy", "link"];
|
|
||||||
} else if (METACOMMANDS[process.argv[2]]) {
|
|
||||||
cmds = METACOMMANDS[process.argv[2]];
|
|
||||||
} else {
|
|
||||||
cmds = [process.argv[2]];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hakEnvs.length > 1 && cmds.some((c) => !["copy", "link"].includes(c))) {
|
|
||||||
// We allow link here too for convenience because it's completely arch independent
|
|
||||||
console.error("Multiple targets only supported with the copy command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let modules = process.argv.slice(3);
|
|
||||||
if (modules.length === 0) modules = Object.keys(deps);
|
|
||||||
|
|
||||||
for (const cmd of cmds) {
|
|
||||||
if (!MODULECOMMANDS.includes(cmd)) {
|
|
||||||
console.error("Unknown command: " + cmd);
|
|
||||||
console.log("Commands I know about:");
|
|
||||||
for (const cmd of MODULECOMMANDS) {
|
|
||||||
console.log("\t" + cmd);
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cmdFunc = (await import("./" + cmd)).default;
|
|
||||||
|
|
||||||
for (const mod of modules) {
|
|
||||||
const depInfo = deps[mod];
|
|
||||||
if (depInfo === undefined) {
|
|
||||||
console.log("Module " + mod + " not found - is it in hakDependencies " + "in your package.json?");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
console.log("hak " + cmd + ": " + mod);
|
|
||||||
await cmdFunc(hakEnv, depInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import path from "node:path";
|
|
||||||
import os from "node:os";
|
|
||||||
import fsProm from "node:fs/promises";
|
|
||||||
|
|
||||||
import type HakEnv from "./hakEnv.js";
|
|
||||||
import { type DependencyInfo } from "./dep.js";
|
|
||||||
|
|
||||||
export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
|
||||||
const yarnrc = path.join(hakEnv.projectRoot, ".yarnrc");
|
|
||||||
// this is fairly terrible but it's reasonably clunky to either parse a yarnrc
|
|
||||||
// properly or get yarn to do it, so this will probably suffice for now.
|
|
||||||
// We just check to see if there is a local .yarnrc at all, and assume that
|
|
||||||
// if you've put one there yourself, you probably know what you're doing and
|
|
||||||
// we won't meddle with it.
|
|
||||||
// Also we do this for each module which is unnecessary, but meh.
|
|
||||||
try {
|
|
||||||
await fsProm.stat(yarnrc);
|
|
||||||
} catch {
|
|
||||||
await fsProm.writeFile(
|
|
||||||
yarnrc,
|
|
||||||
// XXX: 1. This must be absolute, as yarn will resolve link directories
|
|
||||||
// relative to the closest project root, which means when we run it
|
|
||||||
// in the dependency project, it will put the link directory in its
|
|
||||||
// own project folder rather than the main project.
|
|
||||||
// 2. The parser gets very confused by strings with colons in them
|
|
||||||
// (ie. Windows absolute paths) but strings in quotes get parsed as
|
|
||||||
// JSON so need to be valid JSON encoded strings (ie. have the
|
|
||||||
// backslashes escaped). JSON.stringify will add quotes and escape.
|
|
||||||
"--link-folder " + JSON.stringify(path.join(hakEnv.dotHakDir, "links")) + os.EOL,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await hakEnv.spawn("yarn", ["link"], {
|
|
||||||
cwd: moduleInfo.moduleOutDir,
|
|
||||||
});
|
|
||||||
await hakEnv.spawn("yarn", ["link", moduleInfo.name], {
|
|
||||||
cwd: hakEnv.projectRoot,
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,217 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 New Vector Ltd.
|
|
||||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE files in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { GLIBC, MUSL, familySync as processLibC } from "detect-libc";
|
|
||||||
|
|
||||||
// We borrow Rust's target naming scheme as a way of expressing all target
|
|
||||||
// details in a single string.
|
|
||||||
// See https://doc.rust-lang.org/rustc/platform-support.html.
|
|
||||||
export type TargetId =
|
|
||||||
| "aarch64-apple-darwin"
|
|
||||||
| "x86_64-apple-darwin"
|
|
||||||
| "universal-apple-darwin"
|
|
||||||
| "i686-pc-windows-msvc"
|
|
||||||
| "x86_64-pc-windows-msvc"
|
|
||||||
| "aarch64-pc-windows-msvc"
|
|
||||||
| "i686-unknown-freebsd"
|
|
||||||
| "x86_64-unknown-freebsd"
|
|
||||||
| "aarch64-unknown-freebsd"
|
|
||||||
| "i686-unknown-linux-musl"
|
|
||||||
| "i686-unknown-linux-gnu"
|
|
||||||
| "x86_64-unknown-linux-musl"
|
|
||||||
| "x86_64-unknown-linux-gnu"
|
|
||||||
| "aarch64-unknown-linux-musl"
|
|
||||||
| "aarch64-unknown-linux-gnu"
|
|
||||||
| "powerpc64le-unknown-linux-musl"
|
|
||||||
| "powerpc64le-unknown-linux-gnu";
|
|
||||||
|
|
||||||
// Values are expected to match those used in `process.platform`.
|
|
||||||
export type Platform = "darwin" | "freebsd" | "linux" | "win32";
|
|
||||||
|
|
||||||
// Values are expected to match those used in `process.arch`.
|
|
||||||
export type Arch = "arm64" | "ia32" | "x64" | "ppc64" | "universal";
|
|
||||||
|
|
||||||
// Values are expected to match those used by Visual Studio's `vcvarsall.bat`.
|
|
||||||
// See https://docs.microsoft.com/cpp/build/building-on-the-command-line?view=msvc-160#vcvarsall-syntax
|
|
||||||
export type VcVarsArch = "amd64" | "arm64" | "x86";
|
|
||||||
|
|
||||||
export type Target = {
|
|
||||||
id: TargetId;
|
|
||||||
platform: Platform;
|
|
||||||
arch: Arch;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type WindowsTarget = Target & {
|
|
||||||
platform: "win32";
|
|
||||||
vcVarsArch: VcVarsArch;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LinuxTarget = Target & {
|
|
||||||
platform: "linux";
|
|
||||||
libC: typeof GLIBC | typeof MUSL;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UniversalTarget = Target & {
|
|
||||||
arch: "universal";
|
|
||||||
subtargets: Target[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const aarch64AppleDarwin: Target = {
|
|
||||||
id: "aarch64-apple-darwin",
|
|
||||||
platform: "darwin",
|
|
||||||
arch: "arm64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const x8664AppleDarwin: Target = {
|
|
||||||
id: "x86_64-apple-darwin",
|
|
||||||
platform: "darwin",
|
|
||||||
arch: "x64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const universalAppleDarwin: UniversalTarget = {
|
|
||||||
id: "universal-apple-darwin",
|
|
||||||
platform: "darwin",
|
|
||||||
arch: "universal",
|
|
||||||
subtargets: [aarch64AppleDarwin, x8664AppleDarwin],
|
|
||||||
};
|
|
||||||
|
|
||||||
const i686PcWindowsMsvc: WindowsTarget = {
|
|
||||||
id: "i686-pc-windows-msvc",
|
|
||||||
platform: "win32",
|
|
||||||
arch: "ia32",
|
|
||||||
vcVarsArch: "x86",
|
|
||||||
};
|
|
||||||
|
|
||||||
const x8664PcWindowsMsvc: WindowsTarget = {
|
|
||||||
id: "x86_64-pc-windows-msvc",
|
|
||||||
platform: "win32",
|
|
||||||
arch: "x64",
|
|
||||||
vcVarsArch: "amd64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const aarch64WindowsMsvc: WindowsTarget = {
|
|
||||||
id: "aarch64-pc-windows-msvc",
|
|
||||||
platform: "win32",
|
|
||||||
arch: "arm64",
|
|
||||||
vcVarsArch: "arm64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const i686UnknownFreebsd: Target = {
|
|
||||||
id: "i686-unknown-freebsd",
|
|
||||||
platform: "freebsd",
|
|
||||||
arch: "ia32",
|
|
||||||
};
|
|
||||||
|
|
||||||
const x8664UnknownFreebsd: Target = {
|
|
||||||
id: "x86_64-unknown-freebsd",
|
|
||||||
platform: "freebsd",
|
|
||||||
arch: "x64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const aarch64UnknownFreebsd: Target = {
|
|
||||||
id: "aarch64-unknown-freebsd",
|
|
||||||
platform: "freebsd",
|
|
||||||
arch: "arm64",
|
|
||||||
};
|
|
||||||
|
|
||||||
const x8664UnknownLinuxGnu: LinuxTarget = {
|
|
||||||
id: "x86_64-unknown-linux-gnu",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "x64",
|
|
||||||
libC: GLIBC,
|
|
||||||
};
|
|
||||||
|
|
||||||
const x8664UnknownLinuxMusl: LinuxTarget = {
|
|
||||||
id: "x86_64-unknown-linux-musl",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "x64",
|
|
||||||
libC: MUSL,
|
|
||||||
};
|
|
||||||
|
|
||||||
const i686UnknownLinuxGnu: LinuxTarget = {
|
|
||||||
id: "i686-unknown-linux-gnu",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "ia32",
|
|
||||||
libC: GLIBC,
|
|
||||||
};
|
|
||||||
|
|
||||||
const i686UnknownLinuxMusl: LinuxTarget = {
|
|
||||||
id: "i686-unknown-linux-musl",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "ia32",
|
|
||||||
libC: MUSL,
|
|
||||||
};
|
|
||||||
|
|
||||||
const aarch64UnknownLinuxGnu: LinuxTarget = {
|
|
||||||
id: "aarch64-unknown-linux-gnu",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "arm64",
|
|
||||||
libC: GLIBC,
|
|
||||||
};
|
|
||||||
|
|
||||||
const aarch64UnknownLinuxMusl: LinuxTarget = {
|
|
||||||
id: "aarch64-unknown-linux-musl",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "arm64",
|
|
||||||
libC: MUSL,
|
|
||||||
};
|
|
||||||
|
|
||||||
const powerpc64leUnknownLinuxGnu: LinuxTarget = {
|
|
||||||
id: "powerpc64le-unknown-linux-gnu",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "ppc64",
|
|
||||||
libC: GLIBC,
|
|
||||||
};
|
|
||||||
|
|
||||||
const powerpc64leUnknownLinuxMusl: LinuxTarget = {
|
|
||||||
id: "powerpc64le-unknown-linux-musl",
|
|
||||||
platform: "linux",
|
|
||||||
arch: "ppc64",
|
|
||||||
libC: MUSL,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const TARGETS: Record<TargetId, Target> = {
|
|
||||||
// macOS
|
|
||||||
"aarch64-apple-darwin": aarch64AppleDarwin,
|
|
||||||
"x86_64-apple-darwin": x8664AppleDarwin,
|
|
||||||
"universal-apple-darwin": universalAppleDarwin,
|
|
||||||
// Windows
|
|
||||||
"i686-pc-windows-msvc": i686PcWindowsMsvc,
|
|
||||||
"x86_64-pc-windows-msvc": x8664PcWindowsMsvc,
|
|
||||||
"aarch64-pc-windows-msvc": aarch64WindowsMsvc,
|
|
||||||
// FreeBSD
|
|
||||||
"i686-unknown-freebsd": i686UnknownFreebsd,
|
|
||||||
"x86_64-unknown-freebsd": x8664UnknownFreebsd,
|
|
||||||
"aarch64-unknown-freebsd": aarch64UnknownFreebsd,
|
|
||||||
// Linux
|
|
||||||
"i686-unknown-linux-musl": i686UnknownLinuxMusl,
|
|
||||||
"i686-unknown-linux-gnu": i686UnknownLinuxGnu,
|
|
||||||
"x86_64-unknown-linux-musl": x8664UnknownLinuxMusl,
|
|
||||||
"x86_64-unknown-linux-gnu": x8664UnknownLinuxGnu,
|
|
||||||
"aarch64-unknown-linux-musl": aarch64UnknownLinuxMusl,
|
|
||||||
"aarch64-unknown-linux-gnu": aarch64UnknownLinuxGnu,
|
|
||||||
"powerpc64le-unknown-linux-musl": powerpc64leUnknownLinuxMusl,
|
|
||||||
"powerpc64le-unknown-linux-gnu": powerpc64leUnknownLinuxGnu,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getHost(): Target | undefined {
|
|
||||||
return Object.values(TARGETS).find(
|
|
||||||
(target) =>
|
|
||||||
target.platform === process.platform &&
|
|
||||||
target.arch === process.arch &&
|
|
||||||
(process.platform !== "linux" || (target as LinuxTarget).libC === processLibC()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isHostId(id: TargetId): boolean {
|
|
||||||
return getHost()?.id === id;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isHost(target: Target): boolean {
|
|
||||||
return getHost()?.id === target.id;
|
|
||||||
}
|
|
@ -17,7 +17,6 @@ docker run --rm -ti \
|
|||||||
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
|
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
|
||||||
-v ${PWD}:/project \
|
-v ${PWD}:/project \
|
||||||
-v ${PWD}/docker/node_modules:/project/node_modules \
|
-v ${PWD}/docker/node_modules:/project/node_modules \
|
||||||
-v ${PWD}/docker/.hak:/project/.hak \
|
|
||||||
-v ${PWD}/docker/.gnupg:/root/.gnupg \
|
-v ${PWD}/docker/.gnupg:/root/.gnupg \
|
||||||
-v ~/.cache/electron:/root/.cache/electron \
|
-v ~/.cache/electron:/root/.cache/electron \
|
||||||
-v ~/.cache/electron-builder:/root/.cache/electron-builder \
|
-v ~/.cache/electron-builder:/root/.cache/electron-builder \
|
||||||
|
@ -5369,6 +5369,10 @@ math-intrinsics@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
||||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||||
|
|
||||||
|
"matrix-seshat@https://gitpkg.vercel.app/matrix-org/seshat/seshat-node?t3chguy/binding-gyp":
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://gitpkg.vercel.app/matrix-org/seshat/seshat-node?t3chguy/binding-gyp#96cc77502e880d7eb163caaad75c2cbcb3733c6b"
|
||||||
|
|
||||||
matrix-web-i18n@^3.2.1:
|
matrix-web-i18n@^3.2.1:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/matrix-web-i18n/-/matrix-web-i18n-3.3.0.tgz#a9f9d87d18ef96f75171883abbf201952cbfbe22"
|
resolved "https://registry.yarnpkg.com/matrix-web-i18n/-/matrix-web-i18n-3.3.0.tgz#a9f9d87d18ef96f75171883abbf201952cbfbe22"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user