0
0
mirror of https://github.com/cjdelisle/cjdns synced 2025-10-05 16:22:54 +02:00

Separation of concerns between builder and cjdns-specific build stuff

This commit is contained in:
Caleb James DeLisle
2020-10-02 23:54:28 +02:00
parent 6cd2b27ebc
commit 6a29c552ab
18 changed files with 505 additions and 556 deletions

View File

@@ -15,7 +15,7 @@
'use strict';
var Fs = require('fs');
var nThen = require('nthen');
var Semaphore = require('../tools/lib/Semaphore');
var Semaphore = require('saferphore');
var Child = require('child_process');
var headerLines = [

View File

@@ -1,6 +1,6 @@
'use strict';
var Fs = require("fs");
var Semaphore = require('../tools/lib/Semaphore');
var Semaphore = require('saferphore');
var nThen = require('nthen');
var sema = Semaphore.create(64);

View File

@@ -1,36 +0,0 @@
'use strict';
var nThen = require("nthen");
var Fs = require("fs");
module.exports.check = function (builder, func, ldflags, callback) {
var file = builder.tmpFile();
var outputFile = builder.tmpFile();
nThen(function (waitFor) {
Fs.writeFile(file, "int main() { " + func + "(); }", waitFor(function (err, ret) {
if (err) {
waitFor.abort();
callback(err);
}
}));
}).nThen(function (waitFor) {
var flags = [];
flags.push.apply(flags, ["-x", "c", "-o", outputFile, file]);
flags.push.apply(flags, ldflags);
builder.cc(flags, waitFor(function (ret, out, err) {
if (ret && /undefined reference/.test(err)) {
callback(undefined, false);
} else if (ret) {
callback(new Error(err));
} else {
callback(undefined, true);
}
}));
});
};

View File

@@ -19,136 +19,7 @@ const Fs = require('fs');
const Spawn = require('child_process').spawn;
const nThen = require('nthen');
const Crypto = require('crypto');
const Semaphore = require('../tools/lib/Semaphore');
const GetVersion = require('./GetVersion');
/*
* Why hello dear packager,
*
* I suppose you have found this place as you are trying to figure out how to work this into your
* build system. You're probably faced with a decision between getting node.js into your build and
* "fixing" this build process so it doesn't need such a silly thing. A 500 line script is certainly
* not unapproachable, right?
* The reason why I am speaking to you now is because I care about you. I want you to be happy
* and live a carefree life, and because you are standing on the precipice of a cavern so dark and
* deep that while you may well make it out alive, your personal pride and innocence almost
* certainly will not. Imagine yourself after months of sleepless nights wallowing in the quicksand,
* forever trying to slay the dragon which is always so close yet and so far away. Imagine the deep
* hatred you will have for humanity, code, and the creator of this doomsday machine. I beg you to
* turn back now while there is still hope. You need not die here, your life is important, and
* whether you close this file now or not, in the end you will still end up including node.js in
* your build.
*
* The Creator
*/
// Since many of the compile operations are short, the best
// performance seems to be when running 1.25x the number of jobs as
// cpu cores. On BSD and iphone systems, os.cpus() is not reliable so
// if it returns undefined let's just assume 1
const cpus = Os.cpus(); // workaround, nodejs seems to be broken on openbsd (undefined result after second call)
const PROCESSORS = Math.floor((typeof cpus === 'undefined' ? 1 : cpus.length) * 1.25);
const error = function (message) /*:Error*/ {
try {
throw new Error(message);
} catch (e) {
return e;
}
};
const throwIfErr = function(err) {
if (err) {
throw new Error(err);
}
};
const expandArgs = function (args) {
const out = [];
for (let i = 0; i < args.length; i++) {
if (typeof(args[i]) === 'object') {
if (Array.isArray(args[i])) {
out.push.apply(out, expandArgs(args[i]));
} else {
throw new Error("object in arguments [" + args.join() + "]");
}
} else {
out.push(args[i]);
}
}
return out;
};
const sema = Semaphore.create(PROCESSORS);
const compiler = function (
compilerPath /*:string*/,
args /*:string[]*/,
callback /*:(number, string, string)=>bool|void*/,
content /*:string*/
) {
let stop = false;
args = expandArgs(args);
sema.take(function (returnAfter) {
if (stop) {
return returnAfter(function (ret) {
callback(1, '', 'interrupted');
});
}
if (process.env.VERBOSE) {
console.log(compilerPath + ' ' + args.join(' '));
}
const gcc = Spawn(compilerPath, args);
let err = '';
let out = '';
gcc.stdout.on('data', function (dat) { out += dat.toString(); });
gcc.stderr.on('data', function (dat) { err += dat.toString(); });
gcc.on('close', returnAfter(function (ret) {
if (callback(ret, out, err)) { stop = true; }
}));
gcc.on('error', function (err) {
if (err.code === 'ENOENT') {
console.error('\x1b[1;31mError: ' + compilerPath + ' is required!\x1b[0m');
} else {
console.error(
'\x1b[1;31mFail run ' + process.cwd() + ': ' + compilerPath + ' '
+ args.join(' ') + '\x1b[0m'
);
console.error('Message:' + err);
}
// handle the error safely
console.log(args);
});
if (content) {
gcc.stdin.write(content, function (err) {
if (err) { throw err; }
gcc.stdin.end();
});
}
});
};
const cc = function (
gcc /*:string*/,
args /*:string[]*/,
callback /*:(?Error, ?string)=>bool|void*/,
content /*:string*/
) {
compiler(gcc, args, function (ret, out, err) {
if (ret) {
return callback(error("gcc " + args.map(String).join(' ') + "\n\n" + err));
}
if (err !== '') {
//process.stdout.write(err);
}
return callback(undefined, out);
}, content);
};
const Saferphore = require('saferphore');
/*::
export type Builder_File_t = {|
@@ -184,34 +55,26 @@ export type Builder_t = {|
lintFiles: (Builder_Linter_t)=>void,
config: Builder_Config_t,
tmpFile: (?string)=>string,
compilerType: () => Builder_Compiler_t,
processors: number,
compilerType: () => Builder_Compiler_t
|};
export type Builder_BaseConfig_t = {|
systemName: string,
crossCompiling: bool,
gcc: string,
tempDir: string,
optimizeLevel: string,
logLevel: string,
buildDir?: string,
systemName?: ?string,
gcc?: ?string,
buildDir?: ?string,
|};
export type Builder_Config_t = {
systemName: string,
crossCompiling: bool,
gcc: string,
buildDir: string,
tempDir: string,
optimizeLevel: string,
logLevel: string,
includeDirs: string[],
cflags: string[],
ldflags: string[],
libs: string[],
version: string,
jobs: number,
fileCflags: {[string]: string[]},
} & {[string]:any};
import type { Nthen_WaitFor_t } from 'nthen';
import type { Saferphore_t } from 'saferphore';
export type Builder_Stage_t = (Builder_t, Nthen_WaitFor_t)=>void;
export type Builder_CompileJob_t = { cFile: string, outputFile: ?string };
export type Builder_PreCtx_t = {
@@ -228,12 +91,108 @@ export type Builder_PreCtx_t = {
tests: Array<(Builder_TestRunnerCb_t)=>void>,
toCompile: { [string]: Builder_File_t },
config: Builder_Config_t,
sema: Saferphore_t,
};
export type Builder_Ctx_t = Builder_PreCtx_t & {
builder: Builder_t,
state: Builder_State_t,
};
*/
const error = function (message) /*:Error*/ {
try {
throw new Error(message);
} catch (e) {
return e;
}
};
const expandArgs = function (args) {
const out = [];
for (let i = 0; i < args.length; i++) {
if (typeof(args[i]) === 'object') {
if (Array.isArray(args[i])) {
out.push.apply(out, expandArgs(args[i]));
} else {
throw new Error("object in arguments [" + args.join() + "]");
}
} else {
out.push(args[i]);
}
}
return out;
};
const compiler = function (
ctx /*:Builder_Ctx_t*/,
args /*:string[]*/,
callback /*:(number, string, string)=>bool|void*/,
content /*:string*/
) {
let stop = false;
args = expandArgs(args);
ctx.sema.take(function (returnAfter) {
if (stop) {
return void returnAfter(function (ret) {
callback(1, '', 'interrupted');
});
}
if (process.env.VERBOSE) {
console.log(ctx.config.gcc + ' ' + args.join(' '));
}
const gcc = Spawn(ctx.config.gcc, args);
let err = '';
let out = '';
gcc.stdout.on('data', function (dat) { out += dat.toString(); });
gcc.stderr.on('data', function (dat) { err += dat.toString(); });
gcc.on('close', returnAfter(function (ret) {
if (callback(ret, out, err)) { stop = true; }
}));
gcc.on('error', function (err) {
if (err.code === 'ENOENT') {
console.error('\x1b[1;31mError: ' + ctx.config.gcc + ' is required!\x1b[0m');
} else {
console.error(
'\x1b[1;31mFail run ' + process.cwd() + ': ' + ctx.config.gcc + ' '
+ args.join(' ') + '\x1b[0m'
);
console.error('Message:' + err);
}
// handle the error safely
console.log(args);
});
if (content) {
gcc.stdin.write(content, function (err) {
if (err) { throw err; }
gcc.stdin.end();
});
}
});
};
const cc = function (
ctx /*:Builder_Ctx_t*/,
args /*:string[]*/,
callback /*:(?Error, ?string)=>bool|void*/,
content /*:string*/
) {
compiler(ctx, args, function (ret, out, err) {
if (ret) {
return callback(error("gcc " + args.map(String).join(' ') + "\n\n" + err));
}
if (err !== '') {
//process.stdout.write(err);
}
return callback(undefined, out);
}, content);
};
const getStatePrototype = function () /*:Builder_State_t*/ {
return {
rebuildIfChanges: [],
@@ -253,7 +212,7 @@ const getStatePrototype = function () /*:Builder_State_t*/ {
const tmpFile = function (ctx /*:Builder_Ctx_t*/, name) {
name = name || '';
return ctx.config.tempDir + '/jsmake-' + name + Crypto.pseudoRandomBytes(10).toString('hex');
return ctx.config.buildDir + '/tmp/' + name + Crypto.pseudoRandomBytes(10).toString('hex');
};
const finalizeCtx = function (
@@ -264,7 +223,7 @@ const finalizeCtx = function (
ctx.state = state;
ctx.builder = (Object.freeze({
cc: function (args, callback) {
compiler(ctx.builder.config.gcc, args, callback, '');
compiler(ctx, args, callback, '');
},
buildExecutable: function (cFile, outputFile) {
@@ -293,8 +252,6 @@ const finalizeCtx = function (
compilerType: () => JSON.parse(JSON.stringify(ctx.state.compilerType)),
// Concurrency...
processors: PROCESSORS
}) /*:Builder_t*/);
return ctx;
};
@@ -500,7 +457,7 @@ const preprocessFile = function (cFile, ctx, callback)
nThen((w) => {
//debug("CPP");
cc(ctx.config.gcc, ['-E', ...cflags, cFile], w(function (err, output) {
cc(ctx, ['-E', ...cflags, cFile], w(function (err, output) {
if (err) { throw err; }
fileContent = output;
return false;
@@ -635,25 +592,12 @@ const makeTime = function () {
const link = function (cFile, callback, ctx /*:Builder_Ctx_t*/) {
const state = ctx.state;
let tempDir;
const temp = getTempExe(ctx, cFile);
nThen(function (waitFor) {
tempDir = tmpFile(ctx);
Fs.mkdir(tempDir, {}, waitFor(function (err) {
if (err) { throw err; }
}));
// TODO delete all other tmp files
}).nThen(function (waitFor) {
nThen((waitFor) => {
const linkOrder = getLinkOrder(cFile, state.cFiles);
for (let i = 0; i < linkOrder.length; i++) {
linkOrder[i] = getOFile(ctx, linkOrder[i]);
}
const fileObj = state.cFiles[cFile];
const ldArgs = []
.concat(ctx.config.ldflags)
@@ -662,37 +606,11 @@ const link = function (cFile, callback, ctx /*:Builder_Ctx_t*/) {
.concat(linkOrder)
.concat(ctx.config.libs);
debug('\x1b[1;31mLinking C executable ' + cFile + '\x1b[0m');
cc(ctx.config.gcc, ldArgs, waitFor(function (err, ret) {
cc(ctx, ldArgs, waitFor(function (err, ret) {
if (err) { throw err; }
return false;
}), '');
}).nThen(function (waitFor) {
Fs.readdir(tempDir, waitFor(function (err, files) {
if (err) { throw err; }
files.forEach(function (file) {
Fs.unlink(tempDir + '/' + file, waitFor(function (err) {
if (err) { throw err; }
}));
});
}));
}).nThen(function (waitFor) {
Fs.rmdir(tempDir, waitFor(function (err) {
if (err) { throw err; }
}));
}).nThen(function (waitFor) {
if (callback) {
callback();
}
});
}).nThen((_) => callback());
};
const compile = function (ctx, cFile, done) {
@@ -700,7 +618,7 @@ const compile = function (ctx, cFile, done) {
const file = ctx.state.cFiles[cFile];
const oFile = getOFile(ctx, cFile);
const iFile = getIFile(ctx, cFile);
cc(ctx.config.gcc, ['-c', '-x', 'cpp-output', '-o', oFile, ...file.cflags, iFile], (err) => {
cc(ctx, ['-c', '-x', 'cpp-output', '-o', oFile, ...file.cflags, iFile], (err) => {
done(err);
return typeof(err) !== 'undefined';
}, '');
@@ -753,7 +671,7 @@ const probeCompiler = function (ctx /*:Builder_Ctx_t*/, callback) {
isGCC: false,
version: ''
};
compiler(ctx.config.gcc, ['-v'], waitFor(function (ret, out, err) {
compiler(ctx, ['-v'], waitFor(function (ret, out, err) {
// TODO(cjd): afl-clang-fast errors when called with -v
//if (ret !== 0) { throw new Error("Failed to probe compiler ret[" + ret + "]\n" + err); }
if (/Apple LLVM version /.test(err)) {
@@ -788,7 +706,7 @@ const probeCompiler = function (ctx /*:Builder_Ctx_t*/, callback) {
compilerType.isGCC = true;
compilerType.version = err.match(/gcc version ([^ ]+) /)[1];
}
console.log(JSON.stringify(compilerType));
//console.log(JSON.stringify(compilerType));
}), '');
}).nThen(callback);
};
@@ -804,6 +722,34 @@ const deepFreeze = (obj) => {
}
};
const sweep = (path, done) => {
let files = [];
nThen((w) => {
Fs.readdir(path, w((err, fls) => {
if (err) { throw err; }
files = fls;
}));
}).nThen((w) => {
files.forEach((f) => {
const file = path + '/' + f;
Fs.stat(file, w((err, st) => {
if (err) { throw err; }
if (st.isDirectory()) {
sweep(file, w(() => {
Fs.rmdir(file, w((err) => {
if (err) { throw err; }
}));
}));
} else {
Fs.unlink(file, w((err) => {
if (err) { throw err; }
}));
}
}));
});
}).nThen((_) => done());
};
module.exports.configure = function (
params /*:Builder_BaseConfig_t*/,
configFunc /*:(Builder_t, Nthen_WaitFor_t)=>void*/
@@ -813,11 +759,27 @@ module.exports.configure = function (
const time = makeTime();
time();
if (typeof(params.systemName) !== 'string') {
throw new Error("system not specified");
const systemName = params.systemName || process.platform;
const buildDir = params.buildDir || 'build_' + systemName;
let gcc;
if (params.gcc) {
gcc = params.gcc;
} else if (systemName === 'openbsd') {
gcc = 'egcc';
} else if (systemName === 'freebsd') {
gcc = 'clang';
} else {
gcc = 'gcc';
}
const buildDir = params.buildDir = params.buildDir || 'build_' + params.systemName;
// Since many of the compile operations are short, the best
// performance seems to be when running 1.25x the number of jobs as
// cpu cores. On BSD and iphone systems, os.cpus() is not reliable so
// if it returns undefined let's just assume 1
// workaround, nodejs seems to be broken on openbsd (undefined result after second call)
const cpus = Os.cpus();
const jobs = Math.floor((typeof cpus === 'undefined' ? 1 : cpus.length) * 1.25);
const pctx /*:Builder_PreCtx_t*/ = {
buildStage: (_x,_y)=>{},
@@ -832,15 +794,12 @@ module.exports.configure = function (
executables: [],
tests: [],
toCompile: {},
sema: Saferphore.create(1),
config: {
crossCompiling: params.crossCompiling,
buildDir,
gcc: params.gcc,
logLevel: params.logLevel,
optimizeLevel: params.optimizeLevel,
systemName: params.systemName,
tempDir: params.tempDir,
gcc,
systemName,
version: '',
includeDirs: ['.'],
@@ -848,6 +807,7 @@ module.exports.configure = function (
ldflags: [],
libs: [],
fileCflags: {},
jobs,
},
};
let state = getStatePrototype();
@@ -865,6 +825,18 @@ module.exports.configure = function (
}));
}));
}).nThen(function (waitFor) {
Fs.exists(buildDir + '/tmp', waitFor(function (exists) {
if (exists) {
sweep(buildDir + '/tmp', waitFor());
} else {
Fs.mkdir(buildDir + '/tmp', {}, waitFor(function (err) {
if (err) { throw err; }
}));
}
}));
}).nThen(function (waitFor) {
// read out the state if it exists
@@ -905,19 +877,21 @@ module.exports.configure = function (
//if (!ctx.builder) { throw new Error(); }
configFunc(ctx.builder, waitFor);
}).nThen(function (waitFor) {
}).nThen(function (_) {
ctx.sema = Saferphore.create(ctx.config.jobs);
if (!ctx.config.version) {
GetVersion(waitFor(function(err, data) {
if (err === null) {
ctx.config.version = ('' + data).replace(/(\r\n|\n|\r)/gm, "");
} else {
ctx.config.version = 'unknown';
}
}));
if (ctx.config.systemName !== systemName) {
throw new Error("systemName cannot be changed in configure phase " +
"it must be specified in the initial configuration " +
`initial systemName = ${systemName}, changed to ${ctx.config.systemName}`);
}
if (ctx.config.gcc !== gcc) {
throw new Error("gcc cannot be changed in configure phase " +
"it must be specified in the initial configuration " +
`initial gcc = ${gcc}, changed to ${ctx.config.gcc}`);
}
}).nThen(function (_) {
deepFreeze(ctx.config);
debug("Configure " + time() + "ms");
@@ -1070,7 +1044,6 @@ const postConfigure = (ctx /*:Builder_Ctx_t*/, time) => {
deepFreeze(state);
}));
}).nThen(function (w) {
Object.keys(ctx.toCompile).forEach((cFile) => {
compile(ctx, cFile, w((err) => {
if (err) {
@@ -1105,7 +1078,7 @@ const postConfigure = (ctx /*:Builder_Ctx_t*/, time) => {
debug("Checking codestyle");
const sema = Semaphore.create(64);
const sema = Saferphore.create(64);
Object.keys(ctx.toCompile).forEach(function (cFile) {
sema.take(waitFor(function (returnAfter) {
@@ -1177,5 +1150,6 @@ const postConfigure = (ctx /*:Builder_Ctx_t*/, time) => {
ctx.completeStage(ctx.builder, waitFor);
sweep(ctx.config.buildDir + '/tmp', waitFor());
});
};

View File

@@ -19,40 +19,24 @@ var nThen = require('nthen');
var Codestyle = require('./Codestyle');
var Cp = require('./Cp');
var Spawn = require('child_process').spawn;
var Os = require('os');
var FindPython = require('./FindPython');
var CanCompile = require('./CanCompile');
var Builder = require('./builder');
var TestRunner = require('./TestRunner');
const CjdnsTest = require('./CjdnsTest');
const GetVersion = require('./GetVersion');
// ['linux','darwin','sunos','win32','freebsd','openbsd','netbsd']
var SYSTEM = process.env['SYSTEM'] || process.platform;
var GCC = process.env['CC'];
var CFLAGS = process.env['CFLAGS'];
var LDFLAGS = process.env['LDFLAGS'];
var NO_MARCH_FLAG = ['arm', 'ppc', 'ppc64'];
if (GCC) {
// Already specified.
} else if (SYSTEM === 'openbsd') {
GCC = 'egcc';
} else if (SYSTEM === 'freebsd') {
GCC = 'clang';
} else {
GCC = 'gcc';
}
Builder.configure({
systemName: SYSTEM,
crossCompiling: process.env['CROSS'] !== undefined,
gcc: GCC,
tempDir: process.env['CJDNS_BUILD_TMPDIR'] || '/tmp',
optimizeLevel: '-O3',
logLevel: process.env['Log_LEVEL'] || 'DEBUG'
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',
@@ -62,11 +46,10 @@ Builder.configure({
'-Wmissing-prototypes',
'-pedantic',
'-D', builder.config.systemName + '=1',
'-D', 'CJD_PACKAGE_VERSION="' + builder.config.version + '"',
'-Wno-unused-parameter',
'-fomit-frame-pointer',
'-D', 'Log_' + builder.config.logLevel,
'-D', 'Log_' + (process.env['Log_LEVEL'] || 'DEBUG'),
'-g',
@@ -164,18 +147,17 @@ Builder.configure({
var cflags = CFLAGS.split(' ');
cflags.forEach(function(flag) {
if (/^\-O[^02s]$/.test(flag)) {
console.log("Skipping " + flag + ", assuming " +
builder.config.optimizeLevel + " instead.");
console.log("Skipping " + flag + ", assuming " + optimizeLevel + " instead.");
} else if (/^\-O[02s]$/.test(flag)) {
builder.config.optimizeLevel = flag;
optimizeLevel = flag;
} else {
[].push.apply(builder.config.cflags, cflags);
}
});
}
builder.config.cflags.push(builder.config.optimizeLevel);
if (!/^\-O0$/.test(builder.config.optimizeLevel)) {
builder.config.cflags.push(optimizeLevel);
if (!/^\-O0$/.test(optimizeLevel)) {
builder.config.cflags.push('-D_FORTIFY_SOURCE=2');
}
@@ -189,25 +171,6 @@ Builder.configure({
builder.config.cflags.push('-Dandroid=1');
}
if (process.env.NO_LTO) {
console.log("Link time optimization disabled");
} else {
CanCompile.check(builder,
'int main() { return 0; }\n',
[ builder.config.cflags, '-flto', '-x', 'c' ],
waitFor(function (err, can) {
if (can) {
console.log("Compiler supports link time optimization");
builder.config.ldflags.push(
'-flto',
builder.config.optimizeLevel
);
} else {
console.log("Link time optimization not supported [" + err + "]");
}
}));
}
var uclibc = process.env['UCLIBC'] == '1';
var libssp;
switch (process.env['SSP_SUPPORT']) {
@@ -257,6 +220,19 @@ Builder.configure({
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
@@ -295,9 +271,9 @@ Builder.configure({
args.unshift('-fPIC');
}
args.unshift(builder.config.optimizeLevel, '-fomit-frame-pointer');
args.unshift(optimizeLevel, '-fomit-frame-pointer');
if (!/^\-O0$/.test(builder.config.optimizeLevel)) {
if (!/^\-O0$/.test(optimizeLevel)) {
args.unshift('-D_FORTIFY_SOURCE=2');
}
@@ -408,16 +384,16 @@ Builder.configure({
});
gyp.on('close', waitFor(function () {
var args = [
'-j', ''+builder.processors,
'-j', ''+builder.config.jobs,
'-C', 'out',
'BUILDTYPE=Release',
'CC=' + builder.config.gcc,
'CXX=' + builder.config.gcc,
'V=1'
];
var cflags = [builder.config.optimizeLevel, '-DNO_EMFILE_TRICK=1'];
var cflags = [optimizeLevel, '-DNO_EMFILE_TRICK=1'];
if (!/^\-O0$/.test(builder.config.optimizeLevel)) {
if (!/^\-O0$/.test(optimizeLevel)) {
cflags.push('-D_FORTIFY_SOURCE=2');
}

12
node_modules/nthen/package.json generated vendored
View File

@@ -1,4 +1,10 @@
{
"_args": [
[
"nthen@0.2.1",
"/Users/user/wrk/cjdns"
]
],
"_from": "nthen@0.2.1",
"_id": "nthen@0.2.1",
"_inBundle": false,
@@ -16,12 +22,10 @@
"fetchSpec": "0.2.1"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/nthen/-/nthen-0.2.1.tgz",
"_shasum": "cf665cada4afd773f2443d77c5d77e79a965531f",
"_spec": "nthen@0.2.1",
"_spec": "0.2.1",
"_where": "/Users/user/wrk/cjdns",
"author": {
"name": "Caleb James DeLisle"
@@ -29,8 +33,6 @@
"bugs": {
"url": "https://github.com/cjdelisle/nthen/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Simple intuitive asynchronous control flow.",
"devDependencies": {
"flow-bin": "^0.106.2",

7
node_modules/saferphore/.flowconfig generated vendored Normal file
View File

@@ -0,0 +1,7 @@
[ignore]
[include]
[libs]
[options]

1
node_modules/saferphore/.jshintignore generated vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

16
node_modules/saferphore/.jshintrc generated vendored Normal file
View File

@@ -0,0 +1,16 @@
{
"laxcomma": true,
"laxbreak": true,
"node": true,
"browser": true,
"sub": true,
"curly": true,
"eqeqeq": true,
"iterator": true,
"latedef": true,
"nocomma": true,
"notypeof": true,
"shadow": false,
"undef": true,
"unused": false
}

12
node_modules/saferphore/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,12 @@
language: node_js
node_js:
- '6'
- '5'
- '4'
- '0.12'
script:
- npm run-script test
- npm run-script lint
- npm run-script flow

50
node_modules/saferphore/index.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
/*@flow*/
/*::
export type Saferphore_ReturnAfter_t = ((...any)=>void)=>(...any)=>void;
export type Saferphore_t = {
take: ((Saferphore_ReturnAfter_t)=>void)=>void,
};
*/
;(function () {
"use strict";
var create = function (resourceCount /*:number*/) /*:Saferphore_t*/ {
var queue = [];
var check;
var mkRa = function () /*:Saferphore_ReturnAfter_t*/ {
var outerCalled = 0;
return function (func) {
if (outerCalled++) { throw new Error("returnAfter() called multiple times"); }
var called = 0;
return function () {
if (called++) {
throw new Error("returnAfter wrapped callback called multiple times");
}
if (func) { func.apply(null, arguments); }
resourceCount++;
check();
};
};
};
check = function () {
if (resourceCount < 0) { throw new Error("(resourceCount < 0) should never happen"); }
if (resourceCount === 0 || queue.length === 0) { return; }
resourceCount--;
queue.shift()(mkRa());
};
return {
take: function (func) {
queue.push(func);
check();
}
};
};
if (typeof(window) === 'object') {
if (window.define && window.define.amd) {
window.define({ create: create });
} else {
window.Saferphore = { create: create };
}
} else if (typeof(module) === 'object' && module.exports) {
module.exports.create = create;
}
}());

51
node_modules/saferphore/package.json generated vendored Normal file
View File

@@ -0,0 +1,51 @@
{
"_args": [
[
"saferphore@0.0.2",
"/Users/user/wrk/cjdns"
]
],
"_from": "saferphore@0.0.2",
"_id": "saferphore@0.0.2",
"_inBundle": false,
"_integrity": "sha512-gjdCGXxrSKi1oSWJH0vx99WtB2wkjbXPQf6ALHEskLo0e4Vgd57txhracaeLlPt2r4rUiJBe+thriuxS85q7JA==",
"_location": "/saferphore",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "saferphore@0.0.2",
"name": "saferphore",
"escapedName": "saferphore",
"rawSpec": "0.0.2",
"saveSpec": null,
"fetchSpec": "0.0.2"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/saferphore/-/saferphore-0.0.2.tgz",
"_spec": "0.0.2",
"_where": "/Users/user/wrk/cjdns",
"bugs": {
"url": "https://github.com/cjdelisle/saferphore/issues"
},
"description": "Node Semaphore which has protection against double-returning",
"devDependencies": {
"flow-bin": "^0.115.0",
"jshint": "~2.9.1"
},
"homepage": "https://github.com/cjdelisle/saferphore#readme",
"license": "MIT",
"name": "saferphore",
"repository": {
"type": "git",
"url": "git+https://github.com/cjdelisle/saferphore.git"
},
"scripts": {
"flow": "flow",
"lint": "jshint --verbose --config .jshintrc --exclude-path .jshintignore .",
"test": "node test"
},
"version": "0.0.2"
}

30
node_modules/saferphore/readme.md generated vendored Normal file
View File

@@ -0,0 +1,30 @@
# Saferphore - Node semaphore with protection against double-returning
# node
npm install --save saferphore
# Browser
bower install --save saferphore
```javascript
const Saferphore = require('saferphore');
var sem = Saferphore.create(4);
for (var i = 0; i < 10000; i++) {
sem.take(function (returnAfter) {
Fs.writeFile('file_' + i, 'hi', returnAfter(function (err) {
if (err) { throw err; }
});
});
}
```
You can only return what you take, if you try to call returnAfter() twice then it will throw a
clear error instead of creating a leaky semaphore.
```javascript
sem.take(function (returnAfter) {
stream.on('data', returnAfter(processData)); // BZZZZZZZT error when it's called more than once
});
```

54
node_modules/saferphore/test.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
'use strict';
var Saferphore = require('./index');
var assert = function (x) { if (!x) { throw new Error(); } };
var basicTest = function () {
var sem = Saferphore.create(4);
var out = [];
(new Array(10)).join().split(',').forEach(function (x,y) {
sem.take(function (returnAfter) {
out.push(y);
setTimeout(returnAfter(function () {
if (out.length === 10) {
if (out.join() !== "0,1,2,3,4,5,6,7,8,9") { throw new Error(); }
}
}));
});
});
if (out.join() !== "0,1,2,3") {
throw new Error(out.join());
}
};
var doubleCallTest = function () {
var sem = Saferphore.create(4);
var catcher = setTimeout(function () {
throw new Error();
}, 1000);
sem.take(function (returnAfter) {
setTimeout(returnAfter(function () {
setTimeout(function () {
clearTimeout(catcher);
try { returnAfter()(); } catch (e) { return; }
throw new Error();
});
}));
});
};
var doubleCallbackTest = function () {
var sem = Saferphore.create(4);
var catcher = setTimeout(function () {
throw new Error();
}, 1000);
sem.take(function (returnAfter) {
var wrapped = returnAfter();
wrapped();
try { wrapped(); } catch (e) { clearTimeout(catcher); return; }
throw new Error();
});
};
basicTest();
doubleCallTest();
doubleCallbackTest();

225
package-lock.json generated
View File

@@ -1,233 +1,18 @@
{
"name": "cjdns",
"version": "0.17.2",
"version": "0.17.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"cli": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz",
"integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=",
"requires": {
"exit": "0.1.2",
"glob": "^7.1.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"console-browserify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
"integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
"requires": {
"date-now": "^0.1.4"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"date-now": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
"integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
},
"dom-serializer": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
"integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
"requires": {
"domelementtype": "^2.0.1",
"entities": "^2.0.0"
},
"dependencies": {
"domelementtype": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz",
"integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA=="
},
"entities": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
}
}
},
"domelementtype": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
},
"domhandler": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
"integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
"requires": {
"domelementtype": "1"
}
},
"domutils": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
"requires": {
"dom-serializer": "0",
"domelementtype": "1"
}
},
"entities": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
"integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY="
},
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
"integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"htmlparser2": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
"integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
"requires": {
"domelementtype": "1",
"domhandler": "2.3",
"domutils": "1.5",
"entities": "1.0",
"readable-stream": "1.1"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"jshint": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/jshint/-/jshint-2.12.0.tgz",
"integrity": "sha512-TwuuaUDmra0JMkuqvqy+WGo2xGHSNjv1BA1nTIgtH2K5z1jHuAEeAgp7laaR+hLRmajRjcrM71+vByBDanCyYA==",
"requires": {
"cli": "~1.0.0",
"console-browserify": "1.1.x",
"exit": "0.1.x",
"htmlparser2": "3.8.x",
"lodash": "~4.17.19",
"minimatch": "~3.0.2",
"shelljs": "0.3.x",
"strip-json-comments": "1.0.x"
}
},
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"nthen": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nthen/-/nthen-0.2.1.tgz",
"integrity": "sha512-QW3p6gxOaHHLFM+2HcytugGUiji4pNpLkNAtPQi2gX2+hSmndnNSDYbDSUdIEy7vGJ+LkocZ3EvgwxeKfToZGg=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"shelljs": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz",
"integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E="
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
},
"strip-json-comments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
"integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E="
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
"saferphore": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/saferphore/-/saferphore-0.0.2.tgz",
"integrity": "sha512-gjdCGXxrSKi1oSWJH0vx99WtB2wkjbXPQf6ALHEskLo0e4Vgd57txhracaeLlPt2r4rUiJBe+thriuxS85q7JA=="
}
}
}

View File

@@ -1,8 +1,8 @@
{
"name": "cjdns",
"version": "0.17.2",
"version": "0.17.3",
"dependencies": {
"jshint": "^2.12.0",
"nthen": "^0.2.1"
"nthen": "^0.2.1",
"saferphore": "0.0.2"
}
}

View File

@@ -1,24 +1,51 @@
module.exports.create = function (resourceCount) {
var queue = [];
var returnAfter = function (func) {
var called = 0;
return function () {
if (called++) { throw new Error("Function called multiple times"); }
if (func) { func.apply(null, arguments); }
resourceCount++;
check();
/*@flow*/
/*::
export type Saferphore_ReturnAfter_t = ((...any)=>void)=>(...any)=>void;
export type Saferphore_t = {
take: ((Saferphore_ReturnAfter_t)=>void)=>void,
};
*/
;(function () {
"use strict";
var create = function (resourceCount /*:number*/) /*:Saferphore_t*/ {
var queue = [];
var check;
var mkRa = function () /*:Saferphore_ReturnAfter_t*/ {
var outerCalled = 0;
return function (func) {
if (outerCalled++) { throw new Error("returnAfter() called multiple times"); }
var called = 0;
return function () {
if (called++) {
throw new Error("returnAfter wrapped callback called multiple times");
}
if (func) { func.apply(null, arguments); }
resourceCount++;
check();
};
};
};
check = function () {
if (resourceCount < 0) { throw new Error("(resourceCount < 0) should never happen"); }
if (resourceCount === 0 || queue.length === 0) { return; }
resourceCount--;
queue.shift()(mkRa());
};
return {
take: function (func) {
queue.push(func);
check();
}
};
};
var check = function () {
if (resourceCount < 0) { throw new Error("(resourceCount < 0) should never happen"); }
if (resourceCount === 0 || queue.length === 0) { return; }
resourceCount--;
queue.shift()(returnAfter);
};
return {
take: function (func) {
queue.push(func);
check();
if (typeof(window) === 'object') {
if (window.define && window.define.amd) {
window.define({ create: create });
} else {
window.Saferphore = { create: create };
}
};
};
} else if (typeof(module) === 'object' && module.exports) {
module.exports.create = create;
}
}());

View File

@@ -18,7 +18,7 @@ var Bencode = require('./bencode');
var Crypto = require('crypto');
var Fs = require('fs');
var nThen = require('nthen');
var Semaphore = require('../Semaphore.js');
var Semaphore = require('saferphore');
var TIMEOUT_MILLISECONDS = 10000;