Permalink
Browse files

Make the builder capable of building wxWidgets from scratch. Config f…

…ile for building wxWidgets that works.
  • Loading branch information...
1 parent b170036 commit a6a35b3ebd4887bd63987a50aa23f5a6dc14ecb8 @Benvie Benvie committed Feb 22, 2012
Showing with 238 additions and 67 deletions.
  1. +237 −0 build-win32.js
  2. +1 −0 config-win32.json
  3. +0 −67 win32-build.js
View
237 build-win32.js
@@ -0,0 +1,237 @@
+var path = require('path');
+var fs = require('fs');
+var child_process = require('child_process');
+
+var Builder = require('mnm');
+
+
+var exists = fs.existsSync || path.existsSync;
+var resolve = path.resolve;
+
+
+
+function wxBuilder(o){
+ o = Object.keys(o || {}).reduce(function(r,s){ r[s]=o[s]; return r; }, {
+ wxBase: '/wxWidgets',
+ wxConfig: resolve('build', 'config-'+process.platform+'.json'),
+ useDll: false,
+ verbose: false,
+ name: 'wxnode',
+ });
+
+ this.wxConfig = new Config(o.wxConfig);
+ this.name = this.wxConfig.CFG = o.name;
+ this.wxBase = resolve(o.wxBase);
+ this.wxLibDir = resolve(o.wxBase, 'lib/vc_'+(o.useDll ? 'dll' : 'lib')+o.name);
+ this.wxBuildDir = resolve(o.wxBase, 'build/msw');
+ this.wxIncludeDir = resolve(o.wxBase, 'include');
+ this.srcDir = resolve(__dirname, 'src');
+ this.buildDir = resolve(__dirname, 'build');
+}
+
+wxBuilder.msLibs = [ 'kernel32', 'user32', 'gdi32', 'comdlg32',
+ 'comctl32', 'advapi32', 'shell32', 'ole32',
+ 'oleaut32', 'rpcrt4', 'winspool', 'winmm' ];
+
+wxBuilder.prototype = {
+ build: function build(callback){
+ var self = this;
+ if (!exists(this.wxLibDir)) {
+ this.buildWX(function(e){
+ self.buildBindings(callback);
+ });
+ } else {
+ self.buildBindings(callback);
+ }
+ },
+
+ buildWX: function buildWX(callback){
+ if (!this.vcVars()) throw new Error('Unable to find Visual C++');
+ callback = callback || function(){};
+
+ var configname = 'config_'+this.name;
+ var config = new File(this.wxBuildDir + '/'+configname);
+ var makefile = new File(this.wxBuildDir + '/makefile_'+this.name);
+
+ this.wxConfig.save(config);
+ new File(this.wxBuildDir + '/makefile.vc').copy(makefile, function(s){
+ return s.replace('config.vc', configname);
+ });
+ new File(this.wxIncludeDir + '/wx/msw/setup0.h').copy(this.wxIncludeDir + '/wx/msw/setup.h');
+
+ child_process.spawn('nmake', [ makefile.path ], {
+ cwd: this.wxBuildDir,
+ env: process.env,
+ customFds: [0,1,2]
+ }).on('exit', function(code) {
+ config.delete();
+ makefile.delete();
+ callback(code);
+ });
+ },
+
+ buildBindings: function buildBindings(callback){
+ if (!this.vcVars()) throw new Error('Unable to find Visual C++');
+ callback = callback || function(){};
+ var builder = new Builder;
+
+ builder.target = this.name+'_bindings';
+ builder.verbose = this.verbose;
+
+ builder.appendUnique('CXXFLAGS', ['-DUNICODE', '-DNDEBUG']);
+
+ if (this.dll)
+ builder.appendUnique('CXXFLAGS', '-DWXUSINGDLL');
+
+ builder.appendLinkerSearchDir(this.wxLibDir);
+
+ builder.appendLinkerLibrary(dir(this.wxLibDir, '.lib'));
+ builder.appendLinkerLibrary(wxBuilder.msLibs);
+
+ builder.appendIncludeDir([
+ this.srcDir,
+ this.srcDir+'-dummy',
+ this.srcDir+'-generated',
+ this.wxIncludeDir
+ ]);
+
+ builder.appendSourceDir([
+ this.srcDir,
+ this.srcDir+'-generated'
+ ]);
+
+ builder.compileAndLink(callback);
+ },
+
+ vcVars: function vcVars(){
+ var vcpath = [10,9,8].reduce(function(r,s){ return r ? r : (s = 'VS'+s+'0COMNTOOLS') in process.env ? process.env[s] : r; }, null);
+ var vars;
+ if (!vcpath || !exists(vcpath = resolve(vcpath, '../../vc/vcvarsall.bat'))) {
+ vars = null;
+ } else {
+ vars = execSync('"'+vcpath+'" & set').trim().split('\r\n').reduce(function(r,s){
+ var name = s.slice(0, s.indexOf('='));
+ s = s.slice(name.length+1);
+ if (process.env[name] !== s) {
+ process.env[name] = r[name] = s;
+ }
+ return r;
+ }, {});
+ }
+ this.vcVars = function(){ return vars };
+ return vars;
+ },
+}
+
+
+
+function Config(o){
+ if (typeof o === 'string' && path.extname(o) === '.json' && exists(o)) {
+ o = require(o);
+ }
+ if (o && typeof o === 'object') {
+ Object.keys(o).forEach(function(s){ this[s] = o[s] }, this);
+ }
+}
+
+Config.prototype = {
+ constructor: Config,
+ parse: function parse(s){
+ return s.split('\r\n').reduce(function(r,s){
+ if (s && (s=s.trim())[0] !== '#' && ~s.indexOf('=')) {
+ s = s.split('=');
+ r[s[0].toLowerCase().trim()] = s[1].trim();
+ }
+ return r;
+ }, this);
+ },
+ serialize: function serialize(){
+ return Object.keys(this).map(function(s){
+ return s+' = '+this[s]
+ }, this).join('\r\n')+'\r\n';
+ },
+ save: function save(path){
+ new File(path).write(this.serialize());
+ },
+ load: function load(path){
+ return this.parse(new File(path).read());
+ }
+}
+
+
+function File(name){
+ if (File.prototype.isPrototypeOf(name)) return name;
+ if (!File.prototype.isPrototypeOf(this)) return new File(name);
+ this.path = path.resolve(name);
+}
+
+File.prototype = {
+ constructor: File,
+ encoding: 'utf8',
+ chunkSize: 2 << 15,
+ exists: function exists(){
+ return fs.existsSync(this.path);
+ },
+ read: function read(){
+ return fs.readFileSync(this.path, this.encoding);
+ },
+ write: function write(content){
+ fs.writeFileSync(this.path, content);
+ },
+ delete: function delete_(){
+ fs.unlinkSync(this.path);
+ },
+ open: function open(flag){
+ this.fd && this.close();
+ return this.fd = fs.openSync(this.path, flag);
+ },
+ close: function close(){
+ this.fd && fs.closeSync(this.fd);
+ delete this.fd;
+ },
+ copy: function copy(to, processor){
+ to = new File(to);
+ to.write(processor ? processor(this.read()) : this.read());
+ return to.path;
+ }
+};
+ // copy: function copy(to){
+ // var buffer = new Buffer(this.chunkSize);
+ // var dest = new File(to);
+ // var read = 1, offset = 0;
+
+ // this.open('r');
+ // dest.open('w');
+ // while (read > 0) {
+ // read = fs.readSync(this.fd, buffer, 0, this.chunkSize, offset);
+ // fs.writeSync(dest.fd, buffer, 0, read);
+ // offset += read;
+ // }
+ // this.close();
+ // dest.close();
+ // }
+
+
+
+
+function dir(name, filter){
+ if (!exists(name))
+ throw new Error('Path not found: '+pnameath);
+ var files = fs.readdirSync(name);
+ return filter ? files.filter(function(s){ return path.extname(s) === filter }) : files;
+}
+
+function execSync(params){
+ var f = Math.random().toString(36).slice(2)+'.temp';
+ child_process.exec(params+' 1>'+f+' 2>&1 & ren '+f+' _'+f);
+ f = new File('_'+f);
+ while (!f.exists());
+ var output = f.read();
+ f.delete();
+ return output;
+}
+
+
+
+var builder = new wxBuilder;
+builder.build();
View
1 config-win32.json
@@ -0,0 +1 @@
+{"CC":"cl","CXX":"cl","CFLAGS":"","CXXFLAGS":"","CPPFLAGS":"","LDFLAGS":"","CPP":"$(CC) /EP /nologo","SHARED":0,"WXUNIV":0,"UNICODE":1,"MSLU":0,"BUILD":"release","TARGET_CPU":"X86","DEBUG_INFO":1,"DEBUG_FLAG":1,"DEBUG_RUNTIME_LIBS":0,"MONOLITHIC":1,"USE_GUI":1,"USE_HTML":1,"USE_WEBVIEW":1,"USE_MEDIA":1,"USE_XRC":1,"USE_AUI":1,"USE_RIBBON":1,"USE_PROPGRID":1,"USE_RICHTEXT":1,"USE_STC":1,"USE_OPENGL":1,"USE_QA":1,"USE_EXCEPTIONS":1,"USE_RTTI":1,"USE_THREADS":1,"USE_CAIRO":0,"OFFICIAL_BUILD":0,"VENDOR":"","WX_FLAVOUR":"","WX_LIB_FLAVOUR":"","CFG":"wxnode","CPPUNIT_CFLAGS":"","CPPUNIT_LIBS":"","RUNTIME_LIBS":"static"}
View
67 win32-build.js
@@ -1,67 +0,0 @@
-var path = require('path');
-var fs = require('fs');
-path.existsSync = fs.existsSync || path.existsSync;
-var resolve = path.resolve;
-
-var Builder = require('mnm');
-
-
-function wxBuilder(base){
- base = base || '/wxWidgets'
- this.wxBase = resolve(base);
- this.wxLibDir = resolve(base, 'lib/vc_'+(this.dll ? 'dll' : 'lib'));
- this.wxIncludeDir = resolve(base, 'include');
- this.srcDir = resolve(__dirname, 'src');
- this.name = 'wxnode_bindings';
- this.wxBuildConfig = wxBuilder.readConfig(resolve(this.wxLibDir, 'mswu/build.cfg'));
-}
-
-wxBuilder.readConfig = function readConfig(file){
- return fs.readFileSync(file, 'utf8').split(' \r\n').reduce(function(r,s){
- if (s) {
- s = s.split('=');
- r[s[0].toLowerCase()] = s[1];
- }
- return r;
- }, {});
-}
-
-wxBuilder.msLibs = [ 'kernel32', 'user32', 'gdi32', 'comdlg32', 'comctl32', 'advapi32',
- 'shell32', 'ole32', 'oleaut32', 'rpcrt4', 'winspool', 'winmm' ];
-
-wxBuilder.prototype = {
- verbose: false,
- dll: false,
- build: function build(){
- var b = new Builder;
- b.target = this.name;
- b.verbose = this.verbose;
-
- b.appendUnique('CXXFLAGS', ['-DUNICODE', '-DNDEBUG']);
-
- if (this.dll)
- b.appendUnique('CXXFLAGS', '-DWXUSINGDLL');
-
- if (this.wxBuildConfig.cxxflags)
- b.appendUnique('CXXFLAGS', this.wxBuildConfig.cxxflags);
-
- ['IncludeDir', 'SourceDir', 'LinkerSearchDir','Source', 'LinkerLibrary'].forEach(function(s){
- b[s] = function(){ [].forEach.call(arguments, Builder.prototype['append'+s].bind(b)) };
- });
-
- b.LinkerSearchDir(this.wxLibDir);
- b.LinkerLibrary.apply(null, fs.readdirSync(this.wxLibDir).filter(function(s){ return path.extname(s) === '.lib' }));
- b.LinkerLibrary.apply(null, wxBuilder.msLibs);
-
- b.IncludeDir(this.srcDir, this.srcDir+'-dummy', this.srcDir+'-generated', this.wxIncludeDir);
- b.SourceDir(this.srcDir, this.srcDir+'-generated');
-
- b.compileAndLink(function(e){
- console.log(e || 'complete');
- });
- }
-}
-
-
-var builder = new wxBuilder;
-builder.build();

0 comments on commit a6a35b3

Please sign in to comment.