mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-02 04:56:06 +02:00
arm64 support
This commit is contained in:
+4
-2
@@ -13,8 +13,10 @@
|
|||||||
"test:coverage": "jest --coverage",
|
"test:coverage": "jest --coverage",
|
||||||
"prod": "cross-env PLATFORM=windows webpack --config webpack.config.js --mode production",
|
"prod": "cross-env PLATFORM=windows webpack --config webpack.config.js --mode production",
|
||||||
"prod-linux": "cross-env PLATFORM=linux webpack --config webpack.config.js --mode production",
|
"prod-linux": "cross-env PLATFORM=linux webpack --config webpack.config.js --mode production",
|
||||||
"build-electron": "node ./src-electron/download-dotnet-runtime.js && node ./src-electron/patch-package-version.js && electron-builder --publish never",
|
"build-electron": "node ./src-electron/download-dotnet-runtime.js --arch=x64 && node ./src-electron/patch-package-version.js && electron-builder --x64 --publish never",
|
||||||
"postbuild-electron": "node ./src-electron/patch-node-api-dotnet.js && node ./src-electron/rename-builds.js",
|
"build-electron-arm64": "node ./src-electron/download-dotnet-runtime.js --arch=arm64 && node ./src-electron/patch-package-version.js && electron-builder --arm64 --publish never",
|
||||||
|
"postbuild-electron": "node ./src-electron/patch-node-api-dotnet.js --arch=x64 && node ./src-electron/rename-builds.js --arch=x64",
|
||||||
|
"postbuild-electron-arm64": "node ./src-electron/patch-node-api-dotnet.js --arch=arm64 && node ./src-electron/rename-builds.js --arch=arm64",
|
||||||
"start-electron": "electron ."
|
"start-electron": "electron ."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -2,30 +2,9 @@ const fs = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
const { spawnSync } = require('child_process');
|
const { spawnSync } = require('child_process');
|
||||||
|
const { getArchAndPlatform } = require('./utils');
|
||||||
let runnerArch = process.arch.toString();
|
|
||||||
let runnerPlatform = process.platform.toString();
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
for (let i = 0; i < args.length; i++) {
|
|
||||||
if (args[i] === '--arch' && i + 1 < args.length) {
|
|
||||||
runnerArch = args[i + 1];
|
|
||||||
} else if (args[i] === '--platform' && i + 1 < args.length) {
|
|
||||||
runnerPlatform = args[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let platform = '';
|
|
||||||
if (runnerPlatform === 'linux') {
|
|
||||||
platform = 'linux';
|
|
||||||
} else if (runnerPlatform === 'darwin') {
|
|
||||||
platform = 'osx';
|
|
||||||
} else if (runnerPlatform === 'win32') {
|
|
||||||
platform = 'win';
|
|
||||||
} else {
|
|
||||||
throw new Error(`Unsupported platform: ${runnerPlatform}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const DOTNET_VERSION = '9.0.8';
|
const DOTNET_VERSION = '9.0.8';
|
||||||
const DOTNET_RUNTIME_URL = `https://builds.dotnet.microsoft.com/dotnet/Runtime/${DOTNET_VERSION}/dotnet-runtime-${DOTNET_VERSION}-${platform}-${runnerArch}.tar.gz`;
|
|
||||||
const DOTNET_RUNTIME_DIR = path.join(
|
const DOTNET_RUNTIME_DIR = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'..',
|
'..',
|
||||||
@@ -78,25 +57,34 @@ async function extractTarGz(tarGzPath, extractDir) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function downloadDotnetRuntime(arch, platform) {
|
||||||
if (platform !== 'linux' && platform !== 'darwin') {
|
if (!arch || !platform) {
|
||||||
console.log('Skipping .NET runtime download on non supported platform');
|
throw new Error('Architecture and platform must be specified');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
let dotnetPlatform = '';
|
||||||
`Downloading .NET ${DOTNET_VERSION}-${platform}-${runnerArch} runtime...`
|
if (platform === 'linux') {
|
||||||
);
|
dotnetPlatform = 'linux';
|
||||||
|
} else if (platform === 'darwin') {
|
||||||
|
dotnetPlatform = 'osx';
|
||||||
|
} else if (platform === 'win32') {
|
||||||
|
dotnetPlatform = 'win';
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported platform: ${platform}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(DOTNET_RUNTIME_DIR)) {
|
if (!fs.existsSync(DOTNET_RUNTIME_DIR)) {
|
||||||
fs.mkdirSync(DOTNET_RUNTIME_DIR, { recursive: true });
|
fs.mkdirSync(DOTNET_RUNTIME_DIR, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Downloading .NET ${DOTNET_VERSION}-${dotnetPlatform}-${arch} runtime...`
|
||||||
|
);
|
||||||
const tarGzPath = path.join(DOTNET_RUNTIME_DIR, 'dotnet-runtime.tar.gz');
|
const tarGzPath = path.join(DOTNET_RUNTIME_DIR, 'dotnet-runtime.tar.gz');
|
||||||
|
const dotnetRuntimeUrl = `https://builds.dotnet.microsoft.com/dotnet/Runtime/${DOTNET_VERSION}/dotnet-runtime-${DOTNET_VERSION}-${dotnetPlatform}-${arch}.tar.gz`;
|
||||||
|
|
||||||
try {
|
|
||||||
// Download .NET runtime
|
// Download .NET runtime
|
||||||
await downloadFile(DOTNET_RUNTIME_URL, tarGzPath);
|
await downloadFile(dotnetRuntimeUrl, tarGzPath);
|
||||||
console.log('Download completed');
|
console.log('Download completed');
|
||||||
|
|
||||||
// Extract .NET runtime to a temporary directory first
|
// Extract .NET runtime to a temporary directory first
|
||||||
@@ -142,14 +130,7 @@ async function main() {
|
|||||||
console.log(
|
console.log(
|
||||||
`.NET runtime downloaded and extracted to: ${DOTNET_RUNTIME_DIR}`
|
`.NET runtime downloaded and extracted to: ${DOTNET_RUNTIME_DIR}`
|
||||||
);
|
);
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error.message);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (require.main === module) {
|
const { arch, platform } = getArchAndPlatform();
|
||||||
main();
|
downloadDotnetRuntime(arch, platform);
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { downloadFile, extractTarGz };
|
|
||||||
|
|||||||
+10
-7
@@ -16,16 +16,11 @@ const https = require('https');
|
|||||||
|
|
||||||
//app.disableHardwareAcceleration();
|
//app.disableHardwareAcceleration();
|
||||||
|
|
||||||
if (process.platform === 'linux') {
|
const bundledDotNetPath = path.join(process.resourcesPath, 'dotnet-runtime');
|
||||||
// Include bundled .NET runtime
|
|
||||||
const bundledDotNetPath = path.join(
|
|
||||||
process.resourcesPath,
|
|
||||||
'dotnet-runtime'
|
|
||||||
);
|
|
||||||
if (fs.existsSync(bundledDotNetPath)) {
|
if (fs.existsSync(bundledDotNetPath)) {
|
||||||
|
// Include bundled .NET runtime
|
||||||
process.env.DOTNET_ROOT = bundledDotNetPath;
|
process.env.DOTNET_ROOT = bundledDotNetPath;
|
||||||
process.env.PATH = `${bundledDotNetPath}:${process.env.PATH}`;
|
process.env.PATH = `${bundledDotNetPath}:${process.env.PATH}`;
|
||||||
}
|
|
||||||
} else if (process.platform === 'darwin') {
|
} else if (process.platform === 'darwin') {
|
||||||
const dotnetPath = path.join('/usr/local/share/dotnet');
|
const dotnetPath = path.join('/usr/local/share/dotnet');
|
||||||
const dotnetPathArm = path.join('/usr/local/share/dotnet/x64');
|
const dotnetPathArm = path.join('/usr/local/share/dotnet/x64');
|
||||||
@@ -154,6 +149,10 @@ if (!gotTheLock) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipcMain.handle('getArch', () => {
|
||||||
|
return process.arch.toString();
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.handle('applyWindowSettings', (event, position, size, state) => {
|
ipcMain.handle('applyWindowSettings', (event, position, size, state) => {
|
||||||
if (position) {
|
if (position) {
|
||||||
mainWindow.setPosition(parseInt(position.x), parseInt(position.y));
|
mainWindow.setPosition(parseInt(position.x), parseInt(position.y));
|
||||||
@@ -812,6 +811,10 @@ function isDotNetInstalled() {
|
|||||||
const result = spawnSync(dotnetPath, ['--list-runtimes'], {
|
const result = spawnSync(dotnetPath, ['--list-runtimes'], {
|
||||||
encoding: 'utf-8'
|
encoding: 'utf-8'
|
||||||
});
|
});
|
||||||
|
if (result.error) {
|
||||||
|
console.error('Error checking .NET runtimes:', result.error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return result.stdout?.includes('.NETCore.App 9.0');
|
return result.stdout?.includes('.NETCore.App 9.0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const { getArchAndPlatform } = require('./utils');
|
||||||
|
|
||||||
function patchFile(filePath) {
|
function patchFile(filePath) {
|
||||||
if (!fs.existsSync(filePath)) {
|
if (!fs.existsSync(filePath)) {
|
||||||
@@ -30,9 +31,9 @@ managedHostPath = managedHostPath.indexOf('app.asar.unpacked') < 0 ?
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paths to patch
|
function patchNodeApiDotNet(arch, platform) {
|
||||||
let platformName = '';
|
let platformName = '';
|
||||||
switch (process.platform) {
|
switch (platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
platformName = 'win';
|
platformName = 'win';
|
||||||
break;
|
break;
|
||||||
@@ -43,12 +44,17 @@ switch (process.platform) {
|
|||||||
platformName = 'linux';
|
platformName = 'linux';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (process.arch === 'arm64') {
|
if (arch === 'arm64') {
|
||||||
platformName += '-arm64';
|
platformName += '-arm64';
|
||||||
}
|
}
|
||||||
|
|
||||||
const postBuildPath = path.join(
|
const postBuildPath = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
`./../build/${platformName}-unpacked/resources/app.asar.unpacked/node_modules/node-api-dotnet/init.js`
|
`./../build/${platformName}-unpacked/resources/app.asar.unpacked/node_modules/node-api-dotnet/init.js`
|
||||||
);
|
);
|
||||||
console.log('Patching post-build init.js...');
|
console.log('Patching post-build init.js...');
|
||||||
patchFile(postBuildPath);
|
patchFile(postBuildPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { arch, platform } = getArchAndPlatform();
|
||||||
|
patchNodeApiDotNet(arch, platform);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ contextBridge.exposeInMainWorld('interopApi', {
|
|||||||
const validChannels = ['launch-command'];
|
const validChannels = ['launch-command'];
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electron', {
|
contextBridge.exposeInMainWorld('electron', {
|
||||||
|
getArch: () => ipcRenderer.invoke('getArch'),
|
||||||
openFileDialog: () => ipcRenderer.invoke('dialog:openFile'),
|
openFileDialog: () => ipcRenderer.invoke('dialog:openFile'),
|
||||||
openDirectoryDialog: () => ipcRenderer.invoke('dialog:openDirectory'),
|
openDirectoryDialog: () => ipcRenderer.invoke('dialog:openDirectory'),
|
||||||
onWindowPositionChanged: (callback) =>
|
onWindowPositionChanged: (callback) =>
|
||||||
@@ -48,7 +49,6 @@ contextBridge.exposeInMainWorld('electron', {
|
|||||||
ipcRenderer: {
|
ipcRenderer: {
|
||||||
on(channel, func) {
|
on(channel, func) {
|
||||||
if (validChannels.includes(channel)) {
|
if (validChannels.includes(channel)) {
|
||||||
console.log('contextBridge', channel, func);
|
|
||||||
ipcRenderer.on(channel, (event, ...args) => func(...args));
|
ipcRenderer.on(channel, (event, ...args) => func(...args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const { getArchAndPlatform } = require('./utils');
|
||||||
|
|
||||||
const rootDir = path.join(__dirname, '..');
|
const rootDir = path.join(__dirname, '..');
|
||||||
const versionFilePath = path.join(rootDir, 'Version');
|
const versionFilePath = path.join(rootDir, 'Version');
|
||||||
@@ -17,9 +18,13 @@ try {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'linux') {
|
function renameBuild(arch, platform) {
|
||||||
|
if (platform === 'linux') {
|
||||||
const oldAppImage = path.join(buildDir, `VRCX_Version.AppImage`);
|
const oldAppImage = path.join(buildDir, `VRCX_Version.AppImage`);
|
||||||
const newAppImage = path.join(buildDir, `VRCX_${version}.AppImage`);
|
const newAppImage = path.join(
|
||||||
|
buildDir,
|
||||||
|
`VRCX_${version}_${arch}.AppImage`
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(oldAppImage)) {
|
if (fs.existsSync(oldAppImage)) {
|
||||||
fs.renameSync(oldAppImage, newAppImage);
|
fs.renameSync(oldAppImage, newAppImage);
|
||||||
@@ -31,9 +36,9 @@ if (process.platform === 'linux') {
|
|||||||
console.error('Error renaming files:', err);
|
console.error('Error renaming files:', err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
} else if (process.platform === 'darwin') {
|
} else if (platform === 'darwin') {
|
||||||
const oldDmg = path.join(buildDir, `VRCX_Version.dmg`);
|
const oldDmg = path.join(buildDir, `VRCX_Version.dmg`);
|
||||||
const newDmg = path.join(buildDir, `VRCX_${version}.dmg`);
|
const newDmg = path.join(buildDir, `VRCX_${version}_${arch}.dmg`);
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(oldDmg)) {
|
if (fs.existsSync(oldDmg)) {
|
||||||
fs.renameSync(oldDmg, newDmg);
|
fs.renameSync(oldDmg, newDmg);
|
||||||
@@ -48,3 +53,7 @@ if (process.platform === 'linux') {
|
|||||||
} else {
|
} else {
|
||||||
console.log('No renaming needed for this platform.');
|
console.log('No renaming needed for this platform.');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { arch, platform } = getArchAndPlatform();
|
||||||
|
renameBuild(arch, platform);
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
function getArchAndPlatform() {
|
||||||
|
// --arch= win32, darwin, linux
|
||||||
|
// --platform= x64, arm64
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
let arch = process.arch.toString();
|
||||||
|
let platform = process.platform.toString();
|
||||||
|
for (let i = 0; i < args.length; i++) {
|
||||||
|
if (args[i].startsWith('--arch=')) {
|
||||||
|
arch = args[i].split('=')[1];
|
||||||
|
}
|
||||||
|
if (args[i].startsWith('--platform=')) {
|
||||||
|
platform = args[i].split('=')[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(`Using arch: ${arch}, platform: ${platform}`);
|
||||||
|
return { arch, platform };
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { getArchAndPlatform };
|
||||||
@@ -14,6 +14,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
arch: 'x64',
|
||||||
appVersion: '',
|
appVersion: '',
|
||||||
autoUpdateVRCX: 'Auto Download',
|
autoUpdateVRCX: 'Auto Download',
|
||||||
latestAppVersion: '',
|
latestAppVersion: '',
|
||||||
@@ -40,6 +41,12 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function initVRCXUpdaterSettings() {
|
async function initVRCXUpdaterSettings() {
|
||||||
|
if (!WINDOWS) {
|
||||||
|
const arch = await window.electron.getArch();
|
||||||
|
console.log('Architecture:', arch);
|
||||||
|
state.arch = arch;
|
||||||
|
}
|
||||||
|
|
||||||
const [autoUpdateVRCX, vrcxId] = await Promise.all([
|
const [autoUpdateVRCX, vrcxId] = await Promise.all([
|
||||||
configRepository.getString('VRCX_autoUpdateVRCX', 'Auto Download'),
|
configRepository.getString('VRCX_autoUpdateVRCX', 'Auto Download'),
|
||||||
configRepository.getString('VRCX_id', '')
|
configRepository.getString('VRCX_id', '')
|
||||||
@@ -200,7 +207,7 @@ export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
LINUX &&
|
LINUX &&
|
||||||
asset.name.endsWith('.AppImage') &&
|
asset.name.endsWith(`${state.arch}.AppImage`) &&
|
||||||
asset.content_type === 'application/octet-stream'
|
asset.content_type === 'application/octet-stream'
|
||||||
) {
|
) {
|
||||||
downloadUrl = asset.browser_download_url;
|
downloadUrl = asset.browser_download_url;
|
||||||
|
|||||||
Vendored
+2
-1
@@ -30,6 +30,7 @@ declare global {
|
|||||||
) => Promise<any>;
|
) => Promise<any>;
|
||||||
};
|
};
|
||||||
electron: {
|
electron: {
|
||||||
|
getArch: () => Promise<string>;
|
||||||
openFileDialog: () => Promise<string>;
|
openFileDialog: () => Promise<string>;
|
||||||
openDirectoryDialog: () => Promise<string>;
|
openDirectoryDialog: () => Promise<string>;
|
||||||
desktopNotification: (
|
desktopNotification: (
|
||||||
@@ -63,7 +64,7 @@ declare global {
|
|||||||
overlayHand: int
|
overlayHand: int
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
ipcRenderer: {
|
ipcRenderer: {
|
||||||
on(channel: String, func: (...args: unknown[]) => void)
|
on(channel: String, func: (...args: unknown[]) => void);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
__APP_GLOBALS__: AppGlobals;
|
__APP_GLOBALS__: AppGlobals;
|
||||||
|
|||||||
Reference in New Issue
Block a user