mirror of
https://github.com/cjdelisle/cjdns
synced 2025-10-06 00:32:50 +02:00
474 lines
16 KiB
JavaScript
474 lines
16 KiB
JavaScript
/* vim: set expandtab ts=4 sw=4: */
|
|
/*
|
|
* You may redistribute this program and/or modify it under the terms of
|
|
* the GNU General Public License as published by the Free Software Foundation,
|
|
* either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
/*@flow*/
|
|
'use strict';
|
|
var Fs = require('fs');
|
|
var nThen = require('nthen');
|
|
var Codestyle = require('./Codestyle');
|
|
var Cp = require('./Cp');
|
|
var Spawn = require('child_process').spawn;
|
|
var FindPython = require('./FindPython');
|
|
var Builder = require('./builder');
|
|
var TestRunner = require('./TestRunner');
|
|
const CjdnsTest = require('./CjdnsTest');
|
|
const GetVersion = require('./GetVersion');
|
|
|
|
var CFLAGS = process.env['CFLAGS'];
|
|
var LDFLAGS = process.env['LDFLAGS'];
|
|
var NO_MARCH_FLAG = ['arm', 'ppc', 'ppc64'];
|
|
|
|
Builder.configure({
|
|
systemName: process.env['SYSTEM'] || process.platform,
|
|
gcc: process.env['CC'],
|
|
}, function (builder, waitFor) {
|
|
|
|
builder.config.crossCompiling = process.env['CROSS'] !== undefined;
|
|
let optimizeLevel = '-O3';
|
|
|
|
builder.config.cflags.push(
|
|
'-std=c99',
|
|
'-Wall',
|
|
'-Wextra',
|
|
'-Werror',
|
|
'-Wno-pointer-sign',
|
|
'-Wmissing-prototypes',
|
|
'-pedantic',
|
|
'-D', builder.config.systemName + '=1',
|
|
'-Wno-unused-parameter',
|
|
'-fomit-frame-pointer',
|
|
|
|
'-D', 'Log_' + (process.env['Log_LEVEL'] || 'DEBUG'),
|
|
|
|
'-g',
|
|
|
|
// f4 = 16 peers max, fixed width 4 bit
|
|
// f8 = 241 peers max, fixed width 8 bit
|
|
// v3x5x8 = 256 peers max, variable width, 3, 5 or 8 bits plus 1 or 2 bits of prefix
|
|
// v4x8 = 256 peers max, variable width, 4, or 8 bits plus 1 bit prefix
|
|
'-D', 'NumberCompress_TYPE=v3x5x8',
|
|
|
|
// enable for safety (don't worry about speed, profiling shows they add ~nothing)
|
|
'-D', 'Identity_CHECK=1',
|
|
'-D', 'Allocator_USE_CANARIES=1',
|
|
'-D', 'PARANOIA=1'
|
|
);
|
|
|
|
if (process.env["CJDNS_RELEASE_VERSION"]) {
|
|
builder.config.version = '' + process.env["CJDNS_RELEASE_VERSION"];
|
|
}
|
|
|
|
if (process.env['SUBNODE']) { builder.config.cflags.push('-DSUBNODE=1'); }
|
|
|
|
if (process.env['GCOV']) {
|
|
builder.config.cflags.push('-fprofile-arcs', '-ftest-coverage');
|
|
builder.config.ldflags.push('-fprofile-arcs', '-ftest-coverage');
|
|
}
|
|
|
|
var android = /android/i.test(builder.config.gcc);
|
|
|
|
if (process.env['TESTING']) {
|
|
builder.config.cflags.push('-D', 'TESTING=1');
|
|
}
|
|
|
|
if (process.env['ADDRESS_PREFIX']) {
|
|
builder.config.cflags.push('-D', 'ADDRESS_PREFIX=' + process.env['ADDRESS_PREFIX']);
|
|
}
|
|
if (process.env['ADDRESS_PREFIX_BITS']) {
|
|
builder.config.cflags.push('-D', 'ADDRESS_PREFIX_BITS=' + process.env['ADDRESS_PREFIX_BITS']);
|
|
}
|
|
|
|
if (!builder.config.crossCompiling) {
|
|
if (NO_MARCH_FLAG.indexOf(process.arch) == -1) {
|
|
builder.config.cflags.push('-march=native');
|
|
}
|
|
}
|
|
|
|
if (builder.config.systemName === 'win32') {
|
|
builder.config.cflags.push('-Wno-format');
|
|
} else if (builder.config.systemName === 'linux') {
|
|
builder.config.ldflags.push('-Wl,-z,relro,-z,now,-z,noexecstack');
|
|
builder.config.cflags.push('-DHAS_ETH_INTERFACE=1');
|
|
} else if (builder.config.systemName === 'darwin') {
|
|
builder.config.cflags.push('-DHAS_ETH_INTERFACE=1');
|
|
}
|
|
|
|
if (process.env['NO_PIE'] === undefined && builder.config.systemName !== 'freebsd'
|
|
&& builder.config.systemName !== 'win32')
|
|
{
|
|
builder.config.cflags.push('-fPIE');
|
|
|
|
// just using `-pie` on OS X >= 10.10 results in this warning:
|
|
// clang: warning: argument unused during compilation: '-pie'
|
|
if (builder.config.systemName !== "darwin")
|
|
{
|
|
builder.config.ldflags.push('-pie');
|
|
} else {
|
|
builder.config.ldflags.push('-Wl,-pie');
|
|
}
|
|
}
|
|
|
|
if (builder.compilerType().isClang) {
|
|
// blows up when preprocessing before js preprocessor
|
|
builder.config.cflags.push(
|
|
'-Wno-invalid-pp-token',
|
|
'-Wno-dollar-in-identifier-extension',
|
|
'-Wno-newline-eof',
|
|
'-Wno-unused-value',
|
|
|
|
// lots of places where depending on preprocessor conditions, a statement might be
|
|
// a case of if (1 == 1)
|
|
'-Wno-tautological-compare',
|
|
|
|
'-Wno-error'
|
|
);
|
|
builder.config.cflags.slice(builder.config.cflags.indexOf('-Werror'), 1);
|
|
} else {
|
|
builder.config.cflags.push(
|
|
'-fdiagnostics-color=always'
|
|
);
|
|
}
|
|
|
|
// Install any user-defined CFLAGS. Necessary if you are messing about with building cnacl
|
|
// with NEON on the BBB, or want to set -Os (OpenWrt)
|
|
// Allow -O0 so while debugging all variables are present.
|
|
if (CFLAGS) {
|
|
var cflags = CFLAGS.split(' ');
|
|
cflags.forEach(function(flag) {
|
|
if (/^\-O[^02s]$/.test(flag)) {
|
|
console.log("Skipping " + flag + ", assuming " + optimizeLevel + " instead.");
|
|
} else if (/^\-O[02s]$/.test(flag)) {
|
|
optimizeLevel = flag;
|
|
} else {
|
|
[].push.apply(builder.config.cflags, cflags);
|
|
}
|
|
});
|
|
}
|
|
|
|
builder.config.cflags.push(optimizeLevel);
|
|
if (!/^\-O0$/.test(optimizeLevel)) {
|
|
builder.config.cflags.push('-D_FORTIFY_SOURCE=2');
|
|
}
|
|
|
|
// We also need to pass various architecture/floating point flags to GCC when invoked as
|
|
// a linker.
|
|
if (LDFLAGS) {
|
|
[].push.apply(builder.config.ldflags, LDFLAGS.split(' '));
|
|
}
|
|
|
|
if (android) {
|
|
builder.config.cflags.push('-Dandroid=1');
|
|
}
|
|
|
|
var uclibc = process.env['UCLIBC'] == '1';
|
|
var libssp;
|
|
switch (process.env['SSP_SUPPORT']) {
|
|
case 'y':
|
|
case '1': libssp = true; break;
|
|
case 'n':
|
|
case '' :
|
|
case '0': libssp = false; break;
|
|
case undefined: break;
|
|
default: throw new Error();
|
|
}
|
|
if (libssp === false) {
|
|
console.log("Stack Smashing Protection (security feature) is disabled");
|
|
} else if (builder.config.systemName == 'win32') {
|
|
builder.config.libs.push('-lssp');
|
|
} else if ((!uclibc && builder.config.systemName !== 'sunos') || libssp === true) {
|
|
builder.config.cflags.push(
|
|
// Broken GCC patch makes -fstack-protector-all not work
|
|
// workaround is to give -fno-stack-protector first.
|
|
// see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722
|
|
'-fno-stack-protector',
|
|
'-fstack-protector-all',
|
|
'-Wstack-protector'
|
|
);
|
|
|
|
// Static libssp provides __stack_chk_fail_local, which x86 needs in
|
|
// order to avoid expensively looking up the location of __stack_chk_fail.
|
|
var x86 = process.env['TARGET_ARCH'] == 'i386';
|
|
if (uclibc) {
|
|
if (x86) {
|
|
builder.config.libs.push('-Wl,-Bstatic', '-lssp', '-Wl,-Bdynamic');
|
|
} else {
|
|
builder.config.libs.push('-lssp');
|
|
}
|
|
}
|
|
} else {
|
|
console.log("Stack Smashing Protection (security feature) is disabled");
|
|
}
|
|
|
|
if (process.env['Pipe_PREFIX']) {
|
|
builder.config.cflags.push(
|
|
'-D', 'Pipe_PREFIX="' + process.env['Pipe_PREFIX'] + '"'
|
|
);
|
|
}
|
|
|
|
if (typeof(builder.config.cjdnsTest_files) === 'undefined') {
|
|
CjdnsTest.generate(builder, process.env['SUBNODE'] !== '', waitFor());
|
|
}
|
|
|
|
nThen((w) => {
|
|
if (builder.config.version) { return; }
|
|
GetVersion(w(function(err, data) {
|
|
if (!err) {
|
|
builder.config.version = ('' + data).replace(/(\r\n|\n|\r)/gm, "");
|
|
} else {
|
|
builder.config.version = 'unknown';
|
|
}
|
|
}));
|
|
}).nThen((w) => {
|
|
builder.config.cflags.push('-D', 'CJD_PACKAGE_VERSION="' + builder.config.version + '"');
|
|
}).nThen(waitFor());
|
|
|
|
var dependencyDir = builder.config.buildDir + '/dependencies';
|
|
var libuvLib = dependencyDir + '/libuv/out/Release/libuv.a';
|
|
if (['win32', 'netbsd'].indexOf(builder.config.systemName) >= 0) {//this might be needed for other BSDs
|
|
libuvLib = dependencyDir + '/libuv/out/Release/obj.target/libuv.a';
|
|
}
|
|
|
|
// Build dependencies
|
|
nThen(function (waitFor) {
|
|
|
|
Fs.exists(dependencyDir, waitFor(function (exists) {
|
|
if (exists) { return; }
|
|
|
|
console.log("Copy dependencies");
|
|
Cp('./node_build/dependencies', dependencyDir, waitFor());
|
|
}));
|
|
|
|
}).nThen(function (waitFor) {
|
|
|
|
builder.config.libs.push(dependencyDir + '/cnacl/jsbuild/libnacl.a');
|
|
builder.config.includeDirs.push(dependencyDir + '/cnacl/jsbuild/include/');
|
|
|
|
// needed for Sign.c which pulls in crypto_int32.h
|
|
builder.config.includeDirs.push(dependencyDir + '/cnacl/jsbuild/include_internal/');
|
|
|
|
Fs.exists(dependencyDir + '/cnacl/jsbuild/libnacl.a', waitFor(function (exists) {
|
|
if (exists) { return; }
|
|
|
|
console.log("Build NaCl");
|
|
var cwd = process.cwd();
|
|
process.chdir(dependencyDir + '/cnacl/');
|
|
|
|
// $FlowFixMe non-static require
|
|
var NaCl = require(process.cwd() + '/node_build/make.js');
|
|
NaCl.build(function (args, callback) {
|
|
if (builder.config.systemName !== 'win32') {
|
|
args.unshift('-fPIC');
|
|
}
|
|
|
|
args.unshift(optimizeLevel, '-fomit-frame-pointer');
|
|
|
|
if (!/^\-O0$/.test(optimizeLevel)) {
|
|
args.unshift('-D_FORTIFY_SOURCE=2');
|
|
}
|
|
|
|
if (CFLAGS) {
|
|
[].push.apply(args, CFLAGS.split(' '));
|
|
}
|
|
|
|
if (!builder.config.crossCompiling) {
|
|
if (NO_MARCH_FLAG.indexOf(process.arch) == -1) {
|
|
args.unshift('-march=native');
|
|
}
|
|
}
|
|
|
|
builder.cc(args, callback);
|
|
},
|
|
builder.config,
|
|
waitFor(function () {
|
|
process.chdir(cwd);
|
|
}));
|
|
}));
|
|
|
|
}).nThen(function (waitFor) {
|
|
|
|
builder.config.libs.push(libuvLib);
|
|
if (!android) {
|
|
builder.config.libs.push('-lpthread');
|
|
}
|
|
|
|
if (builder.config.systemName === 'win32') {
|
|
builder.config.libs.push(
|
|
'-lws2_32',
|
|
'-lpsapi', // GetProcessMemoryInfo()
|
|
'-liphlpapi' // GetAdapterAddresses()
|
|
);
|
|
} else if (builder.config.systemName === 'linux' && !android) {
|
|
builder.config.libs.push('-lrt'); // clock_gettime()
|
|
} else if (builder.config.systemName === 'darwin') {
|
|
builder.config.libs.push('-framework', 'CoreServices');
|
|
} else if (['freebsd', 'openbsd', 'netbsd'].indexOf(builder.config.systemName) >= 0) {
|
|
builder.config.cflags.push('-Wno-overlength-strings');
|
|
builder.config.libs.push('-lkvm');
|
|
} else if (builder.config.systemName === 'sunos') {
|
|
builder.config.libs.push(
|
|
'-lsocket',
|
|
'-lsendfile',
|
|
'-lkstat',
|
|
'-lnsl'
|
|
);
|
|
}
|
|
|
|
builder.config.includeDirs.push(dependencyDir + '/libuv/include/');
|
|
|
|
var libuvBuilt;
|
|
var python;
|
|
nThen(function (waitFor) {
|
|
|
|
Fs.exists(libuvLib, waitFor(function (exists) {
|
|
if (exists) { libuvBuilt = true; }
|
|
}));
|
|
|
|
}).nThen(function (waitFor) {
|
|
|
|
if (libuvBuilt) { return; }
|
|
FindPython.find(builder.tmpFile(), waitFor(function (err, pythonExec) {
|
|
if (err) { throw err; }
|
|
python = pythonExec;
|
|
}));
|
|
|
|
}).nThen(function (waitFor) {
|
|
|
|
if (libuvBuilt) { return; }
|
|
console.log("Build Libuv");
|
|
var cwd = process.cwd();
|
|
process.chdir(dependencyDir + '/libuv/');
|
|
|
|
var args = ['./gyp_uv.py'];
|
|
var env = process.env;
|
|
env.CC = builder.config.gcc;
|
|
|
|
if (env.TARGET_ARCH) {
|
|
args.push('-Dtarget_arch=' + env.TARGET_ARCH);
|
|
}
|
|
|
|
//args.push('--root-target=libuv');
|
|
if (android) {
|
|
args.push('-DOS=android');
|
|
args.push('-f', 'make-linux');
|
|
}
|
|
|
|
if (builder.config.systemName === 'win32') {
|
|
args.push('-DOS=win');
|
|
args.push('-f', 'make-linux');
|
|
}
|
|
|
|
if (env.GYP_ADDITIONAL_ARGS) {
|
|
args.push.apply(args, env.GYP_ADDITIONAL_ARGS.split(' '));
|
|
}
|
|
|
|
if (['freebsd', 'openbsd', 'netbsd'].indexOf(builder.config.systemName) !== -1) {
|
|
// This platform lacks a functioning sem_open implementation, therefore...
|
|
args.push('--no-parallel');
|
|
args.push('-DOS=' + builder.config.systemName);
|
|
}
|
|
|
|
var gyp = Spawn(python, args, {env:env, stdio:'inherit'});
|
|
gyp.on('error', function () {
|
|
console.error("couldn't launch gyp [" + python + "]");
|
|
});
|
|
gyp.on('close', waitFor(function () {
|
|
var args = [
|
|
'-j', ''+builder.config.jobs,
|
|
'-C', 'out',
|
|
'BUILDTYPE=Release',
|
|
'CC=' + builder.config.gcc,
|
|
'CXX=' + builder.config.gcc,
|
|
'V=1'
|
|
];
|
|
var cflags = [optimizeLevel, '-DNO_EMFILE_TRICK=1'];
|
|
|
|
if (!/^\-O0$/.test(optimizeLevel)) {
|
|
cflags.push('-D_FORTIFY_SOURCE=2');
|
|
}
|
|
|
|
if (!(/darwin|win32/i.test(builder.config.systemName))) {
|
|
cflags.push('-fPIC');
|
|
}
|
|
args.push('CFLAGS=' + cflags.join(' '));
|
|
|
|
var makeCommand = ['freebsd', 'openbsd', 'netbsd'].indexOf(builder.config.systemName) >= 0 ? 'gmake' : 'make';
|
|
var make = Spawn(makeCommand, args, {stdio: 'inherit'});
|
|
|
|
make.on('error', function (err) {
|
|
if (err.code === 'ENOENT') {
|
|
console.error('\x1b[1;31mError: ' + makeCommand + ' is required!\x1b[0m');
|
|
} else {
|
|
console.error(
|
|
'\x1b[1;31mFail run ' + process.cwd() + ': ' + makeCommand + ' '
|
|
+ args.join(' ') + '\x1b[0m'
|
|
);
|
|
console.error('Message:', err);
|
|
}
|
|
waitFor.abort();
|
|
});
|
|
|
|
make.on('close', waitFor(function () {
|
|
process.chdir(cwd);
|
|
}));
|
|
}));
|
|
|
|
}).nThen(waitFor());
|
|
|
|
}).nThen(waitFor());
|
|
|
|
}).build(function (builder, waitFor) {
|
|
|
|
builder.buildExecutable('client/cjdroute2.c', 'cjdroute');
|
|
|
|
builder.buildExecutable('contrib/c/publictoip6.c');
|
|
builder.buildExecutable('contrib/c/privatetopublic.c');
|
|
builder.buildExecutable('contrib/c/sybilsim.c');
|
|
builder.buildExecutable('contrib/c/makekeys.c');
|
|
builder.buildExecutable('contrib/c/mkpasswd.c');
|
|
|
|
builder.buildExecutable('crypto/random/randombytes.c');
|
|
|
|
builder.lintFiles(function (fileName, file, callback) {
|
|
if (/dependencies/.test(fileName) || /crypto\/sign/.test(fileName)) {
|
|
callback('', false);
|
|
return;
|
|
}
|
|
|
|
Codestyle.lint(fileName, file, callback);
|
|
});
|
|
|
|
var testcjdroute = builder.buildTest('test/testcjdroute.c');
|
|
if (builder.config.crossCompiling) {
|
|
console.log("Cross compiling. Building, but not running tests.");
|
|
return;
|
|
}
|
|
|
|
var testRunner = TestRunner.local(['all']);
|
|
if (process.env['REMOTE_TEST']) {
|
|
testRunner = TestRunner.remote(process.env['REMOTE_TEST'], ['all']);
|
|
}
|
|
if (!process.env['NO_TEST']) {
|
|
builder.runTest(testcjdroute, testRunner);
|
|
}
|
|
|
|
}).success(function (builder, waitFor) {
|
|
|
|
console.log('\x1b[1;32mBuild completed successfully, type ./cjdroute to begin setup.\x1b[0m');
|
|
|
|
}).failure(function (builder, waitFor) {
|
|
|
|
console.log('\x1b[1;31mFailed to build cjdns.\x1b[0m');
|
|
process.exit(1);
|
|
|
|
}); |