make.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. var Fs = require('fs');
  16. var nThen = require('nthen');
  17. var Codestyle = require('./Codestyle');
  18. var Cp = require('./Cp');
  19. var Spawn = require('child_process').spawn;
  20. var Os = require('os');
  21. // ['linux','darwin','sunos','win32','freebsd']
  22. var SYSTEM = process.platform;
  23. var GCC = process.env['CC'] || 'gcc';
  24. var BUILDDIR = process.env['BUILDDIR'];
  25. if (BUILDDIR == undefined) {
  26. BUILDDIR = 'build_'+SYSTEM;
  27. }
  28. var WORKERS = Math.floor(Os.cpus().length * 1.25);
  29. process.on('exit', function () {
  30. console.log("Total build time: " + Math.floor(process.uptime() * 1000) + "ms.");
  31. });
  32. var Builder = require('./builder');
  33. Builder.configure({
  34. rebuildIfChanges: Fs.readFileSync(__filename).toString('utf8') + JSON.stringify(process.env),
  35. buildDir: BUILDDIR
  36. }, function(builder, waitFor) {
  37. builder.config.systemName = SYSTEM;
  38. builder.config.gcc = GCC;
  39. builder.config.tempDir = '/tmp';
  40. builder.config.useTempFiles = true;
  41. builder.config.cflags.push(
  42. '-std=c99',
  43. '-Wall',
  44. '-Wextra',
  45. '-Werror',
  46. '-Wno-pointer-sign',
  47. '-pedantic',
  48. '-D',builder.config.systemName + '=1',
  49. '-Wno-unused-parameter',
  50. '-Wno-unused-result',
  51. // Broken GCC patch makes -fstack-protector-all not work
  52. // workaround is to give -fno-stack-protector first.
  53. // see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722
  54. '-fno-stack-protector',
  55. '-fstack-protector-all',
  56. '-Wstack-protector',
  57. '-D','HAS_BUILTIN_CONSTANT_P',
  58. '-g',
  59. // '-flto', not available on some machines
  60. // f4 = 16 peers max, fixed width 4 bit
  61. // f8 = 241 peers max, fixed width 8 bit
  62. // v3x5x8 = 256 peers max, variable width, 3, 5 or 8 bits plus 1 or 2 bits of prefix
  63. // v4x8 = 256 peers max, variable width, 4, or 8 bits plus 1 bit prefix
  64. '-D',' NumberCompress_TYPE=v4x8',
  65. // disable for speed, enable for safety
  66. '-D','Log_DEBUG',
  67. '-D','Identity_CHECK=1',
  68. '-D','Allocator_USE_CANARIES=1',
  69. '-D','PARANOIA=1'
  70. );
  71. if (process.env['NO_PIE'] == undefined) {
  72. builder.config.cflags.push('-fPIE')
  73. }
  74. if (process.env['EXPERIMENTAL_PATHFINDER']) {
  75. console.log("Building with experimental pathfinder");
  76. builder.config.cflags.push(
  77. '-D','EXPERIMENTAL_PATHFINDER=1'
  78. );
  79. }
  80. if (SYSTEM === 'win32') {
  81. builder.config.cflags.push(
  82. '!-fPIE',
  83. '!-pie',
  84. '-Wno-format'
  85. );
  86. builder.config.libs.push(
  87. '-lssp'
  88. );
  89. } else if (SYSTEM === 'linux') {
  90. builder.config.ldflags.push(
  91. '-Wl,-z,relro,-z,now,-z,noexecstack'
  92. );
  93. builder.config.cflags.push(
  94. '-DHAS_ETH_INTERFACE=1'
  95. );
  96. }
  97. if (process.env['NO_PIE'] == undefined) {
  98. builder.config.ldflags.push(
  99. '-pie'
  100. );
  101. }
  102. if (/.*clang.*/.test(GCC) || SYSTEM === 'darwin') {
  103. // blows up when preprocessing before js preprocessor
  104. builder.config.cflags.push(
  105. '-Wno-invalid-pp-token',
  106. '-Wno-dollar-in-identifier-extension',
  107. '-Wno-newline-eof',
  108. // lots of places where depending on preprocessor conditions, a statement might be
  109. // a case of if (1 == 1)
  110. '-Wno-tautological-compare'
  111. );
  112. }
  113. // Build dependencies
  114. nThen(function (waitFor) {
  115. Fs.exists(BUILDDIR+'/dependencies', waitFor(function (exists) {
  116. if (exists) { return; }
  117. console.log("Copy dependencies");
  118. Cp('./node_build/dependencies', BUILDDIR+'/dependencies', waitFor());
  119. }));
  120. }).nThen(function (waitFor) {
  121. builder.config.libs.push(
  122. BUILDDIR+'/dependencies/cnacl/jsbuild/libnacl.a'
  123. );
  124. builder.config.includeDirs.push(
  125. BUILDDIR+'/dependencies/cnacl/jsbuild/include/'
  126. );
  127. Fs.exists(BUILDDIR+'/dependencies/cnacl/jsbuild/libnacl.a', waitFor(function (exists) {
  128. if (exists) { return; }
  129. console.log("Build NaCl");
  130. var cwd = process.cwd();
  131. process.chdir(BUILDDIR+'/dependencies/cnacl/');
  132. var NaCl = require(process.cwd() + '/node_build/make.js');
  133. NaCl.build(function (args, callback) {
  134. if (builder.config.systemName !== 'win32') { args.unshift('-fPIC'); }
  135. args.unshift('-O2', '-fomit-frame-pointer');
  136. builder.cc(args, callback);
  137. }, waitFor(function () {
  138. process.chdir(cwd);
  139. }));
  140. }));
  141. }).nThen(function (waitFor) {
  142. builder.config.libs.push(
  143. BUILDDIR+'/dependencies/libuv/libuv.a',
  144. '-lpthread'
  145. );
  146. if (builder.config.systemName === 'win32') {
  147. builder.config.libs.push(
  148. '-lws2_32',
  149. '-lpsapi', // GetProcessMemoryInfo()
  150. '-liphlpapi' // GetAdapterAddresses()
  151. );
  152. } else if (builder.config.systemName === 'linux') {
  153. builder.config.libs.push(
  154. '-lrt' // clock_gettime()
  155. );
  156. } else if (builder.config.systemName === 'darwin') {
  157. builder.config.libs.push(
  158. '-framework', 'CoreServices'
  159. );
  160. }
  161. builder.config.includeDirs.push(
  162. BUILDDIR+'/dependencies/libuv/include/'
  163. );
  164. Fs.exists(BUILDDIR+'/dependencies/libuv/libuv.a', waitFor(function (exists) {
  165. if (exists) { return; }
  166. console.log("Build Libuv");
  167. var cwd = process.cwd();
  168. process.chdir(BUILDDIR+'/dependencies/libuv/');
  169. var args = ['-j', WORKERS, 'CC='+builder.config.gcc]
  170. if (builder.config.systemName === 'win32') { args.push('PLATFORM=mingw32'); }
  171. if (builder.config.systemName !== 'darwin') { args.push('CFLAGS=-fPIC'); }
  172. var make = Spawn('make', args);
  173. make.stdout.on('data', function(dat) { process.stdout.write(dat.toString()); });
  174. make.stderr.on('data', function(dat) { process.stderr.write(dat.toString()); });
  175. make.on('close', waitFor(function () {
  176. process.chdir(cwd);
  177. }));
  178. }));
  179. }).nThen(waitFor());
  180. }).build(function (builder, waitFor) {
  181. builder.buildExecutable('admin/angel/cjdroute2.c', BUILDDIR+'/cjdroute', waitFor());
  182. builder.buildExecutable('test/testcjdroute.c', BUILDDIR+'/testcjdroute', waitFor());
  183. builder.buildExecutable('contrib/c/publictoip6.c', './publictoip6', waitFor());
  184. builder.buildExecutable('contrib/c/privatetopublic.c', './privatetopublic', waitFor());
  185. builder.buildExecutable('contrib/c/sybilsim.c', './sybilsim', waitFor());
  186. builder.buildExecutable('contrib/c/benc2json.c', './benc2json', waitFor());
  187. builder.buildExecutable('contrib/c/cleanconfig.c', './cleanconfig', waitFor());
  188. builder.buildExecutable('contrib/c/dnsserv.c', './dnsserv', waitFor());
  189. builder.buildExecutable('contrib/c/makekeys.c', './makekeys', waitFor());
  190. }).test(function (builder, waitFor) {
  191. nThen(function (waitFor) {
  192. var out = '';
  193. var err = '';
  194. var test = Spawn(BUILDDIR+'/testcjdroute', ['all']);
  195. test.stdout.on('data', function(dat) { out += dat.toString(); });
  196. test.stderr.on('data', function(dat) { err += dat.toString(); });
  197. test.on('close', waitFor(function (ret) {
  198. if (ret !== 0) {
  199. console.log(out);
  200. console.log(err);
  201. console.log('\033[1;31mFailed to build cjdns.\033[0m');
  202. waitFor.abort();
  203. } else {
  204. console.log(err);
  205. }
  206. }));
  207. }).nThen(function (waitFor) {
  208. console.log("Checking codestyle");
  209. var files = [];
  210. builder.rebuiltFiles.forEach(function (fileName) {
  211. if (fileName.indexOf('/dependencies/') !== -1) { return; }
  212. console.log("Checking " + fileName);
  213. files.push(fileName);
  214. });
  215. Codestyle.checkFiles(files, waitFor(function (output) {
  216. if (output !== '') {
  217. throw new Error("Codestyle failure\n" + output);
  218. }
  219. }));
  220. }).nThen(waitFor());
  221. }).pack(function (builder, waitFor) {
  222. Fs.exists(BUILDDIR+'/cjdroute', waitFor(function (exists) {
  223. if (!exists) { return; }
  224. Fs.rename(BUILDDIR+'/cjdroute', './cjdroute', waitFor(function (err) {
  225. if (err) { throw err; }
  226. }));
  227. }));
  228. console.log('\033[1;32mBuild completed successfully, type ./cjdroute to begin setup.\033[0m');
  229. });