| 1 |
/* ******************************************************* |
|---|
| 2 |
Build is a tool to assist building applications and libraries written |
|---|
| 3 |
using the D programming language. |
|---|
| 4 |
|
|---|
| 5 |
Copyright: (c) 2005 Derek Parnell |
|---|
| 6 |
Authors: Derek Parnell, Melbourne |
|---|
| 7 |
Initial Creation: January 2005 |
|---|
| 8 |
Version: 2.10 |
|---|
| 9 |
Date: August 2005 |
|---|
| 10 |
License: |
|---|
| 11 |
This software is provided 'as-is', without any express or implied |
|---|
| 12 |
warranty. In no event will the authors be held liable for damages |
|---|
| 13 |
of any kind arising from the use of this software. |
|---|
| 14 |
Permission is hereby granted to anyone to use this software for any |
|---|
| 15 |
purpose, including commercial applications, and to alter it and/or |
|---|
| 16 |
redistribute it freely, subject to the following restrictions:$(NL) |
|---|
| 17 |
1. The origin of this software must not be misrepresented; you must |
|---|
| 18 |
not claim that you wrote the original software. If you use this |
|---|
| 19 |
software in a product, an acknowledgment within documentation of |
|---|
| 20 |
said product would be appreciated but is not required.$(NL) |
|---|
| 21 |
2. Altered source versions must be plainly marked as such, and must |
|---|
| 22 |
not be misrepresented as being the original software.$(NL) |
|---|
| 23 |
3. This notice may not be removed or altered from any distribution |
|---|
| 24 |
of the source.$(NL) |
|---|
| 25 |
4. Derivative works are permitted, but they must carry this notice |
|---|
| 26 |
in full and credit the original source. |
|---|
| 27 |
******************************************************* */ |
|---|
| 28 |
|
|---|
| 29 |
module build; |
|---|
| 30 |
private import build_bn; // This module's build number |
|---|
| 31 |
|
|---|
| 32 |
version(unix) version = Unix; |
|---|
| 33 |
version(Unix) version = Posix; |
|---|
| 34 |
version(linux) version = Posix; |
|---|
| 35 |
version(darwin) version = Posix; |
|---|
| 36 |
|
|---|
| 37 |
version(build) |
|---|
| 38 |
{ |
|---|
| 39 |
version(Windows) { |
|---|
| 40 |
// OptLink Definition File |
|---|
| 41 |
pragma (build_def, "VERSION 2.10"); |
|---|
| 42 |
} |
|---|
| 43 |
} |
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
private{ |
|---|
| 47 |
// --------- imports ---------------- |
|---|
| 48 |
import source; // Source File class |
|---|
| 49 |
|
|---|
| 50 |
import util.str; // non-standard string routines. |
|---|
| 51 |
import util.fdt; // File Date-Time class |
|---|
| 52 |
import util.pathex; // Extended Path routines. |
|---|
| 53 |
import util.fileex; // Extended File routines. |
|---|
| 54 |
import util.macro; // Macro processing routines. |
|---|
| 55 |
import util.booltype; // definition of True and False |
|---|
| 56 |
|
|---|
| 57 |
import std.c.stdio; |
|---|
| 58 |
import std.file; |
|---|
| 59 |
import std.outbuffer; |
|---|
| 60 |
import std.path; |
|---|
| 61 |
import std.stdio; |
|---|
| 62 |
import std.stream; |
|---|
| 63 |
import std.string; |
|---|
| 64 |
|
|---|
| 65 |
version(Windows) { |
|---|
| 66 |
import std.c.windows.windows; |
|---|
| 67 |
} |
|---|
| 68 |
else version(linux) { |
|---|
| 69 |
import std.c.linux.linux; |
|---|
| 70 |
} |
|---|
| 71 |
else version(darwin) { |
|---|
| 72 |
import std.c.darwin.darwin; |
|---|
| 73 |
} |
|---|
| 74 |
|
|---|
| 75 |
// --------- C externals ---------------- |
|---|
| 76 |
extern (C) |
|---|
| 77 |
{ |
|---|
| 78 |
char* getenv (char *); |
|---|
| 79 |
int putenv (char *); |
|---|
| 80 |
int system (char *); |
|---|
| 81 |
} |
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
// --------- enums ---------------- |
|---|
| 85 |
enum LibOpt {Implicit, Build, DontBuild} |
|---|
| 86 |
|
|---|
| 87 |
// --------- constants ---------------- |
|---|
| 88 |
const { |
|---|
| 89 |
version(Windows) { |
|---|
| 90 |
char[] kExeExtention=`exe`; |
|---|
| 91 |
char[] kLibExtention=`lib`; |
|---|
| 92 |
char[] kObjExtention=`obj`; |
|---|
| 93 |
char[] kShrLibExtention=`dll`; |
|---|
| 94 |
} |
|---|
| 95 |
|
|---|
| 96 |
version(Posix) { |
|---|
| 97 |
char[] kExeExtention=``; |
|---|
| 98 |
char[] kLibExtention=`a`; |
|---|
| 99 |
char[] kObjExtention=`o`; |
|---|
| 100 |
char[] kShrLibExtention=`s`; |
|---|
| 101 |
} |
|---|
| 102 |
char[] kSrcExtention=`d`; |
|---|
| 103 |
char[] kMacroExtention=`mac`; |
|---|
| 104 |
char[] kDdocExtention=`ddoc`; |
|---|
| 105 |
|
|---|
| 106 |
} |
|---|
| 107 |
|
|---|
| 108 |
// ---------- Module scoped globals ----------- |
|---|
| 109 |
version(DigitalMars) { |
|---|
| 110 |
version(Windows) { |
|---|
| 111 |
char[] vCompilerExe=`dmd.exe`; |
|---|
| 112 |
char[] vCompileOnlySwitch = ` -c`; |
|---|
| 113 |
char[] vLinkerExe=`link.exe`; |
|---|
| 114 |
char[] vConfigFile=`sc.ini`; |
|---|
| 115 |
char[] vCompilerPath=``; |
|---|
| 116 |
char[] vLinkerPath=``; |
|---|
| 117 |
char[] vLinkerDefSwitches=`/noi/map`; |
|---|
| 118 |
char[] vConfigPath=``; |
|---|
| 119 |
char[] vLibPaths = ``; |
|---|
| 120 |
char[] vConfigSep = ";"; |
|---|
| 121 |
char[] vLibrarian = `lib`; |
|---|
| 122 |
char[] vLibrarianOpts = `-c -p256`; |
|---|
| 123 |
char[] vLinkerDebugSymInfoSwitch = " /co"; |
|---|
| 124 |
} |
|---|
| 125 |
|
|---|
| 126 |
version(Posix) { |
|---|
| 127 |
char[] vCompilerExe=`gdmd`; |
|---|
| 128 |
char[] vCompileOnlySwitch= ` -c`; |
|---|
| 129 |
char[] vLinkerExe=`ld`; |
|---|
| 130 |
char[] vConfigFile=`dmd.conf`; |
|---|
| 131 |
char[] vCompilerPath=``; |
|---|
| 132 |
char[] vLinkerPath=``; |
|---|
| 133 |
char[] vLinkerDefSwitches=``; |
|---|
| 134 |
char[] vConfigPath=`/etc/`; |
|---|
| 135 |
char[] vLibPaths = ``; |
|---|
| 136 |
char[] vConfigSep = ":"; |
|---|
| 137 |
char[] vLibrarian = `ar`; |
|---|
| 138 |
char[] vLibrarianOpts = `-r`; |
|---|
| 139 |
char[] vLinkerDebugSymInfoSwitch = " -g"; |
|---|
| 140 |
} |
|---|
| 141 |
|
|---|
| 142 |
char[] vVersionSwitch = "-version="; |
|---|
| 143 |
char[] vDebugSwitch = "-debug"; |
|---|
| 144 |
char[] vKeepPathSwitch = "-op"; |
|---|
| 145 |
char[] vOutFileSwitch = "-of"; |
|---|
| 146 |
char[] vImportPathSwitch = "-I"; |
|---|
| 147 |
char[] vNoLinkSwitch = "-c"; |
|---|
| 148 |
char[] vLinkOutputSwitch = "-o "; |
|---|
| 149 |
char[] vLinkLibSwitch = "-l"; |
|---|
| 150 |
} |
|---|
| 151 |
|
|---|
| 152 |
version(GNU) { |
|---|
| 153 |
version(Windows) { |
|---|
| 154 |
char[] vCompilerExe=`gdc.exe`; |
|---|
| 155 |
char[] vCompileOnlySwitch= ` -c`; |
|---|
| 156 |
char[] vLinkerExe=`gdc.exe`; |
|---|
| 157 |
char[] vConfigFile=null; |
|---|
| 158 |
char[] vCompilerPath=``; |
|---|
| 159 |
char[] vLinkerPath=``; |
|---|
| 160 |
char[] vLinkerDefSwitches=``; |
|---|
| 161 |
char[] vConfigPath=null; |
|---|
| 162 |
char[] vLibPaths = ``; |
|---|
| 163 |
char[] vConfigSep = ";"; |
|---|
| 164 |
char[] vLibrarian = `lib`; |
|---|
| 165 |
char[] vLibrarianOpts = `-c`; |
|---|
| 166 |
|
|---|
| 167 |
char[] vVersionSwitch = "-fversion="; |
|---|
| 168 |
char[] vDebugSwitch = "-fdebug"; |
|---|
| 169 |
char[] vOutFileSwitch = "-o "; |
|---|
| 170 |
char[] vKeepPathSwitch = ""; |
|---|
| 171 |
char[] vImportPathSwitch = "-I "; |
|---|
| 172 |
char[] vLinkOutputSwitch = "-o "; |
|---|
| 173 |
char[] vLinkLibSwitch = "-l"; |
|---|
| 174 |
char[] vLinkerDebugSymInfoSwitch = " /co"; |
|---|
| 175 |
} |
|---|
| 176 |
|
|---|
| 177 |
version(Posix) { |
|---|
| 178 |
// Using GDC's GDMD wrapper script |
|---|
| 179 |
char[] vCompilerExe=`gdmd`; |
|---|
| 180 |
char[] vCompileOnlySwitch= ` -c`; |
|---|
| 181 |
char[] vLinkerExe=`gdmd`; // using gdmd/gdc as linker |
|---|
| 182 |
char[] vConfigFile=``; |
|---|
| 183 |
char[] vCompilerPath=``; |
|---|
| 184 |
char[] vLinkerPath=``; |
|---|
| 185 |
char[] vLinkerDefSwitches=``; |
|---|
| 186 |
char[] vConfigPath=`/etc/`; |
|---|
| 187 |
char[] vLibPaths = ``; |
|---|
| 188 |
char[] vConfigSep = ":"; |
|---|
| 189 |
char[] vLibrarian = `ar`; |
|---|
| 190 |
char[] vLibrarianOpts = `-r`; |
|---|
| 191 |
|
|---|
| 192 |
char[] vVersionSwitch = "-version="; |
|---|
| 193 |
char[] vDebugSwitch = "-debug"; |
|---|
| 194 |
char[] vKeepPathSwitch = "-op"; |
|---|
| 195 |
char[] vOutFileSwitch = "-of"; |
|---|
| 196 |
char[] vImportPathSwitch = "-I"; |
|---|
| 197 |
char[] vLinkOutputSwitch = "-of"; |
|---|
| 198 |
char[] vLinkLibSwitch = "-L-l"; |
|---|
| 199 |
char[] vLinkerDebugSymInfoSwitch = " -g"; |
|---|
| 200 |
} |
|---|
| 201 |
char[] vNoLinkSwitch = "-c"; |
|---|
| 202 |
} |
|---|
| 203 |
|
|---|
| 204 |
char[] vBuildImportPathSwitch = "-I"; |
|---|
| 205 |
char[] vTemporaryPathSwitch = "-od"; |
|---|
| 206 |
char[] vRunSwitch = "-exec"; |
|---|
| 207 |
char[] vLibrarianPath = ""; |
|---|
| 208 |
char[]* vDelayedValue = null; |
|---|
| 209 |
char[] vTemporaryPath = ""; |
|---|
| 210 |
|
|---|
| 211 |
Bool vTestRun; |
|---|
| 212 |
Bool vScanImports; |
|---|
| 213 |
Bool vNoLink; |
|---|
| 214 |
Bool vForceCompile; |
|---|
| 215 |
Bool vSilent; |
|---|
| 216 |
Bool vCleanup; |
|---|
| 217 |
Bool vVerbose; |
|---|
| 218 |
Bool vMacroInput; |
|---|
| 219 |
Bool vNames; |
|---|
| 220 |
Bool vAllObjects; |
|---|
| 221 |
Bool vNoDef; |
|---|
| 222 |
Bool vAutoImports; |
|---|
| 223 |
Bool vExecuteProgram; |
|---|
| 224 |
Bool vUseResponseFile; |
|---|
| 225 |
Bool vConsoleApp; |
|---|
| 226 |
char[] vRunParms; |
|---|
| 227 |
char[] vTargetExe; |
|---|
| 228 |
char[][] vImportRoots; |
|---|
| 229 |
char[][] vModulesToIgnore; |
|---|
| 230 |
char[][] vModulesToNotice; |
|---|
| 231 |
char[][] vBuildDef; |
|---|
| 232 |
char[][] vDefaultLibs; |
|---|
| 233 |
char[][] vDefaultCompArgs; |
|---|
| 234 |
LibOpt vLibraryAction = LibOpt.Implicit; |
|---|
| 235 |
char[] vAppPath; |
|---|
| 236 |
char[] vAppName; |
|---|
| 237 |
char[] vAppVersion = "2.10"; |
|---|
| 238 |
char[] vTargetName; // Output name from first file name. |
|---|
| 239 |
char[] vPragmaTargetName; // Output name from pragma. |
|---|
| 240 |
char[] vCommandTargetName; // Output name from switches. |
|---|
| 241 |
char[][] vCmdLineSourceFiles; // List of source files from command line |
|---|
| 242 |
bool[char[]] vLinkFiles; // List of non-source files from command line |
|---|
| 243 |
char[][] vCombinedArgs; // All the args are gathered here prior to processing. |
|---|
| 244 |
char[][] vBuildArgs; // Arguments passed to build |
|---|
| 245 |
char[][] vCompilerArgs; // Arguments passed to compiler |
|---|
| 246 |
char[][] vSourceScanList; // The list of places to find source files. |
|---|
| 247 |
char[] vRDFName = "default.rdf"; |
|---|
| 248 |
bool[char[]] vNestedDelim; |
|---|
| 249 |
struct ExternRef |
|---|
| 250 |
{ |
|---|
| 251 |
char[] FilePath; |
|---|
| 252 |
char[][] ToolOpts; |
|---|
| 253 |
} |
|---|
| 254 |
ExternRef[] vExternals; |
|---|
| 255 |
|
|---|
| 256 |
Substitute[] vSubstitutions; |
|---|
| 257 |
|
|---|
| 258 |
|
|---|
| 259 |
const static char[] kPathId = "PATH"; // Used to locate the environment symbol |
|---|
| 260 |
|
|---|
| 261 |
version(Windows) |
|---|
| 262 |
{ |
|---|
| 263 |
char[] vWinVer = ""; |
|---|
| 264 |
ubyte vWinVerNum; |
|---|
| 265 |
} |
|---|
| 266 |
|
|---|
| 267 |
} |
|---|
| 268 |
|
|---|
| 269 |
// Module constructor. |
|---|
| 270 |
//------------------------------------------------------- |
|---|
| 271 |
static this() |
|---|
| 272 |
//------------------------------------------------------- |
|---|
| 273 |
{ |
|---|
| 274 |
source.ActivateVersion("build"); //todo |
|---|
| 275 |
|
|---|
| 276 |
vDefaultCompArgs ~= vKeepPathSwitch; // Keep object files in same folder as source. |
|---|
| 277 |
vModulesToIgnore ~= "phobos"; // Assume phobos will be ignored. |
|---|
| 278 |
vSourceScanList ~= "." ~ std.path.sep; |
|---|
| 279 |
vNoLink = False; |
|---|
| 280 |
vTestRun = False; |
|---|
| 281 |
vScanImports = False; |
|---|
| 282 |
vForceCompile = False; |
|---|
| 283 |
vSilent = False; |
|---|
| 284 |
vCleanup = False; |
|---|
| 285 |
vVerbose = False; |
|---|
| 286 |
vMacroInput = True; |
|---|
| 287 |
vNames = False; |
|---|
| 288 |
vAllObjects = False; |
|---|
| 289 |
vNoDef = False; |
|---|
| 290 |
vAutoImports = True; |
|---|
| 291 |
vExecuteProgram = False; |
|---|
| 292 |
vUseResponseFile = False; |
|---|
| 293 |
vConsoleApp = True; |
|---|
| 294 |
|
|---|
| 295 |
version(Posix){ |
|---|
| 296 |
vDefaultCompArgs ~= vVersionSwitch ~ "Posix"; // Until such time as this is standard in dmd. |
|---|
| 297 |
} |
|---|
| 298 |
|
|---|
| 299 |
version(Windows) { |
|---|
| 300 |
vWinVerNum = cast(ubyte)(GetVersion() & 0xFF); |
|---|
| 301 |
vWinVer = std.string.format("%d.0", vWinVerNum); |
|---|
| 302 |
} |
|---|
| 303 |
|
|---|
| 304 |
version(DigitalMars) { |
|---|
| 305 |
version(Windows) { |
|---|
| 306 |
vUseResponseFile = True; |
|---|
| 307 |
} |
|---|
| 308 |
else |
|---|
| 309 |
{ |
|---|
| 310 |
vUseResponseFile = False; |
|---|
| 311 |
} |
|---|
| 312 |
} else |
|---|
| 313 |
{ |
|---|
| 314 |
vUseResponseFile = False; |
|---|
| 315 |
} |
|---|
| 316 |
|
|---|
| 317 |
vNestedDelim["("] = true; |
|---|
| 318 |
vNestedDelim["<"] = true; |
|---|
| 319 |
vNestedDelim["{"] = true; |
|---|
| 320 |
vNestedDelim["["] = true; |
|---|
| 321 |
} |
|---|
| 322 |
|
|---|
| 323 |
static ~this() |
|---|
| 324 |
{ |
|---|
| 325 |
// Clean up any resources held by the source files. |
|---|
| 326 |
Source.Finalize(); |
|---|
| 327 |
} |
|---|
| 328 |
|
|---|
| 329 |
//------------------------------------------------------- |
|---|
| 330 |
void DisplayUsage(bool pFull = true) |
|---|
| 331 |
//------------------------------------------------------- |
|---|
| 332 |
{ |
|---|
| 333 |
|
|---|
| 334 |
writefln( |
|---|
| 335 |
"Path and Version : %s v%s(%d)\n built on %s" |
|---|
| 336 |
,vAppPath, vAppVersion, build_bn.auto_build_number, |
|---|
| 337 |
__TIMESTAMP__); |
|---|
| 338 |
if (pFull == false) |
|---|
| 339 |
return; |
|---|
| 340 |
else { |
|---|
| 341 |
|
|---|
| 342 |
writefln( |
|---|
| 343 |
"Usage: %s sourcefile [options objectfiles libraries]" |
|---|
| 344 |
, vAppName); |
|---|
| 345 |
writefln(" sourcefile D source file"); |
|---|
| 346 |
writefln(" -v Verbose (passed through to D)"); |
|---|
| 347 |
writefln(" -V Verbose (NOT passed through)"); |
|---|
| 348 |
writefln(" -names Displays the names of the files used in building the target."); |
|---|
| 349 |
writefln(" -DCPATH<path> <path> is where the compiler has been installed."); |
|---|
| 350 |
writefln(" Only needed if the compiler is not in the system's"); |
|---|
| 351 |
writefln(" PATH list. Used if you are testing an alternate"); |
|---|
| 352 |
writefln(" version of the compiler."); |
|---|
| 353 |
writefln(" -CFPATH<path> <path> is where the D config file has been installed."); |
|---|
| 354 |
writefln(" -full Causes all source files, except ignored modules,"); |
|---|
| 355 |
writefln(" to be compiled."); |
|---|
| 356 |
writefln(" -link Forces the linker to be called instead of the librarian."); |
|---|
| 357 |
writefln(" (Only needed if the source files do not contain"); |
|---|
| 358 |
writefln(" main/WinMain)"); |
|---|
| 359 |
writefln(" -nolink Ensures that the linker is not called."); |
|---|
| 360 |
writefln(" (Only needed if main/WinMain is found in the source"); |
|---|
| 361 |
writefln(" files and you do NOT want an executable created.)"); |
|---|
| 362 |
writefln(" -lib Forces the object files to be placed in a library."); |
|---|
| 363 |
writefln(" (Only needed if main/WinMain is found in the source"); |
|---|
| 364 |
writefln(" files AND you want it in a library instead of"); |
|---|
| 365 |
writefln(" an executable.)"); |
|---|
| 366 |
writefln(" -nolib Ensures that the object files are not used to form"); |
|---|
| 367 |
writefln(" a library."); |
|---|
| 368 |
writefln(" (Only needed if main/WinMain is not found in the source"); |
|---|
| 369 |
writefln(" files and you do NOT want a library."); |
|---|
| 370 |
writefln(" -obj This is the same as having both -nolib and -nolink switches."); |
|---|
| 371 |
writefln(" -allobj Ensures that all object files are added to a"); |
|---|
| 372 |
writefln(" library."); |
|---|
| 373 |
writefln(" (Normally only those in the same directory are added.)"); |
|---|
| 374 |
writefln(" -cleanup Ensures that all object files created during the run"); |
|---|
| 375 |
writefln(" are removed at the end of the run, plus other work files."); |
|---|
| 376 |
writefln(" -clean Same as -cleanup"); |
|---|
| 377 |
version(Windows) { |
|---|
| 378 |
writefln(" -gui[:x.y] Forces a GUI application to be created. The optional"); |
|---|
| 379 |
writefln(" :x.y can be used to build an application for a "); |
|---|
| 380 |
writefln(" specific version of Windows. eg. -gui:4.0"); |
|---|
| 381 |
writefln(" (Only needed if WinMain is not found in the source files"); |
|---|
| 382 |
writefln(" or if you wish to override the default Windows version)"); |
|---|
| 383 |
writefln(" -dll Forces a DLL library to be created."); |
|---|
| 384 |
writefln(" (Only needed if DllMain is not found in the source files.)"); |
|---|
| 385 |
} |
|---|
| 386 |
|
|---|
| 387 |
writefln(" -LIBOPT<opt> Allows you to pass <opt> to the librarian."); |
|---|
| 388 |
writefln(" -LIBPATH=<pathlist> Used to add a semi-colon delimited list"); |
|---|
| 389 |
writefln(" of search paths for library files."); |
|---|
| 390 |
writefln(" -test Does everything as normal except it displays the commands"); |
|---|
| 391 |
writefln(" instead of running them."); |
|---|
| 392 |
writefln(" -RDF<path> Overrides the default Rule Definition File"); |
|---|
| 393 |
writefln(" -R<y|n> Indicates whether to use a response file or command line"); |
|---|
| 394 |
writefln(" arguments with the compiler tools."); |
|---|
| 395 |
writefln(" -Ry will cause a response to be used."); |
|---|
| 396 |
writefln(" -Rn will cause command line arguments to be used."); |
|---|
| 397 |
writefln(" -R will reverse the current usage."); |
|---|
| 398 |
writefln(" -PP<path> Add a path to the Source Search List"); |
|---|
| 399 |
|
|---|
| 400 |
version(DigitalMars) { |
|---|
| 401 |
version(Windows) { |
|---|
| 402 |
writefln(" ** The default is to use a response file"); } |
|---|
| 403 |
else { |
|---|
| 404 |
writefln(" ** The default is to use command line arguments"); } |
|---|
| 405 |
} |
|---|
| 406 |
else { |
|---|
| 407 |
writefln(" ** The default is to use command line arguments"); } |
|---|
| 408 |
|
|---|
| 409 |
writefln(" -exec<param> If the link is successful, this will cause the"); |
|---|
| 410 |
writefln(" executable just created to run. You can give it "); |
|---|
| 411 |
writefln(" run time parameters. Anything after the '-exec' will"); |
|---|
| 412 |
writefln(" placed in the program's command line. You will need"); |
|---|
| 413 |
writefln(" to quote any embedded spaces."); |
|---|
| 414 |
writefln(" -od<path> Nominate the directory where temporary (work) files"); |
|---|
| 415 |
writefln(" are to be created. By default they are created in"); |
|---|
| 416 |
writefln(" the same directory as the target file."); |
|---|
| 417 |
writefln(" -X<module> Modules/Packages to ignore (eg. -Xmylib)"); |
|---|
| 418 |
writefln(" -M<module> Modules/Packages to notice (eg. -Mphobos)"); |
|---|
| 419 |
writefln(" -T<targetname> The name of the target file to create. Normally"); |
|---|
| 420 |
writefln(" the target name istaken from the first or only name"); |
|---|
| 421 |
writefln(" of the command line."); |
|---|
| 422 |
writefln(" -help Displays the full 'usage' help text. "); |
|---|
| 423 |
writefln(" -h Same as -help, displays the full 'usage' help text."); |
|---|
| 424 |
writefln(" -? Same as -help, displays the full 'usage' help text."); |
|---|
| 425 |
writefln(" -silent Avoids unnecessary messages being displayed."); |
|---|
| 426 |
writefln(" -noautoimport Turns off the automatic addition of source paths"); |
|---|
| 427 |
writefln(" to the list of Import Roots."); |
|---|
| 428 |
writefln(" -info Displays the version and path of the Build application."); |
|---|
| 429 |
writefln(" -nodef Prevents a Module Definition File from being created."); |
|---|
| 430 |
writefln(" [...] All other options, objectfiles and libraries are"); |
|---|
| 431 |
writefln(" passed to the compiler"); |
|---|
| 432 |
writefln("*Note, you can specify all or any command line value in a "); |
|---|
| 433 |
writefln(" response file. Each value appears in its own line in the"); |
|---|
| 434 |
writefln(" response file and you reference this file by prefixing"); |
|---|
| 435 |
writefln(" its name with an '@' symbol on the command line."); |
|---|
| 436 |
writefln(" Example: build @final"); |
|---|
| 437 |
writefln(" where a file called 'final.brf' contains the command"); |
|---|
| 438 |
writefln(" line values (including other response file references)"); |
|---|
| 439 |
writefln(" If the response file reference is just a single '@' then"); |
|---|
| 440 |
writefln(" build looks for a file called 'build.brf'"); |
|---|
| 441 |
} |
|---|
| 442 |
} |
|---|
| 443 |
|
|---|
| 444 |
//------------------------------------------------------- |
|---|
| 445 |
int RunCommand(char[] pCommand) |
|---|
| 446 |
//------------------------------------------------------- |
|---|
| 447 |
{ |
|---|
| 448 |
int lRC; |
|---|
| 449 |
int lTrueRC; |
|---|
| 450 |
|
|---|
| 451 |
if (vTestRun == True) { |
|---|
| 452 |
writefln("Command: '%s'",pCommand); |
|---|
| 453 |
return 0; |
|---|
| 454 |
} |
|---|
| 455 |
else |
|---|
| 456 |
{ |
|---|
| 457 |
|
|---|
| 458 |
|
|---|
| 459 |
if(vVerbose == True) { |
|---|
| 460 |
writefln("Running '%s'",pCommand); |
|---|
| 461 |
} |
|---|
| 462 |
|
|---|
| 463 |
lRC = system(std.string.toStringz(pCommand)); |
|---|
| 464 |
version(Posix) lTrueRC = ((lRC & 0xFF00) >> 8); |
|---|
| 465 |
version(Windows) lTrueRC = lRC; |
|---|
| 466 |
|
|---|
| 467 |
if(vVerbose == True) { |
|---|
| 468 |
if (lTrueRC == 0){ |
|---|
| 469 |
writefln("Successful"); |
|---|
| 470 |
} else { |
|---|
| 471 |
writefln("Failed. Return code: %04x",lRC); |
|---|
| 472 |
} |
|---|
| 473 |
} |
|---|
| 474 |
return lTrueRC; |
|---|
| 475 |
} |
|---|
| 476 |
} |
|---|
| 477 |
|
|---|
| 478 |
//------------------------------------------------------- |
|---|
| 479 |
char[] GetEnv(char[] pSymbol) |
|---|
| 480 |
//------------------------------------------------------- |
|---|
| 481 |
{ |
|---|
| 482 |
return std.string.toString(getenv(pSymbol)); |
|---|
| 483 |
} |
|---|
| 484 |
|
|---|
| 485 |
// Scans all known source files and extacts any modules. |
|---|
| 486 |
// It returns the time of the most recently modified file. |
|---|
| 487 |
//------------------------------------------------------- |
|---|
| 488 |
FileDateTime GetNewestDateTime() |
|---|
| 489 |
//------------------------------------------------------- |
|---|
| 490 |
{ |
|---|
| 491 |
Source lSource; |
|---|
| 492 |
FileDateTime lModsTime = new FileDateTime(); |
|---|
| 493 |
|
|---|
| 494 |
foreach(int i, char[] lFileName; Source.ScanOrder) |
|---|
| 495 |
{ |
|---|
| 496 |
// Get the next Source object to examine. |
|---|
| 497 |
lSource = Source.SourceIndex[lFileName]; |
|---|
| 498 |
if (lSource.Ignore) |
|---|
| 499 |
continue; |
|---|
| 500 |
|
|---|
| 501 |
// Ensure that it has been processed. |
|---|
| 502 |
lSource.search(); |
|---|
| 503 |
|
|---|
| 504 |
if(vVerbose == True) { |
|---|
| 505 |
writefln("source file[%d] %s", i, |
|---|
| 506 |
util.pathex.AbbreviateFileName(lFileName)); |
|---|
| 507 |
} |
|---|
| 508 |
else if(vNames == True) { |
|---|
| 509 |
writefln(" [ %s ]", util.pathex.AbbreviateFileName(lFileName)); |
|---|
| 510 |
} |
|---|
| 511 |
|
|---|
| 512 |
if (lSource.DependantsTime > lModsTime) |
|---|
| 513 |
{ |
|---|
| 514 |
if(vVerbose == True) { |
|---|
| 515 |
writefln("Newer time: from %s to %s", |
|---|
| 516 |
lModsTime.toString(), |
|---|
| 517 |
lSource.DependantsTime.toString() |
|---|
| 518 |
); |
|---|
| 519 |
} |
|---|
| 520 |
|
|---|
| 521 |
lModsTime = lSource.DependantsTime; |
|---|
| 522 |
} |
|---|
| 523 |
} |
|---|
| 524 |
|
|---|
| 525 |
// Examine any link file dependancies too. |
|---|
| 526 |
foreach(int i, char[] lFileName; vLinkFiles.keys) |
|---|
| 527 |
{ |
|---|
| 528 |
FileDateTime lLinkTime = GetFileTime(lFileName); |
|---|
| 529 |
|
|---|
| 530 |
if(vVerbose == True) { |
|---|
| 531 |
writefln("link file[%d] %s %s", i, |
|---|
| 532 |
util.pathex.AbbreviateFileName(lFileName), lLinkTime.toString()); |
|---|
| 533 |
} |
|---|
| 534 |
else if(vNames == True) { |
|---|
| 535 |
writefln(" [ %s ]", util.pathex.AbbreviateFileName(lFileName)); |
|---|
| 536 |
} |
|---|
| 537 |
|
|---|
| 538 |
if (lLinkTime > lModsTime) |
|---|
| 539 |
{ |
|---|
| 540 |
if(vVerbose == True) { |
|---|
| 541 |
writefln("Newer time: from %s to %s", |
|---|
| 542 |
lModsTime.toString(), |
|---|
| 543 |
lLinkTime.toString() |
|---|
| 544 |
); |
|---|
| 545 |
} |
|---|
| 546 |
|
|---|
| 547 |
lModsTime = lLinkTime; |
|---|
| 548 |
} |
|---|
| 549 |
} |
|---|
| 550 |
|
|---|
| 551 |
return lModsTime; |
|---|
| 552 |
} |
|---|
| 553 |
|
|---|
| 554 |
struct Rule |
|---|
| 555 |
{ |
|---|
| 556 |
char[] Name; |
|---|
| 557 |
char[] Input; |
|---|
| 558 |
char[] Output; |
|---|
| 559 |
char[] Tool; |
|---|
| 560 |
}; |
|---|
| 561 |
|
|---|
| 562 |
|
|---|
| 563 |
//------------------------------------------------------- |
|---|
| 564 |
Rule[] LoadRules() |
|---|
| 565 |
//------------------------------------------------------- |
|---|
| 566 |
{ |
|---|
| 567 |
Rule[] lRules; |
|---|
| 568 |
char[][] lRuleText; |
|---|
| 569 |
char[] lRuleDefnFile; |
|---|
| 570 |
|
|---|
| 571 |
static char[] kRuleKey = "rule="; |
|---|
| 572 |
|
|---|
| 573 |
lRuleDefnFile = util.pathex.LocateFile(vRDFName, |
|---|
| 574 |
getDirName(vAppPath) ~ std.path.pathsep ~ GetEnv(kPathId)); |
|---|
| 575 |
if (vVerbose == True) |
|---|
| 576 |
writefln("Rule Definitions from %s", lRuleDefnFile); |
|---|
| 577 |
GetTextLines( lRuleDefnFile, lRuleText ); |
|---|
| 578 |
foreach(char[] lLine; lRuleText) |
|---|
| 579 |
{ |
|---|
| 580 |
lLine = util.str.strip(lLine); |
|---|
| 581 |
if (util.str.begins(lLine, kRuleKey ) == True) |
|---|
| 582 |
{ |
|---|
| 583 |
lRules.length = lRules.length + 1; |
|---|
| 584 |
lRules[$-1].Name = lLine[5 .. $]; |
|---|
| 585 |
} |
|---|
| 586 |
else if (lRules.length > 0) |
|---|
| 587 |
{ |
|---|
| 588 |
if (util.str.begins(lLine, "in=") == True) |
|---|
| 589 |
lRules[$-1].Input = lLine[3..$]; |
|---|
| 590 |
else if (util.str.begins(lLine, "out=") == True) |
|---|
| 591 |
lRules[$-1].Output = lLine[4..$]; |
|---|
| 592 |
else if (util.str.begins(lLine, "tool=") == True) |
|---|
| 593 |
lRules[$-1].Tool = lLine[5..$]; |
|---|
| 594 |
} |
|---|
| 595 |
} |
|---|
| 596 |
|
|---|
| 597 |
if (vVerbose == True) |
|---|
| 598 |
{ |
|---|
| 599 |
foreach(Rule r; lRules) |
|---|
| 600 |
{ |
|---|
| 601 |
writefln("Rule '%s' ==> in:%s, out:%s, tool:'%s'", |
|---|
| 602 |
r.Name, r.Input, r.Output, r.Tool); |
|---|
| 603 |
} |
|---|
| 604 |
} |
|---|
| 605 |
|
|---|
| 606 |
return lRules; |
|---|
| 607 |
} |
|---|
| 608 |
|
|---|
| 609 |
//------------------------------------------------------- |
|---|
| 610 |
int ProcessExternal( ExternRef pRef) |
|---|
| 611 |
//------------------------------------------------------- |
|---|
| 612 |
{ |
|---|
| 613 |
int lResult = -1; |
|---|
| 614 |
static Rule[] lRules; |
|---|
| 615 |
char[] lExtension; |
|---|
| 616 |
char[] lInFile; |
|---|
| 617 |
char[] lOutFile; |
|---|
| 618 |
FileDateTime lInDate; |
|---|
| 619 |
FileDateTime lOutDate; |
|---|
| 620 |
char[] lCommand; |
|---|
| 621 |
|
|---|
| 622 |
|
|---|
| 623 |
if (lRules.length == 0) |
|---|
| 624 |
lRules = LoadRules(); |
|---|
| 625 |
|
|---|
| 626 |
lExtension = std.path.getExt(pRef.FilePath); |
|---|
| 627 |
foreach(Rule r; lRules) |
|---|
| 628 |
{ |
|---|
| 629 |
lInFile = ""; |
|---|
| 630 |
if (lExtension == r.Input) |
|---|
| 631 |
{ |
|---|
| 632 |
lInFile = pRef.FilePath; |
|---|
| 633 |
lOutFile = std.path.addExt(pRef.FilePath, r.Output); |
|---|
| 634 |
|
|---|
| 635 |
} else if (lExtension == r.Output) |
|---|
| 636 |
{ |
|---|
| 637 |
lOutFile = pRef.FilePath; |
|---|
| 638 |
lInFile = std.path.addExt(pRef.FilePath, r.Input); |
|---|
| 639 |
} |
|---|
| 640 |
|
|---|
| 641 |
if (lInFile.length == 0) |
|---|
| 642 |
continue; |
|---|
| 643 |
|
|---|
| 644 |
lInFile = util.pathex.LocateFile(lInFile, vImportRoots); |
|---|
| 645 |
if (! util.fileex.FileExists( lInFile ) ) |
|---|
| 646 |
throw new Exception( |
|---|
| 647 |
std.string.format("External file '%s' not found", lInFile)); |
|---|
| 648 |
|
|---|
| 649 |
lOutFile = getDirName(lInFile) ~ std.path.sep ~ getBaseName(lInFile); |
|---|
| 650 |
lOutFile = std.path.addExt(lOutFile, r.Output); |
|---|
| 651 |
|
|---|
| 652 |
lInFile = util.pathex.AbbreviateFileName(lInFile); |
|---|
| 653 |
lOutFile = util.pathex.AbbreviateFileName(lOutFile); |
|---|
| 654 |
|
|---|
| 655 |
lInDate = new FileDateTime(lInFile); |
|---|
| 656 |
lOutDate = new FileDateTime(lOutFile); |
|---|
| 657 |
|
|---|
| 658 |
if ((lInDate > lOutDate) || (vForceCompile == True)) |
|---|
| 659 |
{ |
|---|
| 660 |
char[] lKeyValues; |
|---|
| 661 |
|
|---|
| 662 |
lKeyValues = "@IN=" ~ lInFile ~ "," ~ "@OUT=" ~ lOutFile; |
|---|
| 663 |
foreach(char[] lOpt; pRef.ToolOpts) |
|---|
| 664 |
{ |
|---|
| 665 |
if (std.string.find(lOpt, "=") != -1) |
|---|
| 666 |
lKeyValues ~= "," ~ lOpt; |
|---|
| 667 |
} |
|---|
| 668 |
lCommand = util.str.Expand(r.Tool,lKeyValues); |
|---|
| 669 |
|
|---|
| 670 |
// Run Compiler to compile the source files that need it. |
|---|
| 671 |
lResult = RunCommand(lCommand); |
|---|
| 672 |
if (lResult != 0) |
|---|
| 673 |
return lResult; |
|---|
| 674 |
} |
|---|
| 675 |
AddLink(lOutFile); |
|---|
| 676 |
|
|---|
| 677 |
} |
|---|
| 678 |
|
|---|
| 679 |
return 0; |
|---|
| 680 |
} |
|---|
| 681 |
|
|---|
| 682 |
/* Build the target. Return an error code if there |
|---|
| 683 |
was a problem, else return zero. |
|---|
| 684 |
*/ |
|---|
| 685 |
//------------------------------------------------------- |
|---|
| 686 |
int Build() |
|---|
| 687 |
//------------------------------------------------------- |
|---|
| 688 |
{ |
|---|
| 689 |
Bool lCompiling; |
|---|
| 690 |
Bool lLinking; |
|---|
| 691 |
Bool lBuildRequired; |
|---|
| 692 |
char[][] lFilesToLink; |
|---|
| 693 |
char[][] lFilesToCompile; |
|---|
| 694 |
int lRunResult; |
|---|
| 695 |
char[] lTargetName; |
|---|
| 696 |
char[] lTargetDir; |
|---|
| 697 |
FileDateTime lTargetTime; |
|---|
| 698 |
FileDateTime lMostRecentTime; |
|---|
| 699 |
auto Source[] lNonLinkingSources; |
|---|
| 700 |
char[] lDResponseFileName; |
|---|
| 701 |
char[] lLinkResponseFileName; |
|---|
| 702 |
char[] lLResponseFileName; |
|---|
| 703 |
char[] lDefName; |
|---|
| 704 |
char[] lOutText; |
|---|
| 705 |
char[] lCompilerOpts; |
|---|
| 706 |
char[] lSourcesToCompile; |
|---|
| 707 |
char[] lCommand; |
|---|
| 708 |
char[][] lObjectFiles; |
|---|
| 709 |
char[][] lLibraryFiles; |
|---|
| 710 |
|
|---|
| 711 |
|
|---|
| 712 |
lCompiling = False; |
|---|
| 713 |
lLinking = False; |
|---|
| 714 |
lBuildRequired = False; |
|---|
| 715 |
|
|---|
| 716 |
// Examine each supplied source file. |
|---|
| 717 |
foreach( char[] lFile; vCmdLineSourceFiles) |
|---|
| 718 |
{ |
|---|
| 719 |
new Source(GetFullPathname(lFile, vSourceScanList)); |
|---|
| 720 |
} |
|---|
| 721 |
|
|---|
| 722 |
// I'm linking if I'm not building a library, and a 'main' was |
|---|
| 723 |
// found, and I was not explicitly told not to link. |
|---|
| 724 |
lLinking = (vLibraryAction == LibOpt.Build) || |
|---|
| 725 |
(Source.WasMainFound == false) || |
|---|
| 726 |
(vNoLink == True) |
|---|
| 727 |
? False : True; |
|---|
| 728 |
|
|---|
| 729 |
lMostRecentTime = GetNewestDateTime(); |
|---|
| 730 |
|
|---|
| 731 |
// If not explictly known, set the library action |
|---|
| 732 |
// based on whether or not 'main' was found in the sources. |
|---|
| 733 |
if (vLibraryAction == LibOpt.Implicit) { |
|---|
| 734 |
if (Source.WasMainFound){ |
|---|
| 735 |
vLibraryAction = LibOpt.DontBuild; |
|---|
| 736 |
} |
|---|
| 737 |
else { |
|---|
| 738 |
vLibraryAction = LibOpt.Build; |
|---|
| 739 |
} |
|---|
| 740 |
} |
|---|
| 741 |
|
|---|
| 742 |
// I'm either creating a library, an executable or neither. |
|---|
| 743 |
|
|---|
| 744 |
// If a target name was supplied in a pragma, use that as the |
|---|
| 745 |
// default target name. |
|---|
| 746 |
if (vPragmaTargetName.length != 0) |
|---|
| 747 |
vTargetName = vPragmaTargetName; |
|---|
| 748 |
|
|---|
| 749 |
// If a target name was supplied on the command line, use that |
|---|
| 750 |
// instead of the default name. |
|---|
| 751 |
if (vCommandTargetName.length != 0) |
|---|
| 752 |
{ |
|---|
| 753 |
char[] lBaseName; |
|---|
| 754 |
|
|---|
| 755 |
lBaseName = vTargetName.dup; |
|---|
| 756 |
for(int i = lBaseName.length-1; i >= 0; i--) |
|---|
| 757 |
{ |
|---|
| 758 |
if (lBaseName[i] == '.') |
|---|
| 759 |
{ |
|---|
| 760 |
lBaseName.length = i; |
|---|
| 761 |
break; |
|---|
| 762 |
} |
|---|
| 763 |
} |
|---|
| 764 |
vTargetName = Expand(vCommandTargetName, "Target=" ~ lBaseName); |
|---|
| 765 |
} |
|---|
| 766 |
|
|---|
| 767 |
// Ensure that the path to the target's location will exist. |
|---|
| 768 |
util.pathex.MakePath(vTargetName); |
|---|
| 769 |
|
|---|
| 770 |
|
|---|
| 771 |
if (vLibraryAction == LibOpt.Build) |
|---|
| 772 |
// Target is a library. |
|---|
| 773 |
lTargetName = ReplaceExtention(vTargetName, kLibExtention); |
|---|
| 774 |
|
|---|
| 775 |
else if (vNoLink == False) |
|---|
| 776 |
{ |
|---|
| 777 |
if (Source.WasMainFound) |
|---|
| 778 |
if (Source.WasMainDLL) |
|---|
| 779 |
// Target is a shared library. |
|---|
| 780 |
lTargetName = ReplaceExtention(vTargetName, kShrLibExtention); |
|---|
| 781 |
else |
|---|
| 782 |
{ |
|---|
| 783 |
// Target is an executable |
|---|
| 784 |
lTargetName = ReplaceExtention(vTargetName, kExeExtention); |
|---|
| 785 |
vTargetExe = lTargetName; |
|---|
| 786 |
} |
|---|
| 787 |
else |
|---|
| 788 |
{ |
|---|
| 789 |
// Possible error. The user wants to link but no 'main' detected |
|---|
| 790 |
// so assume they know what they are doing and also assume an |
|---|
| 791 |
// executable is required. |
|---|
| 792 |
lTargetName = ReplaceExtention(vTargetName, kExeExtention); |
|---|
| 793 |
vTargetExe = lTargetName; |
|---|
| 794 |
} |
|---|
| 795 |
} |
|---|
| 796 |
else |
|---|
| 797 |
// Not linking and not archiving, so no target is required. |
|---|
| 798 |
lTargetName = ""; |
|---|
| 799 |
|
|---|
| 800 |
if (lTargetName.length > 0) |
|---|
| 801 |
{ |
|---|
| 802 |
// Get the full name of the target's location. |
|---|
| 803 |
lTargetName = util.pathex.CanonicalPath(lTargetName, false); |
|---|
| 804 |
lTargetDir = getDirName(lTargetName); |
|---|
| 805 |
|
|---|
| 806 |
// Show user if required to. |
|---|
| 807 |
if((vVerbose == True) || (vNames == True) ) { |
|---|
| 808 |
writefln("\nBuilding target '%s'", lTargetName); |
|---|
| 809 |
} |
|---|
| 810 |
|
|---|
| 811 |
// Shorten the target name for future usages. |
|---|
| 812 |
lTargetName = util.pathex.AbbreviateFileName(lTargetName); |
|---|
| 813 |
|
|---|
| 814 |
|
|---|
| 815 |
// If the target doesn't exist or it is older than |
|---|
| 816 |
// most recently modified dependant file, we need to |
|---|
| 817 |
// rebuild the target. |
|---|
| 818 |
lTargetTime = util.fdt.GetFileTime (lTargetName); |
|---|
| 819 |
if(vVerbose == True) { |
|---|
| 820 |
writefln("Time %s for %s (target)", lTargetTime.toString(), lTargetName); |
|---|
| 821 |
writefln("Time %s (most recent)", lMostRecentTime.toString()); |
|---|
| 822 |
} |
|---|
| 823 |
if(lTargetTime < lMostRecentTime) { |
|---|
| 824 |
lBuildRequired = True; |
|---|
| 825 |
} |
|---|
| 826 |
} |
|---|
| 827 |
else if((vVerbose == True) || (vNames == True) ) { |
|---|
| 828 |
writefln("\nCompiling only. No target will be built."); |
|---|
| 829 |
} |
|---|
| 830 |
|
|---|
| 831 |
// Run any external tools referenced in the source files. |
|---|
| 832 |
foreach( ExternRef lRef; vExternals) |
|---|
| 833 |
{ |
|---|
| 834 |
lRunResult = ProcessExternal( lRef ); |
|---|
| 835 |
if (lRunResult != 0) |
|---|
| 836 |
// If an external tool fails, stop immediately. |
|---|
| 837 |
return lRunResult; |
|---|
| 838 |
} |
|---|
| 839 |
|
|---|
| 840 |
if (Source.SourceIndex.length == 0) |
|---|
| 841 |
{ |
|---|
| 842 |
/* It is possible to only have object and library |
|---|
| 843 |
files on the command line, in which case we |
|---|
| 844 |
just need to link them rather than compile. |
|---|
| 845 |
*/ |
|---|
| 846 |
|
|---|
| 847 |
// No files to compile, just link files, so collect |
|---|
| 848 |
// all the object files to link in. |
|---|
| 849 |
foreach( char[] lFileName; vLinkFiles.keys) |
|---|
| 850 |
{ |
|---|
| 851 |
// Only include OBJECT files. |
|---|
| 852 |
if (util.str.ends(lFileName , kObjExtention) == True) |
|---|
| 853 |
lFilesToLink ~= lFileName; |
|---|
| 854 |
} |
|---|
| 855 |
} |
|---|
| 856 |
else foreach (int i, char[] lFileName; Source.ScanOrder) |
|---|
| 857 |
{ |
|---|
| 858 |
// Check each source to see if we need to recompile it. |
|---|
| 859 |
Source lCurrentSource; |
|---|
| 860 |
Bool lNeedsCompiling; |
|---|
| 861 |
char[] lShortFileName; |
|---|
| 862 |
char[] lFileType; |
|---|
| 863 |
|
|---|
| 864 |
lNeedsCompiling = vForceCompile; |
|---|
| 865 |
|
|---|
| 866 |
lCurrentSource = Source.SourceIndex[lFileName]; |
|---|
| 867 |
if (lCurrentSource.Ignore) |
|---|
| 868 |
continue; |
|---|
| 869 |
|
|---|
| 870 |
lShortFileName = util.pathex.AbbreviateFileName(lFileName); |
|---|
| 871 |
lFileType = std.path.getExt(lShortFileName); |
|---|
| 872 |
if (lFileType != kSrcExtention && lFileType != kDdocExtention) |
|---|
| 873 |
continue; |
|---|
| 874 |
|
|---|
| 875 |
// Only source files are examined from here on. |
|---|
| 876 |
if (lCurrentSource.NoLink || lFileType == kDdocExtention) |
|---|
| 877 |
{ |
|---|
| 878 |
lNonLinkingSources ~= lCurrentSource; |
|---|
| 879 |
} |
|---|
| 880 |
|
|---|
| 881 |
if(lCurrentSource.FilesTime > lCurrentSource.ObjectsTime) |
|---|
| 882 |
{ |
|---|
| 883 |
if (vVerbose == True) |
|---|
| 884 |
writefln("%s newer than its object file", lShortFileName); |
|---|
| 885 |
lNeedsCompiling = True; |
|---|
| 886 |
|
|---|
| 887 |
} else if(lCurrentSource.DependantsTime > lCurrentSource.ObjectsTime) { |
|---|
| 888 |
if (vVerbose == True) |
|---|
| 889 |
writefln("%s has newer dependants than its object file.", |
|---|
| 890 |
lShortFileName); |
|---|
| 891 |
|
|---|
| 892 |
lNeedsCompiling = True; |
|---|
| 893 |
} |
|---|
| 894 |
|
|---|
| 895 |
if(lNeedsCompiling == True) |
|---|
| 896 |
{ |
|---|
| 897 |
lBuildRequired = True; |
|---|
| 898 |
lCompiling = True; |
|---|
| 899 |
lFilesToCompile ~= lShortFileName; |
|---|
| 900 |
|
|---|
| 901 |
// Check to see if I'm allowed to link this file. |
|---|
| 902 |
if (lCurrentSource.NoLink == false) |
|---|
| 903 |
lFilesToLink ~= util.pathex.AbbreviateFileName(lCurrentSource.ObjectName); |
|---|
| 904 |
|
|---|
| 905 |
if (vTestRun == False) |
|---|
| 906 |
{ |
|---|
| 907 |
if (lCurrentSource.IncrementBuildNumber()) |
|---|
| 908 |
{ |
|---|
| 909 |
if (vVerbose == True) |
|---|
| 910 |
writefln("New build number %d for %s", |
|---|
| 911 |
lCurrentSource.BuildNumber, |
|---|
| 912 |
lCurrentSource.ModuleName); |
|---|
| 913 |
|
|---|
| 914 |
} |
|---|
| 915 |
} |
|---|
| 916 |
} |
|---|
| 917 |
else if (lCurrentSource.NoLink == false) |
|---|
| 918 |
{ |
|---|
| 919 |
lFilesToLink ~= util.pathex.AbbreviateFileName(lCurrentSource.ObjectName); |
|---|
| 920 |
} |
|---|
| 921 |
|
|---|
| 922 |
} |
|---|
| 923 |
|
|---|
| 924 |
if( lBuildRequired == False ) |
|---|
| 925 |
{ |
|---|
| 926 |
if (vSilent == False) |
|---|
| 927 |
writefln ("Files are up to date, no build required."); |
|---|
| 928 |
return 0; |
|---|
| 929 |
} |
|---|
| 930 |
|
|---|
| 931 |
foreach(char[] lFileName; lFilesToCompile) |
|---|
| 932 |
{ |
|---|
| 933 |
lSourcesToCompile ~= util.str.enquote(lFileName) ~ "\n"; |
|---|
| 934 |
} |
|---|
| 935 |
|
|---|
| 936 |
// Construct a Optlink Definition file if requested to. |
|---|
| 937 |
version(Windows) |
|---|
| 938 |
{ |
|---|
| 939 |
if (Source.WasMainGUI) { |
|---|
| 940 |
AddBuildDef("EXETYPE NT"); |
|---|
| 941 |
if (vWinVer.length != 0) |
|---|
| 942 |
AddBuildDef("SUBSYSTEM WINDOWS," ~ vWinVer); |
|---|
| 943 |
else |
|---|
| 944 |
AddBuildDef("SUBSYSTEM WINDOWS"); |
|---|
| 945 |
vDefaultLibs ~= "gdi32.lib"; |
|---|
| 946 |
} |
|---|
| 947 |
else if (Source.WasMainDLL) { |
|---|
| 948 |
AddBuildDef(`LIBRARY "` ~ std.path.getBaseName(lTargetName) ~ `"`); |
|---|
| 949 |
AddBuildDef("EXETYPE NT"); |
|---|
| 950 |
if (vWinVer.length != 0) |
|---|
| 951 |
AddBuildDef("SUBSYSTEM WINDOWS," ~ vWinVer); |
|---|
| 952 |
else |
|---|
| 953 |
AddBuildDef("SUBSYSTEM WINDOWS"); |
|---|
| 954 |
AddBuildDef("CODE PRELOAD DISCARDABLE SHARED EXECUTE"); |
|---|
| 955 |
AddBuildDef("DATA PRELOAD SINGLE WRITE"); |
|---|
| 956 |
} |
|---|
| 957 |
else if (vConsoleApp == True) { |
|---|
| 958 |
AddBuildDef(`EXETYPE DOS`); |
|---|
| 959 |
} |
|---|
| 960 |
|
|---|
| 961 |
if ((vNoDef == False) && (vBuildDef.length > 0)) |
|---|
| 962 |
{ |
|---|
| 963 |
lDefName = ReplaceExtention(lTargetName, "def"); |
|---|
| 964 |
if (vTemporaryPath.length != 0) |
|---|
| 965 |
{ |
|---|
| 966 |
lDefName = vTemporaryPath ~ std.path.getBaseName(lDefName); |
|---|
| 967 |
} |
|---|
| 968 |
lDefName = util.pathex.AbbreviateFileName(lDefName); |
|---|
| 969 |
util.fileex.CreateTextFile(lDefName, vBuildDef); |
|---|
| 970 |
|
|---|
| 971 |
} |
|---|
| 972 |
} |
|---|
| 973 |
|
|---|
| 974 |
version(Posix) |
|---|
| 975 |
{ |
|---|
| 976 |
vDefaultLibs ~= "c"; |
|---|
| 977 |
} |
|---|
| 978 |
// Add any library or external obj files required. |
|---|
| 979 |
if (lLinking == True) |
|---|
| 980 |
{ |
|---|
| 981 |
lLibraryFiles.length = 0; |
|---|
| 982 |
|
|---|
| 983 |
foreach (char[] lFileName; vLinkFiles.keys) |
|---|
| 984 |
{ |
|---|
| 985 |
char[] lCmdItem; |
|---|
| 986 |
|
|---|
| 987 |
if (lFileName.length > 0) |
|---|
| 988 |
{ |
|---|
| 989 |
lCmdItem = lFileName; |
|---|
| 990 |
if ( util.str.ends(lCmdItem, "." ~ kLibExtention) == True) |
|---|
| 991 |
{ |
|---|
| 992 |
// Cut off extention. |
|---|
| 993 |
lCmdItem.length = lCmdItem.length - kLibExtention.length - 1; |
|---|
| 994 |
// lPrefix = "-L-l"; // Needed for linker to find the library. |
|---|
| 995 |
lLibraryFiles ~= lCmdItem; |
|---|
| 996 |
} |
|---|
| 997 |
else |
|---|
| 998 |
{ |
|---|
| 999 |
lFilesToLink ~= lCmdItem; |
|---|
| 1000 |
} |
|---|
| 1001 |
} |
|---|
| 1002 |
} |
|---|
| 1003 |
} |
|---|
| 1004 |
|
|---|
| 1005 |
if ((lLinking == True) || (lCompiling == True)) |
|---|
| 1006 |
{ |
|---|
| 1007 |
// COMPILE phase ... |
|---|
| 1008 |
if (lSourcesToCompile.length > 0) |
|---|
| 1009 |
{ |
|---|
| 1010 |
// Ok, I have some compiling to do! |
|---|
| 1011 |
char[] lCommandLine; |
|---|
| 1012 |
|
|---|
| 1013 |
lCommandLine = GatherCompilerArgs(lLinking) ~ lSourcesToCompile; |
|---|
| 1014 |
|
|---|
| 1015 |
if (vUseResponseFile == True) |
|---|
| 1016 |
{ |
|---|
| 1017 |
lDResponseFileName = ReplaceExtention(lTargetName, "rsp"); |
|---|
| 1018 |
if (vTemporaryPath.length != 0) |
|---|
| 1019 |
{ |
|---|
| 1020 |
lDResponseFileName = vTemporaryPath ~ std.path.getBaseName(lDResponseFileName); |
|---|
| 1021 |
} |
|---|
| 1022 |
lDResponseFileName = util.pathex.AbbreviateFileName(lDResponseFileName); |
|---|
| 1023 |
util.fileex.CreateTextFile(lDResponseFileName,lCommandLine); |
|---|
| 1024 |
lCommand = vCompilerPath ~ vCompilerExe ~ vCompileOnlySwitch ~ " @" ~ lDResponseFileName; |
|---|
| 1025 |
} |
|---|
| 1026 |
else |
|---|
| 1027 |
{ // using commandline; may run into limits |
|---|
| 1028 |
lCommandLine=std.string.replace(lCommandLine, "\n", " "); |
|---|
| 1029 |
lCommand = vCompilerPath ~ vCompilerExe ~ vCompileOnlySwitch ~ " " ~ lCommandLine; |
|---|
| 1030 |
} |
|---|
| 1031 |
|
|---|
| 1032 |
if (vVerbose == True) { |
|---|
| 1033 |
writefln("Compiling with ..........\n%s\n", lCommandLine); |
|---|
| 1034 |
} |
|---|
| 1035 |
|
|---|
| 1036 |
// Run Compiler to compile the source files that need it. |
|---|
| 1037 |
lRunResult = RunCommand(lCommand); |
|---|
| 1038 |
if (lRunResult != 0) |
|---|
| 1039 |
vExecuteProgram = False; |
|---|
| 1040 |
} |
|---|
| 1041 |
|
|---|
| 1042 |
// LINK phase ... |
|---|
| 1043 |
if ( (lRunResult == 0) && (lFilesToLink.length > 0) && (lLinking == True)) |
|---|
| 1044 |
{ |
|---|
| 1045 |
char[] lCommandLine; |
|---|
| 1046 |
char[] lLinkerSwitches; |
|---|
| 1047 |
Bool IsMapping = False; |
|---|
| 1048 |
|
|---|
| 1049 |
// Build the command line for the linker. |
|---|
| 1050 |
lCommandLine = ""; |
|---|
| 1051 |
version(Windows) |
|---|
| 1052 |
{ |
|---|
| 1053 |
// Transfer linker switches from Compiler switches. |
|---|
| 1054 |
foreach (char[] lCompileArg; vCompilerArgs) |
|---|
| 1055 |
{ |
|---|
| 1056 |
if (util.str.begins(lCompileArg, "-L") == True) |
|---|
| 1057 |
{ |
|---|
| 1058 |
lLinkerSwitches ~= lCompileArg[2..$]; |
|---|
| 1059 |
} |
|---|
| 1060 |
} |
|---|
| 1061 |
foreach( char[] lSwitch; std.string.split(vLinkerDefSwitches ~ lLinkerSwitches, "/")) |
|---|
| 1062 |
{ |
|---|
| 1063 |
if (lSwitch == "nomap") |
|---|
| 1064 |
{ |
|---|
| 1065 |
IsMapping = False; |
|---|
| 1066 |
} |
|---|
| 1067 |
else if (lSwitch == "map") |
|---|
| 1068 |
{ |
|---|
| 1069 |
IsMapping = True; |
|---|
| 1070 |
} |
|---|
| 1071 |
} |
|---|
| 1072 |
|
|---|
| 1073 |
// (1) Gather the object file names |
|---|
| 1074 |
foreach(char[] lFile; lFilesToLink) |
|---|
| 1075 |
{ |
|---|
| 1076 |
lCommandLine ~= lFile ~ "+"; |
|---|
| 1077 |
} |
|---|
| 1078 |
if (lCommandLine.length > 0) |
|---|
| 1079 |
lCommandLine[$-1] = '\n'; |
|---|
| 1080 |
|
|---|
| 1081 |
// (2) Set the output file name |
|---|
| 1082 |
lCommandLine ~= util.str.enquote(util.pathex.AbbreviateFileName(lTargetName)) ~ "\n"; |
|---|
| 1083 |
|
|---|
| 1084 |
// (3) Set the map name |
|---|
| 1085 |
if (IsMapping == True) |
|---|
| 1086 |
lCommandLine ~= ReplaceExtention(lTargetName, "map"); |
|---|
| 1087 |
|
|---|
| 1088 |
lCommandLine ~= "\n"; |
|---|
| 1089 |
|
|---|
| 1090 |
// (4) Gather the libraries names. |
|---|
| 1091 |
// Include the default libraries first. |
|---|
| 1092 |
lLibraryFiles = vDefaultLibs ~ lLibraryFiles; |
|---|
| 1093 |
if (lLibraryFiles.length > 0) |
|---|
| 1094 |
{ |
|---|
| 1095 |
foreach( char[] lLib; lLibraryFiles) |
|---|
| 1096 |
{ |
|---|
| 1097 |
lCommandLine ~= util.str.enquote(lLib) ~"+"; |
|---|
| 1098 |
} |
|---|
| 1099 |
lCommandLine[$-1] = '\n'; |
|---|
| 1100 |
} |
|---|
| 1101 |
else |
|---|
| 1102 |
lCommandLine ~= "\n"; |
|---|
| 1103 |
|
|---|
| 1104 |
// Include the explictly named libraries. |
|---|
| 1105 |
if (vLibPaths.length > 1) |
|---|
| 1106 |
{ |
|---|
| 1107 |
if (vLibPaths[0..1] == vConfigSep) |
|---|
| 1108 |
vLibPaths = vLibPaths[1..$]; |
|---|
| 1109 |
|
|---|
| 1110 |
// Include the paths to the libraries. |
|---|
| 1111 |
if (vVerbose == True) |
|---|
| 1112 |
writefln("Setting LIB=%s", vLibPaths); |
|---|
| 1113 |
putenv("LIB=" ~ vLibPaths[1..$]); |
|---|
| 1114 |
} |
|---|
| 1115 |
|
|---|
| 1116 |
// (5) Set the 'def' file name |
|---|
| 1117 |
if (lDefName.length > 0) |
|---|
| 1118 |
lCommandLine ~= util.str.enquote(lDefName) ~ "\n"; |
|---|
| 1119 |
else |
|---|
| 1120 |
lCommandLine ~= "\n"; |
|---|
| 1121 |
|
|---|
| 1122 |
// (6) Gather the resource file names |
|---|
| 1123 |
|
|---|
| 1124 |
// (7) Gather then switches |
|---|
| 1125 |
lCommandLine ~= vLinkerDefSwitches; |
|---|
| 1126 |
lCommandLine ~= lLinkerSwitches; |
|---|
| 1127 |
lCommandLine ~= "\n"; |
|---|
| 1128 |
} |
|---|
| 1129 |
|
|---|
| 1130 |
version(Posix) |
|---|
| 1131 |
{ |
|---|
| 1132 |
// Transfer linker switches from Compiler switches. |
|---|
| 1133 |
foreach (char[] lCompileArg; vCompilerArgs) |
|---|
| 1134 |
{ |
|---|
| 1135 |
if (util.str.begins(lCompileArg, "-L") == True) |
|---|
| 1136 |
{ |
|---|
| 1137 |
lLinkerSwitches ~= lCompileArg[2..$]; |
|---|
| 1138 |
} |
|---|
| 1139 |
} |
|---|
| 1140 |
foreach( char[] lSwitch; std.string.split(vLinkerDefSwitches ~ lLinkerSwitches, "/")) |
|---|
| 1141 |
{ |
|---|
| 1142 |
if (lSwitch == "nomap") |
|---|
| 1143 |
{ |
|---|
| 1144 |
IsMapping = False; |
|---|
| 1145 |
} |
|---|
| 1146 |
else if (lSwitch == "map") |
|---|
| 1147 |
{ |
|---|
| 1148 |
IsMapping = True; |
|---|
| 1149 |
} |
|---|
| 1150 |
} |
|---|
| 1151 |
|
|---|
| 1152 |
// (1) Gather the object file names |
|---|
| 1153 |
foreach(char[] lFile; lFilesToLink) |
|---|
| 1154 |
{ |
|---|
| 1155 |
lCommandLine ~= lFile ~ "\n"; |
|---|
| 1156 |
} |
|---|
| 1157 |
|
|---|
| 1158 |
// (2) Set the output file name |
|---|
| 1159 |
lCommandLine ~= vLinkOutputSwitch ~ util.str.enquote(util.pathex.AbbreviateFileName(lTargetName)) ~ "\n"; |
|---|
| 1160 |
|
|---|
| 1161 |
// (3) Set the map name |
|---|
| 1162 |
if (IsMapping == True) |
|---|
| 1163 |
lCommandLine ~= "-M\n"; |
|---|
| 1164 |
|
|---|
| 1165 |
// (4) Gather the libraries names. |
|---|
| 1166 |
// Include the default libraries first. |
|---|
| 1167 |
foreach( char[] lLib; vDefaultLibs ~ lLibraryFiles) |
|---|
| 1168 |
{ |
|---|
| 1169 |
lCommandLine ~= vLinkLibSwitch ~ util.str.enquote(lLib) ~ "\n"; |
|---|
| 1170 |
} |
|---|
| 1171 |
|
|---|
| 1172 |
if (vLibPaths.length > 1) |
|---|
| 1173 |
{ |
|---|
| 1174 |
if (vLibPaths[0..1] == vConfigSep) |
|---|
| 1175 |
vLibPaths = vLibPaths[1..$]; |
|---|
| 1176 |
|
|---|
| 1177 |
// Include the paths to the libraries. |
|---|
| 1178 |
if (vVerbose == True) |
|---|
| 1179 |
writefln("Setting LIB=%s", vLibPaths); |
|---|
| 1180 |
char[][] lLibPaths; |
|---|
| 1181 |
lLibPaths = std.string.split(vLibPaths, vConfigSep); |
|---|
| 1182 |
foreach(char[] lLib; lLibPaths) |
|---|
| 1183 |
{ |
|---|
| 1184 |
if (lLib.length > 0) |
|---|
| 1185 |
lCommandLine ~= "-L" ~ util.str.enquote(lLib) ~ "\n"; |
|---|
| 1186 |
} |
|---|
| 1187 |
} |
|---|
| 1188 |
|
|---|
| 1189 |
// (4) Gather then switches |
|---|
| 1190 |
lCommandLine ~= vLinkerDefSwitches; |
|---|
| 1191 |
lCommandLine ~= lLinkerSwitches; |
|---|
| 1192 |
lCommandLine ~= "\n"; |
|---|
| 1193 |
} |
|---|
| 1194 |
|
|---|
| 1195 |
if (vUseResponseFile == True) |
|---|
| 1196 |
{ |
|---|
| 1197 |
lLinkResponseFileName = ReplaceExtention(lTargetName, "ksp"); |
|---|
| 1198 |
if (vTemporaryPath.length != 0) |
|---|
| 1199 |
{ |
|---|
| 1200 |
lLinkResponseFileName = vTemporaryPath ~ std.path.getBaseName(lLinkResponseFileName); |
|---|
| 1201 |
} |
|---|
| 1202 |
lLinkResponseFileName = util.pathex.AbbreviateFileName(lLinkResponseFileName); |
|---|
| 1203 |
util.fileex.CreateTextFile(lLinkResponseFileName,lCommandLine); |
|---|
| 1204 |
lCommand = vLinkerPath ~ vLinkerExe ~ " @" ~ lLinkResponseFileName; |
|---|
| 1205 |
} |
|---|
| 1206 |
else |
|---|
| 1207 |
{ // using commandline; may run into limits |
|---|
| 1208 |
lCommandLine=std.string.replace(lCommandLine, "\n", " "); |
|---|
| 1209 |
lCommand = vLinkerPath ~ vLinkerExe ~ " " ~ lCommandLine; |
|---|
| 1210 |
} |
|---|
| 1211 |
|
|---|
| 1212 |
if (vVerbose == True) { |
|---|
| 1213 |
writefln("Linking with ..........\n%s\n", lCommandLine); |
|---|
| 1214 |
} |
|---|
| 1215 |
|
|---|
| 1216 |
// Run Linker |
|---|
| 1217 |
if (vSilent == True) |
|---|
| 1218 |
{ |
|---|
| 1219 |
version(Posix) lCommand ~= " >/dev/null"; |
|---|
| 1220 |
version(Windows) lCommand ~= " >nul"; |
|---|
| 1221 |
} |
|---|
| 1222 |
|
|---|
| 1223 |
lRunResult = RunCommand(lCommand); |
|---|
| 1224 |
if (lRunResult != 0) |
|---|
| 1225 |
vExecuteProgram = False; |
|---|
| 1226 |
} |
|---|
| 1227 |
|
|---|
| 1228 |
} |
|---|
| 1229 |
else |
|---|
| 1230 |
{ |
|---|
| 1231 |
if (vSilent == False) |
|---|
| 1232 |
writefln("No build required."); |
|---|
| 1233 |
lRunResult = 0; |
|---|
| 1234 |
} |
|---|
| 1235 |
|
|---|
| 1236 |
// Now build a library if requested to. |
|---|
| 1237 |
if ( (Source.WasMainDLL) && (lRunResult == 0) ) |
|---|
| 1238 |
{ |
|---|
| 1239 |
char[] lTargetFileName; |
|---|
| 1240 |
char[] lImpLibPath; |
|---|
| 1241 |
ulong[] lImpManf; |
|---|
| 1242 |
|
|---|
| 1243 |
vExecuteProgram = False; |
|---|
| 1244 |
|
|---|
| 1245 |
lImpLibPath = util.pathex.LocateFile("implib.exe", GetEnv(kPathId)); |
|---|
| 1246 |
if (util.fileex.FileExists(lImpLibPath)) |
|---|
| 1247 |
{ |
|---|
| 1248 |
lImpManf = util.fileex.FindInFile(lImpLibPath, "Borland"); |
|---|
| 1249 |
if (lImpManf.length != 0) |
|---|
| 1250 |
lImpLibPath ~= " -a "; |
|---|
| 1251 |
else |
|---|
| 1252 |
lImpLibPath ~= " /system "; |
|---|
| 1253 |
|
|---|
| 1254 |
lTargetFileName = std.path.getBaseName(lTargetName); |
|---|
| 1255 |
lRunResult = RunCommand(lImpLibPath ~ std.path.addExt(lTargetFileName, "lib") |
|---|
| 1256 |
~ " " ~ std.path.addExt(lTargetFileName, "dll") ); |
|---|
| 1257 |
} |
|---|
| 1258 |
} |
|---|
| 1259 |
else if ( (vLibraryAction == LibOpt.Build) && (lRunResult == 0)) |
|---|
| 1260 |
{ |
|---|
| 1261 |
int lFileCount; |
|---|
| 1262 |
|
|---|
| 1263 |
vExecuteProgram = False; |
|---|
| 1264 |
|
|---|
| 1265 |
lOutText = vLibrarianOpts ~ std.path.linesep; |
|---|
| 1266 |
lOutText ~= lTargetName ~ std.path.linesep; // Create a new library |
|---|
| 1267 |
|
|---|
| 1268 |
foreach( char[] lFileName; lFilesToLink) |
|---|
| 1269 |
{ |
|---|
| 1270 |
char[] lFileDir; |
|---|
| 1271 |
|
|---|
| 1272 |
lFileDir = getDirName(lFileName); |
|---|
| 1273 |
if ((vAllObjects == True) || lFileDir == "" || lFileDir == lTargetDir) |
|---|
| 1274 |
{ |
|---|
| 1275 |
if (lFileName.length > 1 + kSrcExtention.length) |
|---|
| 1276 |
{ |
|---|
| 1277 |
if (lFileName[$-kSrcExtention.length .. $] == kSrcExtention) |
|---|
| 1278 |
{ |
|---|
| 1279 |
lFileName = lFileName[0..$-kSrcExtention.length] ~ kObjExtention; |
|---|
| 1280 |
} |
|---|
| 1281 |
} |
|---|
| 1282 |
lFileCount++; |
|---|
| 1283 |
lOutText ~= lFileName ~ std.path.linesep; |
|---|
| 1284 |
} |
|---|
| 1285 |
} |
|---|
| 1286 |
|
|---|
| 1287 |
if (lFileCount > 0) |
|---|
| 1288 |
{ |
|---|
| 1289 |
if (vUseResponseFile == True) { |
|---|
| 1290 |
lLResponseFileName = ReplaceExtention(lTargetName, "lsp"); |
|---|
| 1291 |
if (vTemporaryPath.length != 0) |
|---|
| 1292 |
{ |
|---|
| 1293 |
lLResponseFileName = vTemporaryPath ~ std.path.getBaseName(lLResponseFileName); |
|---|
| 1294 |
} |
|---|
| 1295 |
util.fileex.CreateTextFile(lLResponseFileName,lOutText); |
|---|
| 1296 |
lCommand = vLibrarianPath ~ vLibrarian ~ " @" ~ lLResponseFileName; |
|---|
| 1297 |
} |
|---|
| 1298 |
else |
|---|
| 1299 |
{ // using commandline, may run into limits |
|---|
| 1300 |
lCommand = vLibrarianPath ~ vLibrarian ~ " " ~ std.string.replace(lOutText,std.path.linesep," "); |
|---|
| 1301 |
} |
|---|
| 1302 |
|
|---|
| 1303 |
if (vVerbose == True) { |
|---|
| 1304 |
writefln("Librarian with ..........\n%s\n", lOutText); |
|---|
| 1305 |
} |
|---|
| 1306 |
|
|---|
| 1307 |
lRunResult = RunCommand(lCommand); |
|---|
| 1308 |
} |
|---|
| 1309 |
} |
|---|
| 1310 |
|
|---|
| 1311 |
// Optional clean up. |
|---|
| 1312 |
if (vCleanup == True) |
|---|
| 1313 |
{ |
|---|
| 1314 |
char[][] lHitList; |
|---|
| 1315 |
|
|---|
| 1316 |
if (vVerbose == True) { |
|---|
| 1317 |
writefln("Cleaning up ..."); |
|---|
| 1318 |
} |
|---|
| 1319 |
foreach(char[] lFileName; Source.ScanOrder) |
|---|
| 1320 |
{ |
|---|
| 1321 |
Source lSource; |
|---|
| 1322 |
lSource = Source.SourceIndex[lFileName]; |
|---|
| 1323 |
if (lSource.Ignore) |
|---|
| 1324 |
continue; |
|---|
| 1325 |
|
|---|
| 1326 |
if (lSource.ObjectName.length > 0) |
|---|
| 1327 |
{ |
|---|
| 1328 |
lHitList ~= lSource.ObjectName; |
|---|
| 1329 |
} |
|---|
| 1330 |
} |
|---|
| 1331 |
|
|---|
| 1332 |
// Build's own temprary files. |
|---|
| 1333 |
lHitList ~= lDResponseFileName; |
|---|
| 1334 |
lHitList ~= lLinkResponseFileName; |
|---|
| 1335 |
lHitList ~= lLResponseFileName; |
|---|
| 1336 |
lHitList ~= lDefName; |
|---|
| 1337 |
|
|---|
| 1338 |
// Possible ones created by compiler, linker, and librarian. |
|---|
| 1339 |
lHitList ~= ReplaceExtention(lTargetName, "map"); |
|---|
| 1340 |
lHitList ~= ReplaceExtention(lTargetName, "bak"); |
|---|
| 1341 |
lHitList ~= ReplaceExtention(lTargetName, "lst"); |
|---|
| 1342 |
|
|---|
| 1343 |
foreach(char[] lFilename; lHitList) |
|---|
| 1344 |
{ |
|---|
| 1345 |
if (lFilename.length > 0) |
|---|
| 1346 |
{ |
|---|
| 1347 |
if (util.fileex.FileExists( lFilename ) ) |
|---|
| 1348 |
{ |
|---|
| 1349 |
if (vVerbose == True) { |
|---|
| 1350 |
writefln(" removing %s", lFilename); |
|---|
| 1351 |
} |
|---|
| 1352 |
std.file.remove(lFilename); |
|---|
| 1353 |
} |
|---|
| 1354 |
} |
|---|
| 1355 |
} |
|---|
| 1356 |
|
|---|
| 1357 |
} |
|---|
| 1358 |
|
|---|
| 1359 |
return lRunResult; |
|---|
| 1360 |
|
|---|
| 1361 |
} |
|---|
| 1362 |
|
|---|
| 1363 |
// ------------------------------------------- |
|---|
| 1364 |
char [] GatherCompilerArgs(Bool pLinking) |
|---|
| 1365 |
// ------------------------------------------- |
|---|
| 1366 |
{ |
|---|
| 1367 |
char[] lOutText; |
|---|
| 1368 |
|
|---|
| 1369 |
foreach(char [] lRoot; vImportRoots) |
|---|
| 1370 |
{ |
|---|
| 1371 |
version(Posix) |
|---|
| 1372 |
vDefaultCompArgs ~= vImportPathSwitch ~ "\"" ~ lRoot ~ "\""; |
|---|
| 1373 |
else |
|---|
| 1374 |
vDefaultCompArgs ~= vImportPathSwitch ~ lRoot; |
|---|
| 1375 |
} |
|---|
| 1376 |
|
|---|
| 1377 |
foreach(char[] lArg; vDefaultCompArgs) |
|---|
| 1378 |
{ |
|---|
| 1379 |
AddCompilerArg( lArg ); |
|---|
| 1380 |
} |
|---|
| 1381 |
|
|---|
| 1382 |
// Build command files for compilation. |
|---|
| 1383 |
foreach (char[] lCompileArg; vCompilerArgs) |
|---|
| 1384 |
{ |
|---|
| 1385 |
// Ignore empty args |
|---|
| 1386 |
if (lCompileArg.length > 0) |
|---|
| 1387 |
{ |
|---|
| 1388 |
// Enclose in quotes if no quotes are currently present. |
|---|
| 1389 |
if (find(lCompileArg, "\"") == -1) |
|---|
| 1390 |
// Arguments containing a blank need to be quoted. |
|---|
| 1391 |
if (find(lCompileArg, " ") != -1) |
|---|
| 1392 |
{ |
|---|
| 1393 |
// Strip off any trailing shell escape lead-in character. |
|---|
| 1394 |
if (lCompileArg[$-1] == '\\') |
|---|
| 1395 |
lCompileArg.length = lCompileArg.length - 1; |
|---|
| 1396 |
lOutText ~= std.string.format(`"%s"`, lCompileArg); |
|---|
| 1397 |
} |
|---|
| 1398 |
else |
|---|
| 1399 |
lOutText ~= lCompileArg; |
|---|
| 1400 |
else |
|---|
| 1401 |
lOutText ~= lCompileArg; |
|---|
| 1402 |
|
|---|
| 1403 |
// Terminate with a newline char. |
|---|
| 1404 |
lOutText ~= "\n"; |
|---|
| 1405 |
} |
|---|
| 1406 |
} |
|---|
| 1407 |
|
|---|
| 1408 |
if (pLinking == False) |
|---|
| 1409 |
{ // No linking allowed. |
|---|
| 1410 |
if (vNoLinkSwitch.length > 0) |
|---|
| 1411 |
{ |
|---|
| 1412 |
if (find(vNoLinkSwitch, " ") != -1) |
|---|
| 1413 |
lOutText ~= std.string.format(`"%s"`,vNoLinkSwitch); |
|---|
| 1414 |
else |
|---|
| 1415 |
lOutText ~= vNoLinkSwitch; |
|---|
| 1416 |
// Terminate with a newline char. |
|---|
| 1417 |
lOutText ~= "\n"; |
|---|
| 1418 |
|
|---|
| 1419 |
AddCompilerArg( vNoLinkSwitch ); |
|---|
| 1420 |
} |
|---|
| 1421 |
} |
|---|
| 1422 |
|
|---|
| 1423 |
return lOutText; |
|---|
| 1424 |
} |
|---|
| 1425 |
|
|---|
| 1426 |
|
|---|
| 1427 |
// ------------------------------------------- |
|---|
| 1428 |
char[][] ModulesToIgnore() |
|---|
| 1429 |
// ------------------------------------------- |
|---|
| 1430 |
{ |
|---|
| 1431 |
return vModulesToIgnore; |
|---|
| 1432 |
} |
|---|
| 1433 |
|
|---|
| 1434 |
|
|---|
| 1435 |
// ------------------------------------------- |
|---|
| 1436 |
void AddExternal(char[] pPath, char[][] pOpts) |
|---|
| 1437 |
// ------------------------------------------- |
|---|
| 1438 |
{ |
|---|
| 1439 |
if (pPath.length > 0) { |
|---|
| 1440 |
vExternals.length = vExternals.length + 1; |
|---|
| 1441 |
vExternals[$-1].FilePath = pPath; |
|---|
| 1442 |
vExternals[$-1].ToolOpts = pOpts; |
|---|
| 1443 |
if (vVerbose == True) { |
|---|
| 1444 |
writef("Added external file to be built: %s", pPath); |
|---|
| 1445 |
foreach( char[] lOpt; pOpts) |
|---|
| 1446 |
writef(" `%s`", lOpt); |
|---|
| 1447 |
writefln(""); |
|---|
| 1448 |
} |
|---|
| 1449 |
} |
|---|
| 1450 |
} |
|---|
| 1451 |
|
|---|
| 1452 |
// ------------------------------------------- |
|---|
| 1453 |
void AddLink(char[] pPath) |
|---|
| 1454 |
// ------------------------------------------- |
|---|
| 1455 |
{ |
|---|
| 1456 |
if (pPath.length == 0) |
|---|
| 1457 |
return; |
|---|
| 1458 |
if ((pPath in vLinkFiles) is null) |
|---|
| 1459 |
vLinkFiles[pPath] = true; |
|---|
| 1460 |
} |
|---|
| 1461 |
|
|---|
| 1462 |
// ------------------------------------------- |
|---|
| 1463 |
void AddTarget(char[] pPath) |
|---|
| 1464 |
// ------------------------------------------- |
|---|
| 1465 |
{ |
|---|
| 1466 |
if (pPath.length == 0) |
|---|
| 1467 |
return; |
|---|
| 1468 |
|
|---|
| 1469 |
if (vPragmaTargetName.length == 0) |
|---|
| 1470 |
vPragmaTargetName = pPath; |
|---|
| 1471 |
else if (vPragmaTargetName != pPath) { |
|---|
| 1472 |
if (vVerbose == True) { |
|---|
| 1473 |
writefln("Multiple pragma(target,...) detected. '%s' will be used and '%s' rejected.", |
|---|
| 1474 |
vPragmaTargetName, pPath ); |
|---|
| 1475 |
} |
|---|
| 1476 |
} |
|---|
| 1477 |
|
|---|
| 1478 |
} |
|---|
| 1479 |
|
|---|
| 1480 |
// ------------------------------------------- |
|---|
| 1481 |
void AddBuildDef(char[] pText, bool pReplace = false) |
|---|
| 1482 |
// ------------------------------------------- |
|---|
| 1483 |
{ |
|---|
| 1484 |
int lPos; |
|---|
| 1485 |
char[] lLowerText; |
|---|
| 1486 |
static uint[ char[] ] lElementIdx; |
|---|
| 1487 |
|
|---|
| 1488 |
if (vNoDef == True) |
|---|
| 1489 |
return; |
|---|
| 1490 |
|
|---|
| 1491 |
lLowerText = std.string.tolower(pText); |
|---|
| 1492 |
|
|---|
| 1493 |
lPos = std.string.find(lLowerText, ' '); |
|---|
| 1494 |
if (lPos == -1) |
|---|
| 1495 |
lPos = lLowerText.length; |
|---|
| 1496 |
lLowerText.length = lPos; |
|---|
| 1497 |
|
|---|
| 1498 |
if (lLowerText in lElementIdx) |
|---|
| 1499 |
{ |
|---|
| 1500 |
if (pReplace) |
|---|
| 1501 |
vBuildDef[ lElementIdx[lLowerText] ] = pText; |
|---|
| 1502 |
} |
|---|
| 1503 |
else { |
|---|
| 1504 |
vBuildDef ~= pText; |
|---|
| 1505 |
lElementIdx[ lLowerText ] = vBuildDef.length-1; |
|---|
| 1506 |
} |
|---|
| 1507 |
} |
|---|
| 1508 |
|
|---|
| 1509 |
// ------------------------------------------- |
|---|
| 1510 |
void AddCompilerArg(char[] pArg) |
|---|
| 1511 |
// ------------------------------------------- |
|---|
| 1512 |
{ |
|---|
| 1513 |
bool lFound; |
|---|
| 1514 |
|
|---|
| 1515 |
if (pArg.length > 0) |
|---|
| 1516 |
{ |
|---|
| 1517 |
// Translate exported version pragmas. |
|---|
| 1518 |
if (pArg.length > 3) |
|---|
| 1519 |
{ |
|---|
| 1520 |
if (pArg[0..3] == `+v+`) |
|---|
| 1521 |
pArg = vVersionSwitch ~ pArg[3..$]; |
|---|
| 1522 |
} |
|---|
| 1523 |
|
|---|
| 1524 |
lFound = false; |
|---|
| 1525 |
foreach(char[] lArg; vCompilerArgs) |
|---|
| 1526 |
{ |
|---|
| 1527 |
if (lArg == pArg) |
|---|
| 1528 |
{ |
|---|
| 1529 |
lFound = true; |
|---|
| 1530 |
break; |
|---|
| 1531 |
} |
|---|
| 1532 |
} |
|---|
| 1533 |
if (! lFound ) |
|---|
| 1534 |
vCompilerArgs ~= pArg; |
|---|
| 1535 |
} |
|---|
| 1536 |
} |
|---|
| 1537 |
|
|---|
| 1538 |
// ------------------------------------------- |
|---|
| 1539 |
char[] AddRoot(char[] pRootName) |
|---|
| 1540 |
// ------------------------------------------- |
|---|
| 1541 |
{ |
|---|
| 1542 |
static bool [char[]] lRootHash; |
|---|
| 1543 |
char[] lFullName; |
|---|
| 1544 |
char[] lSearchName; |
|---|
| 1545 |
|
|---|
| 1546 |
if(pRootName.length == 0) { |
|---|
| 1547 |
return pRootName; |
|---|
| 1548 |
} |
|---|
| 1549 |
else { |
|---|
| 1550 |
lFullName = util.pathex.CanonicalPath(pRootName); |
|---|
| 1551 |
version(Windows) lSearchName = std.string.tolower(lFullName); |
|---|
| 1552 |
version(Posix) lSearchName = lFullName; |
|---|
| 1553 |
if( !(lSearchName in lRootHash) ) |
|---|
| 1554 |
{ |
|---|
| 1555 |
vImportRoots ~= lFullName; |
|---|
| 1556 |
lRootHash[lSearchName] = true; |
|---|
| 1557 |
return lFullName; |
|---|
| 1558 |
} |
|---|
| 1559 |
else |
|---|
| 1560 |
return ""; |
|---|
| 1561 |
} |
|---|
| 1562 |
} |
|---|
| 1563 |
|
|---|
| 1564 |
Bool AutoImports() |
|---|
| 1565 |
{ |
|---|
| 1566 |
return vAutoImports; |
|---|
| 1567 |
} |
|---|
| 1568 |
|
|---|
| 1569 |
char[][] GetImportRoots() |
|---|
| 1570 |
{ |
|---|
| 1571 |
return vImportRoots; |
|---|
| 1572 |
} |
|---|
| 1573 |
|
|---|
| 1574 |
// function to replace tokens in the form %<SYM>% with environment data. |
|---|
| 1575 |
// ------------------------------------------- |
|---|
| 1576 |
char[] ExpandEnvVar(char[] pLine) |
|---|
| 1577 |
// ------------------------------------------- |
|---|
| 1578 |
{ |
|---|
| 1579 |
char[] lLine; |
|---|
| 1580 |
char[] lSymName; |
|---|
| 1581 |
int lPos; |
|---|
| 1582 |
int lEnd; |
|---|
| 1583 |
|
|---|
| 1584 |
lLine.length = 0; |
|---|
| 1585 |
for( lPos = 0; lPos < pLine.length; lPos++ ) |
|---|
| 1586 |
{ |
|---|
| 1587 |
if (pLine[lPos] == '%') |
|---|
| 1588 |
{ |
|---|
| 1589 |
lSymName.length = 0; |
|---|
| 1590 |
for(lEnd = lPos+1; (lEnd < pLine.length) && (pLine[lEnd] != '%'); lEnd++ ) |
|---|
| 1591 |
{ |
|---|
| 1592 |
lSymName ~= pLine[lEnd]; |
|---|
| 1593 |
} |
|---|
| 1594 |
if (lSymName.length > 0) |
|---|
| 1595 |
{ |
|---|
| 1596 |
if (lSymName == "@P") |
|---|
| 1597 |
{ |
|---|
| 1598 |
// Special symbol that refers to the DMD configuration file's directory. |
|---|
| 1599 |
lSymName = (vConfigPath ? vConfigPath[0..length-1] : ""); |
|---|
| 1600 |
} |
|---|
| 1601 |
else if (lSymName == "@D") |
|---|
| 1602 |
{ |
|---|
| 1603 |
// Special symbol that refers to the compiler's file's directory. |
|---|
| 1604 |
lSymName = (vCompilerPath ? vCompilerPath[0..length-1] : ""); |
|---|
| 1605 |
} |
|---|
| 1606 |
else |
|---|
| 1607 |
{ |
|---|
| 1608 |
lSymName = (GetEnv(std.utf.toUTF8(lSymName))); |
|---|
| 1609 |
} |
|---|
| 1610 |
lLine ~= lSymName; |
|---|
| 1611 |
} |
|---|
| 1612 |
lPos = lEnd; |
|---|
| 1613 |
} |
|---|
| 1614 |
else |
|---|
| 1615 |
{ |
|---|
| 1616 |
lLine ~= pLine[lPos]; |
|---|
| 1617 |
} |
|---|
| 1618 |
} |
|---|
| 1619 |
return lLine; |
|---|
| 1620 |
} |
|---|
| 1621 |
|
|---|
| 1622 |
void Process_DFLAGS(char[] pText) |
|---|
| 1623 |
{ |
|---|
| 1624 |
int lPos; |
|---|
| 1625 |
int lEndPos; |
|---|
| 1626 |
char[] lRootName; |
|---|
| 1627 |
char[][] lRoots; |
|---|
| 1628 |
char[][] lArgs; |
|---|
| 1629 |
int lArg; |
|---|
| 1630 |
bool lInArg; |
|---|
| 1631 |
char lQuote; |
|---|
| 1632 |
|
|---|
| 1633 |
lInArg = false; |
|---|
| 1634 |
lArg = -1; |
|---|
| 1635 |
lQuote = 0; |
|---|
| 1636 |
foreach (char lArgChar; pText) |
|---|
| 1637 |
{ |
|---|
| 1638 |
if ( (lArgChar == '"') || (lArgChar == '\'') ) |
|---|
| 1639 |
{ |
|---|
| 1640 |
if (lQuote == lArgChar) |
|---|
| 1641 |
{ |
|---|
| 1642 |
lQuote = 0; |
|---|
| 1643 |
continue; |
|---|
| 1644 |
} |
|---|
| 1645 |
|
|---|
| 1646 |
if (lQuote == 0) |
|---|
| 1647 |
{ |
|---|
| 1648 |
lQuote = lArgChar; |
|---|
| 1649 |
continue; |
|---|
| 1650 |
} |
|---|
| 1651 |
} |
|---|
| 1652 |
|
|---|
| 1653 |
if (lArgChar == ' ') |
|---|
| 1654 |
{ |
|---|
| 1655 |
if (lQuote == 0) |
|---|
| 1656 |
{ |
|---|
| 1657 |
lInArg = false; |
|---|
| 1658 |
continue; |
|---|
| 1659 |
} |
|---|
| 1660 |
} |
|---|
| 1661 |
|
|---|
| 1662 |
if (lInArg == false) |
|---|
| 1663 |
{ |
|---|
| 1664 |
lArg++; |
|---|
| 1665 |
lArgs.length = lArg+1; |
|---|
| 1666 |
lInArg = true; |
|---|
| 1667 |
} |
|---|
| 1668 |
lArgs[lArg] ~= lArgChar; |
|---|
| 1669 |
|
|---|
| 1670 |
} |
|---|
| 1671 |
|
|---|
| 1672 |
foreach(char[] lSwitch; lArgs) |
|---|
| 1673 |
{ |
|---|
| 1674 |
if ((lSwitch.length > 0) && (lSwitch[0] == '-')) |
|---|
| 1675 |
{ |
|---|
| 1676 |
if (vDelayedValue != null) |
|---|
| 1677 |
{ |
|---|
| 1678 |
// Used when an switch needs the subsequent arg to |
|---|
| 1679 |
// be its value. |
|---|
| 1680 |
*vDelayedValue = lSwitch; |
|---|
| 1681 |
vDelayedValue = null; |
|---|
| 1682 |
vBuildArgs ~= lSwitch; |
|---|
| 1683 |
continue; |
|---|
| 1684 |
} |
|---|
| 1685 |
|
|---|
| 1686 |
if (lSwitch[1] == 'I') |
|---|
| 1687 |
{ |
|---|
| 1688 |
lRoots = std.string.split(lSwitch[2..length], vConfigSep); |
|---|
| 1689 |
foreach(char[] lRoot; lRoots) |
|---|
| 1690 |
{ |
|---|
| 1691 |
lRootName = AddRoot(lRoot); |
|---|
| 1692 |
/* |
|---|
| 1693 |
version(Posix) |
|---|
| 1694 |
vDefaultCompArgs ~= vImportPathSwitch ~ "\"" ~ lRoot ~ "\""; |
|---|
| 1695 |
else |
|---|
| 1696 |
vDefaultCompArgs ~= vImportPathSwitch ~ lRoot; |
|---|
| 1697 |
*/ |
|---|
| 1698 |
if(vVerbose == True) { |
|---|
| 1699 |
if (lRootName.length > 0){ |
|---|
| 1700 |
writefln(" added root from config file %s", lRootName); |
|---|
| 1701 |
} |
|---|
| 1702 |
} |
|---|
| 1703 |
} |
|---|
| 1704 |
} |
|---|
| 1705 |
else |
|---|
| 1706 |
{ |
|---|
| 1707 |
version(DigitalMars) |
|---|
| 1708 |
{ |
|---|
| 1709 |
if (util.str.IsLike(lSwitch, (vOutFileSwitch ~ "*")) == True) |
|---|
| 1710 |
{ |
|---|
| 1711 |
// Target name (eg. -oftestapp) |
|---|
| 1712 |
vCommandTargetName = lSwitch[vOutFileSwitch.length .. $]; |
|---|
| 1713 |
vBuildArgs ~= lSwitch; |
|---|
| 1714 |
continue; |
|---|
| 1715 |
} |
|---|
| 1716 |
} |
|---|
| 1717 |
|
|---|
| 1718 |
version(GNU) |
|---|
| 1719 |
{ |
|---|
| 1720 |
if (lSwitch == vOutFileSwitch) |
|---|
| 1721 |
{ |
|---|
| 1722 |
// Target name (eg. -o testapp) |
|---|
| 1723 |
vDelayedValue = &vCommandTargetName; |
|---|
| 1724 |
vBuildArgs ~= lSwitch; |
|---|
| 1725 |
continue; |
|---|
| 1726 |
} |
|---|
| 1727 |
} |
|---|
| 1728 |
|
|---|
| 1729 |
if (util.str.IsLike(lSwitch, std.utf.toUTF32(vTemporaryPathSwitch ~ "*")) == True) |
|---|
| 1730 |
{ |
|---|
| 1731 |
char[] lbRoot; |
|---|
| 1732 |
|
|---|
| 1733 |
vTemporaryPath = lSwitch[vTemporaryPathSwitch.length .. $]; |
|---|
| 1734 |
if (vTemporaryPath.length > 0 && vTemporaryPath[$-1..$] != std.path.sep) |
|---|
| 1735 |
vTemporaryPath ~= std.path.sep; |
|---|
| 1736 |
|
|---|
| 1737 |
version(DigitalMars) |
|---|
| 1738 |
{ |
|---|
| 1739 |
lbRoot = AddRoot(vTemporaryPath); |
|---|
| 1740 |
if (lbRoot.length > 0){ |
|---|
| 1741 |
if(vVerbose == True) { |
|---|
| 1742 |
writefln("Added root from config file Object Write Path = %s",lbRoot); |
|---|
| 1743 |
} |
|---|
| 1744 |
util.pathex.MakePath(lbRoot); |
|---|
| 1745 |
} |
|---|
| 1746 |
} |
|---|
| 1747 |
|
|---|
| 1748 |
vBuildArgs ~= lSwitch; |
|---|
| 1749 |
// This one actually *is* passed thru. |
|---|
| 1750 |
} |
|---|
| 1751 |
|
|---|
| 1752 |
AddCompilerArg ( lSwitch ); |
|---|
| 1753 |
} |
|---|
| 1754 |
} |
|---|
| 1755 |
} |
|---|
| 1756 |
} |
|---|
| 1757 |
|
|---|
| 1758 |
// ------------------------------------------- |
|---|
| 1759 |
void ReadEnviron() |
|---|
| 1760 |
// ------------------------------------------- |
|---|
| 1761 |
{ |
|---|
| 1762 |
char[] lSymValue; |
|---|
| 1763 |
|
|---|
| 1764 |
// Check for a environment flag before config file. |
|---|
| 1765 |
lSymValue = GetEnv("DFLAGS"); |
|---|
| 1766 |
if (lSymValue.length > 0 ) |
|---|
| 1767 |
{ |
|---|
| 1768 |
if (vVerbose == True) |
|---|
| 1769 |
writefln("Analyzing environment symbol DFLAGS=%s", lSymValue); |
|---|
| 1770 |
Process_DFLAGS( lSymValue ); |
|---|
| 1771 |
} |
|---|
| 1772 |
} |
|---|
| 1773 |
|
|---|
| 1774 |
// ------------------------------------------- |
|---|
| 1775 |
void ReadConfigFile() |
|---|
| 1776 |
// ------------------------------------------- |
|---|
| 1777 |
{ |
|---|
| 1778 |
char[] lPath; |
|---|
| 1779 |
char[][] lTextLines; |
|---|
| 1780 |
int lPos; |
|---|
| 1781 |
|
|---|
| 1782 |
if (vConfigFile.length == 0) |
|---|
| 1783 |
{ |
|---|
| 1784 |
// There is no configuration file to process |
|---|
| 1785 |
return; |
|---|
| 1786 |
} |
|---|
| 1787 |
|
|---|
| 1788 |
lPath = vConfigPath ~ vConfigFile ; |
|---|
| 1789 |
util.fileex.GetTextLines(lPath, lTextLines, util.fileex.GetOpt.Exists); |
|---|
| 1790 |
|
|---|
| 1791 |
if (vVerbose == True) { |
|---|
| 1792 |
writefln("Reading from config: %s", lPath); |
|---|
| 1793 |
} |
|---|
| 1794 |
|
|---|
| 1795 |
foreach(int i, char[] lLine; lTextLines) |
|---|
| 1796 |
{ |
|---|
| 1797 |
// Strip off trailing whitespace. |
|---|
| 1798 |
lLine = util.str.stripr(lLine); |
|---|
| 1799 |
|
|---|
| 1800 |
// Replace any environment symbols with their value. |
|---|
| 1801 |
if (vVerbose == True) { |
|---|
| 1802 |
writefln(" Line %d: %s", i+1, lLine); |
|---|
| 1803 |
} |
|---|
| 1804 |
lLine = ExpandEnvVar(lLine); |
|---|
| 1805 |
|
|---|
| 1806 |
// Examine DFLAGS |
|---|
| 1807 |
lPos = find(lLine, "DFLAGS="); |
|---|
| 1808 |
if(lPos == 0) |
|---|
| 1809 |
{ |
|---|
| 1810 |
Process_DFLAGS(lLine[lPos+7..length]); |
|---|
| 1811 |
} // end of DFLAGS processing. |
|---|
| 1812 |
|
|---|
| 1813 |
// Examine LIB |
|---|
| 1814 |
lPos = find(lLine, "LIB="); |
|---|
| 1815 |
if(lPos == 0) |
|---|
| 1816 |
{ |
|---|
| 1817 |
char[][] lPaths; |
|---|
| 1818 |
lLine = lLine[lPos+4 .. length]; |
|---|
| 1819 |
lPaths.length = 1; |
|---|
| 1820 |
foreach(char lChar; lLine) |
|---|
| 1821 |
{ |
|---|
| 1822 |
if (lChar == '"') {} |
|---|
| 1823 |
else if (lChar == ';') |
|---|
| 1824 |
{ |
|---|
| 1825 |
lPaths.length = lPaths.length + 1; |
|---|
| 1826 |
} |
|---|
| 1827 |
else |
|---|
| 1828 |
lPaths[$-1] ~= lChar; |
|---|
| 1829 |
|
|---|
| 1830 |
} |
|---|
| 1831 |
for(int i = 0; i < lPaths.length; i++) |
|---|
| 1832 |
{ |
|---|
| 1833 |
lPaths[i] = std.string.strip(lPaths[i]); |
|---|
| 1834 |
} |
|---|
| 1835 |
|
|---|
| 1836 |
foreach( char[] lPath; lPaths) |
|---|
| 1837 |
{ |
|---|
| 1838 |
if (lPath.length > 0) |
|---|
| 1839 |
{ |
|---|
| 1840 |
if (lPath[0] == '"' && lPath[length-1] == '"') { |
|---|
| 1841 |
lPath = lPath[1..length-1]; |
|---|
| 1842 |
} |
|---|
| 1843 |
vLibPaths ~= vConfigSep ~ `"` ~ util.pathex.CanonicalPath(lPath) ~ `"`; |
|---|
| 1844 |
} |
|---|
| 1845 |
} |
|---|
| 1846 |
if(vVerbose == True) |
|---|
| 1847 |
{ |
|---|
| 1848 |
writefln(" use %s",vLibPaths); |
|---|
| 1849 |
} |
|---|
| 1850 |
continue; |
|---|
| 1851 |
} |
|---|
| 1852 |
|
|---|
| 1853 |
// Examine LINKCMD |
|---|
| 1854 |
lPos = find(lLine, "LINKCMD="); |
|---|
| 1855 |
if(lPos == 0) { |
|---|
| 1856 |
// Strip out any quotes |
|---|
| 1857 |
while( (lPos = find(lLine, "\"")) != -1) |
|---|
| 1858 |
{ |
|---|
| 1859 |
lLine = lLine[0..lPos] ~ lLine[lPos+1 .. $]; |
|---|
| 1860 |
} |
|---|
| 1861 |
|
|---|
| 1862 |
vLinkerPath = std.path.getDirName(lLine[8..$]) ~ std.path.sep; |
|---|
| 1863 |
vLinkerPath = util.pathex.CanonicalPath(vLinkerPath); |
|---|
| 1864 |
vLinkerExe = std.path.getBaseName(lLine[7..$]); |
|---|
| 1865 |
if(vVerbose == True) { |
|---|
| 1866 |
writefln(" linker path %s",vLinkerPath); |
|---|
| 1867 |
writefln(" linker is %s",vLinkerExe); |
|---|
| 1868 |
} |
|---|
| 1869 |
continue; |
|---|
| 1870 |
} |
|---|
| 1871 |
|
|---|
| 1872 |
lPos = find(lLine, "LIBCMD="); |
|---|
| 1873 |
if(lPos == 0) { |
|---|
| 1874 |
// Strip out any quotes |
|---|
| 1875 |
while( (lPos = find(lLine, "\"")) != -1) |
|---|
| 1876 |
{ |
|---|
| 1877 |
lLine = lLine[0..lPos] ~ lLine[lPos+1 .. $]; |
|---|
| 1878 |
} |
|---|
| 1879 |
vLibrarianPath = std.path.getDirName(lLine[7..$]) ~ std.path.sep; |
|---|
| 1880 |
vLibrarianPath = util.pathex.CanonicalPath(vLibrarianPath); |
|---|
| 1881 |
|
|---|
| 1882 |
vLibrarian = std.path.getBaseName(lLine[7..$]); |
|---|
| 1883 |
if(vVerbose == True) { |
|---|
| 1884 |
writefln(" librarian path %s",vLibrarianPath); |
|---|
| 1885 |
writefln(" librarian is %s",vLibrarian); |
|---|
| 1886 |
} |
|---|
| 1887 |
} |
|---|
| 1888 |
|
|---|
| 1889 |
|
|---|
| 1890 |
if (vLinkerPath.length == 0) |
|---|
| 1891 |
vLinkerPath = vCompilerPath; |
|---|
| 1892 |
if (vLibrarianPath.length == 0) |
|---|
| 1893 |
vLibrarianPath = vLinkerPath; |
|---|
| 1894 |
} |
|---|
| 1895 |
} |
|---|
| 1896 |
|
|---|
| 1897 |
// Display each entry in the supplied list. |
|---|
| 1898 |
// ------------------------------------------- |
|---|
| 1899 |
void DisplayItems(char[][] pList, char[] pTitle = "") |
|---|
| 1900 |
// ------------------------------------------- |
|---|
| 1901 |
{ |
|---|
| 1902 |
if (pList.length > 0) { |
|---|
| 1903 |
if (pTitle.length > 0) |
|---|
| 1904 |
writefln("\n%s",pTitle); |
|---|
| 1905 |
|
|---|
| 1906 |
foreach(int lIndex, char[] lListEntry; pList) { |
|---|
| 1907 |
writefln(" [%2d]: %s",lIndex,lListEntry); |
|---|
| 1908 |
} |
|---|
| 1909 |
} |
|---|
| 1910 |
} |
|---|
| 1911 |
|
|---|
| 1912 |
// ------------------------------------------- |
|---|
| 1913 |
void DisplayItems(ExternRef[] pList, char[] pTitle = "") |
|---|
| 1914 |
// ------------------------------------------- |
|---|
| 1915 |
{ |
|---|
| 1916 |
if (pList.length > 0) { |
|---|
| 1917 |
if (pTitle.length > 0) |
|---|
| 1918 |
writefln("\n%s",pTitle); |
|---|
| 1919 |
|
|---|
| 1920 |
foreach(int lIndex, ExternRef lListEntry; pList) |
|---|
| 1921 |
{ |
|---|
| 1922 |
writef(" [%2d]: %s",lIndex,lListEntry.FilePath); |
|---|
| 1923 |
if (lListEntry.ToolOpts.length > 0) |
|---|
| 1924 |
foreach(char[] lOpt; lListEntry.ToolOpts) |
|---|
| 1925 |
writef(" [%s]",lOpt); |
|---|
| 1926 |
writefln(""); |
|---|
| 1927 |
} |
|---|
| 1928 |
} |
|---|
| 1929 |
} |
|---|
| 1930 |
|
|---|
| 1931 |
// ------------------------------------------------ |
|---|
| 1932 |
char[] GetTemporaryPath() |
|---|
| 1933 |
{ |
|---|
| 1934 |
return vTemporaryPath; |
|---|
| 1935 |
} |
|---|
| 1936 |
|
|---|
| 1937 |
// ------------------------------------------------ |
|---|
| 1938 |
Substitute[] GetMacros() |
|---|
| 1939 |
{ |
|---|
| 1940 |
return vSubstitutions; |
|---|
| 1941 |
} |
|---|
| 1942 |
|
|---|
| 1943 |
// ------------------------------------------------ |
|---|
| 1944 |
char[] GetFullPathnameScan(char[] pFileName, int pScanList) |
|---|
| 1945 |
// ------------------------------------------- |
|---|
| 1946 |
{ |
|---|
| 1947 |
if (pScanList == 0) |
|---|
| 1948 |
return GetFullPathname(pFileName); |
|---|
| 1949 |
else |
|---|
| 1950 |
return GetFullPathname(pFileName, vSourceScanList); |
|---|
| 1951 |
} |
|---|
| 1952 |
|
|---|
| 1953 |
// ------------------------------------------------ |
|---|
| 1954 |
char[] GetFullPathname(char[] pFileName, char[][] pScanList = null) |
|---|
| 1955 |
// ------------------------------------------- |
|---|
| 1956 |
{ |
|---|
| 1957 |
char[] lPossiblePath; |
|---|
| 1958 |
char[] lLocalPath; |
|---|
| 1959 |
|
|---|
| 1960 |
if (util.pathex.IsRelativePath(pFileName) == True && pScanList.length > 0) |
|---|
| 1961 |
{ |
|---|
| 1962 |
// Do explicit scanning of supplied paths. |
|---|
| 1963 |
foreach(char[] lNextRoot; pScanList) { |
|---|
| 1964 |
lPossiblePath = ( lNextRoot ~ pFileName ); |
|---|
| 1965 |
if(util.fileex.FileExists(lPossiblePath)) { |
|---|
| 1966 |
return util.pathex.AbbreviateFileName(lPossiblePath); |
|---|
| 1967 |
} |
|---|
| 1968 |
} |
|---|
| 1969 |
|
|---|
| 1970 |
// If not found in scan list, drop through to standard scan. |
|---|
| 1971 |
} |
|---|
| 1972 |
|
|---|
| 1973 |
// Look for file in current folder first. |
|---|
| 1974 |
lLocalPath = util.pathex.CanonicalPath(pFileName, false); |
|---|
| 1975 |
if(util.fileex.FileExists(lLocalPath)) { |
|---|
| 1976 |
return util.pathex.AbbreviateFileName(lLocalPath); |
|---|
| 1977 |
} |
|---|
| 1978 |
|
|---|
| 1979 |
// Examine each known import root to see if the file lives there. |
|---|
| 1980 |
foreach(char[] lNextRoot; vImportRoots) { |
|---|
| 1981 |
lPossiblePath = ( lNextRoot ~ pFileName ); |
|---|
| 1982 |
if(util.fileex.FileExists(lPossiblePath)) { |
|---|
| 1983 |
return util.pathex.AbbreviateFileName(lPossiblePath); |
|---|
| 1984 |
} |
|---|
| 1985 |
} |
|---|
| 1986 |
|
|---|
| 1987 |
return util.pathex.AbbreviateFileName(lLocalPath); |
|---|
| 1988 |
} |
|---|
| 1989 |
|
|---|
| 1990 |
|
|---|
| 1991 |
// Function to locate where Complier is installed from the PATH symbol |
|---|
| 1992 |
// ------------------------------------------- |
|---|
| 1993 |
char[] FindFileInPathList(char[] pSymName, char[] pFileName) |
|---|
| 1994 |
// ------------------------------------------- |
|---|
| 1995 |
{ |
|---|
| 1996 |
char[][] lPaths; |
|---|
| 1997 |
char[] lCompilerPath; |
|---|
| 1998 |
char[] lRawValue; |
|---|
| 1999 |
|
|---|
| 2000 |
// Assume that an environment symbol name was supplied, |
|---|
| 2001 |
// but if that fails, assume its a list of paths. |
|---|
| 2002 |
lRawValue = GetEnv(pSymName); |
|---|
| 2003 |
if (lRawValue.length == 0) |
|---|
| 2004 |
lRawValue = pSymName; |
|---|
| 2005 |
|
|---|
| 2006 |
// Rearrange path list into an array of paths. |
|---|
| 2007 |
lPaths = split(util.str.toASCII(lRawValue), std.path.pathsep); |
|---|
| 2008 |
|
|---|
| 2009 |
lCompilerPath.length = 0; |
|---|
| 2010 |
foreach(char[] lPath; lPaths) |
|---|
| 2011 |
{ |
|---|
| 2012 |
if (lPath.length > 0) |
|---|
| 2013 |
{ |
|---|
| 2014 |
// Ensure that the path ends with a valid separator. |
|---|
| 2015 |
if (lPath[length-1] != std.path.sep[0] ) |
|---|
| 2016 |
lPath ~= std.path.sep; |
|---|
| 2017 |
// If the file is in the current path we can stop looking. |
|---|
| 2018 |
if(util.fileex.FileExists(lPath ~ pFileName)) |
|---|
| 2019 |
{ |
|---|
| 2020 |
// Return the path we actually found it in. |
|---|
| 2021 |
lCompilerPath = lPath; |
|---|
| 2022 |
break; |
|---|
| 2023 |
} |
|---|
| 2024 |
} |
|---|
| 2025 |
} |
|---|
| 2026 |
|
|---|
| 2027 |
return lCompilerPath; |
|---|
| 2028 |
} |
|---|
| 2029 |
|
|---|
| 2030 |
// ------------------------------------------- |
|---|
| 2031 |
int main(char[][] pArgs) |
|---|
| 2032 |
// ------------------------------------------- |
|---|
| 2033 |
{ |
|---|
| 2034 |
int lBuildResult; |
|---|
| 2035 |
char[] lCompPath; |
|---|
| 2036 |
bool lSetPath = false; |
|---|
| 2037 |
|
|---|
| 2038 |
/* Set routine addresses in the Source module. This allows |
|---|
| 2039 |
the methods and functions in Source to access the optional |
|---|
| 2040 |
functionality provided by this module. |
|---|
| 2041 |
*/ |
|---|
| 2042 |
source.AddRoot = &AddRoot; |
|---|
| 2043 |
source.GetImportRoots = &GetImportRoots; |
|---|
| 2044 |
source.ModulesToIgnore = &ModulesToIgnore; |
|---|
| 2045 |
source.AutoImports = &AutoImports; |
|---|
| 2046 |
source.AddTarget = &AddTarget; |
|---|
| 2047 |
source.AddLink = &AddLink; |
|---|
| 2048 |
source.AddExternal = &AddExternal; |
|---|
| 2049 |
source.AddBuildDef = &AddBuildDef; |
|---|
| 2050 |
source.GetFullPathname = &GetFullPathname; |
|---|
| 2051 |
source.GetFullPathnameScan = &GetFullPathnameScan; |
|---|
| 2052 |
source.GetObjWritePath = &GetTemporaryPath; |
|---|
| 2053 |
source.GetMacros = &GetMacros; |
|---|
| 2054 |
source.AddCompilerArg = &AddCompilerArg; |
|---|
| 2055 |
|
|---|
| 2056 |
// Scan the PATH env symbol to locate the D compiler. |
|---|
| 2057 |
lCompPath = FindFileInPathList(kPathId, vCompilerExe); |
|---|
| 2058 |
if (lCompPath.length > 0){ |
|---|
| 2059 |
if (lCompPath[length-1] != std.path.sep[0]) |
|---|
| 2060 |
lCompPath ~= std.path.sep; |
|---|
| 2061 |
vCompilerPath = lCompPath.dup; |
|---|
| 2062 |
// Set config path to same as compiler unless it is already set. |
|---|
| 2063 |
if (!(vConfigPath is null) && (vConfigPath.length == 0)) |
|---|
| 2064 |
vConfigPath = lCompPath.dup; |
|---|
| 2065 |
} |
|---|
| 2066 |
|
|---|
| 2067 |
if (vCompilerPath.length == 0) |
|---|
| 2068 |
{ |
|---|
| 2069 |
vCompilerPath = util.pathex.GetInitCurDir; |
|---|
| 2070 |
lSetPath = true; |
|---|
| 2071 |
} |
|---|
| 2072 |
|
|---|
| 2073 |
// Strip off application's path from arglist. |
|---|
| 2074 |
vAppPath=pArgs[0]; |
|---|
| 2075 |
vAppName=getBaseName(vAppPath); |
|---|
| 2076 |
version (Windows) |
|---|
| 2077 |
{ |
|---|
| 2078 |
int DotPos; |
|---|
| 2079 |
DotPos = rfind(vAppName, '.'); |
|---|
| 2080 |
if (DotPos != -1) |
|---|
| 2081 |
{ |
|---|
| 2082 |
vAppName.length = DotPos; |
|---|
| 2083 |
} |
|---|
| 2084 |
} |
|---|
| 2085 |
|
|---|
| 2086 |
pArgs=pArgs[1..pArgs.length]; |
|---|
| 2087 |
if (pArgs.length == 0) { |
|---|
| 2088 |
// No other arguments so show usage message. |
|---|
| 2089 |
DisplayUsage (); |
|---|
| 2090 |
return 0; |
|---|
| 2091 |
} |
|---|
| 2092 |
|
|---|
| 2093 |
|
|---|
| 2094 |
GatherArgs( pArgs ); |
|---|
| 2095 |
source.mVerboseMode = vVerbose; |
|---|
| 2096 |
if (vVerbose == True){ |
|---|
| 2097 |
writefln("*** build v%s (build %d)***", vAppVersion, build_bn.auto_build_number); |
|---|
| 2098 |
} |
|---|
| 2099 |
|
|---|
| 2100 |
foreach(char[] lArg; vCombinedArgs) { |
|---|
| 2101 |
ProcessCmdLineArg( lArg ); |
|---|
| 2102 |
} |
|---|
| 2103 |
|
|---|
| 2104 |
source.mMacroInput = vMacroInput; |
|---|
| 2105 |
if (vMacroInput == True) |
|---|
| 2106 |
ProcessMacroDefs(vVerbose); |
|---|
| 2107 |
|
|---|
| 2108 |
if( (vTargetName.length == 0) && (vCommandTargetName.length == 0) ){ |
|---|
| 2109 |
throw new Exception("No target name supplied."); |
|---|
| 2110 |
} |
|---|
| 2111 |
|
|---|
| 2112 |
if ((vVerbose == True) || (vNames == True) ) |
|---|
| 2113 |
writefln("Current Dir '%s'", util.pathex.GetInitCurDir()); |
|---|
| 2114 |
|
|---|
| 2115 |
if (lSetPath) |
|---|
| 2116 |
{ |
|---|
| 2117 |
if (vVerbose == True) |
|---|
| 2118 |
{ |
|---|
| 2119 |
writefln("%s not found in PATH symbol, so assuming current directory", |
|---|
| 2120 |
vCompilerExe); |
|---|
| 2121 |
} |
|---|
| 2122 |
} |
|---|
| 2123 |
|
|---|
| 2124 |
if (vCompilerPath[length-1] != std.path.sep[0]) |
|---|
| 2125 |
vCompilerPath ~= std.path.sep; |
|---|
| 2126 |
|
|---|
| 2127 |
|
|---|
| 2128 |
if (vConfigPath.length == 0) |
|---|
| 2129 |
{ |
|---|
| 2130 |
vConfigPath = vCompilerPath; |
|---|
| 2131 |
if (vVerbose == True) |
|---|
| 2132 |
{ |
|---|
| 2133 |
writefln("No configuration file path, so assuming current directory"); |
|---|
| 2134 |
} |
|---|
| 2135 |
} |
|---|
| 2136 |
if (util.str.ends(vConfigPath, std.path.sep) is False) |
|---|
| 2137 |
vConfigPath ~= std.path.sep; |
|---|
| 2138 |
|
|---|
| 2139 |
version(DigitalMars) |
|---|
| 2140 |
{ |
|---|
| 2141 |
if (util.fileex.FileExists(vConfigPath ~ vConfigFile) == false) |
|---|
| 2142 |
{ |
|---|
| 2143 |
throw new Exception(std.string.format("The configuration file '%s' was not found.", |
|---|
| 2144 |
vConfigPath ~ vConfigFile)); |
|---|
| 2145 |
} |
|---|
| 2146 |
} |
|---|
| 2147 |
|
|---|
| 2148 |
if (util.fileex.FileExists(vCompilerPath ~ vCompilerExe) == false) |
|---|
| 2149 |
{ |
|---|
| 2150 |
throw new Exception(std.string.format("The compiler '%s' was not found.", |
|---|
| 2151 |
vCompilerPath ~ vCompilerExe)); |
|---|
| 2152 |
} |
|---|
| 2153 |
|
|---|
| 2154 |
if (vVerbose == True){ |
|---|
| 2155 |
writefln("Compiler installed in %s",vCompilerPath); |
|---|
| 2156 |
writefln("Configuration File installed in %s",vConfigPath); |
|---|
| 2157 |
} |
|---|
| 2158 |
|
|---|
| 2159 |
source.SetKnownVersions(); |
|---|
| 2160 |
|
|---|
| 2161 |
ReadEnviron(); |
|---|
| 2162 |
version(DigitalMars) ReadConfigFile(); |
|---|
| 2163 |
|
|---|
| 2164 |
// Rationalize the ignored modules list. |
|---|
| 2165 |
foreach(char[] m; vModulesToNotice) { |
|---|
| 2166 |
for (int i=0; i < vModulesToIgnore.length; i++) { |
|---|
| 2167 |
if (vModulesToIgnore[i] == m) { |
|---|
| 2168 |
// Must remove from ignored list. |
|---|
| 2169 |
vModulesToIgnore = vModulesToIgnore[0..i] ~ vModulesToIgnore[i+1..length]; |
|---|
| 2170 |
i--; |
|---|
| 2171 |
} |
|---|
| 2172 |
} |
|---|
| 2173 |
} |
|---|
| 2174 |
|
|---|
| 2175 |
|
|---|
| 2176 |
// Process the D Source files that were on the command line. |
|---|
| 2177 |
// Each file must already exist. If any does not exist, then |
|---|
| 2178 |
// the application will abort. |
|---|
| 2179 |
bool lAllExist = true; |
|---|
| 2180 |
|
|---|
| 2181 |
// List all missing files (if any). |
|---|
| 2182 |
foreach( char[] lFile; vCmdLineSourceFiles) |
|---|
| 2183 |
{ |
|---|
| 2184 |
if (! util.fileex.FileExists( GetFullPathname(lFile, vSourceScanList)) ) |
|---|
| 2185 |
{ |
|---|
| 2186 |
if (vSilent == False) |
|---|
| 2187 |
writefln("** File '%s' not found.", lFile); |
|---|
| 2188 |
lAllExist = false; |
|---|
| 2189 |
} |
|---|
| 2190 |
} |
|---|
| 2191 |
|
|---|
| 2192 |
if ( lAllExist == false) |
|---|
| 2193 |
{ |
|---|
| 2194 |
throw new Exception ("Not all supplied files exist."); |
|---|
| 2195 |
} |
|---|
| 2196 |
|
|---|
| 2197 |
lBuildResult = Build(); |
|---|
| 2198 |
|
|---|
| 2199 |
if(vVerbose == True) { |
|---|
| 2200 |
writefln(""); |
|---|
| 2201 |
DisplayItems(vBuildArgs, "build args: ..............."); |
|---|
| 2202 |
DisplayItems(vCompilerArgs, "compiler args: ................"); |
|---|
| 2203 |
DisplayItems(vCmdLineSourceFiles, "command line files: ..............."); |
|---|
| 2204 |
DisplayItems(Source.ScanOrder, |
|---|
| 2205 |
"source files: ..............."); |
|---|
| 2206 |
DisplayItems(vLinkFiles.keys, "link files: ..............."); |
|---|
| 2207 |
DisplayItems(vExternals, "externally built files: ..............."); |
|---|
| 2208 |
DisplayItems(vImportRoots, "import roots: ................."); |
|---|
| 2209 |
DisplayItems(vModulesToIgnore,"ignored packages: ................."); |
|---|
| 2210 |
DisplayItems(vModulesToNotice,"noticed package: ................."); |
|---|
| 2211 |
} |
|---|
| 2212 |
|
|---|
| 2213 |
if ((vExecuteProgram == True) && (vTargetExe.length > 0)) |
|---|
| 2214 |
{ |
|---|
| 2215 |
RunCommand( vTargetExe ~ " " ~ std.string.strip(vRunParms)); |
|---|
| 2216 |
} |
|---|
| 2217 |
|
|---|
| 2218 |
return lBuildResult; |
|---|
| 2219 |
|
|---|
| 2220 |
|
|---|
| 2221 |
} |
|---|
| 2222 |
|
|---|
| 2223 |
void ProcessResponseFile(char[] pArg, Bool pVerbose) |
|---|
| 2224 |
{ |
|---|
| 2225 |
// A response file is being used. |
|---|
| 2226 |
char[] lRespFileName; |
|---|
| 2227 |
char[][] lRespLines; |
|---|
| 2228 |
|
|---|
| 2229 |
if (pArg.length == 1) |
|---|
| 2230 |
lRespFileName = "build.brf"; |
|---|
| 2231 |
else |
|---|
| 2232 |
lRespFileName = pArg[1..length].dup; |
|---|
| 2233 |
|
|---|
| 2234 |
if (std.path.getExt(lRespFileName).length == 0) |
|---|
| 2235 |
{ |
|---|
| 2236 |
lRespFileName ~= ".brf"; |
|---|
| 2237 |
} |
|---|
| 2238 |
|
|---|
| 2239 |
if (pVerbose == True) |
|---|
| 2240 |
writefln("Response file %s", lRespFileName); |
|---|
| 2241 |
|
|---|
| 2242 |
lRespLines = util.fileex.GetTextLines(lRespFileName, util.fileex.GetOpt.Exists); |
|---|
| 2243 |
foreach(char[] lArg; lRespLines) |
|---|
| 2244 |
{ |
|---|
| 2245 |
// Locate any comment text in the line. |
|---|
| 2246 |
int lPos = std.string.find(lArg, "#"); |
|---|
| 2247 |
if (lPos != -1) |
|---|
| 2248 |
{ |
|---|
| 2249 |
// Truncate the line at the '#' character. |
|---|
| 2250 |
lArg.length = lPos; |
|---|
| 2251 |
} |
|---|
| 2252 |
|
|---|
| 2253 |
lArg = std.string.strip(lArg); |
|---|
| 2254 |
if (lArg.length > 1){ |
|---|
| 2255 |
if (pVerbose == True) |
|---|
| 2256 |
writefln("Response file arg: %s", lArg); |
|---|
| 2257 |
GatherOneArg( lArg ); |
|---|
| 2258 |
} |
|---|
| 2259 |
} |
|---|
| 2260 |
} |
|---|
| 2261 |
|
|---|
| 2262 |
void ProcessCmdLineArg( char[] pArg ) |
|---|
| 2263 |
{ |
|---|
| 2264 |
char[] lNewPath; |
|---|
| 2265 |
static char[] lImportSwitch; |
|---|
| 2266 |
|
|---|
| 2267 |
if(util.str.begins(pArg, "-version=") == True) { |
|---|
| 2268 |
char[] lVersionString; |
|---|
| 2269 |
|
|---|
| 2270 |
lVersionString=pArg [9 .. $]; |
|---|
| 2271 |
source.ActivateVersion(lVersionString); |
|---|
| 2272 |
pArg = vVersionSwitch ~ lVersionString; |
|---|
| 2273 |
} |
|---|
| 2274 |
else if(util.str.begins(pArg, "-fversion=") == True) { |
|---|
| 2275 |
char[] lVersionString; |
|---|
| 2276 |
|
|---|
| 2277 |
lVersionString=pArg [10 .. $]; |
|---|
| 2278 |
source.ActivateVersion(lVersionString); |
|---|
| 2279 |
pArg = vVersionSwitch ~ lVersionString; |
|---|
| 2280 |
} |
|---|
| 2281 |
|
|---|
| 2282 |
else if(pArg == "-fdebug") { |
|---|
| 2283 |
source.ActivateDebug("1"); |
|---|
| 2284 |
pArg = vDebugSwitch; |
|---|
| 2285 |
} |
|---|
| 2286 |
else if(pArg == "-debug") { |
|---|
| 2287 |
source.ActivateDebug("1"); |
|---|
| 2288 |
pArg = vDebugSwitch; |
|---|
| 2289 |
} |
|---|
| 2290 |
else if(util.str.begins(pArg, "-fdebug=") == True) { |
|---|
| 2291 |
char[] lDebugString; |
|---|
| 2292 |
|
|---|
| 2293 |
lDebugString=pArg [8 .. $]; |
|---|
| 2294 |
source.ActivateDebug(lDebugString); |
|---|
| 2295 |
pArg = vDebugSwitch ~ "=" ~ lDebugString; |
|---|
| 2296 |
} |
|---|
| 2297 |
else if(util.str.begins(pArg, "-debug=") == True) { |
|---|
| 2298 |
char[] lDebugString; |
|---|
| 2299 |
|
|---|
| 2300 |
lDebugString=pArg [7 .. $]; |
|---|
| 2301 |
source.ActivateDebug(lDebugString); |
|---|
| 2302 |
pArg = vDebugSwitch ~ "=" ~ lDebugString; |
|---|
| 2303 |
} |
|---|
| 2304 |
|
|---|
| 2305 |
switch(pArg) { |
|---|
| 2306 |
case "-full": |
|---|
| 2307 |
vForceCompile = True; |
|---|
| 2308 |
vBuildArgs ~= pArg; |
|---|
| 2309 |
// Not passed thru. |
|---|
| 2310 |
break; |
|---|
| 2311 |
|
|---|
| 2312 |
case "-link": |
|---|
| 2313 |
Source.WasMainFound = true; |
|---|
| 2314 |
vBuildArgs ~= pArg; |
|---|
| 2315 |
// Not passed thru. |
|---|
| 2316 |
break; |
|---|
| 2317 |
|
|---|
| 2318 |
case "-nolink": |
|---|
| 2319 |
vNoLink = True; |
|---|
| 2320 |
vBuildArgs ~= pArg; |
|---|
| 2321 |
// Not passed thru. |
|---|
| 2322 |
break; |
|---|
| 2323 |
|
|---|
| 2324 |
case "-lib": |
|---|
| 2325 |
vLibraryAction = LibOpt.Build; |
|---|
| 2326 |
vBuildArgs ~= pArg; |
|---|
| 2327 |
// Not passed thru. |
|---|
| 2328 |
break; |
|---|
| 2329 |
|
|---|
| 2330 |
case "-nolib": |
|---|
| 2331 |
vLibraryAction = LibOpt.DontBuild; |
|---|
| 2332 |
vBuildArgs ~= pArg; |
|---|
| 2333 |
// Not passed thru. |
|---|
| 2334 |
break; |
|---|
| 2335 |
|
|---|
| 2336 |
case "-obj": |
|---|
| 2337 |
vLibraryAction = LibOpt.DontBuild; |
|---|
| 2338 |
vNoLink = True; |
|---|
| 2339 |
vBuildArgs ~= pArg; |
|---|
| 2340 |
// Not passed thru. |
|---|
| 2341 |
break; |
|---|
| 2342 |
|
|---|
| 2343 |
case "-nounittest": |
|---|
| 2344 |
// Not passed thru. Deprecated switch is now ignored. |
|---|
| 2345 |
if (vSilent == False) |
|---|
| 2346 |
writefln("Note: '-nounittest' ignored. This switch is no longer used."); |
|---|
| 2347 |
break; |
|---|
| 2348 |
|
|---|
| 2349 |
case "-info": |
|---|
| 2350 |
DisplayUsage(false); |
|---|
| 2351 |
vBuildArgs ~= pArg; |
|---|
| 2352 |
// Not passed thru. |
|---|
| 2353 |
break; |
|---|
| 2354 |
|
|---|
| 2355 |
case "-silent": |
|---|
| 2356 |
vSilent = True; |
|---|
| 2357 |
vBuildArgs ~= pArg; |
|---|
| 2358 |
// Not passed thru. |
|---|
| 2359 |
break; |
|---|
| 2360 |
|
|---|
| 2361 |
case "-noautoimport": |
|---|
| 2362 |
vAutoImports = False; |
|---|
| 2363 |
vBuildArgs ~= pArg; |
|---|
| 2364 |
// Not passed thru |
|---|
| 2365 |
break; |
|---|
| 2366 |
|
|---|
| 2367 |
case "-nodef": |
|---|
| 2368 |
vNoDef = True; |
|---|
| 2369 |
vBuildArgs ~= pArg; |
|---|
| 2370 |
// Not passed thru. |
|---|
| 2371 |
break; |
|---|
| 2372 |
|
|---|
| 2373 |
case "-nomacro": |
|---|
| 2374 |
vMacroInput = False; |
|---|
| 2375 |
vBuildArgs ~= pArg; |
|---|
| 2376 |
// Not passed thru. |
|---|
| 2377 |
break; |
|---|
| 2378 |
|
|---|
| 2379 |
case "-usage": |
|---|
| 2380 |
case "-help": |
|---|
| 2381 |
case "-h": |
|---|
| 2382 |
case "-?": |
|---|
| 2383 |
DisplayUsage(); |
|---|
| 2384 |
vBuildArgs ~= pArg; |
|---|
| 2385 |
// Not passed thru. |
|---|
| 2386 |
break; |
|---|
| 2387 |
|
|---|
| 2388 |
case "-allobj": |
|---|
| 2389 |
vAllObjects = True; |
|---|
| 2390 |
vBuildArgs ~= pArg; |
|---|
| 2391 |
// Not passed thru. |
|---|
| 2392 |
break; |
|---|
| 2393 |
|
|---|
| 2394 |
case "-test": |
|---|
| 2395 |
vTestRun = True; |
|---|
| 2396 |
vBuildArgs ~= pArg; |
|---|
| 2397 |
// Not passed thru. |
|---|
| 2398 |
break; |
|---|
| 2399 |
|
|---|
| 2400 |
case "-cleanup": |
|---|
| 2401 |
// drop through ... |
|---|
| 2402 |
case "-clean": |
|---|
| 2403 |
vCleanup = True; |
|---|
| 2404 |
vBuildArgs ~= pArg; |
|---|
| 2405 |
// Not passed thru. |
|---|
| 2406 |
break; |
|---|
| 2407 |
|
|---|
| 2408 |
case "-V": /* we need verbose status earlier */ |
|---|
| 2409 |
vBuildArgs ~= pArg; |
|---|
| 2410 |
// Not passed thru. |
|---|
| 2411 |
break; |
|---|
| 2412 |
|
|---|
| 2413 |
case "-names": |
|---|
| 2414 |
vBuildArgs ~= pArg; |
|---|
| 2415 |
vNames = True; |
|---|
| 2416 |
// Not passed thru. |
|---|
| 2417 |
break; |
|---|
| 2418 |
|
|---|
| 2419 |
default: |
|---|
| 2420 |
if (pArg.length > 0) |
|---|
| 2421 |
{ |
|---|
| 2422 |
if (pArg[0] == '-') { |
|---|
| 2423 |
if (pArg == "-g") |
|---|
| 2424 |
{ |
|---|
| 2425 |
// Requires symbolic debug info. |
|---|
| 2426 |
vLinkerDefSwitches ~= vLinkerDebugSymInfoSwitch; |
|---|
| 2427 |
AddCompilerArg(pArg); |
|---|
| 2428 |
break; |
|---|
| 2429 |
} |
|---|
| 2430 |
|
|---|
| 2431 |
// Test for Librarian options. |
|---|
| 2432 |
if (util.str.IsLike(pArg, "-LIBOPT*"d) == True) |
|---|
| 2433 |
{ |
|---|
| 2434 |
vLibrarianOpts ~= " " ~ pArg[7..$].dup; |
|---|
| 2435 |
vBuildArgs ~= pArg; |
|---|
| 2436 |
break; |
|---|
| 2437 |
|
|---|
| 2438 |
} |
|---|
| 2439 |
|
|---|
| 2440 |
if (util.str.begins(pArg, "-LIBPATH=") == True) |
|---|
| 2441 |
{ |
|---|
| 2442 |
vLibPaths ~= vConfigSep ~ pArg[9..$].dup; |
|---|
| 2443 |
vBuildArgs ~= pArg; |
|---|
| 2444 |
break; |
|---|
| 2445 |
} |
|---|
| 2446 |
|
|---|
| 2447 |
// Test for alternate install locations. |
|---|
| 2448 |
if (util.str.IsLike(pArg, "-DCPATH?*"d) == True) |
|---|
| 2449 |
{ |
|---|
| 2450 |
lNewPath = pArg[7..length].dup; |
|---|
| 2451 |
if (vCompilerPath == vConfigPath) |
|---|
| 2452 |
{ |
|---|
| 2453 |
if (vVerbose == True) |
|---|
| 2454 |
writefln("CFPATH was %s now %s", vConfigPath, lNewPath); |
|---|
| 2455 |
vConfigPath = lNewPath; |
|---|
| 2456 |
} |
|---|
| 2457 |
if (vVerbose == True) |
|---|
| 2458 |
writefln("DCPATH was %s now %s", vCompilerPath, lNewPath); |
|---|
| 2459 |
vCompilerPath = lNewPath; |
|---|
| 2460 |
vBuildArgs ~= pArg; |
|---|
| 2461 |
break; |
|---|
| 2462 |
|
|---|
| 2463 |
} |
|---|
| 2464 |
|
|---|
| 2465 |
if (util.str.IsLike(pArg, "-CFPATH?*"d) == True) |
|---|
| 2466 |
{ |
|---|
| 2467 |
if (vVerbose == True) |
|---|
| 2468 |
writefln("CFPATH was %s now %s", vConfigPath, pArg[7..length]); |
|---|
| 2469 |
vConfigPath = pArg[7..length].dup; |
|---|
| 2470 |
vBuildArgs ~= pArg; |
|---|
| 2471 |
break; |
|---|
| 2472 |
|
|---|
| 2473 |
} |
|---|
| 2474 |
|
|---|
| 2475 |
if (util.str.IsLike(pArg, "-PP?*"d) == True) |
|---|
| 2476 |
{ |
|---|
| 2477 |
char[] lNewPath; |
|---|
| 2478 |
lNewPath = pArg[3..length].dup; |
|---|
| 2479 |
if (vVerbose == True) |
|---|
| 2480 |
writefln("Added %s to Source Scan List", lNewPath); |
|---|
| 2481 |
vBuildArgs ~= pArg; |
|---|
| 2482 |
if ( util.str.ends(lNewPath, std.path.sep) == False) |
|---|
| 2483 |
lNewPath ~= std.path.sep; |
|---|
| 2484 |
vSourceScanList ~= lNewPath; |
|---|
| 2485 |
break; |
|---|
| 2486 |
|
|---|
| 2487 |
} |
|---|
| 2488 |
|
|---|
| 2489 |
if (util.str.IsLike(pArg, "-RDF?*"d) == True) |
|---|
| 2490 |
{ |
|---|
| 2491 |
if (vVerbose == True) |
|---|
| 2492 |
writefln("RDF was %s now %s", vRDFName, pArg[4..$]); |
|---|
| 2493 |
vRDFName = pArg[4..$].dup; |
|---|
| 2494 |
vBuildArgs ~= pArg; |
|---|
| 2495 |
break; |
|---|
| 2496 |
|
|---|
| 2497 |
} |
|---|
| 2498 |
|
|---|
| 2499 |
if (pArg == vBuildImportPathSwitch) |
|---|
| 2500 |
{ |
|---|
| 2501 |
vDelayedValue = &lImportSwitch; |
|---|
| 2502 |
vBuildArgs ~= pArg; |
|---|
| 2503 |
break; |
|---|
| 2504 |
} |
|---|
| 2505 |
else if ( util.str.begins(pArg, vBuildImportPathSwitch) == True) |
|---|
| 2506 |
{ |
|---|
| 2507 |
char [] lRoot; |
|---|
| 2508 |
foreach(char[] lCmdRoot; std.string.split(pArg[vBuildImportPathSwitch.length .. $], ";")) |
|---|
| 2509 |
{ |
|---|
| 2510 |
lRoot = AddRoot(lCmdRoot); |
|---|
| 2511 |
if (lRoot.length > 0){ |
|---|
| 2512 |
if(vVerbose == True) { |
|---|
| 2513 |
writefln("Added root from command line = %s",lRoot); |
|---|
| 2514 |
} |
|---|
| 2515 |
} |
|---|
| 2516 |
} |
|---|
| 2517 |
break; |
|---|
| 2518 |
} |
|---|
| 2519 |
|
|---|
| 2520 |
if (util.str.IsLike(pArg, std.utf.toUTF32(vRunSwitch ~ "*")) == True) |
|---|
| 2521 |
{ |
|---|
| 2522 |
vRunParms ~= pArg[vRunSwitch.length .. $] ~ " "; |
|---|
| 2523 |
vExecuteProgram = True; |
|---|
| 2524 |
vBuildArgs ~= pArg; |
|---|
| 2525 |
break; |
|---|
| 2526 |
} |
|---|
| 2527 |
|
|---|
| 2528 |
|
|---|
| 2529 |
// Special check for Object Write Path |
|---|
| 2530 |
version(DigitalMars) |
|---|
| 2531 |
{ |
|---|
| 2532 |
if (util.str.IsLike(pArg, std.utf.toUTF32(vTemporaryPathSwitch ~ "*")) == True) |
|---|
| 2533 |
{ |
|---|
| 2534 |
char[] lRoot; |
|---|
| 2535 |
|
|---|
| 2536 |
vTemporaryPath = pArg[vTemporaryPathSwitch.length .. $]; |
|---|
| 2537 |
if (vTemporaryPath.length > 0 && vTemporaryPath[$-1..$] != std.path.sep) |
|---|
| 2538 |
vTemporaryPath ~= std.path.sep; |
|---|
| 2539 |
|
|---|
| 2540 |
lRoot = AddRoot(vTemporaryPath); |
|---|
| 2541 |
if (lRoot.length > 0){ |
|---|
| 2542 |
if(vVerbose == True) { |
|---|
| 2543 |
writefln("Added root from Object Write Path = %s",lRoot); |
|---|
| 2544 |
} |
|---|
| 2545 |
util.pathex.MakePath(lRoot); |
|---|
| 2546 |
} |
|---|
| 2547 |
|
|---|
| 2548 |
vBuildArgs ~= pArg; |
|---|
| 2549 |
// This one actually *is* passed thru. |
|---|
| 2550 |
} |
|---|
| 2551 |
} |
|---|
| 2552 |
|
|---|
| 2553 |
if (util.str.IsLike(pArg, "-X?*"d) == True) |
|---|
| 2554 |
{ |
|---|
| 2555 |
// Modules to ignore (eg. -Xmylib) |
|---|
| 2556 |
vModulesToIgnore ~= pArg[2..$]; |
|---|
| 2557 |
vBuildArgs ~= pArg; |
|---|
| 2558 |
break; |
|---|
| 2559 |
} |
|---|
| 2560 |
|
|---|
| 2561 |
if (util.str.IsLike(pArg, "-M?*"d) == True) |
|---|
| 2562 |
{ |
|---|
| 2563 |
// Modules to notice (eg. -Mphobos) |
|---|
| 2564 |
vModulesToNotice ~= pArg[2..$]; |
|---|
| 2565 |
vBuildArgs ~= pArg; |
|---|
| 2566 |
break; |
|---|
| 2567 |
} |
|---|
| 2568 |
|
|---|
| 2569 |
if (util.str.IsLike(pArg, "-T?*"d) == True) |
|---|
| 2570 |
{ |
|---|
| 2571 |
// Target name (eg. -Ttestapp) |
|---|
| 2572 |
vCommandTargetName = pArg[2..$]; |
|---|
| 2573 |
vBuildArgs ~= pArg; |
|---|
| 2574 |
break; |
|---|
| 2575 |
} |
|---|
| 2576 |
|
|---|
| 2577 |
version(DigitalMars) |
|---|
| 2578 |
{ |
|---|
| 2579 |
if (util.str.IsLike(pArg, (vOutFileSwitch ~ "*")) == True) |
|---|
| 2580 |
{ |
|---|
| 2581 |
// Target name (eg. -oftestapp) |
|---|
| 2582 |
vCommandTargetName = pArg[vOutFileSwitch.length .. $]; |
|---|
| 2583 |
vBuildArgs ~= pArg; |
|---|
| 2584 |
break; |
|---|
| 2585 |
} |
|---|
| 2586 |
} |
|---|
| 2587 |
|
|---|
| 2588 |
version(GNU) |
|---|
| 2589 |
{ |
|---|
| 2590 |
if (pArg == vOutFileSwitch) |
|---|
| 2591 |
{ |
|---|
| 2592 |
// Target name (eg. -o testapp) |
|---|
| 2593 |
vDelayedValue = &vCommandTargetName; |
|---|
| 2594 |
vBuildArgs ~= pArg; |
|---|
| 2595 |
break; |
|---|
| 2596 |
} |
|---|
| 2597 |
} |
|---|
| 2598 |
|
|---|
| 2599 |
if (util.str.IsLike(pArg, "-R*"d) == True) |
|---|
| 2600 |
{ |
|---|
| 2601 |
// Response file usage (eg. -Ry) |
|---|
| 2602 |
if (pArg.length == 2) |
|---|
| 2603 |
vUseResponseFile = ~vUseResponseFile; |
|---|
| 2604 |
|
|---|
| 2605 |
else if (pArg[2] == 'y') |
|---|
| 2606 |
vUseResponseFile = True; |
|---|
| 2607 |
|
|---|
| 2608 |
else |
|---|
| 2609 |
vUseResponseFile = False; |
|---|
| 2610 |
|
|---|
| 2611 |
vBuildArgs ~= pArg; |
|---|
| 2612 |
break; |
|---|
| 2613 |
} |
|---|
| 2614 |
|
|---|
| 2615 |
version(Windows) { |
|---|
| 2616 |
if (util.str.IsLike(pArg, "-gui*"d) == True) |
|---|
| 2617 |
{ |
|---|
| 2618 |
Source.WasMainGUI = true; |
|---|
| 2619 |
vBuildArgs ~= pArg; |
|---|
| 2620 |
if (pArg.length == 4) |
|---|
| 2621 |
break; |
|---|
| 2622 |
if (pArg[4] == ':') |
|---|
| 2623 |
vWinVer = pArg[5..length]; |
|---|
| 2624 |
else |
|---|
| 2625 |
vWinVer = pArg[4..length]; |
|---|
| 2626 |
break; |
|---|
| 2627 |
} |
|---|
| 2628 |
|
|---|
| 2629 |
if (pArg == "-dll") |
|---|
| 2630 |
{ |
|---|
| 2631 |
Source.WasMainDLL = true; |
|---|
| 2632 |
vBuildArgs ~= pArg; |
|---|
| 2633 |
break; |
|---|
| 2634 |
} |
|---|
| 2635 |
} |
|---|
| 2636 |
|
|---|
| 2637 |
AddCompilerArg( pArg ); |
|---|
| 2638 |
|
|---|
| 2639 |
} else { |
|---|
| 2640 |
|
|---|
| 2641 |
if (vDelayedValue != null) |
|---|
| 2642 |
{ |
|---|
| 2643 |
// Used when an switch needs the subsequent arg to |
|---|
| 2644 |
// be its value. |
|---|
| 2645 |
if ( vDelayedValue == &lImportSwitch) |
|---|
| 2646 |
{ |
|---|
| 2647 |
char [] lRoot; |
|---|
| 2648 |
foreach(char[] lCmdRoot; std.string.split(pArg, ";")) |
|---|
| 2649 |
{ |
|---|
| 2650 |
lRoot = AddRoot(lCmdRoot); |
|---|
| 2651 |
if (lRoot.length > 0){ |
|---|
| 2652 |
if(vVerbose == True) { |
|---|
| 2653 |
writefln("Added root from command line = %s",lRoot); |
|---|
| 2654 |
} |
|---|
| 2655 |
} |
|---|
| 2656 |
} |
|---|
| 2657 |
} |
|---|
| 2658 |
else |
|---|
| 2659 |
{ |
|---|
| 2660 |
*vDelayedValue = pArg; |
|---|
| 2661 |
vBuildArgs ~= pArg; |
|---|
| 2662 |
} |
|---|
| 2663 |
vDelayedValue = null; |
|---|
| 2664 |
break; |
|---|
| 2665 |
} |
|---|
| 2666 |
|
|---|
| 2667 |
version(Windows) |
|---|
| 2668 |
{ |
|---|
| 2669 |
// Convert non-standard but sometimes used unix seps |
|---|
| 2670 |
// with standard Windows seps. |
|---|
| 2671 |
pArg = std.string.replace(pArg, "/", std.path.sep); |
|---|
| 2672 |
} |
|---|
| 2673 |
switch(std.path.getExt(pArg)) { |
|---|
| 2674 |
case "": |
|---|
| 2675 |
pArg ~= "." ~ kSrcExtention; |
|---|
| 2676 |
vCmdLineSourceFiles ~= pArg; |
|---|
| 2677 |
break; |
|---|
| 2678 |
|
|---|
| 2679 |
case kSrcExtention: |
|---|
| 2680 |
case kMacroExtention: |
|---|
| 2681 |
case kDdocExtention: |
|---|
| 2682 |
vCmdLineSourceFiles ~= pArg; |
|---|
| 2683 |
break; |
|---|
| 2684 |
|
|---|
| 2685 |
default: |
|---|
| 2686 |
AddLink(GetFullPathname(pArg)); |
|---|
| 2687 |
} |
|---|
| 2688 |
if(vTargetName is null) { |
|---|
| 2689 |
vTargetName = pArg; |
|---|
| 2690 |
} |
|---|
| 2691 |
} |
|---|
| 2692 |
break; |
|---|
| 2693 |
} |
|---|
| 2694 |
} |
|---|
| 2695 |
} |
|---|
| 2696 |
|
|---|
| 2697 |
void GatherOneArg( char[] pArg ) |
|---|
| 2698 |
{ |
|---|
| 2699 |
static bool[char[]] lKnownArgs; |
|---|
| 2700 |
|
|---|
| 2701 |
pArg = std.string.strip(pArg); |
|---|
| 2702 |
if (pArg.length == 0) |
|---|
| 2703 |
return; |
|---|
| 2704 |
|
|---|
| 2705 |
if ((pArg == "-V") || (pArg == "-v")) |
|---|
| 2706 |
vVerbose = True; |
|---|
| 2707 |
|
|---|
| 2708 |
if ( pArg.length >= 2 && pArg[0..2] == "--") |
|---|
| 2709 |
{ // Need to remove an earlier matching argument. |
|---|
| 2710 |
pArg = pArg[1..$]; |
|---|
| 2711 |
if ((pArg == "-V") || (pArg == "-v")) |
|---|
| 2712 |
vVerbose = False; |
|---|
| 2713 |
for(int i = vCombinedArgs.length-1; i >= 0; i--) |
|---|
| 2714 |
{ |
|---|
| 2715 |
if (pArg[$-1] == '*') |
|---|
| 2716 |
{ |
|---|
| 2717 |
if (vCombinedArgs[i].begins(pArg[0..$-1]) == True) |
|---|
| 2718 |
{ |
|---|
| 2719 |
vCombinedArgs = vCombinedArgs[0..i] ~ |
|---|
| 2720 |
vCombinedArgs[i+1 .. $]; |
|---|
| 2721 |
break; |
|---|
| 2722 |
} |
|---|
| 2723 |
} |
|---|
| 2724 |
else if (vCombinedArgs[i] == pArg) |
|---|
| 2725 |
{ |
|---|
| 2726 |
vCombinedArgs = vCombinedArgs[0..i] ~ |
|---|
| 2727 |
vCombinedArgs[i+1 .. $]; |
|---|
| 2728 |
break; |
|---|
| 2729 |
} |
|---|
| 2730 |
} |
|---|
| 2731 |
} |
|---|
| 2732 |
else if (pArg[0] == '@') |
|---|
| 2733 |
ProcessResponseFile(pArg, vVerbose); |
|---|
| 2734 |
else if (pArg[0] == '+') |
|---|
| 2735 |
ProcessBuildConfig(pArg, vVerbose); |
|---|
| 2736 |
else |
|---|
| 2737 |
{ // Only add an argument if it is not already been added. |
|---|
| 2738 |
if ( !(pArg in lKnownArgs) ) |
|---|
| 2739 |
{ |
|---|
| 2740 |
vCombinedArgs ~= pArg; |
|---|
| 2741 |
lKnownArgs[pArg] = true; |
|---|
| 2742 |
} |
|---|
| 2743 |
} |
|---|
| 2744 |
} |
|---|
| 2745 |
|
|---|
| 2746 |
void GatherArgs( char[][] pArgs ) |
|---|
| 2747 |
{ |
|---|
| 2748 |
/* This collects together all the original command line arguments, |
|---|
| 2749 |
any command line arguments in any configuration files, and |
|---|
| 2750 |
the contents of any response files. |
|---|
| 2751 |
*/ |
|---|
| 2752 |
|
|---|
| 2753 |
// Collect from configuration file(s). |
|---|
| 2754 |
ProcessBuildConfig("+", vVerbose); |
|---|
| 2755 |
|
|---|
| 2756 |
// Collect from original command line. |
|---|
| 2757 |
foreach( char[] lArg; pArgs) |
|---|
| 2758 |
{ |
|---|
| 2759 |
GatherOneArg( lArg ); |
|---|
| 2760 |
} |
|---|
| 2761 |
|
|---|
| 2762 |
|
|---|
| 2763 |
} |
|---|
| 2764 |
|
|---|
| 2765 |
void ProcessMacroDefs(Bool pVerbose) |
|---|
| 2766 |
{ |
|---|
| 2767 |
// From build.exe location |
|---|
| 2768 |
ProcessOneMacroDef(pVerbose, std.path.getDirName(vAppPath)); |
|---|
| 2769 |
|
|---|
| 2770 |
// From compiler location |
|---|
| 2771 |
ProcessOneMacroDef(pVerbose, vCompilerPath); |
|---|
| 2772 |
|
|---|
| 2773 |
} |
|---|
| 2774 |
|
|---|
| 2775 |
void ProcessOneMacroDef(Bool pVerbose, char[] pPath) |
|---|
| 2776 |
{ |
|---|
| 2777 |
char[] lMacroDefFileName; |
|---|
| 2778 |
char[][] lMacroDefLines; |
|---|
| 2779 |
char[] lOpen; |
|---|
| 2780 |
char[] lClose; |
|---|
| 2781 |
char[] lEscapeOpen; |
|---|
| 2782 |
char[] lEscapeClose; |
|---|
| 2783 |
char[] lCommentLead; |
|---|
| 2784 |
static char[] lDefOpen = "\""; |
|---|
| 2785 |
static char[] lDefClose = "\""; |
|---|
| 2786 |
static char[] lDefEscapeOpen = "\\"; |
|---|
| 2787 |
static char[] lDefEscapeClose = ""; |
|---|
| 2788 |
static char[] lDefCommentLead = "#"; |
|---|
| 2789 |
|
|---|
| 2790 |
lOpen = lDefOpen; |
|---|
| 2791 |
lClose = lDefClose; |
|---|
| 2792 |
lEscapeOpen = lDefEscapeOpen; |
|---|
| 2793 |
lEscapeClose = lDefEscapeClose; |
|---|
| 2794 |
lCommentLead = lDefCommentLead; |
|---|
| 2795 |
|
|---|
| 2796 |
lMacroDefFileName = pPath.dup; |
|---|
| 2797 |
|
|---|
| 2798 |
if ((lMacroDefFileName.length > 0) && |
|---|
| 2799 |
(lMacroDefFileName[$-std.path.sep.length..$] != std.path.sep) ) |
|---|
| 2800 |
lMacroDefFileName ~= std.path.sep; |
|---|
| 2801 |
|
|---|
| 2802 |
lMacroDefFileName ~= "build.mdf"; |
|---|
| 2803 |
|
|---|
| 2804 |
|
|---|
| 2805 |
if ((pVerbose == True) && util.fileex.FileExists(lMacroDefFileName) ) |
|---|
| 2806 |
writefln("Build Macro Definition file %s", lMacroDefFileName); |
|---|
| 2807 |
lMacroDefLines = util.fileex.GetTextLines(lMacroDefFileName, util.fileex.GetOpt.Always); |
|---|
| 2808 |
|
|---|
| 2809 |
foreach(char[] lArg; lMacroDefLines) |
|---|
| 2810 |
{ |
|---|
| 2811 |
char[][] lOptions; |
|---|
| 2812 |
|
|---|
| 2813 |
lArg = ExpandEnvVar(lArg); |
|---|
| 2814 |
// Locate any comment text in the line. |
|---|
| 2815 |
int lPos = std.string.find(lArg, lCommentLead); |
|---|
| 2816 |
if (lPos != -1) |
|---|
| 2817 |
{ |
|---|
| 2818 |
// Truncate the line at the comment lead-in character. |
|---|
| 2819 |
lArg.length = lPos; |
|---|
| 2820 |
} |
|---|
| 2821 |
|
|---|
| 2822 |
lArg = std.string.strip(lArg); |
|---|
| 2823 |
if (lArg.length > 1) |
|---|
| 2824 |
{ |
|---|
| 2825 |
|
|---|
| 2826 |
if (lArg.begins("replace ") == True) |
|---|
| 2827 |
{ |
|---|
| 2828 |
int lStartPos; |
|---|
| 2829 |
int lEndPos; |
|---|
| 2830 |
bool lEndFound; |
|---|
| 2831 |
int lDepthInc; |
|---|
| 2832 |
int lDepth; |
|---|
| 2833 |
int lDataPos; |
|---|
| 2834 |
char[] lPattern; |
|---|
| 2835 |
char[] lResolution; |
|---|
| 2836 |
|
|---|
| 2837 |
lArg = std.string.strip(lArg[8..$]); |
|---|
| 2838 |
if (lOpen in vNestedDelim) |
|---|
| 2839 |
lDepthInc = 1; |
|---|
| 2840 |
else |
|---|
| 2841 |
lDepthInc = 0; |
|---|
| 2842 |
|
|---|
| 2843 |
// Format should be <open> <pattern> <close> <open> <resolution> <close> |
|---|
| 2844 |
lStartPos = 0; |
|---|
| 2845 |
lEndPos = lStartPos + lOpen.length; |
|---|
| 2846 |
while( (lEndPos < lArg.length) && |
|---|
| 2847 |
(lArg[lStartPos .. lEndPos] != lOpen) |
|---|
| 2848 |
) |
|---|
| 2849 |
{ |
|---|
| 2850 |
lStartPos ++; |
|---|
| 2851 |
lEndPos ++; |
|---|
| 2852 |
} |
|---|
| 2853 |
if (lEndPos >= lArg.length) |
|---|
| 2854 |
continue; // No open delim found. |
|---|
| 2855 |
lDepth += lDepthInc; |
|---|
| 2856 |
lDataPos = lEndPos; |
|---|
| 2857 |
lStartPos = lDataPos; |
|---|
| 2858 |
lEndPos = lStartPos + lClose.length; |
|---|
| 2859 |
while( (lEndPos < lArg.length) && |
|---|
| 2860 |
(lArg[lStartPos .. lEndPos] != lClose) |
|---|
| 2861 |
) |
|---|
| 2862 |
{ |
|---|
| 2863 |
lStartPos ++; |
|---|
| 2864 |
lEndPos ++; |
|---|
| 2865 |
} |
|---|
| 2866 |
if (lEndPos >= lArg.length) |
|---|
| 2867 |
continue; // No close delim found. |
|---|
| 2868 |
lPattern = std.string.strip(lArg[lDataPos .. lStartPos]); |
|---|
| 2869 |
|
|---|
| 2870 |
lStartPos = lEndPos; |
|---|
| 2871 |
lEndPos = lStartPos + lOpen.length; |
|---|
| 2872 |
while( (lEndPos < lArg.length) && |
|---|
| 2873 |
(lArg[lStartPos .. lEndPos] != lOpen) |
|---|
| 2874 |
) |
|---|
| 2875 |
{ |
|---|
| 2876 |
lStartPos ++; |
|---|
| 2877 |
lEndPos ++; |
|---|
| 2878 |
} |
|---|
| 2879 |
if (lEndPos >= lArg.length) |
|---|
| 2880 |
continue; // No open delim found. |
|---|
| 2881 |
lDepth += lDepthInc; |
|---|
| 2882 |
lDataPos = lEndPos; |
|---|
| 2883 |
lStartPos = lDataPos; |
|---|
| 2884 |
lEndPos = lStartPos + lClose.length; |
|---|
| 2885 |
while( (lEndPos < lArg.length) && |
|---|
| 2886 |
(lArg[lStartPos .. lEndPos] != lClose) |
|---|
| 2887 |
) |
|---|
| 2888 |
{ |
|---|
| 2889 |
lStartPos ++; |
|---|
| 2890 |
lEndPos ++; |
|---|
| 2891 |
} |
|---|
| 2892 |
if (lEndPos > lArg.length) |
|---|
| 2893 |
continue; // No close delim found. |
|---|
| 2894 |
lResolution = std.string.strip(lArg[lDataPos .. lStartPos]); |
|---|
| 2895 |
|
|---|
| 2896 |
vSubstitutions.length = vSubstitutions.length + 1; |
|---|
| 2897 |
vSubstitutions[$-1].Pattern = lPattern; |
|---|
| 2898 |
vSubstitutions[$-1].Resolution = lResolution; |
|---|
| 2899 |
vSubstitutions[$-1].EscapeOpen = lEscapeOpen; |
|---|
| 2900 |
vSubstitutions[$-1].EscapeClose = lEscapeClose; |
|---|
| 2901 |
|
|---|
| 2902 |
} |
|---|
| 2903 |
else if (lArg.begins("delim ") == True ) |
|---|
| 2904 |
{ |
|---|
| 2905 |
|
|---|
| 2906 |
lArg = std.string.strip(lArg[6..$]); |
|---|
| 2907 |
|
|---|
| 2908 |
lOptions = std.string.split(lArg); |
|---|
| 2909 |
foreach(char[] lOption; lOptions) |
|---|
| 2910 |
{ |
|---|
| 2911 |
if (lOption == "std") |
|---|
| 2912 |
{ |
|---|
| 2913 |
lOpen = lDefOpen; |
|---|
| 2914 |
lClose = lDefClose; |
|---|
| 2915 |
lEscapeOpen = lDefEscapeOpen; |
|---|
| 2916 |
lEscapeClose = lDefEscapeClose; |
|---|
| 2917 |
lCommentLead = lDefCommentLead; |
|---|
| 2918 |
} |
|---|
| 2919 |
else |
|---|
| 2920 |
{ |
|---|
| 2921 |
char[][] lKeyValue; |
|---|
| 2922 |
lKeyValue = std.string.split(lOption, "="); |
|---|
| 2923 |
switch (lKeyValue[0]) |
|---|
| 2924 |
{ |
|---|
| 2925 |
case "open": |
|---|
| 2926 |
lOpen = lKeyValue[1]; |
|---|
| 2927 |
break; |
|---|
| 2928 |
case "close": |
|---|
| 2929 |
lClose = lKeyValue[1]; |
|---|
| 2930 |
break; |
|---|
| 2931 |
case "escapeopen": |
|---|
| 2932 |
lEscapeOpen = lKeyValue[1]; |
|---|
| 2933 |
break; |
|---|
| 2934 |
case "escapeclose": |
|---|
| 2935 |
lEscapeClose = lKeyValue[1]; |
|---|
| 2936 |
break; |
|---|
| 2937 |
case "comment": |
|---|
| 2938 |
lCommentLead = lKeyValue[1]; |
|---|
| 2939 |
break; |
|---|
| 2940 |
default: |
|---|
| 2941 |
if (pVerbose == True) |
|---|
| 2942 |
writefln("Bad Macro 'delim' option '%s'", |
|---|
| 2943 |
lOption); |
|---|
| 2944 |
// Ignore bad options. |
|---|
| 2945 |
break; |
|---|
| 2946 |
} |
|---|
| 2947 |
} |
|---|
| 2948 |
} |
|---|
| 2949 |
} |
|---|
| 2950 |
else if (vVerbose == True) |
|---|
| 2951 |
{ |
|---|
| 2952 |
writefln("Bad configuration command '%s'", lArg); |
|---|
| 2953 |
} |
|---|
| 2954 |
} |
|---|
| 2955 |
} |
|---|
| 2956 |
} |
|---|
| 2957 |
|
|---|
| 2958 |
void ProcessBuildConfig(char[] pArg, Bool pVerbose) |
|---|
| 2959 |
{ |
|---|
| 2960 |
// From build.exe location |
|---|
| 2961 |
ProcessOneBuildConfig(pArg, pVerbose, std.path.getDirName(vAppPath)); |
|---|
| 2962 |
|
|---|
| 2963 |
// From compiler location |
|---|
| 2964 |
ProcessOneBuildConfig(pArg, pVerbose, vCompilerPath); |
|---|
| 2965 |
|
|---|
| 2966 |
// From current location |
|---|
| 2967 |
ProcessOneBuildConfig(pArg, pVerbose, util.pathex.GetInitCurDir() ); |
|---|
| 2968 |
|
|---|
| 2969 |
} |
|---|
| 2970 |
|
|---|
| 2971 |
void ProcessOneBuildConfig(char[] pArg, Bool pVerbose, char[] pPath) |
|---|
| 2972 |
{ |
|---|
| 2973 |
char[] lConfigFileName; |
|---|
| 2974 |
char[][] lConfigLines; |
|---|
| 2975 |
bool lFoundGroup; |
|---|
| 2976 |
|
|---|
| 2977 |
|
|---|
| 2978 |
lConfigFileName = pPath.dup; |
|---|
| 2979 |
|
|---|
| 2980 |
if ((lConfigFileName.length > 0) && |
|---|
| 2981 |
(lConfigFileName[$-std.path.sep.length..$] != std.path.sep) ) |
|---|
| 2982 |
lConfigFileName ~= std.path.sep; |
|---|
| 2983 |
|
|---|
| 2984 |
lConfigFileName ~= "build.cfg"; |
|---|
| 2985 |
|
|---|
| 2986 |
if ((pVerbose == True) && util.fileex.FileExists(lConfigFileName)) |
|---|
| 2987 |
writefln("Build Configuration file %s [%s]", lConfigFileName, pArg); |
|---|
| 2988 |
|
|---|
| 2989 |
lConfigLines = util.fileex.GetTextLines(lConfigFileName, util.fileex.GetOpt.Always); |
|---|
| 2990 |
if (pArg.length == 1) |
|---|
| 2991 |
lFoundGroup = true; |
|---|
| 2992 |
else |
|---|
| 2993 |
{ |
|---|
| 2994 |
lFoundGroup = false; |
|---|
| 2995 |
pArg = pArg[1..$]; |
|---|
| 2996 |
} |
|---|
| 2997 |
|
|---|
| 2998 |
foreach(char[] lArg; lConfigLines) |
|---|
| 2999 |
{ |
|---|
| 3000 |
lArg = ExpandEnvVar(lArg); |
|---|
| 3001 |
if (!lFoundGroup) |
|---|
| 3002 |
{ |
|---|
| 3003 |
if (lArg == "[" ~ pArg ~ "]") |
|---|
| 3004 |
{ |
|---|
| 3005 |
lFoundGroup = true; |
|---|
| 3006 |
continue; |
|---|
| 3007 |
} |
|---|
| 3008 |
} |
|---|
| 3009 |
|
|---|
| 3010 |
if (lFoundGroup) |
|---|
| 3011 |
{ |
|---|
| 3012 |
// Locate any comment text in the line. |
|---|
| 3013 |
int lPos = std.string.find(lArg, "#"); |
|---|
| 3014 |
if (lPos != -1) |
|---|
| 3015 |
{ |
|---|
| 3016 |
// Truncate the line at the '#' character. |
|---|
| 3017 |
lArg.length = lPos; |
|---|
| 3018 |
} |
|---|
| 3019 |
|
|---|
| 3020 |
lArg = std.string.strip(lArg); |
|---|
| 3021 |
if (lArg.length > 1) |
|---|
| 3022 |
{ |
|---|
| 3023 |
if ((lArg[0] == '[') && (lArg[$-1] == ']')) |
|---|
| 3024 |
break; // Don't process any more lines. |
|---|
| 3025 |
|
|---|
| 3026 |
if (pVerbose == True) |
|---|
| 3027 |
writefln("Build Configuration file arg: %s", lArg); |
|---|
| 3028 |
|
|---|
| 3029 |
|
|---|
| 3030 |
while ((lPos = find(lArg, "{Group}")) != -1) |
|---|
| 3031 |
{ |
|---|
| 3032 |
lArg = lArg[0..lPos] ~ pArg ~ lArg[lPos + 7 .. $]; |
|---|
| 3033 |
} |
|---|
| 3034 |
|
|---|
| 3035 |
if (lArg.begins("CMDLINE=") == True) |
|---|
| 3036 |
{ |
|---|
| 3037 |
int lStartPos; |
|---|
| 3038 |
int lEndPos; |
|---|
| 3039 |
bool lEndFound; |
|---|
| 3040 |
lArg = std.string.strip(lArg[8..$]); |
|---|
| 3041 |
lStartPos = 0; |
|---|
| 3042 |
lEndPos = 0; |
|---|
| 3043 |
lEndFound = false; |
|---|
| 3044 |
while(lEndPos < lArg.length) |
|---|
| 3045 |
{ |
|---|
| 3046 |
if (!lEndFound) |
|---|
| 3047 |
{ |
|---|
| 3048 |
if (lArg[lEndPos] == ' ') |
|---|
| 3049 |
{ |
|---|
| 3050 |
lEndFound = true; |
|---|
| 3051 |
} |
|---|
| 3052 |
} |
|---|
| 3053 |
else |
|---|
| 3054 |
{ |
|---|
| 3055 |
if (find("-+@", lArg[lEndPos..lEndPos+1]) != -1) |
|---|
| 3056 |
{ |
|---|
| 3057 |
GatherOneArg( lArg[lStartPos..lEndPos] ); |
|---|
| 3058 |
lStartPos = lEndPos; |
|---|
| 3059 |
lEndFound = false; |
|---|
| 3060 |
} |
|---|
| 3061 |
} |
|---|
| 3062 |
lEndPos++; |
|---|
| 3063 |
} |
|---|
| 3064 |
if (lStartPos != lEndPos) |
|---|
| 3065 |
GatherOneArg( lArg[lStartPos..lEndPos] ); |
|---|
| 3066 |
|
|---|
| 3067 |
} |
|---|
| 3068 |
else if (lArg.begins("LIBCMD=") == True) |
|---|
| 3069 |
{ |
|---|
| 3070 |
int lPos; |
|---|
| 3071 |
|
|---|
| 3072 |
while( (lPos = find(lArg, "\"")) != -1) |
|---|
| 3073 |
{ |
|---|
| 3074 |
lArg = lArg[0..lPos] ~ lArg[lPos+1 .. $]; |
|---|
| 3075 |
} |
|---|
| 3076 |
vLibrarianPath = std.path.getDirName(lArg[7..$]) ~ std.path.sep; |
|---|
| 3077 |
vLibrarianPath = util.pathex.CanonicalPath(vLibrarianPath); |
|---|
| 3078 |
|
|---|
| 3079 |
vLibrarian = std.path.getBaseName(lArg[7..$]); |
|---|
| 3080 |
if(vVerbose == True) { |
|---|
| 3081 |
writefln(" librarian path %s",vLibrarianPath); |
|---|
| 3082 |
writefln(" librarian is %s",vLibrarian); |
|---|
| 3083 |
} |
|---|
| 3084 |
} |
|---|
| 3085 |
else if (lArg.begins("LINKSWITCH=") == True) |
|---|
| 3086 |
{ |
|---|
| 3087 |
vLinkerDefSwitches = lArg[11..$].dup; |
|---|
| 3088 |
} |
|---|
| 3089 |
else if (vVerbose == True) |
|---|
| 3090 |
{ |
|---|
| 3091 |
writefln("Bad configuration command '%s'", lArg); |
|---|
| 3092 |
} |
|---|
| 3093 |
} |
|---|
| 3094 |
} |
|---|
| 3095 |
} |
|---|
| 3096 |
} |
|---|