diff --git a/binding.gyp b/binding.gyp index 919189e..05b9c17 100644 --- a/binding.gyp +++ b/binding.gyp @@ -5,7 +5,7 @@ 'sources': [ 'src/addon.cc', 'src/canWrapper.cc', - ], + ], 'include_dirs': [ "src/", "externalCompileTimeDeps/include", @@ -15,21 +15,88 @@ "NAPI_VERSION=<(napi_build_version)" ], 'dependencies': [" Look at Octokit: https://github.com/octokit/octokit.js + await Promise.all([ + 'CANBridge-linuxarm32.zip', + 'CANBridge-linuxarm64.zip', + 'CANBridge-linuxx86-64.zip', + 'CANBridge-osxuniversal.zip', + 'CANBridge-windowsx86-64.zip', + 'headers.zip' + ].map(filename => downloadCanBridgeArtifact(filename))); + console.log("CANBridge download completed"); + console.log("Extracting headers"); - + const zipFiles = fs.readdirSync(tempDir).filter(filename => filename.endsWith('.zip') && filename !== 'headers.zip'); + for (const filename of zipFiles) { + await unzipCanBridgeArtifact(filename, tempDir); + } const headersZip = new AdmZip(path.join(tempDir, "headers.zip")); + headersZip.extractAllTo(path.join(externalCompileTimeDepsPath, 'include')); + console.log("Headers extracted"); + + moveRuntimeDeps(); - await headersZip.extractAllTo(path.join(externalCompileTimeDepsPath, 'include'), true); - console.log(`Successfully downloaded CANBridge ${canBridgeTag}`); + moveCompileTimeDeps(); } catch (e) { if (axios.isAxiosError(e) && e.request) { - console.error(`Failed to download CANBridge file ${e.request.protocol}//${e.request.host}/${e.request.path}`); + console.error(`Failed to download CANBridge file ${e.request.protocol}//${e.request.host}${e.request.path}`); } else { - console.error(`Failed to download CANBridge`); + console.error(`Other error occurred: ${e.message}`); // For non-axios errors, the stacktrace will likely be helpful throw e; } process.exit(1); } finally { if (fs.existsSync(tempDir)) { - fs.rmSync(tempDir, { recursive: true }); + fs.rmSync(tempDir, { recursive: true, force: true}); } } -async function downloadCanBridgeArtifact(filename, destDir) { +/** + * Move external compile time dependencies to the correct directory + * + * This function is used to move the external compile time dependencies to the correct directory based on the platform and architecture from downloaded artifacts + */ +function moveCompileTimeDeps() { + console.log("Moving external compile time dependencies to correct directories"); + if (!fs.existsSync(externalCompileTimeDepsPath)) { + fs.mkdirSync(externalCompileTimeDepsPath, { recursive: true }); + } + if (platform() === 'win32') { + const deps = ['CANBridge.lib', 'wpiHal.lib', 'wpiutil.lib']; + deps.forEach(dep => moveExternalCompileTimeDeps(path.join('win32-x64', dep))); + } else if (platform() === 'darwin') { + const deps = ['libCANBridge.a']; + deps.forEach(dep => moveExternalCompileTimeDeps(path.join('darwin-osxuniversal', dep))); + } else if (platform() === 'linux') { + const deps = ['libCANBridge.a']; + const archDepMap = { + x64: 'linux-x64', + arm64: 'linux-arm64', + arm: 'linux-arm32' + }; + deps.forEach(dep => moveExternalCompileTimeDeps(path.join(archDepMap[arch()], dep))); + } + console.log("External compile time dependencies moved to correct directories"); +} + +/** + * Move runtime dependencies to the correct directory + * + * This function is used to move the runtime dependencies to the correct directory based on the platform and architecture from downloaded artifacts + */ +function moveRuntimeDeps() { + console.log("Moving artifacts to correct directories"); + if (!fs.existsSync('prebuilds')) { + fs.mkdirSync('prebuilds', { recursive: true }); + } + if (platform() === 'win32') { + const deps = ['CANBridge.dll', 'wpiHal.dll', 'wpiutil.dll']; + deps.forEach(dep => moveRuntimeArtifactsDeps(path.join('win32-x64', dep), runtimeArtifactsPath.win)); + } else if (platform() === 'darwin') { + const deps = ['libCANBridge.dylib', 'libwpiHal.dylib', 'libwpiutil.dylib']; + deps.forEach(dep => moveRuntimeArtifactsDeps(path.join('darwin-osxuniversal', dep), runtimeArtifactsPath.osx)); + } else if (platform() === 'linux') { + const deps = ['libCANBridge.so', 'libwpiHal.so', 'libwpiutil.so']; + if (arch() === 'x64') { + deps.forEach(dep => moveRuntimeArtifactsDeps(path.join('linux-x64', dep), runtimeArtifactsPath.linux)); + } + if (arch() === 'arm64') { + deps.forEach(dep => moveRuntimeArtifactsDeps(path.join('linux-arm64', dep), runtimeArtifactsPath.linuxArm)); + } + if (arch() === 'arm') { + deps.forEach(dep => moveRuntimeArtifactsDeps(path.join('linux-arm32', dep), runtimeArtifactsPath.linuxArm32)); + } + } + console.log("CANBridge artifacts moved to correct directories"); +} + +/** + * Download artifacts from the CANBridge GitHub release page + * + * @param {*} filename filename of the artifact to download + * @param {*} destDir destination directory to save the artifact, defaults to tempDir + */ +async function downloadCanBridgeArtifact(filename, destDir = tempDir) { fs.mkdirSync(destDir, { recursive: true }); const response = await axios.get(`${canBridgeReleaseAssetUrlPrefix}/${filename}`, { responseType: "stream" }); const fileStream = fs.createWriteStream(`${destDir}/${filename}`); @@ -51,3 +131,40 @@ async function downloadCanBridgeArtifact(filename, destDir) { fileStream.on('finish', resolve); }); } + +/** + * Unzip the CANBridge artifacts + * + * @param {string} filename - filename of the artifact to unzip + * @param {string} destDir - destination directory to unzip the artifact + */ +async function unzipCanBridgeArtifact(filename, destDir) { + const zip = new AdmZip(`${destDir}/${filename}`); + let filepath; + if (filename.includes('linuxarm32')) filepath = "linux-arm32"; + else if (filename.includes('linuxarm64')) filepath = "linux-arm64"; + else if (filename.includes('linuxx86-64')) filepath = "linux-x64"; + else if (filename.includes('osxuniversal')) filepath = "darwin-osxuniversal"; + else if (filename.includes('windowsx86-64')) filepath = "win32-x64"; + zip.extractAllTo(`${destDir}/${filepath}`); +} + +/** + * Move runtime artifacts to the correct directory + * + * @param {*} filename filename of the artifact to move + * @param {*} destDir destination directory to save the artifact + */ +function moveRuntimeArtifactsDeps(filename, destDir) { + fs.mkdirSync(destDir, { recursive: true }); + fs.renameSync(path.join(tempDir, filename), path.join(destDir, path.basename(filename))); +} + +/** + * Move External Compile Time Dependencies to the correct directory + * + * @param {*} filename filename of the artifact to move + */ +function moveExternalCompileTimeDeps(filename) { + fs.renameSync(path.join(tempDir, filename), path.join(externalCompileTimeDepsPath, path.basename(filename))); +} \ No newline at end of file