Skip to content

Commit 50943a3

Browse files
garrettsummerfi3ldqwertychouskie
authored andcommitted
Major refactor for handling CANBridge
Added proper support for macOS, Linux, ARM64, and ARM32 based systems. Rewrote handling artifacts from unzipping, to moving artifacts to correct directories based on what platforms are downloaded and what is currently running on. Added documentation to helper functions.
1 parent 45ab8d8 commit 50943a3

File tree

1 file changed

+137
-18
lines changed

1 file changed

+137
-18
lines changed

scripts/download-CanBridge.mjs

Lines changed: 137 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,128 @@ import * as fs from "fs";
22
import * as path from "path";
33
import axios from 'axios';
44
import AdmZip from 'adm-zip';
5+
import { platform, arch } from 'os';
56

6-
const canBridgeTag = "v2.3.0";
7+
const canBridgeTag = "v2.3.1";
78
const canBridgeReleaseAssetUrlPrefix = `https://github.com/unofficial-rev-port/CANBridge/releases/download/${canBridgeTag}`;
89

910
const externalCompileTimeDepsPath = 'externalCompileTimeDeps';
10-
const runtimeArtifactsPath = path.join('prebuilds', 'win32-x64');
11+
const runtimeArtifactsPath = {
12+
win: 'prebuilds/win32-x64',
13+
osx: 'prebuilds/darwin-x64',
14+
osxArm: 'prebuilds/darwin-arm64',
15+
linux: 'prebuilds/linux-x64',
16+
linuxArm: 'prebuilds/linux-arm64',
17+
linuxArm32: 'prebuilds/linux-arm32'
18+
};
1119
const tempDir = 'temp';
1220

1321
try {
14-
await Promise.all(Array.of(
15-
downloadCanBridgeArtifact('CANBridge.lib', externalCompileTimeDepsPath),
16-
downloadCanBridgeArtifact('CANBridge.dll', runtimeArtifactsPath),
17-
downloadCanBridgeArtifact('wpiHal.lib', externalCompileTimeDepsPath),
18-
downloadCanBridgeArtifact('wpiHal.dll', runtimeArtifactsPath),
19-
downloadCanBridgeArtifact('wpiutil.lib', externalCompileTimeDepsPath),
20-
downloadCanBridgeArtifact('wpiutil.dll', runtimeArtifactsPath),
21-
downloadCanBridgeArtifact('headers.zip', tempDir),
22-
));
23-
22+
// TODO: Do not hardcode the filenames, instead get them from the GitHub API -> Look at Octokit: https://github.com/octokit/octokit.js
23+
await Promise.all([
24+
'CANBridge-linuxarm32-LinuxARM32.zip',
25+
'CANBridge-linuxarm64-LinuxARM64.zip',
26+
'CANBridge-linuxx86-64-Linux64.zip',
27+
'CANBridge-osxuniversal-MacOS64.zip',
28+
'CANBridge-osxuniversal-MacOSARM64.zip',
29+
'CANBridge-windowsx86-64-Win64.zip',
30+
'headers.zip'
31+
].map(filename => downloadCanBridgeArtifact(filename)));
2432
console.log("CANBridge download completed");
25-
console.log("Extracting headers");
2633

34+
35+
console.log("Extracting headers");
36+
const zipFiles = fs.readdirSync(tempDir).filter(filename => filename.endsWith('.zip') && filename !== 'headers.zip');
37+
for (const filename of zipFiles) {
38+
await unzipCanBridgeArtifact(filename, tempDir);
39+
}
2740
const headersZip = new AdmZip(path.join(tempDir, "headers.zip"));
41+
headersZip.extractAllTo(path.join(externalCompileTimeDepsPath, 'include'));
42+
console.log("Headers extracted");
43+
44+
moveRuntimeDeps();
2845

29-
await headersZip.extractAllTo(path.join(externalCompileTimeDepsPath, 'include'));
46+
moveCompileTimeDeps();
3047
} catch (e) {
3148
if (axios.isAxiosError(e) && e.request) {
32-
console.error(`Failed to download CANBridge file ${e.request.protocol}//${e.request.host}/${e.request.path}`);
49+
console.error(`Failed to download CANBridge file ${e.request.protocol}//${e.request.host}${e.request.path}`);
3350
} else {
34-
console.error(`Failed to download CANBridge`);
51+
console.error(`Other error occurred: ${e.message}`);
3552
// For non-axios errors, the stacktrace will likely be helpful
3653
throw e;
3754
}
3855
process.exit(1);
3956
} finally {
4057
if (fs.existsSync(tempDir)) {
41-
fs.rmSync(tempDir, { recursive: true });
58+
fs.rmSync(tempDir, { recursive: true, force: true});
4259
}
4360
}
4461

45-
async function downloadCanBridgeArtifact(filename, destDir) {
62+
/**
63+
* Move external compile time dependencies to the correct directory
64+
*
65+
* This function is used to move the external compile time dependencies to the correct directory based on the platform and architecture from downloaded artifacts
66+
*/
67+
function moveCompileTimeDeps() {
68+
console.log("Moving external compile time dependencies to correct directories");
69+
if (platform() === 'win32') {
70+
const deps = ['CANBridge.lib', 'wpiHal.lib', 'wpiutil.lib'];
71+
deps.forEach(dep => moveExternalCompileTimeDeps(path.join('win32-x64', dep)));
72+
} else if (platform() === 'darwin') {
73+
const deps = ['libCANBridge.a'];
74+
const archDepMap = {
75+
x64: 'darwin-x64',
76+
arm64: 'darwin-arm64'
77+
};
78+
deps.forEach(dep => moveExternalCompileTimeDeps(path.join(archDepMap[arch()], dep)));
79+
} else if (platform() === 'linux') {
80+
const deps = ['libCANBridge.a'];
81+
const archDepMap = {
82+
x64: 'linux-x64',
83+
arm64: 'linux-arm64',
84+
arm: 'linux-arm32'
85+
};
86+
deps.forEach(dep => moveExternalCompileTimeDeps(path.join(archDepMap[arch()], dep)));
87+
}
88+
console.log("External compile time dependencies moved to correct directories");
89+
}
90+
91+
/**
92+
* Move runtime dependencies to the correct directory
93+
*
94+
* This function is used to move the runtime dependencies to the correct directory based on the platform and architecture from downloaded artifacts
95+
*/
96+
function moveRuntimeDeps() {
97+
console.log("Moving artifacts to correct directories");
98+
if (platform() === 'win32') {
99+
const deps = ['CANBridge.dll', 'wpiHal.dll', 'wpiutil.dll'];
100+
deps.forEach(dep => moveRuntimeArtifactsDeps(path.join('win32-x64', dep), runtimeArtifactsPath.win));
101+
} else if (platform() === 'darwin') {
102+
const deps = ['libCANBridge.dylib', 'libwpiHal.dylib', 'libwpiutil.dylib'];
103+
const archDepMap = {
104+
x64: runtimeArtifactsPath.osx,
105+
arm64: runtimeArtifactsPath.osxArm
106+
};
107+
deps.forEach(dep => moveRuntimeArtifactsDeps(path.join(archDepMap[arch()], dep), archDepMap[arch()]));
108+
} else if (platform() === 'linux') {
109+
const deps = ['libCANBridge.so', 'libwpiHal.so', 'libwpiutil.so'];
110+
const archDepMap = {
111+
x64: runtimeArtifactsPath.linux,
112+
arm64: runtimeArtifactsPath.linuxArm,
113+
arm: runtimeArtifactsPath.linuxArm32
114+
};
115+
deps.forEach(dep => moveRuntimeArtifactsDeps(path.join(archDepMap[arch()], dep), archDepMap[arch()]));
116+
}
117+
console.log("CANBridge artifacts moved to correct directories");
118+
}
119+
120+
/**
121+
* Download artifacts from the CANBridge GitHub release page
122+
*
123+
* @param {*} filename filename of the artifact to download
124+
* @param {*} destDir destination directory to save the artifact, defaults to tempDir
125+
*/
126+
async function downloadCanBridgeArtifact(filename, destDir = tempDir) {
46127
fs.mkdirSync(destDir, { recursive: true });
47128
const response = await axios.get(`${canBridgeReleaseAssetUrlPrefix}/${filename}`, { responseType: "stream" });
48129
const fileStream = fs.createWriteStream(`${destDir}/${filename}`);
@@ -51,3 +132,41 @@ async function downloadCanBridgeArtifact(filename, destDir) {
51132
fileStream.on('finish', resolve);
52133
});
53134
}
135+
136+
/**
137+
* Unzip the CANBridge artifacts
138+
*
139+
* @param {string} filename - filename of the artifact to unzip
140+
* @param {string} destDir - destination directory to unzip the artifact
141+
*/
142+
async function unzipCanBridgeArtifact(filename, destDir) {
143+
const zip = new AdmZip(`${destDir}/${filename}`);
144+
let filepath;
145+
if (filename.includes('linuxarm32')) filepath = "linux-arm32";
146+
else if (filename.includes('linuxarm64')) filepath = "linux-arm64";
147+
else if (filename.includes('linuxx86-64')) filepath = "linux-x64";
148+
else if (filename.includes('MacOS64')) filepath = "darwin-x64";
149+
else if (filename.includes('MacOSARM64')) filepath = "darwin-arm64";
150+
else if (filename.includes('windowsx86-64')) filepath = "win32-x64";
151+
zip.extractAllTo(`${destDir}/${filepath}`);
152+
}
153+
154+
/**
155+
* Move runtime artifacts to the correct directory
156+
*
157+
* @param {*} filename filename of the artifact to move
158+
* @param {*} destDir destination directory to save the artifact
159+
*/
160+
function moveRuntimeArtifactsDeps(filename, destDir) {
161+
fs.mkdirSync(destDir, { recursive: true });
162+
fs.renameSync(path.join(tempDir, filename), path.join(destDir, path.basename(filename)));
163+
}
164+
165+
/**
166+
* Move External Compile Time Dependencies to the correct directory
167+
*
168+
* @param {*} filename filename of the artifact to move
169+
*/
170+
function moveExternalCompileTimeDeps(filename) {
171+
fs.renameSync(path.join(tempDir, filename), path.join(externalCompileTimeDepsPath, path.basename(filename)));
172+
}

0 commit comments

Comments
 (0)