diff --git a/clang/tools/ccc/ccclib/Arguments.py b/clang/tools/ccc/ccclib/Arguments.py index 075d3b909f4b..ed9e1f2471d5 100644 --- a/clang/tools/ccc/ccclib/Arguments.py +++ b/clang/tools/ccc/ccclib/Arguments.py @@ -1,3 +1,16 @@ + +### + +class InvalidArgumentsError(ValueError): + """InvalidArgumentsError - The driver arguments are invalid or + inconsistent.""" + +class MissingArgumentError(ValueError): + """MissingArgumentError - An option required an argument but none + was given.""" + +### + class Option(object): """Option - Root option class.""" diff --git a/clang/tools/ccc/ccclib/Driver.py b/clang/tools/ccc/ccclib/Driver.py index d10081224a20..427bc0ea6761 100644 --- a/clang/tools/ccc/ccclib/Driver.py +++ b/clang/tools/ccc/ccclib/Driver.py @@ -19,14 +19,10 @@ import Util #### -class MissingArgumentError(ValueError): - """MissingArgumentError - An option required an argument but none - was given.""" - -### - class Driver(object): - def __init__(self): + def __init__(self, driverName, driverDir): + self.driverName = driverName + self.driverDir = driverDir self.hostInfo = None self.parser = Arguments.OptionParser() self.cccHostBits = self.cccHostMachine = None @@ -104,7 +100,8 @@ class Driver(object): self.cccFallback = True while argv and argv[0].startswith('-ccc-'): - opt,argv = argv[0][5:],argv[1:] + fullOpt,argv = argv[0],argv[1:] + opt = fullOpt[5:] if opt == 'print-options': cccPrintOptions = True @@ -127,7 +124,7 @@ class Driver(object): elif opt == 'host-release': self.cccHostRelease,argv = argv[0],argv[1:] else: - raise ValueError,"Invalid ccc option: %r" % opt + raise Arguments.InvalidArgumentsError("invalid option: %r" % fullOpt) self.hostInfo = HostInfo.getHostInfo(self) self.toolChain = self.hostInfo.getToolChain() @@ -209,7 +206,7 @@ class Driver(object): pass def warning(self, message): - print >>sys.stderr,'%s: %s' % (sys.argv[0], message) + print >>sys.stderr,'%s: %s' % (self.driverName, message) def printOptions(self, args): for i,arg in enumerate(args): @@ -325,8 +322,9 @@ class Driver(object): inputs = [] for a in args: if a.opt is self.parser.inputOption: + inputValue = args.getValue(a) if inputType is None: - base,ext = os.path.splitext(args.getValue(a)) + base,ext = os.path.splitext(inputValue) if ext and ext in Types.kTypeSuffixMap: klass = Types.kTypeSuffixMap[ext] else: @@ -339,7 +337,15 @@ class Driver(object): assert inputTypeOpt is not None self.claim(inputTypeOpt) klass = inputType - inputs.append((klass, a)) + + # Check that the file exists. It isn't clear this is + # worth doing, since the tool presumably does this + # anyway, and this just adds an extra stat to the + # equation, but this is gcc compatible. + if not os.path.exists(inputValue): + self.warning("%s: No such file or directory" % inputValue) + else: + inputs.append((klass, a)) elif a.opt.isLinkerInput: # Treat as a linker input. # @@ -348,13 +354,8 @@ class Driver(object): # that other code which needs to know the inputs # handles this properly. Best not to try and lipo # this, for example. - # - # FIXME: Actually, this is just flat out broken, the - # tools expect inputs to be accessible by .getValue - # but that of course only yields the argument. inputs.append((Types.ObjectType, a)) elif a.opt is self.parser.xOption: - self.claim(a) inputTypeOpt = a value = args.getValue(a) if value in Types.kTypeSpecifierMap: @@ -396,7 +397,11 @@ class Driver(object): # FIXME: Support -combine. if hasCombine: - raise NotImplementedError,"-combine is not yet supported." + raise NotImplementedError,"-combine is not yet supported" + + if (not inputs and + not args.getLastArg(self.parser.hashHashHashOption)): + raise Arguments.InvalidArgumentsError("no input files") actions = [] linkerInputs = [] @@ -511,9 +516,9 @@ class Driver(object): # these cause downstream. if len(archs) > 1: if hasDashM: - raise ValueError,"Cannot use -M options with multiple arch flags." + raise Arguments.InvalidArgumentsError("Cannot use -M options with multiple arch flags.") elif hasSaveTemps: - raise ValueError,"Cannot use -save-temps with multiple arch flags." + raise Arguments.InvalidArgumentsError("Cannot use -save-temps with multiple arch flags.") # Execute once per arch. finalActions = [] @@ -531,7 +536,7 @@ class Driver(object): # developers. if (len(archs) > 1 and p.type not in (Types.NothingType,Types.ObjectType,Types.ImageType)): - raise ValueError,'Cannot use %s output with multiple arch flags.' % p.type.name + raise Arguments.InvalidArgumentsError('Cannot use %s output with multiple arch flags.' % p.type.name) inputs = [] for arch in archs: @@ -701,8 +706,7 @@ class Driver(object): # It is an error to provide a -o option if we are making multiple # output files. if finalOutput and len([a for a in phases if a.type is not Types.NothingType]) > 1: - # FIXME: Custom exception. - raise ValueError,"Cannot specify -o when generating multiple files." + raise Arguments.InvalidArgumentsError("cannot specify -o when generating multiple files") for phase in phases: createJobs(self.toolChain, phase, diff --git a/clang/tools/ccc/ccclib/Tools.py b/clang/tools/ccc/ccclib/Tools.py index da258673ff09..df84d4791c44 100644 --- a/clang/tools/ccc/ccclib/Tools.py +++ b/clang/tools/ccc/ccclib/Tools.py @@ -375,12 +375,12 @@ class Darwin_X86_CompileTool(Tool): usePP = False isCXX = True else: - raise RuntimeError,"Unexpected input type for Darwin compile tool." + raise ValueError,"Unexpected input type for Darwin compile tool." cmd_args = [] if (arglist.getLastArg(arglist.parser.traditionalOption) or arglist.getLastArg(arglist.parser.f_traditionalOption)): - raise ValueError,"-traditional is not supported without -E" + raise Arguments.InvalidArgumentsError("-traditional is not supported without -E") if usePP: # Derived from cpp_options. @@ -390,7 +390,7 @@ class Darwin_X86_CompileTool(Tool): if (arglist.getLastArg(arglist.parser.COption) or arglist.getLastArg(arglist.parser.CCOption)): if not arglist.getLastArg(arglist.parser.EOption): - raise ValueError,"-C or -CC is not supported without -E" + raise Arguments.InvalidArgumentsError("-C or -CC is not supported without -E") if not arglist.getLastArg(arglist.parser.QOption): cmd_args.append('-quiet') arglist.addAllArgs(cmd_args, arglist.parser.nostdincOption) @@ -491,7 +491,7 @@ class Darwin_X86_CompileTool(Tool): if (arglist.getLastArg(arglist.parser.pgOption) and arglist.getLastArg(arglist.parser.f_omitFramePointerOption)): - raise ValueError,"-pg and -fomit-frame-pointer are incompatible" + raise Arguments.InvalidArgumentsError("-pg and -fomit-frame-pointer are incompatible") self.addCC1Args(cmd_args, arch, arglist) @@ -596,7 +596,7 @@ class Darwin_X86_LinkTool(Tool): try: return tuple(map(int, components)) except: - raise ValueError,"invalid version number %r" % version + raise Arguments.InvalidArgumentsError("invalid version number %r" % version) else: major,minor,minorminor = self.toolChain.darwinVersion return (10, major-4, minor) diff --git a/clang/tools/ccc/test/ccc/darwin-x86-cc1.m b/clang/tools/ccc/test/ccc/darwin-x86-cc1.m index 91fe0888b4cc..f5d05260505b 100644 --- a/clang/tools/ccc/test/ccc/darwin-x86-cc1.m +++ b/clang/tools/ccc/test/ccc/darwin-x86-cc1.m @@ -1,4 +1,4 @@ // RUN: xcc -ccc-host-bits 32 -ccc-host-machine i386 -ccc-host-system darwin -ccc-host-release 10.5.0 -### -x objective-c -arch i386 -fmessage-length=0 -Wno-trigraphs -fpascal-strings -fasm-blocks -Os -mdynamic-no-pic -DUSER_DEFINE_0 -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -IINCLUDE_PATH_0 -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -Wno-four-char-constants -Wno-unknown-pragmas -Wno-format-y2k -Wpointer-arith -Wreturn-type -Wwrite-strings -Wswitch -Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wint-to-pointer-cast -Wpointer-to-int-cast -Wshorten-64-to-32 -FFRAMEWORK_0 -IINCLUDE_PATH_1 -FFRAMEWORK_1 -include USER_INCLUDE_0 -c %s -o %t.out &> %t.opts && -// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1obj" "-quiet" "-IINCLUDE_PATH_0" "-FFRAMEWORK_0" "-IINCLUDE_PATH_1" "-FFRAMEWORK_1" "-D__DYNAMIC__" "-DUSER_DEFINE_0" "-include" "USER_INCLUDE_0" "darwin-x86-cc1.m" "-quiet" "-dumpbase" "darwin-x86-cc1.m" "-mpascal-strings" "-mdynamic-no-pic" "-mmacosx-version-min=10.5" "-mtune=core2" "-auxbase-strip" "Output/darwin-x86-cc1.m.out.tmp.out" "-gdwarf-2" "-Os" "-Wno-trigraphs" "-Wall" "-Wextra" "-Wno-missing-field-initializers" "-Wno-unused-parameter" "-Wno-four-char-constants" "-Wno-unknown-pragmas" "-Wno-format-y2k" "-Wpointer-arith" "-Wreturn-type" "-Wwrite-strings" "-Wswitch" "-Wcast-align" "-Wchar-subscripts" "-Winline" "-Wnested-externs" "-Wint-to-pointer-cast" "-Wpointer-to-int-cast" "-Wshorten-64-to-32" "-fmessage-length=0" "-fasm-blocks" "-fvisibility=hidden" "-o"' %t.opts && -// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/as" "-arch" "i386" "-force_cpusubtype_ALL" "-o" "Output/darwin-x86-cc1.m.out.tmp.out" ' %t.opts +// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/cc1obj" "-quiet" "-IINCLUDE_PATH_0" "-FFRAMEWORK_0" "-IINCLUDE_PATH_1" "-FFRAMEWORK_1" "-D__DYNAMIC__" "-DUSER_DEFINE_0" "-include" "USER_INCLUDE_0" ".*" "-quiet" "-dumpbase" "darwin-x86-cc1.m" "-mpascal-strings" "-mdynamic-no-pic" "-mmacosx-version-min=10.5" "-mtune=core2" "-auxbase-strip" ".*" "-gdwarf-2" "-Os" "-Wno-trigraphs" "-Wall" "-Wextra" "-Wno-missing-field-initializers" "-Wno-unused-parameter" "-Wno-four-char-constants" "-Wno-unknown-pragmas" "-Wno-format-y2k" "-Wpointer-arith" "-Wreturn-type" "-Wwrite-strings" "-Wswitch" "-Wcast-align" "-Wchar-subscripts" "-Winline" "-Wnested-externs" "-Wint-to-pointer-cast" "-Wpointer-to-int-cast" "-Wshorten-64-to-32" "-fmessage-length=0" "-fasm-blocks" "-fvisibility=hidden" "-o"' %t.opts && +// RUN: grep ' "/usr/libexec/gcc/i686-apple-darwin10/4.2.1/as" "-arch" "i386" "-force_cpusubtype_ALL" "-o"' %t.opts diff --git a/clang/tools/ccc/test/ccc/phases.c b/clang/tools/ccc/test/ccc/phases.c index 3a24f93b7a5f..902ceb429882 100644 --- a/clang/tools/ccc/test/ccc/phases.c +++ b/clang/tools/ccc/test/ccc/phases.c @@ -1,41 +1,46 @@ // One C file. -// RUN: xcc -ccc-host-system unknown -ccc-print-phases a.c > %t && -// RUN: grep '0: input, "a.c", c' %t && +// RUN: touch %t.c && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases %t.c > %t && +// RUN: grep '0: input, "%t.c", c' %t && // RUN: grep '1: preprocessor, {0}, cpp-output' %t && // RUN: grep '2: compiler, {1}, assembler' %t && // RUN: grep '3: assembler, {2}, object' %t && // RUN: grep '4: linker, {3}, image' %t && // PCH. -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x c-header a.h > %t && -// RUN: grep '0: input, "a.h", c-header' %t && +// RUN: touch %t.h && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x c-header %t.h > %t && +// RUN: grep '0: input, "%t.h", c-header' %t && // RUN: grep '1: preprocessor, {0}, c-header-cpp-output' %t && // RUN: grep '2: precompiler, {1}, precompiled-header' %t && // Assembler w/ and w/o preprocessor. -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x assembler a.s > %t && -// RUN: grep '0: input, "a.s", assembler' %t && +// RUN: touch %t.s && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x assembler %t.s > %t && +// RUN: grep '0: input, "%t.s", assembler' %t && // RUN: grep '1: assembler, {0}, object' %t && // RUN: grep '2: linker, {1}, image' %t && -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x assembler-with-cpp a.s > %t && -// RUN: grep '0: input, "a.s", assembler-with-cpp' %t && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -x assembler-with-cpp %t.s > %t && +// RUN: grep '0: input, "%t.s", assembler-with-cpp' %t && // RUN: grep '1: preprocessor, {0}, assembler' %t && // RUN: grep '2: assembler, {1}, object' %t && // RUN: grep '3: linker, {2}, image' %t && // Check the various ways of early termination. -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -E a.c > %t && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -E %s > %t && // RUN: not grep ': compiler, ' %t && -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -fsyntax-only a.c > %t && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -fsyntax-only %s > %t && // RUN: grep ': compiler, {1}, nothing' %t && // RUN: not grep ': assembler, ' %t && -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -S a.c > %t && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -S %s > %t && // RUN: not grep ': assembler, ' %t && -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -c a.c > %t && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -c %s > %t && // RUN: not grep ': linker, ' %t && // Multiple output files. -// RUN: xcc -ccc-host-system unknown -ccc-print-phases -c a.c b.c > %t && +// RUN: touch %t.1.c && +// RUN: touch %t.2.c && +// RUN: xcc -ccc-host-system unknown -ccc-print-phases -c %t.1.c %t.2.c > %t && // RUN: grep ': assembler,' %t | count 2 && // FIXME: Only for darwin. diff --git a/clang/tools/ccc/xcc b/clang/tools/ccc/xcc index 70954aca9566..52baa6660686 100755 --- a/clang/tools/ccc/xcc +++ b/clang/tools/ccc/xcc @@ -1,12 +1,25 @@ #!/usr/bin/python +import os import sys +from ccclib import Arguments from ccclib import Driver def main(): - d = Driver.Driver() - # FIXME: We should pass program name here as well. - d.run(sys.argv[1:]) + progDir = os.path.dirname(sys.argv[0]) + progName = os.path.basename(sys.argv[0]) + + d = Driver.Driver(progDir, progName) + try: + d.run(sys.argv[1:]) + except Arguments.InvalidArgumentsError,e: + print >>sys.stderr, "%s: %s" % (progName, e.args[0]) + sys.exit(1) + except Arguments.MissingArgumentError,e: + print >>sys.stderr, "%s: %s" % (progName, e.args[0]) + sys.exit(1) + except NotImplementedError,e: + print >>sys.stderr, "%s: not implemented: %s" % (progName, e.args[0]) if __name__=='__main__': main()