diff --git a/gulpfile.js b/gulpfile.js index d539afbfdb..108b087bb5 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,6 +4,8 @@ const pkg = require('./package.json'); const child_process = require('child_process'); const fs = require('fs'); +const fse = require('fs-extra'); +const https = require('follow-redirects').https; const path = require('path'); const zip = require('gulp-zip'); @@ -13,6 +15,7 @@ const makensis = require('makensis'); const deb = require('gulp-debian'); const buildRpm = require('rpm-builder'); const commandExistsSync = require('command-exists').sync; +const targz = require('targz'); const gulp = require('gulp'); const concat = require('gulp-concat'); @@ -33,6 +36,8 @@ var nwBuilderOptions = { winIco: './src/images/bf_icon.ico' }; +var nwArmVersion = '0.27.6'; + //----------------- //Pre tasks operations //----------------- @@ -74,12 +79,13 @@ gulp.task('default', debugBuild); // Get platform from commandline args // # -// # gulp []+ Run only for platform(s) (with one of --linux64, --linux32, --osx64, --win32, --win64, or --chromeos) -// # +// # gulp []+ Run only for platform(s) (with one of --linux64, --linux32, --armv7, --osx64, --win32, --win64, or --chromeos) +// # function getInputPlatforms() { - var supportedPlatforms = ['linux64', 'linux32', 'osx64', 'win32','win64', 'chromeos']; + var supportedPlatforms = ['linux64', 'linux32', 'armv7', 'osx64', 'win32','win64', 'chromeos']; var platforms = []; var regEx = /--(\w+)/; + console.log(process.argv); for (var i = 3; i < process.argv.length; i++) { var arg = process.argv[i].match(regEx)[1]; if (supportedPlatforms.indexOf(arg) > -1) { @@ -88,7 +94,7 @@ function getInputPlatforms() { console.log('Unknown platform: ' + arg); process.exit(); } - } + } if (platforms.length === 0) { var defaultPlatform = getDefaultPlatform(); @@ -126,10 +132,10 @@ function getDefaultPlatform() { defaultPlatform = 'win32'; break; - + default: defaultPlatform = ''; - + break; } return defaultPlatform; @@ -156,6 +162,7 @@ function getRunDebugAppCommand(arch) { case 'linux64': case 'linux32': + case 'armv7': return path.join(DEBUG_DIR, pkg.name, arch, pkg.name); break; @@ -177,24 +184,24 @@ function getReleaseFilename(platform, ext) { return 'betaflight-configurator_' + pkg.version + '_' + platform + '.' + ext; } -function clean_dist() { - return del([DIST_DIR + '**'], { force: true }); +function clean_dist() { + return del([DIST_DIR + '**'], { force: true }); }; -function clean_apps() { - return del([APPS_DIR + '**'], { force: true }); +function clean_apps() { + return del([APPS_DIR + '**'], { force: true }); }; -function clean_debug() { - return del([DEBUG_DIR + '**'], { force: true }); +function clean_debug() { + return del([DEBUG_DIR + '**'], { force: true }); }; -function clean_release() { - return del([RELEASE_DIR + '**'], { force: true }); +function clean_release() { + return del([RELEASE_DIR + '**'], { force: true }); }; -function clean_cache() { - return del(['./cache/**'], { force: true }); +function clean_cache() { + return del(['./cache/**'], { force: true }); }; // Real work for dist task. Done in another task to call it via @@ -238,8 +245,8 @@ function apps(done) { var platforms = getPlatforms(); removeItem(platforms, 'chromeos'); - buildNWApps(platforms, 'normal', APPS_DIR, done); -}; + buildNWAppsWrapper(platforms, 'normal', APPS_DIR, done); +} function listPostBuildTasks(folder, done) { @@ -255,6 +262,10 @@ function listPostBuildTasks(folder, done) { postBuildTasks.push(function post_build_linux64(done){ return post_build('linux64', folder, done) }); } + if (platforms.indexOf('armv7') != -1) { + postBuildTasks.push(function post_build_armv7(done){ return post_build('armv7', folder, done) }); + } + // We need to return at least one task, if not gulp will throw an error if (postBuildTasks.length == 0) { postBuildTasks.push(function post_build_none(done){ done() }); @@ -264,7 +275,7 @@ function listPostBuildTasks(folder, done) { function post_build(arch, folder, done) { - if ((arch =='linux32') || (arch == 'linux64')) { + if ((arch === 'linux32') || (arch === 'linux64')) { // Copy Ubuntu launcher scripts to destination dir var launcherDir = path.join(folder, pkg.name, arch); console.log('Copy Ubuntu launcher scripts to ' + launcherDir); @@ -272,6 +283,11 @@ function post_build(arch, folder, done) { .pipe(gulp.dest(launcherDir)); } + if (arch === 'armv7') { + console.log('Moving ARMv7 build from "linux32" to "armv7" directory...'); + fse.moveSync(path.join(folder, pkg.name, 'linux32'), path.join(folder, pkg.name, 'armv7')); + } + return done(); } @@ -280,11 +296,112 @@ function debug(done) { var platforms = getPlatforms(); removeItem(platforms, 'chromeos'); - buildNWApps(platforms, 'sdk', DEBUG_DIR, done); + buildNWAppsWrapper(platforms, 'sdk', DEBUG_DIR, done); } -function buildNWApps(platforms, flavor, dir, done) { +function injectARMCache(flavor, callback) { + var flavorPostfix = `-${flavor}`; + var flavorDownloadPostfix = flavor !== 'normal' ? `-${flavor}` : ''; + clean_cache().then(function() { + if (!fs.existsSync('./cache')) { + fs.mkdirSync('./cache'); + } + fs.closeSync(fs.openSync('./cache/_ARMv7_IS_CACHED', 'w')); + var versionFolder = `./cache/${nwBuilderOptions.version}${flavorPostfix}`; + if (!fs.existsSync(versionFolder)) { + fs.mkdirSync(versionFolder); + } + if (!fs.existsSync(versionFolder + '/linux32')) { + fs.mkdirSync(`${versionFolder}/linux32`); + } + var downloadedArchivePath = `${versionFolder}/nwjs${flavorPostfix}-v${nwArmVersion}-linux-arm.tar.gz`; + var downloadUrl = `https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases/download/v${nwArmVersion}/nwjs${flavorDownloadPostfix}-v${nwArmVersion}-linux-arm.tar.gz`; + if (fs.existsSync(downloadedArchivePath)) { + console.log('Prebuilt ARMv7 binaries found in /tmp'); + downloadDone(flavorDownloadPostfix, downloadedArchivePath, versionFolder); + } else { + console.log(`Downloading prebuilt ARMv7 binaries from "${downloadUrl}"...`); + process.stdout.write('> Starting download...\r'); + var armBuildBinary = fs.createWriteStream(downloadedArchivePath); + var request = https.get(downloadUrl, function(res) { + var totalBytes = res.headers['content-length']; + var downloadedBytes = 0; + res.pipe(armBuildBinary); + res.on('data', function (chunk) { + downloadedBytes += chunk.length; + process.stdout.write(`> ${parseInt((downloadedBytes * 100) / totalBytes)}% done \r`); + }); + armBuildBinary.on('finish', function() { + process.stdout.write('> 100% done \n'); + armBuildBinary.close(function() { + downloadDone(flavorDownloadPostfix, downloadedArchivePath, versionFolder); + }); + }); + }); + } + }); + function downloadDone(flavorDownloadPostfix, downloadedArchivePath, versionFolder) { + console.log('Injecting prebuilt ARMv7 binaries into Linux32 cache...'); + targz.decompress({ + src: downloadedArchivePath, + dest: versionFolder, + }, function(err) { + if (err) { + console.log(err); + clean_debug(); + process.exit(1); + } else { + fs.rename( + `${versionFolder}/nwjs${flavorDownloadPostfix}-v${nwArmVersion}-linux-arm`, + `${versionFolder}/linux32`, + (err) => { + if (err) { + console.log(err); + clean_debug(); + process.exit(1); + } + callback(); + } + ); + } + }); + } +} + +function buildNWAppsWrapper(platforms, flavor, dir, done) { + function buildNWAppsCallback() { + buildNWApps(platforms, flavor, dir, done); + } + + if (platforms.indexOf('armv7') !== -1) { + if (platforms.indexOf('linux32') !== -1) { + console.log('Cannot build ARMv7 and Linux32 versions at the same time!'); + clean_debug(); + process.exit(1); + } + removeItem(platforms, 'armv7'); + platforms.push('linux32'); + + if (!fs.existsSync('./cache/_ARMv7_IS_CACHED', 'w')) { + console.log('Purging cache because it needs to be overwritten...'); + clean_cache().then(() => { + injectARMCache(flavor, buildNWAppsCallback); + }) + } else { + buildNWAppsCallback(); + } + } else { + if (platforms.indexOf('linux32') !== -1 && fs.existsSync('./cache/_ARMv7_IS_CACHED')) { + console.log('Purging cache because it was previously overwritten...'); + clean_cache().then(buildNWAppsCallback); + } else { + buildNWAppsCallback(); + } + } +} + +function buildNWApps(platforms, flavor, dir, done) { if (platforms.length > 0) { var builder = new NwBuilder(Object.assign({ buildDir: dir, @@ -311,7 +428,7 @@ function start_debug(done) { var platforms = getPlatforms(); - var exec = require('child_process').exec; + var exec = require('child_process').exec; if (platforms.length === 1) { var run = getRunDebugAppCommand(platforms[0]); console.log('Starting debug app (' + run + ')...'); @@ -534,6 +651,10 @@ function listReleaseTasks(done) { releaseTasks.push(function release_linux32_rpm(done){ return release_rpm('linux32', done) }); } + if (platforms.indexOf('armv7') !== -1) { + releaseTasks.push(function release_armv7_zip(){ return release_zip('armv7') }); + } + if (platforms.indexOf('osx64') !== -1) { releaseTasks.push(release_osx64); } diff --git a/package.json b/package.json index 139181d8d7..4dc39e136b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ "devDependencies": { "command-exists": "^1.2.2", "del": "^3.0.0", + "follow-redirects": "^1.4.1", + "fs-extra": "^6.0.1", "gulp": "~4.0.0", "gulp-concat": "~2.6.1", "gulp-debian": "~0.1.8", @@ -55,6 +57,7 @@ "os": "^0.1.1", "platform-dependent-modules": "0.0.14", "rpm-builder": "^0.7.0", + "targz": "^1.0.1", "temp": "^0.8.3" }, "config": {