mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 00:20:40 +03:00
Use LLVM-style command line (instead of DMD-style)
Note: For a backward compatible interface, use the new bin/ldmd script. It supports all old options while passing on anything it doesn't recognize. Some changes caused by this: * -debug and -version are now -d-debug and -d-version due to a conflict with standard LLVM options. * All "flag" options now allow an optional =true/=1/=false/=0 suffix. * Some "hidden debug switches" starting with "--" were renamed because LLVM doesn't care about the number of dashes, so they were conflicting with other options (such as -c). The new versions start with "-hidden-debug-" instead of "--" * --help works, but has a non-zero exit code. This breaks some Tango scripts which use it to test for compiler existence. See tango.patch. Some changes not (directly) caused by this; * (-enable/-disable)-FOO options are now available for pre- and postconditions. * -march is used instead of -m (like other LLVM programs), but -m is an alias for it. * -defaultlib, -debuglib, -d-debug and -d-version allow comma-separated values. The effect should be identical to specifying the same option multiple times. I decided against allowing these for some other options because paths might contain commas on some systems. * -fPIC is removed in favor of the standard LLVM option -relocation-model=pic Bug: * If -run is specified as the last argument in DFLAGS, no error is generated. (Not very serious IMHO)
This commit is contained in:
parent
6a02292c10
commit
b3d87205ad
17 changed files with 908 additions and 549 deletions
41
bin/ldmd
Executable file
41
bin/ldmd
Executable file
|
@ -0,0 +1,41 @@
|
|||
#! /usr/bin/env bash
|
||||
|
||||
# Default to 'ldc' next to this file
|
||||
LDC=`basename "$0"`/ldc
|
||||
if [ ! -x "$LDC" ]; then
|
||||
# If that doesn't work, assume this script was called via $PATH
|
||||
# and do the same for ldc
|
||||
if which ldc &> /dev/null; then
|
||||
LDC=ldc
|
||||
else
|
||||
echo 'ldc not found, check your installation' >/dev/stderr
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
declare -a ARGS
|
||||
SeenFile=0
|
||||
IDX=0
|
||||
for arg; do
|
||||
case "$arg" in
|
||||
-debug|-debug=*|-version=*)
|
||||
arg="-d$arg"
|
||||
;;
|
||||
-fPIC)
|
||||
arg="-relocation-model=pic"
|
||||
;;
|
||||
--a|--b|--c|--f|--r|--w|--x|--y)
|
||||
# "Hidden debug switches"
|
||||
# Are these ever used?
|
||||
arg="-hidden-debug${arg:1}"
|
||||
;;
|
||||
-*)
|
||||
;;
|
||||
*)
|
||||
SeenFile=1
|
||||
;;
|
||||
esac
|
||||
ARGS[IDX++]="$arg"
|
||||
done
|
||||
|
||||
exec "$LDC" "${ARGS[@]}"
|
11
dmd/attrib.c
11
dmd/attrib.c
|
@ -33,6 +33,15 @@
|
|||
|
||||
#include "../gen/enums.h"
|
||||
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore",
|
||||
llvm::cl::desc("Ignore unsupported pragmas"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
|
||||
|
||||
extern void obj_includelib(const char *name);
|
||||
void obj_startaddress(Symbol *s);
|
||||
|
||||
|
@ -962,7 +971,7 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||
|
||||
#endif // LDC
|
||||
|
||||
else if (global.params.ignoreUnsupportedPragmas)
|
||||
else if (ignoreUnsupportedPragmas)
|
||||
{
|
||||
if (global.params.verbose)
|
||||
{
|
||||
|
|
644
dmd/mars.c
644
dmd/mars.c
|
@ -40,6 +40,42 @@
|
|||
#include "gen/linker.h"
|
||||
#include "revisions.h"
|
||||
|
||||
#include "gen/cl_options.h"
|
||||
#include "gen/cl_helpers.h"
|
||||
using namespace opts;
|
||||
|
||||
|
||||
static cl::opt<bool> forceBE("forcebe",
|
||||
cl::desc("Force big-endian"),
|
||||
cl::Hidden,
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static cl::opt<bool> noDefaultLib("nodefaultlib",
|
||||
cl::desc("Don't add a default library for linking implicitly"),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static ArrayAdapter impPathsStore("I", global.params.imppath);
|
||||
static cl::list<std::string, ArrayAdapter> importPaths("I",
|
||||
cl::desc("Where to look for imports"),
|
||||
cl::value_desc("path"),
|
||||
cl::location(impPathsStore),
|
||||
cl::Prefix);
|
||||
|
||||
static ArrayAdapter defaultLibStore("defaultlib", global.params.defaultlibnames);
|
||||
static cl::list<std::string, ArrayAdapter> defaultlibs("defaultlib",
|
||||
cl::desc("Set default libraries for non-debug build"),
|
||||
cl::value_desc("lib,..."),
|
||||
cl::location(defaultLibStore),
|
||||
cl::CommaSeparated);
|
||||
|
||||
static ArrayAdapter debugLibStore("debuglib", global.params.debuglibnames);
|
||||
static cl::list<std::string, ArrayAdapter> debuglibs("debuglib",
|
||||
cl::desc("Set default libraries for debug build"),
|
||||
cl::value_desc("lib,..."),
|
||||
cl::location(debugLibStore),
|
||||
cl::CommaSeparated);
|
||||
|
||||
|
||||
void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
|
||||
|
||||
Global global;
|
||||
|
@ -68,13 +104,17 @@ Global::Global()
|
|||
llvm_version = LLVM_REV;
|
||||
global.structalign = 8;
|
||||
|
||||
memset(¶ms, 0, sizeof(Param));
|
||||
// This should only be used as a global, so the other fields are
|
||||
// automatically initialized to zero when the program is loaded.
|
||||
// In particular, DO NOT zero-initialize .params here (like DMD
|
||||
// does) because command-line options initialize some of those
|
||||
// fields to non-zero defaults, and do so from constructors that
|
||||
// may run before this one.
|
||||
}
|
||||
|
||||
char *Loc::toChars() const
|
||||
{
|
||||
OutBuffer buf;
|
||||
char *p;
|
||||
|
||||
if (filename)
|
||||
{
|
||||
|
@ -150,98 +190,49 @@ void halt()
|
|||
extern void backend_init();
|
||||
extern void backend_term();
|
||||
|
||||
void usage()
|
||||
{
|
||||
void printVersion() {
|
||||
printf("LLVM D Compiler %s\nbased on DMD %s and %s\n%s\n%s\n",
|
||||
global.ldc_version, global.version, global.llvm_version, global.copyright, global.written);
|
||||
printf("\
|
||||
D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
|
||||
LDC Homepage: http://www.dsource.org/projects/ldc\n\
|
||||
Usage:\n\
|
||||
ldc files.d ... { -switch }\n\
|
||||
\n\
|
||||
files.d D source files\n%s\
|
||||
-o- do not write object file\n\
|
||||
-od<objdir> write object files to directory <objdir>\n\
|
||||
-op do not strip paths from source file\n\
|
||||
-oq write object files with fully qualified names\n\
|
||||
-of<filename> name output file to <filename>\n\
|
||||
if -c and extension of <filename> is known, it determines the output type\n\
|
||||
\n\
|
||||
-output-ll write LLVM IR\n\
|
||||
-output-bc write LLVM bitcode\n\
|
||||
-output-s write native assembly\n\
|
||||
-output-o write native object (default if no -output switch passed)\n\
|
||||
\n\
|
||||
-c do not link\n\
|
||||
-L<linkerflag> pass <linkerflag> to linker\n\
|
||||
\n\
|
||||
-w enable warnings\n\
|
||||
\n\
|
||||
-H generate 'header' file\n\
|
||||
-Hd<hdrdir> write 'header' file to <hdrdir> directory\n\
|
||||
-Hf<filename> write 'header' file to <filename>\n\
|
||||
\n\
|
||||
-D generate documentation\n\
|
||||
-Dd<docdir> write documentation file to <docdir> directory\n\
|
||||
-Df<filename> write documentation file to <filename>\n\
|
||||
\n\
|
||||
Codegen control:\n\
|
||||
-m<arch> emit code specific to <arch> being one of:\n\
|
||||
x86 x86-64 ppc32 ppc64 arm thumb\n\
|
||||
-t<os> emit code specific to <os> being one of:\n\
|
||||
Linux, Windows, MacOSX, FreeBSD, Solaris\n\
|
||||
\n\
|
||||
-g, -gc add symbolic debug info\n\
|
||||
\n\
|
||||
-O optimize, same as -O2\n\
|
||||
-O<n> optimize at level <n> (0-5)\n\
|
||||
-inline do function inlining\n\
|
||||
\n\
|
||||
-debug enables asserts, invariants, contracts, boundscheck\n\
|
||||
and sets debug=1\n\
|
||||
-release disables asserts, invariants, contracts, boundscheck\n\
|
||||
\n\
|
||||
-enable-<feature> and\n\
|
||||
-disable-<feature> where <feature> is one of\n\
|
||||
asserts assert statements (default: on)\n\
|
||||
invariants class and struct invariants (default: on)\n\
|
||||
contracts function contracts (default: on)\n\
|
||||
boundscheck array bounds checking (default: on)\n\
|
||||
-debug=level compile in debug stmts <= level (default: 0)\n\
|
||||
-debug=ident compile in debug stmts identified by ident\n\
|
||||
-version=level compile in version code >= level\n\
|
||||
-version=ident compile in version code identified by ident\n\
|
||||
\n\
|
||||
-noasm do not allow use of inline asm\n\
|
||||
-noruntime do not allow code that generates implicit runtime calls\n\
|
||||
-noverify do not run the validation pass before writing bitcode\n\
|
||||
-unittest compile in unit tests\n\
|
||||
-d allow deprecated features\n\
|
||||
\n\
|
||||
-annotate annotate the bitcode with human readable source code\n\
|
||||
-ignore ignore unsupported pragmas\n\
|
||||
\n\
|
||||
Path options:\n\
|
||||
-I<path> where to look for imports\n\
|
||||
-J<path> where to look for string imports\n\
|
||||
-defaultlib=name set default library for non-debug build\n\
|
||||
-debuglib=name set default library for debug build\n\
|
||||
-nodefaultlib don't add a default library for linking implicitly\n\
|
||||
\n\
|
||||
Misc options:\n\
|
||||
-v verbose\n\
|
||||
-vv very verbose (does not include -v)\n\
|
||||
-quiet suppress unnecessary messages\n\
|
||||
-run srcfile args... run resulting program, passing args\n\
|
||||
--help print help\n\
|
||||
",
|
||||
#if WIN32
|
||||
" @cmdfile read arguments from cmdfile\n"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
printf("D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n"
|
||||
"LDC Homepage: http://www.dsource.org/projects/ldc\n");
|
||||
}
|
||||
|
||||
// Helper function to handle -d-debug=* and -d-version=*
|
||||
static void processVersions(std::vector<std::string>& list, char* type,
|
||||
void (*setLevel)(unsigned), void (*addIdent)(char*)) {
|
||||
typedef std::vector<std::string>::iterator It;
|
||||
|
||||
for(It I = list.begin(), E = list.end(); I != E; ++I) {
|
||||
const char* value = I->c_str();
|
||||
if (isdigit(value[0])) {
|
||||
errno = 0;
|
||||
char* end;
|
||||
long level = strtol(value, &end, 10);
|
||||
if (*end || errno || level > INT_MAX) {
|
||||
error("Invalid %s level: %s", type, I->c_str());
|
||||
} else {
|
||||
setLevel((unsigned)level);
|
||||
}
|
||||
} else {
|
||||
char* cstr = mem.strdup(value);
|
||||
if (Lexer::isValidIdentifier(cstr)) {
|
||||
addIdent(cstr);
|
||||
continue;
|
||||
} else {
|
||||
error("Invalid %s identifier or level: '%s'", type, I->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to handle -of, -od, etc.
|
||||
static void initFromString(char*& dest, const cl::opt<std::string>& src) {
|
||||
dest = 0;
|
||||
if (src.getNumOccurrences() != 0) {
|
||||
if (src.empty())
|
||||
error("Expected argument to '-%s'", src.ArgStr);
|
||||
dest = mem.strdup(src.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -251,28 +242,6 @@ int main(int argc, char *argv[])
|
|||
char *p, *ext;
|
||||
Module *m;
|
||||
int status = EXIT_SUCCESS;
|
||||
int argcstart = argc;
|
||||
bool very_verbose = false;
|
||||
|
||||
// Check for malformed input
|
||||
if (argc < 1 || !argv)
|
||||
{
|
||||
Largs:
|
||||
error("missing or null command line arguments");
|
||||
fatal();
|
||||
}
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if (!argv[i])
|
||||
goto Largs;
|
||||
}
|
||||
|
||||
#if __DMC__ // DMC unique support for response files
|
||||
if (response_expand(&argc,&argv)) // expand response files
|
||||
error("can't open response file");
|
||||
#endif
|
||||
|
||||
files.reserve(argc - 1);
|
||||
|
||||
// Set default values
|
||||
#if _WIN32
|
||||
|
@ -282,20 +251,7 @@ int main(int argc, char *argv[])
|
|||
#else
|
||||
global.params.argv0 = argv[0];
|
||||
#endif
|
||||
global.params.link = 1;
|
||||
global.params.useAssert = 1;
|
||||
global.params.useInvariants = 1;
|
||||
global.params.useIn = 1;
|
||||
global.params.useOut = 1;
|
||||
global.params.useArrayBounds = 1;
|
||||
global.params.useSwitchError = 1;
|
||||
global.params.useInline = 0; // this one messes things up to a point where codegen breaks
|
||||
global.params.llvmInline = 0; // use this one instead to know if inline passes should be run
|
||||
global.params.obj = 1;
|
||||
global.params.Dversion = 2;
|
||||
global.params.quiet = 1;
|
||||
|
||||
global.params.output_o = OUTPUTFLAGdefault;
|
||||
|
||||
global.params.linkswitches = new Array();
|
||||
global.params.libfiles = new Array();
|
||||
|
@ -315,14 +271,6 @@ int main(int argc, char *argv[])
|
|||
fatal();
|
||||
}
|
||||
|
||||
global.params.llvmArch = 0;
|
||||
global.params.forceBE = 0;
|
||||
global.params.noruntime = 0;
|
||||
global.params.novalidate = 0;
|
||||
global.params.optimizeLevel = -1;
|
||||
global.params.runtimeImppath = 0;
|
||||
global.params.useInlineAsm = 1;
|
||||
|
||||
// Predefine version identifiers
|
||||
#if IN_LLVM
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
||||
|
@ -365,362 +313,81 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
#endif
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
p = argv[i];
|
||||
if (*p == '-')
|
||||
{
|
||||
if (strcmp(p + 1, "d") == 0)
|
||||
global.params.useDeprecated = 1;
|
||||
else if (strcmp(p + 1, "c") == 0)
|
||||
global.params.link = 0;
|
||||
else if (strcmp(p + 1, "fPIC") == 0)
|
||||
global.params.pic = 1;
|
||||
else if (strcmp(p + 1, "g") == 0)
|
||||
global.params.symdebug = 1;
|
||||
else if (strcmp(p + 1, "gc") == 0)
|
||||
global.params.symdebug = 2;
|
||||
else if (strcmp(p + 1, "v") == 0)
|
||||
global.params.verbose = 1;
|
||||
else if (strcmp(p + 1, "vv") == 0) {
|
||||
Logger::enable();
|
||||
very_verbose = true;
|
||||
}
|
||||
else if (strcmp(p + 1, "v1") == 0)
|
||||
global.params.Dversion = 1;
|
||||
else if (strcmp(p + 1, "w") == 0)
|
||||
global.params.warnings = 1;
|
||||
else if (p[1] == 'O')
|
||||
{
|
||||
global.params.optimize = 1;
|
||||
global.params.optimizeLevel = 2;
|
||||
if (p[2] != 0) {
|
||||
int optlevel = atoi(p+2);
|
||||
if (optlevel < 0 || optlevel > 5) {
|
||||
error("Optimization level must be between 0 and 5. Using default (%d)",
|
||||
global.params.optimizeLevel);
|
||||
}
|
||||
else {
|
||||
global.params.optimizeLevel = optlevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(p + 1, "forcebe") == 0)
|
||||
global.params.forceBE = 1;
|
||||
else if (strcmp(p + 1, "noruntime") == 0)
|
||||
global.params.noruntime = 1;
|
||||
else if (strcmp(p + 1, "noverify") == 0)
|
||||
global.params.novalidate = 1;
|
||||
else if (strcmp(p + 1, "annotate") == 0)
|
||||
global.params.llvmAnnotate = 1;
|
||||
else if (strncmp(p + 1, "enable-", 7) == 0 ||
|
||||
strncmp(p + 1, "disable-", 8) == 0)
|
||||
{
|
||||
bool enable = (p[1] == 'e');
|
||||
char* feature = p + 1 + (enable ? 7 : 8);
|
||||
if (strcmp(feature, "asserts") == 0)
|
||||
global.params.useAssert = enable;
|
||||
else if (strcmp(feature, "boundscheck") == 0)
|
||||
global.params.useArrayBounds = enable;
|
||||
else if (strcmp(feature, "contracts") == 0)
|
||||
{
|
||||
global.params.useIn = enable;
|
||||
global.params.useOut = enable;
|
||||
}
|
||||
else if (strcmp(feature, "invariants") == 0)
|
||||
global.params.useInvariants = enable;
|
||||
else
|
||||
error("unrecognized feature '%s'", feature);
|
||||
}
|
||||
else if (strcmp(p + 1, "noasm") == 0)
|
||||
global.params.useInlineAsm = 0;
|
||||
else if (strcmp(p + 1, "nodefaultlib") == 0)
|
||||
global.params.noDefaultLib = 1;
|
||||
else if (p[1] == 'o')
|
||||
{
|
||||
switch (p[2])
|
||||
{
|
||||
case '-':
|
||||
global.params.obj = 0;
|
||||
break;
|
||||
cl::SetVersionPrinter(&printVersion);
|
||||
cl::ParseCommandLineOptions(argc, argv, "LLVM-based D Compiler\n");
|
||||
|
||||
case 'd':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
global.params.objdir = p + 3;
|
||||
break;
|
||||
global.params.optimize = (global.params.optimizeLevel >= 0);
|
||||
|
||||
case 'f':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
global.params.objname = p + 3;
|
||||
break;
|
||||
// Negated options
|
||||
global.params.link = !compileOnly;
|
||||
global.params.obj = !dontWriteObj;
|
||||
global.params.useInlineAsm = !noAsm;
|
||||
|
||||
case 'p':
|
||||
if (p[3])
|
||||
goto Lerror;
|
||||
global.params.preservePaths = 1;
|
||||
break;
|
||||
// String options: std::string --> char*
|
||||
initFromString(global.params.objname, objectFile);
|
||||
initFromString(global.params.objdir, objectDir);
|
||||
|
||||
case 'q':
|
||||
if (p[3])
|
||||
goto Lerror;
|
||||
global.params.fqnNames = 1;
|
||||
break;
|
||||
initFromString(global.params.docdir, ddocDir);
|
||||
initFromString(global.params.docname, ddocFile);
|
||||
global.params.doDocComments |=
|
||||
global.params.docdir || global.params.docname;
|
||||
|
||||
case 'u':
|
||||
if (strncmp(p+1, "output-", 7) != 0)
|
||||
goto Lerror;
|
||||
|
||||
// remove default output
|
||||
if (global.params.output_o == OUTPUTFLAGdefault)
|
||||
global.params.output_o = OUTPUTFLAGno;
|
||||
|
||||
if (strcmp(p+8, global.ll_ext) == 0)
|
||||
global.params.output_ll = OUTPUTFLAGset;
|
||||
else if (strcmp(p+8, global.bc_ext) == 0)
|
||||
global.params.output_bc = OUTPUTFLAGset;
|
||||
else if (strcmp(p+8, global.s_ext) == 0)
|
||||
global.params.output_s = OUTPUTFLAGset;
|
||||
else if (strcmp(p+8, global.obj_ext) == 0)
|
||||
global.params.output_o = OUTPUTFLAGset;
|
||||
else
|
||||
goto Lerror;
|
||||
|
||||
break;
|
||||
|
||||
case 0:
|
||||
error("-o no longer supported, use -of or -od");
|
||||
break;
|
||||
|
||||
default:
|
||||
goto Lerror;
|
||||
}
|
||||
}
|
||||
else if (p[1] == 'D')
|
||||
{ global.params.doDocComments = 1;
|
||||
switch (p[2])
|
||||
{
|
||||
case 'd':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
global.params.docdir = p + 3;
|
||||
break;
|
||||
case 'f':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
global.params.docname = p + 3;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
goto Lerror;
|
||||
}
|
||||
}
|
||||
#ifdef _DH
|
||||
else if (p[1] == 'H')
|
||||
{ global.params.doHdrGeneration = 1;
|
||||
switch (p[2])
|
||||
{
|
||||
case 'd':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
global.params.hdrdir = p + 3;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (!p[3])
|
||||
goto Lnoarg;
|
||||
global.params.hdrname = p + 3;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
goto Lerror;
|
||||
}
|
||||
}
|
||||
initFromString(global.params.hdrdir, hdrDir);
|
||||
initFromString(global.params.hdrname, hdrFile);
|
||||
global.params.doHdrGeneration |=
|
||||
global.params.hdrdir || global.params.hdrname;
|
||||
#endif
|
||||
else if (strcmp(p + 1, "ignore") == 0)
|
||||
global.params.ignoreUnsupportedPragmas = 1;
|
||||
else if (strcmp(p + 1, "inline") == 0) {
|
||||
// TODO
|
||||
// the ast rewrites dmd does for inlining messes up the ast.
|
||||
// someday maybe we can support it, for now llvm does an excellent job at inlining
|
||||
global.params.useInline = 0; //1
|
||||
global.params.llvmInline = 1;
|
||||
}
|
||||
else if (strcmp(p + 1, "quiet") == 0)
|
||||
global.params.quiet = 1;
|
||||
else if (strcmp(p + 1, "release") == 0)
|
||||
{
|
||||
global.params.useInvariants = 0;
|
||||
global.params.useIn = 0;
|
||||
global.params.useOut = 0;
|
||||
global.params.useAssert = 0;
|
||||
global.params.useArrayBounds = 0;
|
||||
}
|
||||
else if (strcmp(p + 1, "unittest") == 0)
|
||||
global.params.useUnitTests = 1;
|
||||
else if (p[1] == 'I')
|
||||
{
|
||||
if (!global.params.imppath)
|
||||
global.params.imppath = new Array();
|
||||
global.params.imppath->push(p + 2);
|
||||
}
|
||||
else if (p[1] == 'J')
|
||||
{
|
||||
if (!global.params.fileImppath)
|
||||
global.params.fileImppath = new Array();
|
||||
global.params.fileImppath->push(p + 2);
|
||||
}
|
||||
else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
|
||||
{
|
||||
// Parse:
|
||||
// -debug
|
||||
// -debug=number
|
||||
// -debug=identifier
|
||||
if (p[6] == '=')
|
||||
{
|
||||
if (isdigit(p[7]))
|
||||
{ long level;
|
||||
|
||||
errno = 0;
|
||||
level = strtol(p + 7, &p, 10);
|
||||
if (*p || errno || level > INT_MAX)
|
||||
goto Lerror;
|
||||
DebugCondition::setGlobalLevel((int)level);
|
||||
}
|
||||
else if (Lexer::isValidIdentifier(p + 7))
|
||||
DebugCondition::addGlobalIdent(p + 7);
|
||||
else
|
||||
goto Lerror;
|
||||
}
|
||||
else if (p[6])
|
||||
goto Lerror;
|
||||
else
|
||||
{
|
||||
global.params.useInvariants = 1;
|
||||
global.params.useIn = 1;
|
||||
global.params.useOut = 1;
|
||||
global.params.useAssert = 1;
|
||||
global.params.useArrayBounds = 1;
|
||||
global.params.debuglevel = 1;
|
||||
}
|
||||
}
|
||||
else if (memcmp(p + 1, "version", 5) == 0)
|
||||
{
|
||||
// Parse:
|
||||
// -version=number
|
||||
// -version=identifier
|
||||
if (p[8] == '=')
|
||||
{
|
||||
if (isdigit(p[9]))
|
||||
{ long level;
|
||||
processVersions(debugArgs, "debug",
|
||||
DebugCondition::setGlobalLevel,
|
||||
DebugCondition::addGlobalIdent);
|
||||
processVersions(versions, "version",
|
||||
VersionCondition::setGlobalLevel,
|
||||
VersionCondition::addGlobalIdent);
|
||||
|
||||
errno = 0;
|
||||
level = strtol(p + 9, &p, 10);
|
||||
if (*p || errno || level > INT_MAX)
|
||||
goto Lerror;
|
||||
VersionCondition::setGlobalLevel((int)level);
|
||||
}
|
||||
else if (Lexer::isValidIdentifier(p + 9))
|
||||
VersionCondition::addGlobalIdent(p + 9);
|
||||
else
|
||||
goto Lerror;
|
||||
}
|
||||
else
|
||||
goto Lerror;
|
||||
}
|
||||
else if (strcmp(p + 1, "-b") == 0)
|
||||
global.params.debugb = 1;
|
||||
else if (strcmp(p + 1, "-c") == 0)
|
||||
global.params.debugc = 1;
|
||||
else if (strcmp(p + 1, "-f") == 0)
|
||||
global.params.debugf = 1;
|
||||
else if (strcmp(p + 1, "-help") == 0)
|
||||
{ usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if (strcmp(p + 1, "-r") == 0)
|
||||
global.params.debugr = 1;
|
||||
else if (strcmp(p + 1, "-x") == 0)
|
||||
global.params.debugx = 1;
|
||||
else if (strcmp(p + 1, "-y") == 0)
|
||||
global.params.debugy = 1;
|
||||
else if (p[1] == 'L')
|
||||
{
|
||||
global.params.linkswitches->push(p + 2);
|
||||
}
|
||||
else if (memcmp(p + 1, "defaultlib=", 11) == 0)
|
||||
{
|
||||
if(!global.params.defaultlibnames)
|
||||
global.params.defaultlibnames = new Array();
|
||||
global.params.defaultlibnames->push(p + 1 + 11);
|
||||
}
|
||||
else if (memcmp(p + 1, "debuglib=", 9) == 0)
|
||||
{
|
||||
if(!global.params.debuglibnames)
|
||||
global.params.debuglibnames = new Array();
|
||||
global.params.debuglibnames->push(p + 1 + 9);
|
||||
}
|
||||
else if (strcmp(p + 1, "run") == 0)
|
||||
{ global.params.run = 1;
|
||||
global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
|
||||
if (global.params.runargs_length)
|
||||
{
|
||||
files.push(argv[i + 1]);
|
||||
global.params.runargs = &argv[i + 2];
|
||||
i += global.params.runargs_length;
|
||||
global.params.runargs_length--;
|
||||
}
|
||||
else
|
||||
{ global.params.run = 0;
|
||||
goto Lnoarg;
|
||||
}
|
||||
}
|
||||
else if (p[1] == 'm')
|
||||
{
|
||||
global.params.llvmArch = p+2;
|
||||
}
|
||||
else if (p[1] == 't')
|
||||
{
|
||||
if(strcmp(p + 2, "Linux") == 0)
|
||||
global.params.os = OSLinux;
|
||||
else if(strcmp(p + 2, "Windows") == 0)
|
||||
global.params.os = OSWindows;
|
||||
else if(strcmp(p + 2, "MacOSX") == 0)
|
||||
global.params.os = OSMacOSX;
|
||||
else if(strcmp(p + 2, "FreeBSD") == 0)
|
||||
global.params.os = OSFreeBSD;
|
||||
else if(strcmp(p + 2, "Solaris") == 0)
|
||||
global.params.os = OSSolaris;
|
||||
else
|
||||
error("unrecognized target os '%s'", p + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Lerror:
|
||||
error("unrecognized switch '%s'", argv[i]);
|
||||
continue;
|
||||
global.params.output_o =
|
||||
opts::output_o == cl::BOU_UNSET
|
||||
? OUTPUTFLAGdefault
|
||||
: opts::output_o == cl::BOU_TRUE
|
||||
? OUTPUTFLAGset
|
||||
: OUTPUTFLAGno;
|
||||
global.params.output_bc = opts::output_bc ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||
global.params.output_ll = opts::output_ll ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||
global.params.output_s = opts::output_s ? OUTPUTFLAGset : OUTPUTFLAGno;
|
||||
|
||||
Lnoarg:
|
||||
error("argument expected for switch '%s'", argv[i]);
|
||||
continue;
|
||||
if (global.params.run || !runargs.empty()) {
|
||||
// FIXME: how to properly detect the presence of a PositionalEatsArgs
|
||||
// option without parameters? We want to emit an error in that case...
|
||||
// You'd think getNumOccurrences would do it, but it just returns the
|
||||
// number of parameters)
|
||||
// NOTE: Hacked around it by detecting -run in getenv_setargv(), where
|
||||
// we're looking for it anyway, and pre-setting the flag...
|
||||
global.params.run = true;
|
||||
if (!runargs.empty()) {
|
||||
files.push(mem.strdup(runargs[0].c_str()));
|
||||
} else {
|
||||
global.params.run = false;
|
||||
error("Expected at least one argument to '-run'\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
files.push(p);
|
||||
}
|
||||
|
||||
if (mArch)
|
||||
global.params.llvmArch = mArch->Name;
|
||||
|
||||
files.reserve(fileList.size());
|
||||
typedef std::vector<std::string>::iterator It;
|
||||
for(It I = fileList.begin(), E = fileList.end(); I != E; ++I)
|
||||
if (!I->empty())
|
||||
files.push(mem.strdup(I->c_str()));
|
||||
|
||||
if (global.errors)
|
||||
{
|
||||
fatal();
|
||||
}
|
||||
if (files.dim == 0)
|
||||
{ usage();
|
||||
{
|
||||
cl::PrintHelpMessage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -740,7 +407,7 @@ int main(int argc, char *argv[])
|
|||
global.params.linkswitches->push(arg);
|
||||
}
|
||||
}
|
||||
else if (!global.params.noDefaultLib)
|
||||
else if (!noDefaultLib)
|
||||
{
|
||||
char *arg;
|
||||
arg = (char *)mem.malloc(64);
|
||||
|
@ -760,7 +427,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (global.params.run)
|
||||
global.params.quiet = 1;
|
||||
quiet = 1;
|
||||
|
||||
if (global.params.useUnitTests)
|
||||
global.params.useAssert = 1;
|
||||
|
@ -893,7 +560,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
assert(global.params.cpu != ARCHinvalid);
|
||||
|
||||
if (allowForceEndianness && global.params.forceBE) {
|
||||
if (allowForceEndianness && forceBE) {
|
||||
VersionCondition::addPredefinedGlobalIdent("BigEndian");
|
||||
global.params.isLE = false;
|
||||
}
|
||||
|
@ -1306,8 +973,24 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
|
|||
argv = new Array();
|
||||
argv->setDim(argc);
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
int argc_left = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!strcmp((*pargv)[i], "-run") || !strcmp((*pargv)[i], "--run")) {
|
||||
// HACK: set flag to indicate we saw '-run' here
|
||||
global.params.run = true;
|
||||
// Don't eat -run yet so the program arguments don't get changed
|
||||
argc_left = argc - i;
|
||||
argc = i;
|
||||
*pargv = &(*pargv)[i];
|
||||
argv->setDim(i);
|
||||
break;
|
||||
} else {
|
||||
argv->data[i] = (void *)(*pargv)[i];
|
||||
}
|
||||
}
|
||||
// HACK to stop required values from command line being drawn from DFLAGS
|
||||
argv->push((char*)"");
|
||||
argc++;
|
||||
|
||||
j = 1; // leave argv[0] alone
|
||||
while (1)
|
||||
|
@ -1382,6 +1065,11 @@ void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
|
|||
}
|
||||
|
||||
Ldone:
|
||||
assert(argc == argv->dim);
|
||||
argv->reserve(argc_left);
|
||||
for (int i = 0; i < argc_left; i++)
|
||||
argv->data[argc++] = (void *)(*pargv)[i];
|
||||
|
||||
*pargc = argc;
|
||||
*pargv = (char **)argv->data;
|
||||
}
|
||||
|
|
84
dmd/mars.h
84
dmd/mars.h
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -72,48 +73,40 @@ enum OS
|
|||
// Put command line switches in here
|
||||
struct Param
|
||||
{
|
||||
char obj; // write object file
|
||||
char link; // perform link
|
||||
char quiet; // suppress non-error messages
|
||||
char verbose; // verbose compile
|
||||
bool obj; // write object file
|
||||
bool link; // perform link
|
||||
bool verbose; // verbose compile
|
||||
char symdebug; // insert debug symbolic information
|
||||
char optimize; // run optimizer
|
||||
bool optimize; // run optimizer
|
||||
char optimizeLevel; // optimization level
|
||||
ARCH cpu; // target CPU
|
||||
OS os; // target OS
|
||||
char is64bit; // generate 64 bit code
|
||||
char isLE; // generate little endian code
|
||||
char scheduler; // which scheduler to use
|
||||
char useDeprecated; // allow use of deprecated features
|
||||
char useAssert; // generate runtime code for assert()'s
|
||||
char useInvariants; // generate class invariant checks
|
||||
char useIn; // generate precondition checks
|
||||
char useOut; // generate postcondition checks
|
||||
char useArrayBounds; // generate array bounds checks
|
||||
char useSwitchError; // check for switches without a default
|
||||
char useUnitTests; // generate unittest code
|
||||
char useInline; // inline expand functions
|
||||
char preservePaths; // !=0 means don't strip path from source file
|
||||
char warnings; // enable warnings
|
||||
char pic; // generate position-independent-code for shared libs
|
||||
char noruntime; // code is not allowed to make implicit calls to the runtime
|
||||
char novalidate;// no bitcode validation
|
||||
bool is64bit; // generate 64 bit code
|
||||
bool isLE; // generate little endian code
|
||||
bool useDeprecated; // allow use of deprecated features
|
||||
bool useAssert; // generate runtime code for assert()'s
|
||||
bool useInvariants; // generate class invariant checks
|
||||
bool useIn; // generate precondition checks
|
||||
bool useOut; // generate postcondition checks
|
||||
bool useArrayBounds; // generate array bounds checks
|
||||
bool useSwitchError; // check for switches without a default
|
||||
bool useUnitTests; // generate unittest code
|
||||
bool useInline; // inline expand functions
|
||||
bool warnings; // enable warnings
|
||||
char Dversion; // D version number
|
||||
char ignoreUnsupportedPragmas; // rather than error on them
|
||||
|
||||
char *argv0; // program name
|
||||
Array *imppath; // array of char*'s of where to look for import modules
|
||||
Array *fileImppath; // array of char*'s of where to look for file import modules
|
||||
char *runtimeImppath; // char* of where to look for the core runtime
|
||||
char *objdir; // .obj file output directory
|
||||
char *objname; // .obj file output name
|
||||
|
||||
char doDocComments; // process embedded documentation comments
|
||||
bool doDocComments; // process embedded documentation comments
|
||||
char *docdir; // write documentation file to docdir directory
|
||||
char *docname; // write documentation file to docname
|
||||
Array *ddocfiles; // macro include files for Ddoc
|
||||
|
||||
char doHdrGeneration; // process embedded documentation comments
|
||||
bool doHdrGeneration; // process embedded documentation comments
|
||||
char *hdrdir; // write 'header' file to docdir directory
|
||||
char *hdrname; // write 'header' file to docname
|
||||
|
||||
|
@ -131,18 +124,16 @@ struct Param
|
|||
char *xmlname; // filename for XML output
|
||||
|
||||
// Hidden debug switches
|
||||
char debuga;
|
||||
char debugb;
|
||||
char debugc;
|
||||
char debugf;
|
||||
char debugr;
|
||||
char debugw;
|
||||
char debugx;
|
||||
char debugy;
|
||||
bool debuga;
|
||||
bool debugb;
|
||||
bool debugc;
|
||||
bool debugf;
|
||||
bool debugr;
|
||||
bool debugw;
|
||||
bool debugx;
|
||||
bool debugy;
|
||||
|
||||
char run; // run resulting executable
|
||||
size_t runargs_length;
|
||||
char** runargs; // arguments for executable
|
||||
bool run; // run resulting executable
|
||||
|
||||
// Linker stuff
|
||||
Array *objfiles;
|
||||
|
@ -153,17 +144,14 @@ struct Param
|
|||
char *exefile;
|
||||
|
||||
// LDC stuff
|
||||
char *llvmArch;
|
||||
char forceBE;
|
||||
char output_ll;
|
||||
char output_bc;
|
||||
char output_s;
|
||||
char output_o;
|
||||
char llvmInline;
|
||||
char llvmAnnotate;
|
||||
char useInlineAsm;
|
||||
char fqnNames; // use fully qualified object names
|
||||
char noDefaultLib;
|
||||
const char *llvmArch;
|
||||
OUTPUTFLAG output_ll;
|
||||
OUTPUTFLAG output_bc;
|
||||
OUTPUTFLAG output_s;
|
||||
OUTPUTFLAG output_o;
|
||||
bool llvmInline;
|
||||
bool llvmAnnotate;
|
||||
bool useInlineAsm;
|
||||
|
||||
// target stuff
|
||||
char *targetTriple;
|
||||
|
|
17
dmd/module.c
17
dmd/module.c
|
@ -44,6 +44,19 @@
|
|||
#include "d-dmd-gcc.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
static llvm::cl::opt<bool> preservePaths("op",
|
||||
llvm::cl::desc("Do not strip paths from source file"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
static llvm::cl::opt<bool> fqnNames("oq",
|
||||
llvm::cl::desc("Write object files with fully qualified names"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
|
||||
|
||||
ClassDeclaration *Module::moduleinfo;
|
||||
|
||||
Module *Module::rootModule;
|
||||
|
@ -139,12 +152,12 @@ File* Module::buildFilePath(char* forcename, char* path, char* ext)
|
|||
argobj = forcename;
|
||||
else
|
||||
{
|
||||
if (global.params.preservePaths)
|
||||
if (preservePaths)
|
||||
argobj = (char*)this->arg;
|
||||
else
|
||||
argobj = FileName::name((char*)this->arg);
|
||||
|
||||
if (global.params.fqnNames)
|
||||
if (fqnNames)
|
||||
{
|
||||
if(md)
|
||||
argobj = FileName::replaceName(argobj, md->toChars());
|
||||
|
|
81
gen/cl_helpers.cpp
Normal file
81
gen/cl_helpers.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#include "gen/cl_helpers.h"
|
||||
|
||||
#include "dmd/root.h"
|
||||
#include "dmd/mem.h"
|
||||
|
||||
#include <cctype> // isupper, tolower
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace opts {
|
||||
|
||||
// Helper function
|
||||
static char toLower(char c) {
|
||||
if (isupper(c))
|
||||
return tolower(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
bool FlagParser::parse(cl::Option &O, const char *ArgName, const std::string &Arg, bool &Val) {
|
||||
// Make a std::string out of it to make comparisons easier
|
||||
// (and avoid repeated conversion)
|
||||
std::string argname = ArgName;
|
||||
|
||||
typedef std::vector<std::pair<std::string, bool> >::iterator It;
|
||||
for (It I = switches.begin(), E = switches.end(); I != E; ++I) {
|
||||
std::string name = I->first;
|
||||
if (name == argname
|
||||
|| (name.length() < argname.length()
|
||||
&& argname.substr(0, name.length()) == name
|
||||
&& argname[name.length()] == '=')) {
|
||||
|
||||
if (!cl::parser<bool>::parse(O, ArgName, Arg, Val)) {
|
||||
Val = (Val == I->second);
|
||||
return false;
|
||||
}
|
||||
// Invalid option value
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FlagParser::getExtraOptionNames(std::vector<const char*> &Names) {
|
||||
typedef std::vector<std::pair<std::string, bool> >::iterator It;
|
||||
for (It I = switches.begin() + 1, E = switches.end(); I != E; ++I) {
|
||||
Names.push_back(I->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MultiSetter::MultiSetter(bool invert, bool* p, ...) {
|
||||
this->invert = invert;
|
||||
if (p) {
|
||||
locations.push_back(p);
|
||||
va_list va;
|
||||
va_start(va, p);
|
||||
while (p = va_arg(va, bool*)) {
|
||||
locations.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MultiSetter::operator=(bool val) {
|
||||
typedef std::vector<bool*>::iterator It;
|
||||
for (It I = locations.begin(), E = locations.end(); I != E; ++I) {
|
||||
**I = (val != invert);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ArrayAdapter::push_back(const char* cstr) {
|
||||
if (!cstr || !*cstr)
|
||||
error("Expected argument to '-%s'", name);
|
||||
|
||||
if (!*arrp)
|
||||
*arrp = new Array;
|
||||
(*arrp)->push(mem.strdup(cstr));
|
||||
}
|
||||
|
||||
} // namespace opts
|
68
gen/cl_helpers.h
Normal file
68
gen/cl_helpers.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#ifndef LDC_CL_HELPERS_H
|
||||
#define LDC_CL_HELPERS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
struct Array;
|
||||
|
||||
namespace opts {
|
||||
namespace cl = llvm::cl;
|
||||
|
||||
/// Helper class for fancier options
|
||||
class FlagParser : public cl::parser<bool> {
|
||||
std::vector<std::pair<std::string, bool> > switches;
|
||||
public:
|
||||
template <class Opt>
|
||||
void initialize(Opt &O) {
|
||||
assert(!(O.getMiscFlags() & cl::AllowInverse)
|
||||
&& "FlagParser doesn't support redundant AllowInverse flag");
|
||||
|
||||
std::string Name = O.ArgStr;
|
||||
switches.push_back(make_pair("enable-" + Name, true));
|
||||
switches.push_back(make_pair("disable-" + Name, false));
|
||||
// Replace <foo> with -enable-<foo>
|
||||
O.ArgStr = switches[0].first.c_str();
|
||||
}
|
||||
|
||||
bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue, bool &Val);
|
||||
|
||||
void getExtraOptionNames(std::vector<const char*> &Names);
|
||||
};
|
||||
|
||||
/// Helper class for options that set multiple flags
|
||||
class MultiSetter {
|
||||
std::vector<bool*> locations;
|
||||
bool invert;
|
||||
MultiSetter(bool); //not implemented, disable auto-conversion
|
||||
public:
|
||||
MultiSetter(bool invert, bool* p, ...) END_WITH_NULL;
|
||||
|
||||
void operator=(bool val);
|
||||
};
|
||||
|
||||
/// Helper class to fill Array with char* when given strings
|
||||
/// (Errors on empty strings)
|
||||
class ArrayAdapter {
|
||||
const char* name;
|
||||
Array** arrp;
|
||||
public:
|
||||
ArrayAdapter(const char* name_, Array*& arr) {
|
||||
name = name_;
|
||||
arrp = &arr;
|
||||
assert(name);
|
||||
assert(arrp);
|
||||
}
|
||||
|
||||
void push_back(const char* cstr);
|
||||
|
||||
void push_back(const std::string& str) {
|
||||
push_back(str.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
337
gen/cl_options.cpp
Normal file
337
gen/cl_options.cpp
Normal file
|
@ -0,0 +1,337 @@
|
|||
#include "gen/cl_options.h"
|
||||
#include "gen/cl_helpers.h"
|
||||
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
|
||||
#include "gen/logger.h"
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
namespace opts {
|
||||
|
||||
// Positional options first, in order:
|
||||
cl::list<std::string> fileList(
|
||||
cl::Positional, cl::desc("files"));
|
||||
|
||||
cl::list<std::string> runargs("run",
|
||||
cl::desc("program args..."),
|
||||
cl::Positional,
|
||||
cl::PositionalEatsArgs);
|
||||
|
||||
|
||||
|
||||
// TODO: Replace this with a proper PassNameParser-based solution
|
||||
static cl::opt<bool, true> doInline("inline",
|
||||
cl::desc("Do function inlining"),
|
||||
cl::location(global.params.llvmInline),
|
||||
cl::ZeroOrMore,
|
||||
cl::init(false));
|
||||
|
||||
|
||||
|
||||
static cl::opt<bool, true> useDeprecated("d",
|
||||
cl::desc("Allow deprecated language features"),
|
||||
cl::ZeroOrMore,
|
||||
cl::location(global.params.useDeprecated));
|
||||
|
||||
static cl::opt<char, true> useDv1(
|
||||
cl::desc("Force language version:"),
|
||||
cl::ZeroOrMore,
|
||||
cl::values(
|
||||
clEnumValN(1, "v1", "D language version 1.00"),
|
||||
clEnumValEnd),
|
||||
cl::location(global.params.Dversion),
|
||||
cl::init(2),
|
||||
cl::Hidden);
|
||||
|
||||
cl::opt<bool> compileOnly("c",
|
||||
cl::desc("Do not link"),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
static cl::opt<bool, true> verbose("v",
|
||||
cl::desc("Verbose"),
|
||||
cl::ZeroOrMore,
|
||||
cl::location(global.params.verbose));
|
||||
|
||||
static cl::opt<bool, true> warnings("w",
|
||||
cl::desc("Enable warnings"),
|
||||
cl::ZeroOrMore,
|
||||
cl::location(global.params.warnings));
|
||||
|
||||
|
||||
static cl::opt<char, true> optimizeLevel(
|
||||
cl::desc("Setting the optimization level:"),
|
||||
cl::ZeroOrMore,
|
||||
cl::values(
|
||||
clEnumValN(2, "O", "Equivalent to -O2"),
|
||||
clEnumValN(0, "O0", "Trivial optimizations only"),
|
||||
clEnumValN(1, "O1", "Simple optimizations"),
|
||||
clEnumValN(2, "O2", "Good optimizations"),
|
||||
clEnumValN(3, "O3", "Aggressive optimizations"),
|
||||
clEnumValN(4, "O4", "Link-time optimization"), // not implemented?
|
||||
clEnumValN(5, "O5", "Link-time optimization"), // not implemented?
|
||||
clEnumValEnd),
|
||||
cl::location(global.params.optimizeLevel),
|
||||
cl::init(-1));
|
||||
|
||||
static cl::opt<char, true> debugInfo(
|
||||
cl::desc("Generating debug information:"),
|
||||
cl::ZeroOrMore,
|
||||
cl::values(
|
||||
clEnumValN(1, "g", "Generate debug information"),
|
||||
clEnumValN(2, "gc", "Same as -g, but pretend to be C"),
|
||||
clEnumValEnd),
|
||||
cl::location(global.params.symdebug),
|
||||
cl::init(0));
|
||||
|
||||
|
||||
static cl::opt<bool, true> annotate("annotate",
|
||||
cl::desc("Annotate the bitcode with human readable source code"),
|
||||
cl::location(global.params.llvmAnnotate));
|
||||
|
||||
cl::opt<bool> noAsm("noasm",
|
||||
cl::desc("Disallow use of inline assembler"));
|
||||
|
||||
// Output file options
|
||||
cl::opt<bool> dontWriteObj("o-",
|
||||
cl::desc("Do not write object file"));
|
||||
|
||||
cl::opt<std::string> objectFile("of",
|
||||
cl::value_desc("filename"),
|
||||
cl::Prefix,
|
||||
cl::desc("Use <filename> as output file name"));
|
||||
|
||||
cl::opt<std::string> objectDir("od",
|
||||
cl::value_desc("objdir"),
|
||||
cl::Prefix,
|
||||
cl::desc("Write object files to directory <objdir>"));
|
||||
|
||||
|
||||
// Output format options
|
||||
cl::opt<bool> output_bc("output-bc",
|
||||
cl::desc("Write LLVM bitcode"));
|
||||
|
||||
cl::opt<bool> output_ll("output-ll",
|
||||
cl::desc("Write LLVM IR"));
|
||||
|
||||
cl::opt<bool> output_s("output-s",
|
||||
cl::desc("Write native assembly"));
|
||||
|
||||
cl::opt<cl::boolOrDefault> output_o("output-o",
|
||||
cl::desc("Write native object"));
|
||||
|
||||
|
||||
// DDoc options
|
||||
static cl::opt<bool, true> doDdoc("D",
|
||||
cl::desc("Generate documentation"),
|
||||
cl::location(global.params.doDocComments));
|
||||
|
||||
cl::opt<std::string> ddocDir("Dd",
|
||||
cl::desc("Write documentation file to <docdir> directory"),
|
||||
cl::value_desc("docdir"),
|
||||
cl::Prefix);
|
||||
|
||||
cl::opt<std::string> ddocFile("Df",
|
||||
cl::desc("Write documentation file to <filename>"),
|
||||
cl::value_desc("filename"),
|
||||
cl::Prefix);
|
||||
|
||||
|
||||
// Header generation options
|
||||
#ifdef _DH
|
||||
static cl::opt<bool, true> doHdrGen("H",
|
||||
cl::desc("Generate 'header' file"),
|
||||
cl::location(global.params.doHdrGeneration));
|
||||
|
||||
cl::opt<std::string> hdrDir("Hd",
|
||||
cl::desc("Write 'header' file to <hdrdir> directory"),
|
||||
cl::value_desc("hdrdir"),
|
||||
cl::Prefix);
|
||||
|
||||
cl::opt<std::string> hdrFile("Hf",
|
||||
cl::desc("Write 'header' file to <filename>"),
|
||||
cl::value_desc("filename"),
|
||||
cl::Prefix);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static cl::opt<bool, true> unittest("unittest",
|
||||
cl::desc("Compile in unit tests"),
|
||||
cl::location(global.params.useUnitTests));
|
||||
|
||||
|
||||
static ArrayAdapter strImpPathStore("J", global.params.fileImppath);
|
||||
static cl::list<std::string, ArrayAdapter> stringImportPaths("J",
|
||||
cl::desc("Where to look for string imports"),
|
||||
cl::value_desc("path"),
|
||||
cl::location(strImpPathStore),
|
||||
cl::Prefix);
|
||||
|
||||
|
||||
|
||||
// -d-debug is a bit messy, it has 3 modes:
|
||||
// -d-debug=ident, -d-debug=level and -d-debug (without argument)
|
||||
// That last of these must be acted upon immediately to ensure proper
|
||||
// interaction with other options, so it needs some special handling:
|
||||
std::vector<std::string> debugArgs;
|
||||
|
||||
struct D_DebugStorage {
|
||||
void push_back(const std::string& str) {
|
||||
if (str.empty()) {
|
||||
// Bare "-d-debug" has a special meaning.
|
||||
global.params.useAssert = true;
|
||||
global.params.useArrayBounds = true;
|
||||
global.params.useInvariants = true;
|
||||
global.params.useIn = true;
|
||||
global.params.useOut = true;
|
||||
debugArgs.push_back("1");
|
||||
} else {
|
||||
debugArgs.push_back(str);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static D_DebugStorage dds;
|
||||
|
||||
// -debug is already declared in LLVM (at least, in debug builds),
|
||||
// so we need to be a bit more verbose.
|
||||
static cl::list<std::string, D_DebugStorage> debugVersionsOption("d-debug",
|
||||
cl::desc("Compile in debug code >= <level> or identified by <idents>."),
|
||||
cl::value_desc("level/idents"),
|
||||
cl::location(dds),
|
||||
cl::CommaSeparated,
|
||||
cl::ValueOptional);
|
||||
|
||||
|
||||
|
||||
// -version is also declared in LLVM, so again we need to be a bit more verbose.
|
||||
cl::list<std::string> versions("d-version",
|
||||
cl::desc("Compile in version code >= <level> or identified by <idents>"),
|
||||
cl::value_desc("level/idents"),
|
||||
cl::CommaSeparated);
|
||||
|
||||
|
||||
static ArrayAdapter linkSwitchStore("L", global.params.linkswitches);
|
||||
static cl::list<std::string, ArrayAdapter> linkerSwitches("L",
|
||||
cl::desc("Pass <linkerflag> to the linker"),
|
||||
cl::value_desc("linkerflag"),
|
||||
cl::location(linkSwitchStore),
|
||||
cl::Prefix);
|
||||
|
||||
|
||||
cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
||||
llvm::RegistryParser<llvm::TargetMachine> > mArch("march",
|
||||
cl::desc("Architecture to generate code for:"));
|
||||
|
||||
static cl::alias m("m",
|
||||
cl::desc("Alias for '-march' for backwards compatibility"),
|
||||
cl::Prefix,
|
||||
cl::aliasopt(mArch));
|
||||
|
||||
|
||||
static cl::opt<OS, true> os("t",
|
||||
cl::desc("Emit code for the specified OS:"),
|
||||
cl::values(
|
||||
#define ENUMVAL_N(Name, Desc) clEnumValN(OS##Name, #Name, Desc)
|
||||
#define ENUMVAL(Name) ENUMVAL_N(Name, #Name)
|
||||
ENUMVAL(Linux),
|
||||
ENUMVAL(Windows),
|
||||
ENUMVAL_N(MacOSX, "Mac OS X"),
|
||||
ENUMVAL(FreeBSD),
|
||||
ENUMVAL(Solaris),
|
||||
#undef ENUMVAL
|
||||
#undef ENUMVAL_N
|
||||
clEnumValEnd),
|
||||
cl::Prefix,
|
||||
cl::location(global.params.os));
|
||||
|
||||
|
||||
// "Hidden debug switches"
|
||||
// Are these ever used?
|
||||
static cl::opt<bool, true> debuga("hidden-debug--a",
|
||||
cl::desc("Hidden debug option A"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debuga));
|
||||
static cl::opt<bool, true> debugb("hidden-debug-b",
|
||||
cl::desc("Hidden debug option B"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugb));
|
||||
static cl::opt<bool, true> debugc("hidden-debug-c",
|
||||
cl::desc("Hidden debug option C"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugc));
|
||||
static cl::opt<bool, true> debugf("hidden-debug-f",
|
||||
cl::desc("Hidden debug option F"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugf));
|
||||
static cl::opt<bool, true> debugr("hidden-debug-r",
|
||||
cl::desc("Hidden debug option R"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugr));
|
||||
static cl::opt<bool, true> debugw("hidden-debug-w",
|
||||
cl::desc("Hidden debug option W"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugw));
|
||||
static cl::opt<bool, true> debugx("hidden-debug-x",
|
||||
cl::desc("Hidden debug option X"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugx));
|
||||
static cl::opt<bool, true> debugy("hidden-debug-y",
|
||||
cl::desc("Hidden debug option Y"),
|
||||
cl::ReallyHidden,
|
||||
cl::location(global.params.debugy));
|
||||
|
||||
|
||||
static cl::opt<bool, true, FlagParser> asserts("asserts",
|
||||
cl::desc("(*) Enable assertions"),
|
||||
cl::value_desc("bool"),
|
||||
cl::location(global.params.useAssert),
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<bool, true, FlagParser> boundsChecks("boundscheck",
|
||||
cl::desc("(*) Enable array bounds checks"),
|
||||
cl::value_desc("bool"),
|
||||
cl::location(global.params.useArrayBounds),
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<bool, true, FlagParser> invariants("invariants",
|
||||
cl::desc("(*) Enable invariants"),
|
||||
cl::location(global.params.useInvariants),
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<bool, true, FlagParser> preconditions("preconditions",
|
||||
cl::desc("(*) Enable function preconditions"),
|
||||
cl::location(global.params.useIn),
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<bool, true, FlagParser> postconditions("postconditions",
|
||||
cl::desc("(*) Enable function postconditions"),
|
||||
cl::location(global.params.useOut),
|
||||
cl::init(true));
|
||||
|
||||
|
||||
static MultiSetter ContractsSetter(false,
|
||||
&global.params.useIn, &global.params.useOut, NULL);
|
||||
static cl::opt<MultiSetter, true, FlagParser> contracts("contracts",
|
||||
cl::desc("(*) Enable function pre- and post-conditions"),
|
||||
cl::location(ContractsSetter));
|
||||
|
||||
static MultiSetter ReleaseSetter(true, &global.params.useAssert,
|
||||
&global.params.useArrayBounds, &global.params.useInvariants,
|
||||
&global.params.useOut, &global.params.useIn, NULL);
|
||||
static cl::opt<MultiSetter, true, cl::parser<bool> > release("release",
|
||||
cl::desc("Disables asserts, invariants, contracts and boundscheck"),
|
||||
cl::location(ReleaseSetter),
|
||||
cl::ValueDisallowed);
|
||||
|
||||
|
||||
static cl::extrahelp footer("\n"
|
||||
"-d-debug can also be specified without options, in which case it enables all\n"
|
||||
"debug checks (i.e. (asserts, boundchecks, contracts and invariants) as well\n"
|
||||
"as acting as -d-debug=1\n\n"
|
||||
"Options marked with (*) also have a -disable-FOO variant with inverted\n"
|
||||
"meaning.\n");
|
||||
|
||||
} // namespace opts
|
46
gen/cl_options.h
Normal file
46
gen/cl_options.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef LDC_CL_OPTIONS_H
|
||||
#define LDC_CL_OPTIONS_H
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include "llvm/Support/RegistryParser.h"
|
||||
#include "llvm/Target/TargetMachineRegistry.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
namespace opts {
|
||||
namespace cl = llvm::cl;
|
||||
|
||||
/* Mostly generated with the following command:
|
||||
egrep -e '^(cl::|#if|#e)' gen/cl_options.cpp \
|
||||
| sed -re 's/^(cl::.*)\(.*$/ extern \1;/'
|
||||
*/
|
||||
extern cl::list<std::string> fileList;
|
||||
extern cl::list<std::string> runargs;
|
||||
extern cl::opt<bool> compileOnly;
|
||||
extern cl::opt<bool> noAsm;
|
||||
extern cl::opt<bool> dontWriteObj;
|
||||
extern cl::opt<std::string> objectFile;
|
||||
extern cl::opt<std::string> objectDir;
|
||||
extern cl::opt<bool> output_bc;
|
||||
extern cl::opt<bool> output_ll;
|
||||
extern cl::opt<bool> output_s;
|
||||
extern cl::opt<cl::boolOrDefault> output_o;
|
||||
extern cl::opt<std::string> ddocDir;
|
||||
extern cl::opt<std::string> ddocFile;
|
||||
#ifdef _DH
|
||||
extern cl::opt<std::string> hdrDir;
|
||||
extern cl::opt<std::string> hdrFile;
|
||||
#endif
|
||||
extern cl::list<std::string> versions;
|
||||
|
||||
extern cl::opt<const llvm::TargetMachineRegistry::entry*, false,
|
||||
llvm::RegistryParser<llvm::TargetMachine> > mArch;
|
||||
|
||||
// Arguments to -d-debug
|
||||
extern std::vector<std::string> debugArgs;
|
||||
// Arguments to -run
|
||||
}
|
||||
#endif
|
|
@ -1,3 +1,4 @@
|
|||
#include "gen/linker.h"
|
||||
#include "gen/llvm.h"
|
||||
#include "llvm/Linker.h"
|
||||
#include "llvm/System/Program.h"
|
||||
|
@ -11,6 +12,16 @@
|
|||
|
||||
#define NO_COUT_LOGGER
|
||||
#include "gen/logger.h"
|
||||
#include "gen/cl_options.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Is this useful?
|
||||
llvm::cl::opt<bool> quiet("quiet",
|
||||
llvm::cl::desc("Suppress output of link command (unless -v is also passed)"),
|
||||
llvm::cl::Hidden,
|
||||
llvm::cl::ZeroOrMore,
|
||||
llvm::cl::init(true));
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -173,7 +184,7 @@ int linkExecutable(const char* argv0)
|
|||
}
|
||||
|
||||
// print link command?
|
||||
if (!global.params.quiet || global.params.verbose)
|
||||
if (!quiet || global.params.verbose)
|
||||
{
|
||||
// Print it
|
||||
for (int i = 0; i < args.size(); i++)
|
||||
|
@ -311,7 +322,7 @@ int linkObjToExecutable(const char* argv0)
|
|||
args.push_back("-m64");
|
||||
|
||||
// print link command?
|
||||
if (!global.params.quiet || global.params.verbose)
|
||||
if (!quiet || global.params.verbose)
|
||||
{
|
||||
// Print it
|
||||
for (int i = 0; i < args.size(); i++)
|
||||
|
@ -363,10 +374,12 @@ int runExectuable()
|
|||
|
||||
// build arguments
|
||||
std::vector<const char*> args;
|
||||
for (size_t i = 0; i < global.params.runargs_length; i++)
|
||||
// args[0] should be the name of the executable
|
||||
args.push_back(gExePath.toString().c_str());
|
||||
// Skip first argument to -run; it's a D source file.
|
||||
for (size_t i = 1, length = opts::runargs.size(); i < length; i++)
|
||||
{
|
||||
char *a = global.params.runargs[i];
|
||||
args.push_back(a);
|
||||
args.push_back(opts::runargs[i].c_str());
|
||||
}
|
||||
// terminate args list
|
||||
args.push_back(NULL);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#ifndef LDC_GEN_LINKER_H
|
||||
#define LDC_GEN_LINKER_H
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include <vector>
|
||||
|
||||
extern llvm::cl::opt<bool> quiet;
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
class Module;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "mars.h"
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "gen/logger.h"
|
||||
|
||||
namespace Logger
|
||||
|
@ -15,7 +16,10 @@ namespace Logger
|
|||
static std::string indent_str;
|
||||
static std::ofstream null_out("/dev/null");
|
||||
|
||||
static bool _enabled = false;
|
||||
llvm::cl::opt<bool> _enabled("vv",
|
||||
llvm::cl::desc("Very verbose"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
void indent()
|
||||
{
|
||||
if (_enabled) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "llvm/Module.h"
|
||||
#include "llvm/Bitcode/ReaderWriter.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
|
@ -15,6 +16,14 @@
|
|||
#include "gen/tollvm.h"
|
||||
#include "gen/irstate.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::cl::opt<bool> noruntime("noruntime",
|
||||
llvm::cl::desc("Do not allow code that generates implicit runtime calls"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::Module* M = NULL;
|
||||
static bool runtime_failed = false;
|
||||
|
||||
|
@ -44,7 +53,7 @@ void LLVM_D_FreeRuntime()
|
|||
|
||||
llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name)
|
||||
{
|
||||
if (global.params.noruntime) {
|
||||
if (noruntime) {
|
||||
error("No implicit runtime calls allowed with -noruntime option enabled");
|
||||
fatal();
|
||||
}
|
||||
|
@ -80,7 +89,7 @@ llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char*
|
|||
return gv;
|
||||
}
|
||||
|
||||
if (global.params.noruntime) {
|
||||
if (noruntime) {
|
||||
error("No implicit runtime calls allowed with -noruntime option enabled");
|
||||
fatal();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "llvm/System/Program.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
|
@ -55,6 +56,12 @@
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static llvm::cl::opt<bool> noVerify("noverify",
|
||||
llvm::cl::desc("Do not run the validation pass before writing bitcode"),
|
||||
llvm::cl::ZeroOrMore);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// in gen/optimize.cpp
|
||||
void ldc_optimize_module(llvm::Module* m, char lvl, bool doinline);
|
||||
|
||||
|
@ -124,10 +131,6 @@ void Module::genobjfile(int multiobj)
|
|||
// for (unsigned i = 0; i != MAttrs.size(); ++i)
|
||||
// Features.AddFeature(MAttrs[i]);
|
||||
|
||||
// only generate PIC code when -fPIC switch is used
|
||||
if (global.params.pic)
|
||||
llvm::TargetMachine::setRelocationModel(llvm::Reloc::PIC_);
|
||||
|
||||
// allocate the target machine
|
||||
std::auto_ptr<llvm::TargetMachine> target(MArch->CtorFn(*ir.module, Features.getString()));
|
||||
assert(target.get() && "Could not allocate target machine!");
|
||||
|
@ -182,7 +185,7 @@ void Module::genobjfile(int multiobj)
|
|||
}
|
||||
|
||||
// verify the llvm
|
||||
if (!global.params.novalidate) {
|
||||
if (!noVerify) {
|
||||
std::string verifyErr;
|
||||
Logger::println("Verifying module...");
|
||||
LOG_SCOPE;
|
||||
|
@ -200,7 +203,7 @@ void Module::genobjfile(int multiobj)
|
|||
ldc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline);
|
||||
|
||||
// verify the llvm
|
||||
if (!global.params.novalidate && (global.params.optimizeLevel >= 0 || global.params.llvmInline)) {
|
||||
if (!noVerify && (global.params.optimizeLevel >= 0 || global.params.llvmInline)) {
|
||||
std::string verifyErr;
|
||||
Logger::println("Verifying module... again...");
|
||||
LOG_SCOPE;
|
||||
|
|
|
@ -38,7 +38,7 @@ testversion=PIC
|
|||
|
||||
[compile]
|
||||
oneatatime=yes
|
||||
cmd=ldc -c $i
|
||||
cmd=ldmd -c $i
|
||||
|
||||
flag=$i
|
||||
incdir=-I$i
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[Environment]
|
||||
DFLAGS=-I@RUNTIME_DIR@ -I@RUNTIME_DIR@/lib/common -L-L%@P%/../lib -version=Tango -defaultlib=@RUNTIME_AIO@ -debuglib=@RUNTIME_AIO@
|
||||
DFLAGS=-I@RUNTIME_DIR@ -I@RUNTIME_DIR@/lib/common -L-L%@P%/../lib -d-version=Tango -defaultlib=@RUNTIME_AIO@ -debuglib=@RUNTIME_AIO@
|
||||
|
|
56
tango.patch
Normal file
56
tango.patch
Normal file
|
@ -0,0 +1,56 @@
|
|||
Index: lib/unittest.sh
|
||||
===================================================================
|
||||
--- lib/unittest.sh (revision 4330)
|
||||
+++ lib/unittest.sh (working copy)
|
||||
@@ -15,14 +15,14 @@
|
||||
usage() {
|
||||
echo 'Usage: ./unittest.sh [otions ...]
|
||||
Options:
|
||||
- --help: This message
|
||||
+ --help: This message
|
||||
--run-all: Reports result instead of breaking. Do not use this if you want to
|
||||
- run unittest runner through a debugger.
|
||||
- dmd: Builds unittests for dmd
|
||||
- gdc: Builds unittests for gdc
|
||||
- ldc: Builds unittests for ldc
|
||||
+ run unittest runner through a debugger.
|
||||
+ dmd: Builds unittests for dmd
|
||||
+ gdc: Builds unittests for gdc
|
||||
+ ldc: Builds unittests for ldc
|
||||
|
||||
- <none>: Builds unittests for all known compilers.'
|
||||
+ <none>: Builds unittests for all known compilers.'
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
rebuild --help >& /dev/null || die "rebuild required, aborting" 1
|
||||
|
||||
- if ! $DC --help >& /dev/null
|
||||
+ if ! which $DC >& /dev/null
|
||||
then
|
||||
echo "$DC not found on your \$PATH!"
|
||||
else
|
||||
Index: lib/build-tango.sh
|
||||
===================================================================
|
||||
--- lib/build-tango.sh (revision 4330)
|
||||
+++ lib/build-tango.sh (working copy)
|
||||
@@ -131,7 +131,7 @@
|
||||
DC=$1
|
||||
LIB=$2
|
||||
|
||||
- if ! $DC --help >& /dev/null
|
||||
+ if ! which "$DC" >& /dev/null
|
||||
then
|
||||
echo "$DC not found on your \$PATH!"
|
||||
return
|
||||
@@ -203,7 +203,7 @@
|
||||
build gdmd libgtango.a libgphobos.a
|
||||
;;
|
||||
ldc)
|
||||
- build ldc libtango-user-ldc.a build-tango.sh
|
||||
+ build ldmd libtango-user-ldc.a build-tango.sh
|
||||
;;
|
||||
mac)
|
||||
POSIXFLAG="-version=Posix"
|
Loading…
Add table
Add a link
Reference in a new issue