1076 lines
32 KiB
XML
1076 lines
32 KiB
XML
<?xml version="1.0" ?><!-- -*- SGML -*- -->
|
|
<package>
|
|
<comment>
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
</comment>
|
|
<job id="configure" prompt="no">
|
|
<?job error="false" debug="false" ?>
|
|
<runtime>
|
|
<description>
|
|
Run configuration tests and produces config.h file.
|
|
</description>
|
|
<named helpstring="Name of the solution" name="SolutionName"
|
|
required="true" type="string"/>
|
|
<named helpstring="Name of the configuration"
|
|
name="ConfigurationName" required="true" type="string"/>
|
|
<named helpstring="Output directory" name="OutDir"
|
|
required="false" type="string"/>
|
|
<named helpstring="Output file" name="OutFile"
|
|
required="false" type="string"/>
|
|
<named helpstring="Test sources directory" name="SrcDir"
|
|
required="false" type="string"/>
|
|
<named helpstring="Log file name" name="LogFile"
|
|
required="false" type="string"/>
|
|
<example>cscript configure.wsf /SolutionName:msvc-7.1
|
|
/ConfigurationName:"Release Static"
|
|
</example>
|
|
<usage>
|
|
Usage: cscript configure.wsf /SolutionName:@Solution
|
|
/ConfigurationName:@Configuration [/OutDir:@OutDir] [/OutFile:@OutFile]
|
|
[/SrcDir:@SrcDir] [/LogFile:@LogFile],
|
|
where
|
|
@Solution is the compiler configuration (msvc-7.1, icc-9.0 etc.)
|
|
@Configuration = 11s Debug Static | 11d Debug Dll , etc
|
|
@OutDir - output directory (default: script_directory\tests),
|
|
@OutFile - output file name (default: config.h),
|
|
@SrcDir - test sources directory (default: script_directory\..\src),
|
|
@LogFile - log file name (default: config.log).
|
|
</usage>
|
|
</runtime>
|
|
<object id="fso" progid="Scripting.FileSystemObject"/>
|
|
<object id="WshShell" progid="WScript.Shell"/>
|
|
<script language="JScript" src="config.js"/>
|
|
<script language="JScript" src="data.js"/>
|
|
<script language="JScript" src="utilities.js"/>
|
|
<script id="configure" language="JScript">
|
|
<![CDATA[
|
|
//
|
|
// Configuration script for Stdcxx library
|
|
//
|
|
|
|
// constants
|
|
var scriptDir = getParentFolder(WScript.ScriptFullName);
|
|
var slnDir = getParentFolder(getParentFolder(getParentFolder(scriptDir)));
|
|
var stageDir = scriptDir + "\\tests";
|
|
var configTargerDir = slnDir + "\\include";
|
|
var configFileName = "config.h";
|
|
var configFile = configTargerDir + "\\" + configFileName;
|
|
var stageFile = stageDir + "\\" + configFileName;
|
|
var srcDir = slnDir + "\\etc\\config\\src";
|
|
var runWindowMode = 0;
|
|
var timeOut = 30000; // 30 sec
|
|
var logFileName = "config.log";
|
|
var confInfo = null;
|
|
|
|
var description = new configure; // run
|
|
|
|
// clean tests folder
|
|
// print msg to the StdErr, if specified
|
|
// quit with exitcode
|
|
function cleanQuit(exitcode, msg)
|
|
{
|
|
// clean Tests folder
|
|
if (fso.FolderExists(stageDir))
|
|
{
|
|
try
|
|
{
|
|
fso.DeleteFolder(stageDir, true);
|
|
}
|
|
catch (e) { }
|
|
}
|
|
|
|
if (typeof(msg) != "undefined")
|
|
WScript.StdErr.WriteLine(msg);
|
|
|
|
WScript.Quit(exitcode);
|
|
}
|
|
|
|
// the main function of the script
|
|
function configure()
|
|
{
|
|
if (!WScript.Arguments.Named.Exists("SolutionName")
|
|
|| !WScript.Arguments.Named.Exists("ConfigurationName"))
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Missing required argument.");
|
|
WScript.Arguments.ShowUsage();
|
|
WScript.Quit(2);
|
|
}
|
|
|
|
if (WScript.Arguments.Named.Exists("LogFile"))
|
|
logFileName = WScript.Arguments.Named("LogFile");
|
|
|
|
// check that log file is writable
|
|
if (!touchFile(logFileName))
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Unable to create log file "
|
|
+ logFileName);
|
|
WScript.Quit(2);
|
|
}
|
|
|
|
if (WScript.Arguments.Named.Exists("SrcDir"))
|
|
{
|
|
srcDir = WScript.Arguments.Named("SrcDir");
|
|
if (!fso.FolderExists(srcDir))
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Unable to read sources folder "
|
|
+ srcDir);
|
|
WScript.Quit(2);
|
|
}
|
|
}
|
|
|
|
if (WScript.Arguments.Named.Exists("OutFile"))
|
|
configFile = WScript.Arguments.Named("OutFile");
|
|
|
|
// check that config file is writable
|
|
if (!touchFile(configFile))
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Unable to create output file "
|
|
+ configFile);
|
|
WScript.Quit(2);
|
|
}
|
|
|
|
if (WScript.Arguments.Named.Exists("OutDir"))
|
|
{
|
|
stageDir = WScript.Arguments.Named("OutDir") + "\\tests";
|
|
stageFile = stageDir + "\\" + configFileName;
|
|
}
|
|
|
|
// clean Tests folder
|
|
if (fso.FolderExists(stageDir))
|
|
{
|
|
try
|
|
{
|
|
fso.DeleteFolder(stageDir, true);
|
|
}
|
|
catch (e)
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Unable to delete folder "
|
|
+ stageDir);
|
|
WScript.Quit(3);
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
fso.CreateFolder(stageDir);
|
|
}
|
|
catch (e)
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Unable to create stage folder "
|
|
+ stageDir);
|
|
WScript.Quit(2);
|
|
}
|
|
|
|
removeFile(logFileName);
|
|
removeFile(stageFile);
|
|
removeFile(configFile + ".bak");
|
|
|
|
// save previous file
|
|
if (fso.FileExists(configFile))
|
|
fso.MoveFile(configFile, configFile + ".bak");
|
|
|
|
var msg = "for " + WScript.Arguments.Named("SolutionName")
|
|
+ " - " + WScript.Arguments.Named("ConfigurationName");
|
|
WScript.Echo("Configuring " + msg);
|
|
|
|
appendLineToOutFile("// Configured " + msg);
|
|
|
|
var logFileNameURI = "file://" + logFileName.replace(/\\/mg, "/");
|
|
|
|
// remove VS_UNICODE_OUTPUT environment variable
|
|
// http://blogs.msdn.com/freik/archive/2006/04/05/569025.aspx
|
|
{
|
|
var env = WshShell.Environment("PROCESS");
|
|
var name = "VS_UNICODE_OUTPUT";
|
|
var str = env.Item(name);
|
|
if ("undefined" != typeof(str) && "" != str)
|
|
env.Remove(name);
|
|
}
|
|
|
|
getCompilerOpts(WScript.Arguments.Named("SolutionName"));
|
|
|
|
confInfo = configs.get(WScript.Arguments.Named("ConfigurationName"));
|
|
|
|
CPPFLAGS += " /GR"; // enable RTTI for tests
|
|
|
|
CPPFLAGS += " /M";
|
|
|
|
LDFLAGS += " /NODEFAULTLIB:\"";
|
|
|
|
if (confInfo.dll)
|
|
{
|
|
CPPFLAGS += "D";
|
|
LDFLAGS += confInfo.debug ? "msvcprtd" : "msvcprt";
|
|
}
|
|
else
|
|
{
|
|
if (confInfo.mt || NOSTCRT)
|
|
{
|
|
CPPFLAGS += "T";
|
|
LDFLAGS += confInfo.debug ? "libcpmtd" : "libcpmt";
|
|
}
|
|
else
|
|
{
|
|
CPPFLAGS += "L";
|
|
LDFLAGS += confInfo.debug ? "libcpd" : "libcp";
|
|
}
|
|
}
|
|
|
|
LDFLAGS += ".lib\"";
|
|
|
|
if (confInfo.debug)
|
|
{
|
|
CPPFLAGS += "d /Zi /Gm";
|
|
LDFLAGS += " /DEBUG";
|
|
}
|
|
|
|
CPPFLAGS += " /I\"" + stageDir + "\"";
|
|
|
|
var defines = new Array ();
|
|
|
|
if (confInfo.dll)
|
|
defines.push("_RWSHARED");
|
|
|
|
CPPFLAGS += joinArray(defines, "/D");
|
|
|
|
var exitmsg = "You may see log here: " + logFileNameURI;
|
|
|
|
// sanity check
|
|
if (0 == checkSanity())
|
|
cleanQuit(1, exitmsg);
|
|
|
|
// check architecture
|
|
checkArchitecture();
|
|
|
|
// headers and functions check
|
|
checkHeaders();
|
|
|
|
if (confInfo.mt)
|
|
appendLineToOutFile("// #define _RWSTD_NO_REENTRANT");
|
|
else
|
|
appendLineToOutFile("#define _RWSTD_NO_REENTRANT");
|
|
|
|
// compile, link and run .cpp's (if possible)
|
|
if (0 == runExeTests())
|
|
cleanQuit(1, exitmsg);
|
|
|
|
fso.MoveFile(stageFile, configFile);
|
|
cleanQuit(0);
|
|
}
|
|
|
|
// performs compiler and linker sanity checks
|
|
function checkSanity()
|
|
{
|
|
var objName = stageDir + "\\sanity.obj";
|
|
removeFile(objName);
|
|
var srcName = stageDir + "\\sanity.cpp";
|
|
writeTextFile(srcName, "int main () { return 0; }\r\n");
|
|
WScript.StdOut.Write("checking if compiler is sane... ");
|
|
var ret = compileFiles(srcName);
|
|
if (ret == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
}
|
|
else
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Compiler failed sanity check");
|
|
return 0;
|
|
}
|
|
|
|
var exeName = "sanity.exe";
|
|
var exeFullName = stageDir + "\\" + exeName;
|
|
removeFile(exeFullName);
|
|
WScript.StdOut.Write("checking if linker is sane... ");
|
|
ret = linkFiles(objName, exeName);
|
|
if (ret == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
}
|
|
else
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Linker failed sanity check");
|
|
return 0;
|
|
}
|
|
|
|
WScript.StdOut.Write("checking if run environment is sane... ");
|
|
ret = 1;
|
|
try
|
|
{
|
|
ret = WshShell.Run(exeFullName, runWindowMode, true);
|
|
}
|
|
catch (e) {}
|
|
if (ret == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
}
|
|
else
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: \
|
|
Runtime environment failed sanity check");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// removes file if it exists
|
|
function removeFile(fileName)
|
|
{
|
|
if (fso.FileExists(fileName))
|
|
{
|
|
fso.DeleteFile(fileName, true);
|
|
}
|
|
}
|
|
|
|
// writes text into a file
|
|
function writeTextFile(fileName, fileContent)
|
|
{
|
|
var stream = fso.CreateTextFile(fileName, true, false);
|
|
stream.Write(fileContent);
|
|
stream.Close();
|
|
}
|
|
|
|
// perform architecture check
|
|
function checkArchitecture()
|
|
{
|
|
//TODO: This test seems to be useless
|
|
WScript.StdOut.Write("checking system architecture");
|
|
var types = new Array("int", "long", "long long", "void*");
|
|
var srcFile = stageDir + "\\arch.cpp";
|
|
var objFile = stageDir + "\\arch.obj";
|
|
var exeFile = "arch.exe";
|
|
var exeFullName = stageDir + "\\" + exeFile;
|
|
var sizes = "";
|
|
for (i in types)
|
|
{
|
|
var ret2;
|
|
removeFile(exeFullName);
|
|
removeFile(objFile);
|
|
removeFile(srcFile);
|
|
writeTextFile(srcFile
|
|
, "int main () { return sizeof (" + types[i] + "); }\r\n");
|
|
var ret = compileFiles(srcFile);
|
|
if (ret == 0)
|
|
{
|
|
ret = linkFiles(objFile, exeFile);
|
|
if (ret == 0)
|
|
{
|
|
ret2 = WshShell.Run(exeFullName, runWindowMode, true);
|
|
}
|
|
}
|
|
if (ret == 0)
|
|
{
|
|
sizes += new String(ret2);
|
|
}
|
|
else
|
|
{
|
|
sizes += "-";
|
|
}
|
|
}
|
|
var rxLP32 = /24?4/;
|
|
var rxILP32 = /44?4/;
|
|
var rxILP64 = /88?8/;
|
|
var rxLLP64 = /4488/;
|
|
var rxLP64 = /48?8/;
|
|
var arch;
|
|
if (rxLP32.test(sizes))
|
|
{
|
|
arch = "LP32";
|
|
}
|
|
else if (rxILP32.test(sizes))
|
|
{
|
|
arch = "ILP32";
|
|
}
|
|
else if (rxILP64.test(sizes))
|
|
{
|
|
arch = "ILP64";
|
|
}
|
|
else if (rxLLP64.test(sizes))
|
|
{
|
|
arch = "LLP64";
|
|
}
|
|
else if (rxLP64.test(sizes))
|
|
{
|
|
arch = "LP64";
|
|
}
|
|
else
|
|
{
|
|
arch = sizes;
|
|
}
|
|
// there is no known big endian architectures on Windows
|
|
WScript.StdOut.WriteLine("\t" + arch + " little endian");
|
|
}
|
|
|
|
// perform headers presence check
|
|
function checkHeaders()
|
|
{
|
|
inc = fso.OpenTextFile(srcDir + "\\headers.inc", 1, false);
|
|
code = "";
|
|
var rx = /^([A-Za-z]\w*)=(.*)"([^\$]*)\$([A-Za-z]\w*)(.*)"$/;
|
|
|
|
while (!inc.AtEndOfStream)
|
|
{
|
|
var line = inc.ReadLine();
|
|
if (0 == line.length || '#' == line.charAt(0))
|
|
continue;
|
|
|
|
while (true)
|
|
{
|
|
var arr = rx.exec(line);
|
|
if (null == arr)
|
|
break;
|
|
|
|
line = arr[1] + "=";
|
|
if (arr[2].length)
|
|
{
|
|
line += arr[2];
|
|
if ('+' != arr[2].charAt(arr[2].length - 1))
|
|
line += "+";
|
|
}
|
|
if (arr[3].length)
|
|
line += "\"" + arr[3] + "\"+";
|
|
line += arr[4];
|
|
if (arr[5].length)
|
|
line += "+\"" + arr[5] + "\"";
|
|
}
|
|
|
|
code += line;
|
|
|
|
if ('\\' != line.charAt(line.length - 1))
|
|
code += ";";
|
|
|
|
code += "\n";
|
|
}
|
|
|
|
eval(code);
|
|
|
|
hdrs = hdrs.replace(/ +/g, " ");
|
|
var headers = hdrs.split(" ");
|
|
|
|
WScript.StdOut.WriteLine("checking for headers... ");
|
|
|
|
var noNewHeaders = false;
|
|
for (i in headers)
|
|
{
|
|
var h = headers[i];
|
|
var hdr_base = basename(h, "\\.h");
|
|
var hdr = h;
|
|
|
|
if (hdr_base == h) // if header does not have .h
|
|
{
|
|
// check for C++ C library headers first
|
|
if (h != "new" && h != "typeinfo")
|
|
{
|
|
hdr = "c" + h;
|
|
}
|
|
WScript.StdOut.Write("checking for <" + hdr + ">... ");
|
|
var defstring = "_RWSTD_NO_" + hdr.toUpperCase();
|
|
if (checkHeader(hdr) == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
appendLineToOutFile("// #define " + defstring);
|
|
}
|
|
else
|
|
{
|
|
WScript.StdOut.WriteLine("\tno (" + defstring +")");
|
|
appendLineToOutFile("#define " + defstring);
|
|
// <ciso646> is a bogus header, ignore if missing
|
|
if (hdr != "ciso646")
|
|
{
|
|
noNewHeaders = true;
|
|
}
|
|
}
|
|
}
|
|
// check for (deprecated C++) C library headers
|
|
// or for any headers specified with the .h suffix
|
|
hdr = hdr_base + ".h";
|
|
WScript.StdOut.Write("checking for <" + hdr + ">... ");
|
|
var sym = hdr_base.toUpperCase();
|
|
var defstring = "_RWSTD_NO_" + sym + "_H";
|
|
if (checkHeader(hdr) == 0)
|
|
{
|
|
var text = readTextFile(stageDir + "\\hdrcheck.i");
|
|
var rxInternalHdrName =
|
|
new RegExp("^[^\"]* (\".*[/\\\\]" + hdr_base + "\\.h\")", "im");
|
|
var matches = rxInternalHdrName.exec(text);
|
|
|
|
// handle headers implemented internally by some compilers
|
|
// (such as <stdarg.h> with the vanilla EDG eccp)
|
|
var path = hdr;
|
|
if (matches != null)
|
|
{
|
|
path = matches[1];
|
|
}
|
|
WScript.StdOut.WriteLine(" ok (" + path + ")");
|
|
if (hdr_base == h)
|
|
{
|
|
appendLineToOutFile("#define _RWSTD_ANSI_C_" +
|
|
sym + "_H " + path);
|
|
}
|
|
//TODO: it looks like original script has a problem with
|
|
// dependencies here however it looks like it simply drops
|
|
// unresolved dependencies
|
|
// else
|
|
// {
|
|
appendLineToOutFile("// #define " + defstring +
|
|
" /* " + path + " */");
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
WScript.StdOut.WriteLine("\tno (" + defstring +")");
|
|
appendLineToOutFile("#define " + defstring);
|
|
}
|
|
}
|
|
|
|
// determine the support for namespaces
|
|
WScript.StdOut.Write("checking for namespaces");
|
|
var noNamespaces = false;
|
|
var ret = compileFiles(srcDir + "\\NAMESPACE.CPP");
|
|
if (ret == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
appendLineToOutFile("// #define _RWSTD_NO_NAMESPACE");
|
|
}
|
|
else
|
|
{
|
|
WScript.StdOut.WriteLine("\tno (_RWSTD_NO_NAMESPACE)");
|
|
appendLineToOutFile("#define _RWSTD_NO_NAMESPACE");
|
|
noNamespaces = true;
|
|
}
|
|
|
|
// determine wheteher each function is declared/defined
|
|
// create a test source file template into which each iteration below
|
|
// substitutes the header name, function name, and function arguments
|
|
var srcFile = scriptDir + "\\fun_present_check.cpp";
|
|
var objFile = stageDir + "\\fun_present_check.obj";
|
|
var exeFile = "fun_present_check.exe";
|
|
var exeFullName = stageDir + "\\" + exeFile;
|
|
|
|
var funs;
|
|
var lib;
|
|
for (i in headers)
|
|
{
|
|
var fun_params = "";
|
|
var hdr_base = headers[i];
|
|
|
|
try
|
|
{
|
|
eval("funs=" + hdr_base);
|
|
}
|
|
catch (e)
|
|
{
|
|
funs = "";
|
|
}
|
|
|
|
if (0 == funs.length)
|
|
continue;
|
|
|
|
funs = funs.replace(/ +/g, " ").split(" ");
|
|
|
|
lib = ("math" == hdr_base) ? "m" : "c";
|
|
|
|
var useCHeader = false;
|
|
for (j in funs)
|
|
{
|
|
var fun = funs[j];
|
|
// determine whether the tested function is followed by
|
|
// a function argument list; if so, call it, otherwise
|
|
// take its address
|
|
var take_addr = 1;
|
|
var funname = fun;
|
|
var paramsIndx = fun.indexOf("(");
|
|
if (paramsIndx != -1)
|
|
{
|
|
take_addr = 0;
|
|
funname = fun.substr(0, paramsIndx);
|
|
}
|
|
|
|
// starting with acosf(), look in <math.h> rather than <cmath>
|
|
if (fun == "acosf")
|
|
{
|
|
useCHeader = true;
|
|
}
|
|
|
|
var std = "";
|
|
|
|
// determine which form of the header to #include
|
|
var hdrname = hdr_base + ".h";
|
|
if (!useCHeader && !noNewHeaders)
|
|
{
|
|
hdrname = "c" + hdr_base;
|
|
if (!noNamespaces)
|
|
{
|
|
std = "std::";
|
|
}
|
|
}
|
|
|
|
hdrname = "<" + hdrname + ">";
|
|
removeFile(exeFullName);
|
|
removeFile(objFile);
|
|
WScript.StdOut.Write("checking for " + std + funname + "() in " +
|
|
hdrname + "... ");
|
|
var sym = "_RWSTD_NO_" + funname.toUpperCase();
|
|
var defines = new Array("CHECK_DECL", "HDRNAME=" + hdrname,
|
|
"FUNNAME=" + funname, "FUN=" + fun,
|
|
"TAKE_ADDR=" + take_addr);
|
|
if (noNamespaces)
|
|
{
|
|
defines.push("NONAMESPACE");
|
|
}
|
|
if (paramsIndx != -1 && fun_params != "")
|
|
{
|
|
defines.push("FUN_PARAMS=" + fun_params);
|
|
}
|
|
var ret = compileFiles(srcFile, defines);
|
|
if (ret == 0)
|
|
{
|
|
ret = linkFiles(objFile, exeFile);
|
|
}
|
|
if (ret == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
appendLineToOutFile("// #define " + sym);
|
|
}
|
|
else
|
|
{
|
|
// if a symbol isn't declared in the header,
|
|
// see if it maybe exists in the library
|
|
WScript.StdOut.WriteLine("\tno (" + sym + ")");
|
|
appendLineToOutFile("#define " + sym);
|
|
// that is quite strange because there is no LIBM on Windows?
|
|
sym = sym + "_IN_LIB" + lib.toUpperCase();
|
|
|
|
removeFile(exeFullName);
|
|
removeFile(objFile);
|
|
WScript.StdOut.Write("checking for extern \"C\" "
|
|
+ funname + "() in libc... ");
|
|
ret = compileFiles(srcFile, "FUNNAME=" + funname);
|
|
if (ret == 0)
|
|
{
|
|
ret = linkFiles(objFile, exeFile);
|
|
}
|
|
if (ret == 0)
|
|
{
|
|
WScript.StdOut.WriteLine(" ok");
|
|
appendLineToOutFile("// #define " + sym);
|
|
}
|
|
else
|
|
{
|
|
appendLineToOutFile("#define " + sym);
|
|
WScript.StdOut.WriteLine(" no (" + sym + ")");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//TODO: there are also some <cmath> related stuff in
|
|
//the libc_decl.sh but it is unreachable.
|
|
}
|
|
|
|
// removes extension from fileName if it is present
|
|
function basename(fileName, extension)
|
|
{
|
|
var rx = new RegExp(extension + "$", "i");
|
|
return fileName.replace(rx, "");
|
|
}
|
|
|
|
// check for presense of the header
|
|
function checkHeader(header)
|
|
{
|
|
var srcFile = stageDir + "\\hdrcheck.cpp";
|
|
var preprocFile = stageDir + "\\hdrcheck.i";
|
|
removeFile(preprocFile);
|
|
removeFile(srcFile);
|
|
writeTextFile(srcFile, "#include <" + header + ">\r\n");
|
|
return preprocessFile(srcFile, preprocFile);
|
|
}
|
|
|
|
// appends text line to the stage file (config.h.tmp)
|
|
function appendLineToOutFile(line)
|
|
{
|
|
var stream = fso.OpenTextFile(stageFile, 8, true, 0);
|
|
stream.WriteLine(line);
|
|
stream.Close();
|
|
}
|
|
|
|
// reads text file into a string
|
|
function readTextFile(fileName)
|
|
{
|
|
var stream = fso.OpenTextFile(fileName, 1, false, 0);
|
|
var text = stream.ReadAll();
|
|
stream.Close();
|
|
return text;
|
|
}
|
|
|
|
// gets description from text if present
|
|
function getDescription(text)
|
|
{
|
|
// description shall be the first line in format "// description"
|
|
var idx = text.indexOf("\r");
|
|
if (idx == -1)
|
|
{
|
|
idx = text.indexOf("\n");
|
|
if (idx == -1)
|
|
{
|
|
idx = text.length;
|
|
}
|
|
}
|
|
var firstLine = text.substr(0, idx);
|
|
var results = /\/\/\s*(.*)/.exec(firstLine);
|
|
if (results == null)
|
|
{
|
|
return "";
|
|
}
|
|
return results[1];
|
|
}
|
|
|
|
// compiles, links and runs (if possible) all .cpp
|
|
function runExeTests()
|
|
{
|
|
// first determine all files to be processed
|
|
var folder = fso.GetFolder(srcDir);
|
|
var fc = new Enumerator(folder.Files);
|
|
var srcs = new Array();
|
|
for (; !fc.atEnd(); fc.moveNext())
|
|
{
|
|
var file = fc.item();
|
|
if (!(/\.cpp$/i).test(file.Name))
|
|
continue; // not an cpp file
|
|
srcs.push(file.Name); // save file name for processing
|
|
}
|
|
|
|
// WScript.StdOut.WriteLine("Running tests " + srcs.join(" "));
|
|
|
|
// first dependency of a file on _RWSTD_ variables will be checked
|
|
// if undefined variable will be found file will be postponed
|
|
// for the next iteration
|
|
// iterations will continue until there will be no postponed files
|
|
// or circular dependency will be found (on some step all files
|
|
// will be postponed)
|
|
var configText = readTextFile(stageFile); // cache config contents
|
|
do
|
|
{
|
|
var postponed = new Array();
|
|
for (i in srcs)
|
|
{
|
|
var test = srcs[i];
|
|
var srcFile = srcDir + "\\" + test;
|
|
var srcText = readTextFile(srcFile);
|
|
if (!checkDependencies(srcText, configText))
|
|
{
|
|
// undefined dependencies found. test shall be postponed
|
|
postponed.push(test);
|
|
continue;
|
|
}
|
|
var descText = getDescription(srcText);
|
|
if (descText && descText != "")
|
|
WScript.StdOut.Write(descText + "... ");
|
|
|
|
var symbol = "#define _RWSTD_";
|
|
var outSymbol = "_RWSTD_";
|
|
var base = basename(test, "\\.cpp");
|
|
var negate = !(/^NO_/.test(base));
|
|
if (negate)
|
|
{
|
|
symbol += "NO_";
|
|
outSymbol += "NO_";
|
|
}
|
|
symbol += base;
|
|
outSymbol += base;
|
|
|
|
var textResult = ""; // text output of a test
|
|
// compile file
|
|
var result = 0;
|
|
if ((/\.lib\.cpp$/i).test(test))
|
|
{
|
|
// this is a library file
|
|
var outLibName = test.replace(/\.cpp/i, ".lib");
|
|
result = makeLibrary(srcDir + "\\" + test, outLibName, confInfo.dll);
|
|
if (result)
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Failed to build library "
|
|
+ outLibName);
|
|
}
|
|
else
|
|
{
|
|
result = compileFiles(srcFile);
|
|
if (0 == result && /\s*main\s*\(/.test(srcText))
|
|
{
|
|
// main function present. file is runnable
|
|
// get library and object dependencies
|
|
var fileBase = stageDir + "\\" + base;
|
|
var modules = fileBase + ".obj";
|
|
var ldopts =
|
|
(/^[^A-Z_a-z0-9]*LDOPTS\s*=\s*(\S*)\s*$/m).exec(srcText);
|
|
if (ldopts != null)
|
|
{
|
|
// replace $(LIBSUFFIX) with .lib and replace .o with .obj
|
|
modules += " " + stageDir + "\\" +
|
|
ldopts[1].replace(/\$\(LIBSUFFIX\)/, ".lib").
|
|
replace(/\.o/, ".obj");
|
|
}
|
|
var exeFile = base + ".exe";
|
|
var fullExeName = fileBase + ".exe";
|
|
result = linkFiles(modules, exeFile);
|
|
if (result == 0) // can execute
|
|
{
|
|
var exec = WshShell.Exec(fullExeName);
|
|
var time = 0;
|
|
while (exec.Status == 0)
|
|
{
|
|
WScript.Sleep(100); // wait for completion
|
|
time += 100;
|
|
if (time > timeOut)
|
|
{
|
|
WScript.StdErr.WriteLine(
|
|
"Configure: Fatal error: Test " + test
|
|
+ " failed to complete in " + timeOut / 1000
|
|
+ " seconds");
|
|
return 0;
|
|
}
|
|
}
|
|
result = exec.ExitCode;
|
|
textResult = exec.StdOut.ReadAll();
|
|
}
|
|
}
|
|
}
|
|
// append symbol result
|
|
// !((result == 0 && !negate) || (result != 0 && negate))
|
|
if (!((result == 0) ^ negate))
|
|
{
|
|
symbol = "// " + symbol;
|
|
outSymbol = "";
|
|
}
|
|
appendLineToOutFile(symbol);
|
|
if (descText && descText != "") {
|
|
if ("" != outSymbol)
|
|
WScript.StdOut.WriteLine(" no (" + outSymbol + ")");
|
|
else
|
|
WScript.StdOut.WriteLine(" ok ");
|
|
}
|
|
|
|
// append text results if present
|
|
if (textResult.length != 0)
|
|
{
|
|
appendLineToOutFile(textResult);
|
|
}
|
|
// update cache since config file is changed
|
|
configText = readTextFile(stageFile);
|
|
}
|
|
|
|
if (postponed.length == srcs.length) // circular dependency
|
|
{
|
|
WScript.StdErr.Write(
|
|
"Configure: Fatal error: Circular dependencies found");
|
|
WScript.StdErr.WriteLine(" in the following tests:");
|
|
WScript.StdErr.WriteLine(postponed.join(" "));
|
|
for (i in postponed)
|
|
{
|
|
var test = postponed[i];
|
|
WScript.StdErr.Write("File: " + test + "\t");
|
|
var srcFile = srcDir + "\\" + test;
|
|
var srcText = readTextFile(srcFile);
|
|
checkDependencies(srcText, configText, true);
|
|
}
|
|
return 0;
|
|
}
|
|
srcs = postponed;
|
|
}
|
|
while (srcs.length != 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
// located dependencies (symbols _RWSTD_XXX and _RWSTD_NO_XXX) in a text
|
|
// and checks that they are already defined (present in the config file text)
|
|
function checkDependencies(srcText, configText, dumpUnresolved)
|
|
{
|
|
var deps = srcText.match(/^\s*#\s*ifn?def\s+_RWSTD_(?!USE_CONFIG)\S+/gm);
|
|
if (deps == null) // no dependencies
|
|
{
|
|
return true;
|
|
}
|
|
|
|
for (i = 0; i < deps.length; ++i)
|
|
{
|
|
var dep = /_RWSTD_(?:NO_)?(\S+)/.exec(deps[i])[1];
|
|
// remove _IN_LIBC | _IN_LIBM from dependency string
|
|
dep = dep.replace(/_IN_LIB[CM]/, "");
|
|
var rx = new RegExp("_RWSTD_NO_" + dep);
|
|
if (!rx.test(configText))
|
|
{
|
|
if (dumpUnresolved)
|
|
{
|
|
WScript.StdErr.WriteLine("unresolved dependency: " + dep);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// check that file is writable
|
|
function touchFile(fileName)
|
|
{
|
|
try
|
|
{
|
|
if (fso.FileExists(fileName))
|
|
{
|
|
var stream = fso.OpenTextFile(fileName, 8, false, 0);
|
|
stream.Close();
|
|
}
|
|
else
|
|
{
|
|
var stream = fso.CreateTextFile(fileName, false, false);
|
|
stream.Close();
|
|
fso.DeleteFile(fileName);
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// returns string contains quoted all array items prefixed
|
|
// by prefix and delimited with space
|
|
function joinArray(arr, prefix)
|
|
{
|
|
var res = "";
|
|
for (var i = 0; i < arr.length; ++i)
|
|
res += " " + prefix + "\"" + arr[i] + "\"";
|
|
return res;
|
|
}
|
|
|
|
// performs preprocessing the source file
|
|
// src - source file to preprocess
|
|
// preprocFile - preprocessed file
|
|
function preprocessFile(src, preprocFile)
|
|
{
|
|
var command = CXX + " /E \"" + src + "\"";
|
|
|
|
var message = "Preprocessing with command \"" + command + "\"";
|
|
logLine(message);
|
|
return WshShell.Run("cmd /c \"" + command +"\" > "
|
|
+ preprocFile + " 2>> " + logFileName, runWindowMode, true);
|
|
}
|
|
|
|
// performs compilation of the the source files
|
|
// src - string with source file names delimited by space
|
|
// defines - additional defines (string or array of strings)
|
|
function compileFiles(srcs, defines)
|
|
{
|
|
var srcsArr = srcs.split(" ");
|
|
|
|
if (typeof(defines) == "string")
|
|
defines = new Array(defines);
|
|
|
|
var command = CXX + " /c /EHsc /GS " + CPPFLAGS +
|
|
" /Fo\"" + stageDir + "\\\\\"" +
|
|
" /Fd\"" + stageDir + "\\" +
|
|
changeFileExt(getFileName(srcsArr[0]), "pdb") + "\"";
|
|
|
|
if (defines instanceof Array)
|
|
command += joinArray(defines, "/D")
|
|
|
|
command += joinArray(srcsArr, "");
|
|
|
|
var message = "Compiling with command \"" + command + "\"";
|
|
logLine(message);
|
|
return WshShell.Run("cmd /c \"" + command +"\" >> " +
|
|
logFileName + " 2>&1", runWindowMode, true);
|
|
}
|
|
|
|
// performs linking of the files
|
|
// srcs - string with object file names and libraries delimited by space
|
|
// outName - filename of the resulting file
|
|
function linkFiles(srcs, outName)
|
|
{
|
|
var command = LD + " ";
|
|
|
|
command += joinArray(srcs.split(" "), "");
|
|
|
|
command += " " + LIBS + " /Fe\"" + stageDir + "\\" + outName + "\"" +
|
|
" /link " + LDFLAGS;
|
|
|
|
var message = "Linking with command \"" + command + "\"";
|
|
logLine(message);
|
|
return WshShell.Run("cmd /c \"" + command +"\" >> "
|
|
+ logFileName + " 2>&1", runWindowMode, true);
|
|
}
|
|
|
|
// performs compilation of the source files to the library file
|
|
// src - string with source file names delimited by space
|
|
// outFile - filename of the library file
|
|
function makeLibrary(srcFiles, outFile, shared)
|
|
{
|
|
var ret = compileFiles(srcFiles);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
var objNames = srcFiles.replace(/(?:[\S]+[/\\\\])?([^/\\\\]+\.)cpp/gi,
|
|
stageDir + "\\$1obj");
|
|
|
|
if (shared)
|
|
{
|
|
var libname = "\"" + stageDir + "\\" + outFile + "\"";
|
|
var dllname = "\"" + stageDir + "\\" + basename(outFile, "\\.lib") + ".dll\"";
|
|
var command = LD + " ";
|
|
command += joinArray(objNames.split(" "), "");
|
|
command += " " + LIBS + " /Fe" + dllname + " /link /DLL " + LDFLAGS +
|
|
" /IMPLIB:" + libname;
|
|
var message = "Making library with command \"" + command + "\"";
|
|
logLine(message);
|
|
ret = WshShell.Run("cmd /c \"" + command +"\" >> "
|
|
+ logFileName + " 2>&1", runWindowMode, true);
|
|
}
|
|
else
|
|
{
|
|
var command = AR + " /OUT:\"" + stageDir + "\\" + outFile + "\"" +
|
|
joinArray(objNames.split(" "), "");
|
|
var message = "Making library with command \"" + command + "\"";
|
|
logLine(message);
|
|
ret = WshShell.Run("cmd /c \"" + command +"\" >> "
|
|
+ logFileName + " 2>&1", runWindowMode, true);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// append line to the log file
|
|
function logLine(line)
|
|
{
|
|
var stream = fso.OpenTextFile(logFileName, 8, true, 0);
|
|
stream.WriteLine(line);
|
|
stream.Close();
|
|
}
|
|
]]>
|
|
</script>
|
|
</job>
|
|
</package>
|