UNPKG

nertc-electron-sdk

Version:
413 lines (377 loc) 14.7 kB
#! /usr/bin/env node const { execSync } = require('child_process'); const path = require('path'); const requireWithFallback = (name) => { try { return require(name); } catch (err) { if (process.env.INIT_CWD) { try { return require(path.join(process.env.INIT_CWD, 'node_modules', name)); } catch (_) {} } throw err; } }; const fetch = requireWithFallback('node-fetch'); const tar = requireWithFallback('tar'); const glob = requireWithFallback('glob'); const download = requireWithFallback('download'); const fse = requireWithFallback('fs-extra'); const {Command} = requireWithFallback('commander'); const program = new Command(); const package_json = require(process.cwd() + '/package.json'); if (!package_json.node_pre_build) { package_json.node_pre_build = {}; } const name_addon = package_json.node_pre_build['name'] ? package_json.node_pre_build['name'] : (package_json.node_pre_build['name-addon'] ? package_json.node_pre_build['name-addon'] : package_json.name); const name_sdk = package_json.node_pre_build['name'] ? package_json.node_pre_build['name'] : (package_json.node_pre_build['name-sdk'] ? package_json.node_pre_build['name-sdk'] : package_json.name); const sdk_path = path.join(process.cwd(), package_json.node_pre_build['sdk-dir'] ? package_json.node_pre_build['sdk-dir'] : 'sdk'); const temp_path = path.join(process.cwd(), 'temporary'); const sdk_group = package_json.node_pre_build['sdk-group']; const addon_group = package_json.node_pre_build['addon-group']; const binary_dir = package_json.node_pre_build['binary-dir'] ? package_json.node_pre_build['binary-dir'] : 'build/Release'; const package_dir = package_json.node_pre_build['package-dir'] ? package_json.node_pre_build['package-dir'] : 'packages'; const platform = process.platform; if (!sdk_group || !addon_group) { console.error('[node_pre_build] please specify \'sdk-group\' and \'addon-group\' in field \'node_pre_build\'.'); } // check if project has electron dependency const node_modules = requireWithFallback('node_modules-path'); const { arch } = require('os'); let is_electron = false; let electron_version; let electron_path = node_modules('electron', process.cwd().split(path.sep)); if (!electron_path && process.env.INIT_CWD) { electron_path = node_modules('electron', process.env.INIT_CWD.split(path.sep)); } if (electron_path) { is_electron = true; electron_version = require(path.join(electron_path, 'electron', 'package.json')).version; } console.log(`[node_pre_build] is_electron: ${is_electron}, electron_version: ${electron_version}`) function removeNativeSdk() { if(fse.pathExistsSync(sdk_path)){ fse.rmdirSync(sdk_path, { recursive: true }) console.log(`[node_pre_build] delecte NertcSdk end`) } } function copySDKToBinaryDir() { const temp = glob.sync('/**/+(*.dll|*.framework|*.xcframework|*.dylib|*.so|*.node)', { root: sdk_path }) const files = [] temp.forEach((filepath) => { console.log('pre copySync file:' + path.basename(filepath)) if(!filepath.includes('dSYM')){ files.push(filepath) } }); if (!fse.pathExistsSync(path.join(process.cwd(), binary_dir))) { fse.mkdirSync(path.join(process.cwd(), binary_dir), {recursive: true}); } files.forEach((filepath) => { console.log('after copySync file:' + path.basename(filepath)) fse.copySync(filepath, path.join(process.cwd(), binary_dir, path.basename(filepath))) }); console.log(`[node_pre_build] copySDKToBinaryDir end`) } function build(arch) { console.log(`build arch:${arch}`) const silent = false; const gypPath = path.join(process.cwd(), '/node_modules/node-gyp/bin/node-gyp.js'); const gypExec = `node ${gypPath}`; const run = (command) => { execSync(command, { stdio: silent ? 'pipe' : 'inherit', shell: true }); }; run(`${gypExec} clean`); if(platform === 'darwin') { const command = [`${gypExec} configure`]; if (arch) { command.push(`--arch=${arch}`); } command.push('-- -f xcode'); run(command.join(' ')); run(`xcodebuild -project ./build/binding.xcodeproj -configuration Release -arch x86_64 -arch arm64`); } else { const command = [`${gypExec} configure`]; command.push(`--arch=${arch}`); run(command.join(' ')); run(`${gypExec} build`); // shell.exec(`msbuild build/binding.sln /p:Configuration=Release`, {silent}); } } // ---- merged from support/5.7.4: smarter publish member selection ---- function getRcFromFilename(filename) { if (!filename) { return -1; } const match = filename.match(/-rc-(\d+)/i); if (!match) { return -1; } return Number.parseInt(match[1], 10); } function filterPublishMembers(list, options) { const { name, platform, arch, } = options; return (list || []).filter((member) => { if (!member || !member.filename) { return false; } return member.filename.includes(name) && member.filename.includes(platform) && member.filename.includes(arch); }); } function logPublishDebug(tag, groupName, versionBucket, list, options, selectedMember) { const candidates = filterPublishMembers(list, options); console.log(`[node_pre_build][${tag}] group:${groupName}, version_bucket:${versionBucket}, exact_version:${options.exactVersion}, platform:${options.platform}, arch:${options.arch}, require_exact:${options.requireExactVersion}`); console.log(`[node_pre_build][${tag}] bucket_size:${(list || []).length}, candidate_size:${candidates.length}`); console.log(`[node_pre_build][${tag}] candidates:${candidates.map((member) => member.filename).join(', ') || 'none'}`); console.log(`[node_pre_build][${tag}] selected:${selectedMember ? selectedMember.filename : 'none'}`); } function pickPublishMember(list, options) { const { name, platform, arch, exactVersion, requireExactVersion, } = options; const candidates = filterPublishMembers(list, options); if (!candidates.length) { return null; } const exactHit = candidates.find((member) => member.filename.includes(exactVersion)); if (exactHit) { return exactHit; } if (requireExactVersion) { return null; } candidates.sort((left, right) => { const rcDiff = getRcFromFilename(right.filename) - getRcFromFilename(left.filename); if (rcDiff !== 0) { return rcDiff; } const idDiff = (Number(right.id) || 0) - (Number(left.id) || 0); if (idDiff !== 0) { return idDiff; } const leftTime = Date.parse((left.updated_at || '').replace(/-/g, '/')) || 0; const rightTime = Date.parse((right.updated_at || '').replace(/-/g, '/')) || 0; return rightTime - leftTime; }); return candidates[0]; } // ---- end merged section ---- function downloadSDK(name_sdk, arch, publish_json) { return new Promise((resolve, reject) => { let sdk_list = []; const exact_version = package_json.version; const version_bucket = package_json.version.split('-')[0]; Object.keys(publish_json[sdk_group]).forEach((temp) => { if (version_bucket === temp) { sdk_list = publish_json[sdk_group][temp]; }; }); console.log(`[node_pre_build] downloadSDK name_sdk:${name_sdk}, platform:${platform}, arch:${arch}`) const sdk_member = pickPublishMember(sdk_list, { name: name_sdk, platform, arch, exactVersion: exact_version, requireExactVersion: false, }); logPublishDebug('sdk', sdk_group, version_bucket, sdk_list, { name: name_sdk, platform, arch, exactVersion: exact_version, requireExactVersion: false, }, sdk_member); const sdk_url = sdk_member ? sdk_member.cdnlink : undefined; if (!sdk_url) { return reject(new Error('[node_pre_build] Failed to get download url of the pre-built sdk')); } console.log(`[node_pre_build] selected sdk filename:${sdk_member.filename}`) console.info(`[node_pre_build] Downloading prebuilt sdk from ${sdk_url} to ${sdk_path}`); download(sdk_url, sdk_path, { extract: true, // strip: 1, filter: (file) => { return !file.path.includes('._'); }, }).then(() => { console.info(`[node_pre_build] Downloading prebuilt sdk complete`); return resolve(); }).catch((err) => { console.log(`[node_pre_build] downloadSDK error:${err}`) return reject(err); }); }); } function downloadAddon(name_addon, arch, fallBackToBuild, publish_json) { return new Promise((resolve, reject) => { let addon_list = []; const exact_version = package_json.version; const version_bucket = package_json.version.split('-')[0]; Object.keys(publish_json[addon_group]).forEach((temp) => { if (version_bucket === temp) { addon_list = publish_json[addon_group][temp]; }; }); const addon_member = pickPublishMember(addon_list, { name: name_addon, platform, arch, exactVersion: exact_version, requireExactVersion: false, }); logPublishDebug('addon', addon_group, version_bucket, addon_list, { name: name_addon, platform, arch, exactVersion: exact_version, requireExactVersion: false, }, addon_member); const addon_url = addon_member ? addon_member.cdnlink : undefined; if (!addon_url) { if (!fallBackToBuild) { return reject(new Error('[node_pre_build] Failed to get download url of the pre-built addon.')); } console.info('[node_pre_build] Failed to get download url of the pre-built addon, falling back to build.'); build(arch); return resolve(); } console.log(`[node_pre_build] selected addon filename:${addon_member.filename}`) console.info(`[node_pre_build] Downloading prebuilt addon from ${addon_url}`); download(addon_url, sdk_path, { extract: true, filter: (file) => { return !file.path.includes('._'); }, }).then(() => { copySDKToBinaryDir(); console.log(`[node_pre_build] downloadAddon copySDKToBinaryDir end`) // removeNativeSdk(); }).catch((err) => { console.log(`[node_pre_build] downloadAddon err:${err}`) if (!fallBackToBuild) { return reject(err); } console.info(`[node_pre_build] Failed to download pre-built addon from ${addon_url}, error ${err}, falling back to build.`); build(arch); return resolve(); }); }); } function install(options) { let arch = package_json.node_pre_build['arch']; arch = options.arch ? options.arch : arch; if (typeof arch === 'undefined') { arch = process.env.npm_config_arch; console.log(`install optins npm_config_arch:${arch}`) if(typeof arch === 'undefined') { if (platform === 'darwin') { arch = 'universal' } else { arch = process.arch; } } } console.log(`install optins arch:${arch}`) // fetch publish list fetch('https://admin.netease.im/public-service/free/publish/list').then((res) => {return res.json()}).then((json) => { let res_data = json.data; return downloadSDK(name_sdk, arch, res_data).then(() => { return downloadAddon(name_addon, arch, options.fallBackToBuild, res_data); }); }).catch((err) => { console.error(err); }); } // command-line options // clean program .command('clean') .description('Clean installed pre-built binary') .action((options) => { console.info(`[node_pre_build] removing ${sdk_path}.`); fse.removeSync(sdk_path); console.info(`[node_pre_build] removing ${temp_path}.`); fse.removeSync(temp_path); }); // install program .command('install') .description('Install pre-built binary for module') .option('-a, --arch <architecture>', 'architecture of the host machine.') .option('--fall-back-to-build [build-script]', 'build when download pre-built binary failed.') .action((options) => { console.log(`[node_pre_build] start install`) if (fse.pathExistsSync(sdk_path) && fse.readdirSync(sdk_path).length > 0) { console.info(`[node_pre_build] sdk already installed in ${sdk_path}.`); return; } install(options); }); // reinstall program .command('reinstall') .description('Reinstall pre-built binary for module') .option('-a, --arch <architecture>', 'architecture of the host machine.') .option('--fall-back-to-build [build-script]', 'build when download pre-built binary failed.') .action((options) => { console.info(`[node_pre_build] removing ${sdk_path}.`); fse.removeSync(sdk_path); console.info(`[node_pre_build] removing ${temp_path}.`); fse.removeSync(temp_path); install(options); }); // build program .command('build') .description('Build and pack your pre-built binaries.') .option('-r, --runtime <runtime...>', 'array of runtimes to build for, such as [electron, node, nw].') .option('-rv, --runtime-version <runtime-version...>', 'array of runtime versions to build for, support multiple versions.') .option('-a, --arch <arch...>', 'array of architechtures to build for, such as [x64, ia32, arm64, arm].') .option('-p, --pack', 'pack the binaries after build.') .action((options) => { let arch_array = options.arch ? options.arch : package_json.node_pre_build['arch']; if (!Array.isArray(arch_array)) { arch_array = [arch_array]; }; if (!fse.pathExistsSync(process.cwd() + '/' + package_dir)) { fse.mkdirSync(process.cwd() + '/' + package_dir); }; console.log(`---platform:${platform} arch:${arch_array[0]}-----`) build(arch_array[0]); if (!options.pack) { return; }; let package_name = `${process.cwd() + '/' + package_dir}/${name_addon}-v${package_json.version}-${platform}-${arch_array[0]}.tar.gz` console.log(`package_name:${package_name}`) tar.create({ gzip: true, sync: true, cwd: process.cwd() + '/' + binary_dir, file: package_name, filter: (path, stat) => { if (path.match(/\.pdb|\.node|\.so/) !== null) { console.info(`[node_pre_build] ${path} packed.`); return true; } }, }, fse.readdirSync(process.cwd() + '/' + binary_dir)); }); // parse program.parse();