projectgen.js   [plain text]


/* check for duplicate entries */
function check_duplicates(local, core)
{
	if (!local) {
		return core;
	}

	arr = local.split(" ");

	for(i = 0; i < arr.length; i++) {
		if (core.match(arr[i])) {
			continue;
		}
		core += " " + arr[i];
	}

	return core;
}

/* read .dsp source blocks */
function read_src_files(ext, tmpl, path)
{
	sources = file_get_contents("tmp\\src\\" + ext + ".sources.tmp");
	sources = (path ? sources.replace(/\.\//g, path) : sources);
	tmpl = tmpl.replace("SOURCEFILES", sources);
	FSO.DeleteFile("tmp\\src\\" + ext + ".sources.tmp");

	headers = file_get_contents("tmp\\src\\" + ext + ".headers.tmp");
	headers = (path ? headers.replace(/\.\//g, path) : headers);
	tmpl = tmpl.replace("HEADERFILES", headers);
	FSO.DeleteFile("tmp\\src\\" + ext + ".headers.tmp");

	return tmpl;
}

/* write a .dsp source block */
function write_src_file(fname, path, intpath, arr)
{
	FSO.FolderExists("tmp\\src") ? "" : FSO.CreateFolder("tmp\\src");
	var src = FSO.CreateTextFile("tmp\\src\\" + fname, true);
	var out = get_define("BUILD_DIR");
	var libpath = "";

	for (i = 0; i < arr.length; i++) {
		if (arr[i].length > 1) {
			if (arr[i].match('alloca.c') ||
				arr[i].match(/internal_functions_(nw|win32)\.c/) ||
				arr[i].match(/flock\.(c|h)/) ||
				arr[i].match(/zend_static_allocator\.(c|h)/) ||
				arr[i].match(/zend_(ini|language)_scanner_defs\.h/)) {
				continue;
			}

			libpath = arr[i].substr(2, arr[i].lastIndexOf("\\") - 2);
			if (libpath) {
				libpath = "\\" + libpath;
			}

			src.WriteLine("# Begin Source File");
			src.WriteLine("SOURCE=" + arr[i]);
			src.WriteLine('# PROP Intermediate_Dir "' + intpath + out + '\\' + path + libpath + '"');
			src.WriteLine("# End Source File");
			src.WriteBlankLines(1);
		}
	}

	src.Close();
	return;
}

/* generate list of text files */
function generate_text_filelist(ext, ext_dir)
{
	var txtdir = FSO.GetFolder(ext_dir);

	block = '# Begin Group "Text Files"\r\n\# PROP Default_Filter ""\r\n\r\n';
	txt = new Enumerator(txtdir.Files);

	for (; !txt.atEnd(); txt.moveNext()) {
		fname = FSO.GetFileName(txt.item());
		munged = fname.replace(ext, ""); /* TSRM...! */

		if (munged.match(/[A-Z]{4}/)){
			block += "# Begin Source File\r\n";
			block += "SOURCE=./" + fname + "\r\n";
			block += "# End Source File\r\n\r\n";
		}
	}

	block += "# End Group\r\n";
	return block;
}

/* generate list of resource files */
function generate_resource_filelist(ext, ext_dir)
{
	var resdir = FSO.GetFolder(ext_dir);
	res = new Enumerator(resdir.Files);
	block = "";

	for (; !res.atEnd(); res.moveNext()) {
		fname = FSO.GetFileName(res.item());

		if (fname.match(/\.(ico|rc)/)) {
			block += "# Begin Source File\r\n";
			block += "SOURCE=./" + fname + "\r\n";
			block += "# End Source File\r\n\r\n";
		}
	}

	return block;
}

/* generate parser and scanner files for Zend */
function generate_parsers_or_scanners(arr, type)
{
	var filter = (type.match("Parsers") ? "y" : "l");

	ret = '# Begin Group "' + type + '"\r\n# PROP Default_Filter "' + filter + '"\r\n\r\n';

	for (i = 0; i < arr.length; i++) {

		fl = "zend_" + arr[i] + "_" + type.toLowerCase().substr(0, type.length - 1);
		ret += "# Begin Source File\r\n";
		ret += "SOURCE=.\\" + fl + "." + filter + "\r\n\r\n";
		ret += '# Begin Custom Build\r\n\r\n';

		if (type.match("Parsers")) {
			pre = (arr[i].match(/ini/) ? "ini_ " : "zend ");
			ret += fl + ".c " + fl + ".h: " + fl + ".y\r\n";
			ret += "\tbison --output=" + fl + ".c -v -d -p " + pre + fl + ".y\r\n\r\n";
		} else {
			ret += fl + ".c: " + fl + ".l\r\n";
			ret += "\tre2c --case-inverted -cbdFt " + fl + "_defs.h -o" + fl + ".c " + fl + ".l\r\n\r\n";
		}

		ret += "# End Custom Build\r\n";
		ret += "# End Source File\r\n";
	}

	ret += "# End Group\r\n\r\n";
	return ret;
}

/* generate .defs file for php5[ts].dll */
function generate_php_defs()
{
	var defs = get_define("PHP_DLL_DEF_SOURCES").split(" ");
	var bdir = get_define("BUILD_DIR") + "\\";
	var file = get_define("PHPLIB").replace("lib", "def");
	var path = "..\\" + bdir + file;
	var deps = "USERDEP__PHP5TS=";
	var cmds = "BuildCmds= \\\r\n";
	var cmd = '$(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r\n\t$(BuildCmds)\r\n';

	for (i = 0; i < defs.length; i++) {
		deps += '"..\\' + defs[i] + '" ';
		cmds += "\ttype ..\\" + defs[i] + (i == 0 ? " > " : " >> ") + path + " \\\r\n";
	}

	ret = '# Begin Group "Defs Files"\r\n\r\n';
	ret += "# Begin Source File\r\nSOURCE=" + path + "\r\n\r\n";
	ret += deps.substr(0, deps.length-1) + "\r\n# Begin Custom Build - ";
	ret += "Generating $(InputPath)\r\nInputPath=" + path + "\r\n\r\n";
	ret += cmds + '\r\n\"' + path + '" : ' + cmd + "\r\n";
	ret += "# End Custom Build\r\n# End Source File\r\n\r\n";
	ret += "# End Group\r\n";
	return ret;
}

/* generate win32\wsyslog.h for php5[ts].dll */
function generate_wsyslog()
{
	var path = ".\\build\\wsyslog.mc\r\n\r\n";
	var intdir = "..\\" + get_define("BUILD_DIR");

	ret = "# Begin Source File\r\nSOURCE=" + path;
	ret += "# Begin Custom Build\r\nInputDir=.\\build\r\n";
	ret += "IntDir=" + intdir + "\r\nInputPath=" + path;
	ret += '"wsyslog.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r\n';
	ret += "\tmc -h $(InputDir)/.. -r $(InputDir) -x $(IntDir) $(InputPath)\r\n\r\n";
	ret += "# End Custom Build\r\n# End Source File\r\n";
	return ret;
}

/* generate ext\date\lib\timelib_config.h for php5[ts].dll */
function generate_timelib_conf(headers)
{
	var file = "timelib_config.h";
	var path = "..\\ext\\date\\lib\\timelib_config.h";
	var pos = headers.search(file);
	var entry = headers.slice(pos, pos + 64);

	replace = entry.replace(file, file + ".win32");
	replace += "\r\n\r\n# Begin Custom Build\r\nInputDir=..\\ext\\date\\lib\r\n";
	replace += "InputPath=" + path + ".win32\r\n\r\n";
	replace += '"' + path + '" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r\n';
	replace += "\tcopy $(InputPath) $(InputDir)\\" + file + "\r\n\r\n";
	replace += "# End Custom Build";

	headers = headers.replace(entry, replace);
	return headers;
}

/* generate php5[ts].dsp */
function generate_core_dsp(core_headers, core_sources, headers, sources, cflags, ldflags, libs)
{
	var ts = (PHP_ZTS != "no" ? "ts" : "");
	var extname = "php5" + ts;
	var tmpl = generate_dsp_file(extname, ".", false, false);

	cflags += get_define("CFLAGS_PHP").replace("/D _USRDLL", "");
	cflags = cflags.replace(/\/(I|D)(\S)/g, "/$1 $2");
	ldflags += get_define("LDFLAGS_PHP");
	libs += get_define("LIBS_PHP");

	tmpl = tmpl.replace(/LOCALCPP/, cflags.replace(/\"ext/g, '"../ext') + " /c");
	tmpl = tmpl.replace(/LOCALLIBS/, libs);
	tmpl = tmpl.replace(/LOCALLDFLAGS/, ldflags);
	tmpl = tmpl.replace(extname + ".dll", get_define("PHPDLL"));

	wsyslog = (core_headers.match("wsyslog.h") ? "" : generate_wsyslog(core_headers));
	core_sources = '# Begin Group "CORE"\r\n' + core_sources + "# End Group\r\n";
	tmpl = tmpl.replace(/CORESOURCES/, core_sources);
	core_headers = '# Begin Group "CORE "\r\n' + core_headers + "# End Group\r\n";
	tmpl = tmpl.replace(/COREHEADERS/, core_headers + wsyslog);

	headers = generate_timelib_conf(headers);
	tmpl = tmpl.replace(/SOURCEFILES/, sources);
	tmpl = tmpl.replace(/HEADERFILES/, headers);

	defs = generate_php_defs();
	tmpl = tmpl.replace(/DEFS/, defs);

	dsp = FSO.CreateTextFile("win32\\php5" + ts + ".dsp", true);
	STDOUT.WriteLine("\tGenerating win32\\php5" + ts + ".dsp");
	dsp.Write(tmpl);
	dsp.Close();

	return;
}

/* generate .dsw files */
function generate_dsw_files(sblocks, mblocks)
{
	var stmpl = file_get_contents("win32\\build\\template.dsw");
	var mtmpl = file_get_contents("win32\\build\\template.dsw");
	var ts = (PHP_ZTS != "no" ? "ts" : "");

	/* push all the sapi blocks to the same tag */
	stmpl = stmpl.replace("INSERT", sblocks);
	stmpl = (PHP_ZTS != "no" ? stmpl : stmpl.replace(/dllts/g, "dll"));
	sdsw = FSO.CreateTextFile("win32\\php5" + ts + ".dsw", true);
	STDOUT.WriteLine("\tGenerating win32\\php5" + ts + ".dsw");
	sdsw.Write(stmpl);
	sdsw.Close();

	/* same for shared modules - except that nothing else goes in here */
	garbage = mtmpl.slice(200, mtmpl.search("INSERT"));
	mtmpl = mtmpl.replace(garbage, "\r\n");
	mtmpl = mtmpl.replace("INSERT", mblocks);
	mtmpl = (PHP_ZTS != "no" ? mtmpl : mtmpl.replace(/dllts/g, "dll"));
	mdsw = FSO.CreateTextFile("win32\\php_modules.dsw", true);
	STDOUT.WriteLine("\tGenerating win32\\php_modules.dsw");
	mdsw.Write(mtmpl);
	mdsw.Close();

	return;
}

/* finalize .dsp files and copy to final destination */
function copy_dsp_files()
{
	var tmp = FSO.GetFolder("tmp");
	var CORE_HEADERS = "";
	var CORE_SOURCES = "";
	var EXT_HEADERS = "";
	var EXT_SOURCES = "";
	var EXT_CFLAGS = "";
	var EXT_LDFLAGS = "";
	var EXT_LIBS = "";
	var sblocks = ""; /* for sapis */
	var mblocks = ""; /* for modules */

	f = new Enumerator(tmp.Files);

	for (; !f.atEnd(); f.moveNext()) {
		/* retrieve the path */
		contents = file_get_contents(f.item());
		address = contents.slice(0, contents.indexOf("#"));
		contents = contents.slice(contents.indexOf("#")+1);
		shared = contents.slice(0, contents.indexOf("#"));
		contents = contents.slice(contents.indexOf("#"));

		/* pick up module name and path */
		path = address.slice(0, address.lastIndexOf("\\")+1);
		ext = address.slice(address.lastIndexOf("\\")+1, address.length-4);
		EXT = ext.toUpperCase();

		if (path.match(/(sapi|ext)/)) {
			rel = "..\\..\\";
		} else {
			rel = "..\\";
		}

		/* pick up local flags and libs */
		cflags = get_define("CFLAGS_" + EXT);
		cflags += (ext.match(/(TSRM|Zend)/) ? "/D TSRM_EXPORTS " : "");
		cflags += (ext.match(/Zend/) ? "/D LIBZEND_EXPORTS " : "");
		libs = get_define("LIBS_" + EXT);
		ldflags = get_define("LDFLAGS_" + EXT);
		ldflags = ldflags.replace(/(\.\.\\)/g, rel + "$1");
		contents = contents.replace(/LOCALCPP/, cflags + " /c");
		contents = contents.replace(/LOCALLIBS/, libs);
		contents = contents.replace(/LOCALLDFLAGS/, ldflags);

		if (ext.match("Zend")) {
			arr = new Array("ini", "language");
			parsers = generate_parsers_or_scanners(arr, "Parsers");
			scanners = generate_parsers_or_scanners(arr, "Scanners");
			contents = contents.replace(/DEFS/, parsers + scanners);
		}

		/* none of these are core... */
		contents = contents.replace(/\r\n(CORESOURCES|COREHEADERS|EXTSOURCES|EXTHEADERS|DEFS)\r\n/g, "");

		if (address.match("sapi")) {
			/* most sapis are .dlls, just not cgi, cli, embed */

			if (ext == "cli") {

				/* change of address: php.dsp */
				newext = "cli";
				address = "win32\\php.dsp";
				srcpath = "..\\" + path;
				contents = contents.replace(/cli\.exe/g, "php.exe");

			} else if (ext == "cgi") {

				/* change of address: php-cgi.dsp */
				newext = "cgi";
				address = "win32\\php-cgi.dsp";
				srcpath = "..\\" + path;
				contents = contents.replace(/cgi\.exe/g, "php-cgi.exe");

			} else {

				/* there's always one... most sapis just get a 'php5' prefix */
				newext = (ext.match(/apache2handler/) ? "php5apache2" : "php5" + ext);
				address = address.replace(ext + ".dsp", newext + ".dsp");
				srcpath = ".\\";
				oldext = new RegExp(('[^=\\\\]'+ext), "g");
				contents = contents.replace(oldext, newext);
				contents = contents.replace(ext + ".dll", newext + ".dll");
				contents = contents.replace("CFG=" + ext, "CFG=" + newext);
			}

			contents = read_src_files(ext, contents, (srcpath ? srcpath : false));
			dsp = FSO.CreateTextFile(address, true);
			STDOUT.WriteLine("\tGenerating " + address);
			dsp.Write(contents);
			dsp.Close();

			/* add all configured sapis to the list in php5ts.dsw */
			sblocks += file_get_contents("win32\\build\\block.template.dsw");
			sblocks = sblocks.replace("ADDRESS", address);
			sblocks = sblocks.replace("EXTNAME", newext);

		} else if (address.match("ext") && shared == "true") {

			/* independent modules with their own .dsp */
			contents = read_src_files(ext, contents, false);
			dsp = FSO.CreateTextFile(address, true);
			STDOUT.WriteLine("\tGenerating " + address);
			dsp.Write(contents);
			dsp.Close();

			mblocks += file_get_contents("win32\\build\\block.template.dsw");
			mblocks = mblocks.replace("ADDRESS", address);
			mblocks = mblocks.replace("EXTNAME", ext);

		} else if (ext.match(/(TSRM|Zend)/)) {

			contents = read_src_files(ext, contents, false);
			dsp = FSO.CreateTextFile(address, true);
			STDOUT.WriteLine("\tGenerating " + address);
			dsp.Write(contents);
			dsp.Close();

		} else {

			/* bound for php5[ts].dsp */
			cflags = get_define("CFLAGS_" + EXT);
			cflags = cflags ? cflags.replace(/-(I|D)/g, " /$1") : "";
			cflags = cflags? cflags.replace(/\/(I|D)\s+/g, "/$1") : "";
			cflags = cflags ? cflags.replace(/\/I(?!\")(\S+)/g, '/I"$1"') : "";

			EXT_CFLAGS = check_duplicates(cflags, EXT_CFLAGS);
			EXT_LDFLAGS = check_duplicates(ldflags, EXT_LDFLAGS);
			EXT_LIBS = check_duplicates(libs, EXT_LIBS);

			beginh = '# Begin Group "' + ext + ' "\r\n';
			begins = '# Begin Group "' + ext + '"\r\n';

			hdr = file_get_contents("tmp\\src\\" + ext + ".headers.tmp");
			hdr = hdr.replace(/\.\//g, "..\\" + path);
			hdr = hdr.replace(/\.\.\\\.\.\\/g, "..\\");

			src = file_get_contents("tmp\\src\\" + ext + ".sources.tmp");
			src = src.replace(/\.\//g, "..\\" + path);
			src = src.replace(/\.\.\\\.\.\\/g, "..\\");

			if (ext.match(/(main|standard|streams|win32)/)) {
				CORE_HEADERS += beginh + hdr + "# End Group\r\n";
				CORE_SOURCES += begins + src + "# End Group\r\n";
			} else {
				EXT_HEADERS += beginh + hdr + "# End Group\r\n";
				EXT_SOURCES += begins + src + "# End Group\r\n";
			}

			FSO.DeleteFile("tmp\\src\\" + ext + ".headers.tmp");
			FSO.DeleteFile("tmp\\src\\" + ext + ".sources.tmp");
		}

		FSO.DeleteFile(f.item());
	}

	generate_core_dsp(CORE_HEADERS, CORE_SOURCES, EXT_HEADERS, EXT_SOURCES, EXT_CFLAGS, EXT_LDFLAGS, EXT_LIBS);
	generate_dsw_files(sblocks, mblocks);

	/* goodnight vienna */
	FSO.DeleteFolder("tmp\\src");
	FSO.DeleteFolder("tmp");
}

/* generate source and header entries for .dsp files */
function generate_dsp_filelist(ext, ext_dir, files, intpath)
{
	var EXT = ext.toUpperCase();
	var tabs = new RegExp("[\t\r\n\'\"]", "gm");
	var ws = new RegExp("\\s+", "g");
	var dir = FSO.GetFolder(ext_dir);
	var configfile = FSO.BuildPath(ext_dir, "config.w32");
	var headers = "";
	var path = "";

	if (!files) {
		/* module either lacks a config.w32 or is core
		 * either way, we know nothing about its sources
		 */
		files = "";
		f = new Enumerator(dir.Files);

		for (; !f.atEnd(); f.moveNext()) {
			name = FSO.GetFileName(f.item());

			if (name.substr(name.length-2) == ".c") {
				files += " ./" + name;
			}
		}
	} else {
		files = files.replace(tabs, "");
		files = "./" + files.replace(/ /g, " ./");
	}

	DSP_SOURCES = files.split(" ");

	/* pick up headers (all modules) */
	f = new Enumerator(dir.Files);

	for (; !f.atEnd(); f.moveNext()) {
		name = FSO.GetFileName(f.item());

		if (name.substr(name.length-2) == ".h") {
			headers += " ./" + name;
		}
	}

	DSP_HEADERS = headers.split(" ");

	/* check for bundled library paths and sourcefiles */
	if (FSO.FileExists(configfile)) {
		config = file_get_contents(configfile);

		if (config.match("ADD_SOURCES")) {
			sources = new RegExp("ADD_SOURCES\\([^,]*\\s*,\\s*['\"]([^'\"]+)['\"].*\\)", "gm");
			arr = config.match(sources);
			line = arr[0].replace(tabs, "");
			line = line.replace(/ADD_SOURCES\((.+)\)/, "$1");
			newarr = line.split(',');
			orig_path = newarr[0].replace(/\//g, "\\");
			orig_path = orig_path.replace(/configure_module_dirname(\s?\+\s?)?/, ext_dir);
			path = orig_path.replace(ext_dir + '\\', "");

			if (path.length > 0 && path != ext_dir) {
				subdir = FSO.GetFolder(orig_path);
				lib = new Enumerator(subdir.Files);
				libheaders = "";

				for (; !lib.atEnd(); lib.moveNext()) {
					name = FSO.GetFileName(lib.item());

					if (name.substr(name.length-2) == ".h") {
						libheaders += " ./" + path + "\\" + name;
					}
				}

				DSP_HEADERS = DSP_HEADERS.concat(libheaders.split(" "));

			} else {
				path = "";
			}

			sources = newarr[1].replace(/\\/g, ""); /* continuation lines */
			sources = sources.replace(ws, " ");
			sources = sources.replace(/\s/g, (path ? " ./" + path + "\\" : " ./"));
			sources = check_duplicates(DSP_SOURCES.join(" "), sources);
			DSP_SOURCES = sources.split(" ");
		}
	}

	/* store the array contents in temp files for now */
	write_src_file(ext + ".headers.tmp", ext_dir, intpath, DSP_HEADERS);
	write_src_file(ext + ".sources.tmp", ext_dir, intpath, DSP_SOURCES);

	return;
}

/* entry point. Called from EXTENSION(), SAPI() and generate_files() (confutils.js) */
function generate_dsp_file(ext, ext_dir, files, shared)
{
	var dsp = FSO.CreateTextFile("tmp\\" + ext + ".dsp", true);
	var tmpl = file_get_contents("win32\\build\\template.dsp");
	var ts = (PHP_ZTS != "no" ? "ts" : "");
	var debug = (PHP_DEBUG != "no" ? " /debug" : "");
	var ld = (debug ? "/LDd" : "/LD");
	var status = (PHP_DEBUG == "no" ? 'Release' : 'Debug');
	var statusts = status + (ts ? "_" + ts.toUpperCase() : "");
	var baseflags = "";

	/* store the final path and value of shared in the tmp file */
	if (!ext.match("php5")) {
		tmpl = ext_dir + "\\" + ext + ".dsp#" + shared + tmpl;
	}

	tmpl = tmpl.replace(/extname/g, ext);
	tmpl = tmpl.replace(/Status_TS/g, statusts);

	if (debug) {
		tmpl = tmpl.replace(/Use_Debug_Libraries 0/g, "Use_Debug_Libraries 1");
		tmpl = tmpl.replace(/NDEBUG/g, "_DEBUG");
	}

	if (ext == "cli" || ext == "cgi") {
		tmpl = tmpl.replace(/Dynamic-Link Library/g, "Console Application");
		tmpl = tmpl.replace(/0x0102/, "0x0103");
		path = "..\\";
		type = ".exe";
	} else if (ext == "embed" || ext == "TSRM" || ext == "Zend") {
		tmpl = tmpl.replace(/Dynamic-Link/g, "Static");
		tmpl = tmpl.replace(/0x0102/, "0x0104");
		tmpl = tmpl.replace(/LINK32/g, "LIB32");
		tmpl = tmpl.replace("link.exe", "link.exe -lib");
		tmpl = tmpl.replace(/BASELIBS/g, "/nologo");
		tmpl = tmpl.replace(/\s(LOCALLIBS|BASELDFLAGS|LOCALLDFLAGS|OUTPATH)/g, "");
		path = "..\\";
		if (ext == "embed") {
			path += "..\\";
		}
		type = ".lib";
	} else if (ext.match("php5")) {
		path = "..\\";
		type = ".dll";
	} else {
		path = "..\\..\\";
		type = ".dll";
	}

	outpath = path + get_define("BUILD_DIR");
	tmpl = tmpl.replace(/OUTPUTDIR/g, outpath);

	/* populate the baseline CFLAGS and libs */
	cflags = get_define("CFLAGS").replace(/\s+/g, " ");
	cflags = cflags.replace('/I "..\\bindlib_w32" ', "");
	bcflags = (cflags.replace(/\/([A-Z])\s/g, "/$1")).split(" ");

	for (i= 0; i < bcflags.length; i++) {
		baseflags += (bcflags[i].match(/(PHP|ZEND|ZTS|BASE|FD|WINDOWS)/) ? "" : bcflags[i]);
	}

	baseflags = baseflags.replace(/\//g, " /");
	baseflags = baseflags.substr(1).replace(/(\/D)/g, "$1 ") + " /c";
	tmpl = tmpl.replace(/BASECPP/, (type == ".dll" ? baseflags : baseflags.replace(ld + " ", "")));

	tmpl = tmpl.replace(/BASELIBS/, "/nologo " + get_define("LIBS").replace(/\sresolv.lib/, ""));

	/* now populate the bases in the 'local' lines */
	incs = get_define("BASE_INCLUDES").replace(/\/I (\S+)/g, '/I "' + path + '$1"');
	incs = incs.replace('"' + path + '."', '".."');
	lcflags = cflags.replace(/\$\(BASE_INCLUDES\)/, incs + (type == ".exe" ? '/I "..\\sapi" ' : "") + '/I "' + path + '..\\bindlib_w32"');
	tmpl = tmpl.replace(/BASECPP/, (type == ".dll" ? lcflags : lcflags.replace(ld + " ", "")));
	tmpl = tmpl.replace(/BASELIBS/, "/nologo " + get_define("LIBS") + " " + (ext.match("php5") ? "" : get_define("PHPLIB")));
	ldflags = get_define("LDFLAGS").replace(/\s?(\/nologo|\/libpath:\S+)\s?/g, "");
	tmpl = tmpl.replace(/BASELDFLAGS/, ldflags + (type == ".dll" ? " " + get_define("DLL_LDFLAGS") : "") + (debug ? ' /nodefaultlib:"msvcrt"' : ""));
	out = '/out:"' + outpath + "\\" + ext + type + '"' + ' /libpath:"' + outpath + '"' + ' /libpath:"..\\' + path + 'bindlib_w32\\' + status + '"';
	tmpl = tmpl.replace(/OUTPATH/, out);

	txt = generate_text_filelist(ext, ext_dir);
	res = generate_resource_filelist(ext, ext_dir);

	tmpl = tmpl.replace(/TEXTFILES/, txt);
	tmpl = tmpl.replace(/RESOURCEFILES/, res);

	if (ext.match("php5")) {
		return tmpl;
	}

	/* generate source and header blocks for .dsp */
	generate_dsp_filelist(ext, ext_dir, files, path);

	dsp.Write(tmpl);
	dsp.Close();

	return;
}