123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- var crypto = require('crypto');
- var fs = require('fs');
- var fse = require('fs-extra');
- var path = require('path');
- var child_process = require('child_process');
- var co = require('co');
- var S = require('string');
- var filewalker = require('filewalker');
- var dependencies = require('../data/Dependencies');
- var Builder = module.exports = function(basePath, sources) {
- this.avrconfig = {
- Path:'/usr/share/arduino/hardware/tools/avr/bin',
- BOARD_TAG: 'uno',
- Tools: {
- CC_NAME: 'avr-gcc',
- CXX_NAME: 'avr-g++',
- OBJCOPY_NAME: 'avr-objcopy',
- AR_NAME: 'avr-ar',
- SIZE_NAME: 'avr-size',
- NM_NAME: 'avr-nm'
- }
- };
- this.id = null;
- this.filename = 'main.ino';
- this.lib = {
- Path: {
- core: path.join(__dirname, '..', 'libraries/core'),
- external: path.join(__dirname, '..', 'libraries/external'),
- thirdparty: path.join(__dirname, '..', 'libraries/thirdparty')
- },
- libs: {
- core: [],
- external: [],
- thirdparty: []
- },
- dirs: {
- external: [],
- thirdparty: []
- }
- };
- this.basePath = basePath;
- this.sources = sources || {};
- this.workingPath = '';
- };
- Builder.prototype.init = function(callback) {
- var self = this;
- self.id = crypto.randomBytes(16).toString('hex').substr(0, 8) + Date.now();
- self.workingPath = path.join(self.basePath, self.id);
- fse.mkdirs(self.workingPath, function(err) {
- if (callback)
- callback(err);
- });
- };
- Builder.prototype.scanLibraries = function(callback) {
- var self = this;
- co(function *() {
- try {
- // Scanning core libraries
- self.lib.libs.core = yield function(done) {
- fs.readdir(self.lib.Path.core, done);
- };
- } catch(e) {}
- yield function(done) {
- filewalker(self.lib.Path.thirdparty)
- .on('dir', function(p) {
- if(!S(p).contains('/')){
- //console.log('dir: %s', p);
- self.lib.dirs.thirdparty.push(p);
- }
- })
- .on('file', function(p, s) {
- if(S(p).contains('.o')){
- //console.log('file: %s, %d bytes', p, s.size);
- self.lib.libs.thirdparty.push(p);
- }
- })
- .on('error', function(err) {
- console.error(err);
- })
- .on('done', function() {
- //console.log('%d dirs, %d files, %d bytes', this.dirs, this.files, this.bytes);
- done();
- })
- .walk();
- };
- yield function(done) {
- filewalker(self.lib.Path.external)
- .on('dir', function(p) {
- if(!S(p).contains('/')){
- //console.log('dir: %s', p);
- self.lib.dirs.external.push(p);
- }
- })
- .on('file', function(p, s) {
- if(S(p).contains('.o')){
- //console.log('file: %s, %d bytes', p, s.size);
- self.lib.libs.external.push(p);
- }
- })
- .on('error', function(err) {
- console.error(err);
- })
- .on('done', function() {
- //console.log('%d dirs, %d files, %d bytes', this.dirs, this.files, this.bytes);
- done();
- })
- .walk();
- };
- if (callback)
- callback();
- });
- };
- Builder.prototype.scanSources = function(callback) {
- var self = this;
- var content = '';
- var tmplist = [];
- var filepath = path.join(self.workingPath, self.filename);
- co(function *() {
- try {
- content = yield function(done) {
- fs.readFile(filepath, done);
- };
- } catch(e) {}
- var lines = S(content.toString()).lines();
- lines.forEach(function(line, index, array) {
- if(S(line).contains('#include')){
- if(!S(line).contains('stdio')){
- tmplist.push(S(line).between('#include <', '.h>').s);
- }
- }
- else if (S(line).contains('Serial.begin')) {
- tmplist.push('SoftwareSerial');
- }
- else{
- }
- });
- if (callback)
- callback(null, tmplist);
- });
- };
- Builder.prototype.parseOps = function(liblist, callback) {
- var self = this;
- var prelinkOps = [];
- var current = '';
- function checklib(lib) {
- return S(lib).contains(current+'.o');
- }
- function checkutilitylib(lib, index, array) {
- if (S(lib).contains(current+'/utility/')){
- prelinkOps.push( path.join(self.lib.Path.external, lib) );
- }
- return true;
- }
- liblist.forEach(function(lib, index, array) {
- current = lib;
- var externaltmp = self.lib.libs.external.findIndex(checklib);
- var thirdpartytmp = self.lib.libs.thirdparty.findIndex(checklib);
- if(externaltmp != -1){
- prelinkOps.push( path.join(self.lib.Path.external, self.lib.libs.external[externaltmp]) );
- if ( lib == 'Ethernet' ||
- lib == 'SD' ||
- lib == 'TFT' ||
- lib == 'Wire' ){
- self.lib.libs.external.every(checkutilitylib);
- }
- }
- else if(thirdpartytmp != -1){
- prelinkOps.push(path.join(self.lib.Path.thirdparty, self.lib.libs.thirdparty[thirdpartytmp]));
- }
- else{
- console.log('[parseOps]none.');
- }
- });
- if (callback)
- callback(null, prelinkOps);
- };
- Builder.prototype.parseDeps = function(liblist, prelinkOps, callback) {
- var self = this;
- var linkOps = prelinkOps;
- liblist.forEach(function(lib, index, array) {
- for (var prop in dependencies) {
- if (prop == lib){
- var checkDeps = dependencies[prop];
- if(checkDeps.external){
- checkDeps.external.forEach(function(dep, index, array) {
- linkOps.push( path.join(self.lib.Path.external, dep) );
- });
- }
- if(checkDeps.thirdparty){
- checkDeps.thirdparty.forEach(function(dep, index, array) {
- linkOps.push( path.join(self.lib.Path.thirdparty, dep) );
- });
- }
- }
- }
- });
- if (callback)
- callback(null, linkOps);
- };
- Builder.prototype.generateSources = function(callback) {
- var self = this;
- co(function *() {
- // Generating all source files
- for (var filename in self.sources) {
- var filepath = path.join(self.workingPath, self.filename); // Need to be fixed.
- yield function(done) {
- fse.outputFile(filepath, self.sources[filename], done);
- };
- }
- if (callback)
- callback();
- });
- };
- Builder.prototype.generateCompileOps = function(linkOps, callback) {
- var self = this;
- var Ops = {
- CXX: [],
- AR: [],
- CC: [],
- OBJCOPY_eep: [],
- OBJCOPY_hex: []
- }
- var preCXX = [path.join(self.avrconfig.Path, self.avrconfig.Tools.CXX_NAME),
- '-x c++',
- '-include /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h',
- '-MMD -c -mmcu=atmega328p',
- '-DF_CPU=16000000L',
- '-DARDUINO=105',
- '-D__PROG_TYPES_COMPAT__',
- '-I. -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/standard'
- ];
- self.lib.dirs.external.forEach(function(lib, index, array) {
- preCXX.push('-I/usr/share/arduino/libraries/' + lib);
- });
- self.lib.dirs.thirdparty.forEach(function(lib, index, array) {
- preCXX.push('-I' + path.join(__dirname, '../libraries/thirdparty', lib));
- });
- preCXX.push('-Wall -ffunction-sections -fdata-sections -Os -fno-exceptions ',
- path.join(self.workingPath, self.filename),
- '-o ' + path.join(self.workingPath, self.id + '.o'));
- Ops.CXX = preCXX.join(' ');
- var preAR = [path.join(self.avrconfig.Path, self.avrconfig.Tools.AR_NAME),
- 'rcs',
- path.join(self.workingPath, 'libcore.a')
- ];
- self.lib.libs.core.forEach(function(lib, index, array) {
- preAR.push(path.join(__dirname, '../libraries/core', lib));
- });
- linkOps.forEach(function(lib, index, array) {
- preAR.push(lib);
- });
- Ops.AR = preAR.join(' ');
- Ops.CC = [path.join(self.avrconfig.Path, self.avrconfig.Tools.CC_NAME),
- '-mmcu=atmega328p',
- '-Wl,--gc-sections -Os',
- '-o ' + path.join(self.workingPath, self.id + '.elf'),
- path.join(self.workingPath, self.id + '.o'),
- path.join(self.workingPath, 'libcore.a'),
- '-lc -lm'
- ].join(' ');
- Ops.OBJCOPY_eep = [path.join(self.avrconfig.Path, self.avrconfig.Tools.OBJCOPY_NAME),
- '-j .eeprom --set-section-flags=.eeprom="alloc,load"',
- '--change-section-lma .eeprom=0 -O ihex',
- path.join(self.workingPath, self.id + '.elf'),
- path.join(self.workingPath, self.id + '.eep')
- ].join(' ');
- Ops.OBJCOPY_hex = [path.join(self.avrconfig.Path, self.avrconfig.Tools.OBJCOPY_NAME),
- '-O ihex -R .eeprom',
- path.join(self.workingPath, self.id + '.elf'),
- path.join(self.workingPath, self.id + '.hex')
- ].join(' ');
- if (callback)
- callback(null, Ops);
- };
- Builder.prototype.compile = function(CompileOps, callback) {
- var self = this;
- co(function *() {
- try {
- yield function(done) {
- child_process.exec(CompileOps.CXX, done);
- };
- } catch(e) {}
- try {
- yield function(done) {
- child_process.exec(CompileOps.AR, done);
- };
- } catch(e) {}
- try {
- yield function(done) {
- child_process.exec(CompileOps.CC, done);
- };
- } catch(e) {}
- try {
- yield function(done) {
- child_process.exec(CompileOps.OBJCOPY_eep, done);
- };
- } catch(e) {}
- child_process.exec(CompileOps.OBJCOPY_hex, function(err, cmdout, cmderr) {
- if (err) {
- callback(err);
- } else if (callback) {
- return callback(null, path.join(self.workingPath, self.id + '.hex'));
- }
- });
- });
- };
|