1.1 --- a/ambuild2/frontend/cpp.py Fri Nov 15 20:15:05 2013 -0800
1.2 +++ b/ambuild2/frontend/cpp.py Fri Nov 15 22:20:02 2013 -0800
1.3 @@ -33,7 +33,8 @@
1.4 self.definePrefix = '/D'
1.5 self.pdbSuffix = '.pdb'
1.6
1.7 - def formatInclude(self, outputPath, includePath):
1.8 + @staticmethod
1.9 + def IncludePath(outputPath, includePath):
1.10 #Hack - try and get a relative path because CL, with either
1.11 #/Zi or /ZI, combined with subprocess, apparently tries and
1.12 #looks for paths like c:\bleh\"c:\bleh" <-- wtf
1.13 @@ -43,8 +44,14 @@
1.14 outputDrive = os.path.splitdrive(outputPath)[0]
1.15 includeDrive = os.path.splitdrive(includePath)[0]
1.16 if outputDrive == includeDrive:
1.17 - return ['/I', os.path.relpath(includePath, outputPath)]
1.18 - return ['/I', includePath]
1.19 + return os.path.relpath(includePath, outputPath)
1.20 + return includePath
1.21 +
1.22 + def formatInclude(self, outputPath, includePath):
1.23 + return ['/I', self.IncludePath(outputPath, includePath)]
1.24 +
1.25 + def preprocessArgs(self, sourceFile):
1.26 + return ['/showIncludes', '/nologo', '/E', '/c', sourceFile]
1.27
1.28 def objectArgs(self, sourceFile, objFile):
1.29 return ['/showIncludes', '/nologo', '/c', sourceFile, '/Fo' + objFile]
1.30 @@ -246,6 +253,8 @@
1.31 'defines', # C and C++ #defines
1.32 'cxxdefines', # C++-only #defines
1.33
1.34 + 'rcdefines', # Resource Compiler (RC) defines
1.35 +
1.36 # Link flags. If any members are not strings, they will be interpreted as
1.37 # Dep entries created from BinaryBuilder.
1.38 'linkflags',
1.39 @@ -300,12 +309,9 @@
1.40 if compiler == config.cxx:
1.41 for include in config.cxxincludes:
1.42 args += compiler.formatInclude(outputPath, include)
1.43 - self.argv_ = args
1.44 + self.argv = args
1.45 self.compiler = compiler
1.46
1.47 - def argv(self, sourceFile, objPath):
1.48 - return self.argv_ + self.compiler.objectArgs(sourceFile, objPath)
1.49 -
1.50 def NameForObjectFile(file):
1.51 return re.sub('[^a-zA-Z0-9_]+', '_', os.path.splitext(file)[0]);
1.52
1.53 @@ -315,6 +321,13 @@
1.54 self.outputFile = outputFile
1.55 self.argv = argv
1.56
1.57 +class RCFile(object):
1.58 + def __init__(self, sourceFile, outputFile, cl_argv, rc_argv):
1.59 + self.sourceFile = sourceFile
1.60 + self.outputFile = outputFile
1.61 + self.cl_argv = cl_argv
1.62 + self.rc_argv = rc_argv
1.63 +
1.64 def LinkFlags(compiler):
1.65 argv = []
1.66 for item in compiler.linkflags:
1.67 @@ -368,7 +381,50 @@
1.68 self.default_c_env = CCommandEnv(self.outputPath, self.compiler, self.compiler.cc)
1.69 self.default_cxx_env = CCommandEnv(self.outputPath, self.compiler, self.compiler.cxx)
1.70
1.71 - self.objfiles = [self.generateItem(cx, item) for item in self.sources]
1.72 + self.objects = []
1.73 + self.resources = []
1.74 + for item in self.sources:
1.75 + filename, extension = os.path.splitext(item)
1.76 + if extension == '.rc':
1.77 + cenv = self.default_c_env
1.78 + suffix = '.res'
1.79 + else:
1.80 + if extension == '.c':
1.81 + cenv = self.default_c_env
1.82 + else:
1.83 + cenv = self.default_cxx_env
1.84 + self.used_cxx_ = True
1.85 + suffix = cenv.compiler.objSuffix
1.86 +
1.87 + if os.path.isabs(item):
1.88 + sourceFile = item
1.89 + else:
1.90 + sourceFile = os.path.join(cx.currentSourcePath, item)
1.91 + sourceFile = os.path.normpath(sourceFile)
1.92 + objectFile = NameForObjectFile(filename) + suffix
1.93 +
1.94 + if extension == '.rc':
1.95 + # This is only relevant on Windows.
1.96 + vendor = cenv.compiler
1.97 + defines = self.compiler.defines + self.compiler.cxxdefines + self.compiler.rcdefines
1.98 + cl_argv = vendor.command.split(' ')
1.99 + cl_argv += [vendor.definePrefix + define for define in defines]
1.100 + for include in (self.compiler.includes + self.compiler.cxxincludes):
1.101 + cl_argv += vendor.formatInclude(objectFile, include)
1.102 + cl_argv += vendor.preprocessArgs(sourceFile)
1.103 +
1.104 + rc_argv = ['rc', '/nologo']
1.105 + for define in defines:
1.106 + rc_argv.extend(['/d', define])
1.107 + for include in (self.compiler.includes + self.compiler.cxxincludes):
1.108 + rc_argv.extend(['/i', MSVC.IncludePath(objectFile, include)])
1.109 + rc_argv.append('/fo' + objectFile)
1.110 + rc_argv.append(sourceFile)
1.111 +
1.112 + self.resources.append(RCFile(sourceFile, objectFile, cl_argv, rc_argv))
1.113 + else:
1.114 + argv = cenv.argv + cenv.compiler.objectArgs(sourceFile, objectFile)
1.115 + self.objects.append(ObjectFile(sourceFile, objectFile, argv))
1.116
1.117 if not self.linker_:
1.118 if self.used_cxx_:
1.119 @@ -377,69 +433,49 @@
1.120 self.linker_ = self.compiler.cc
1.121
1.122 argv = self.linker_.command.split(' ')
1.123 - for objfile in self.objfiles:
1.124 + for objfile in self.objects:
1.125 argv.append(objfile.outputFile)
1.126 + for rcfile in self.resources:
1.127 + argv.append(rcfile.outputFile)
1.128
1.129 - name, argv = self.generateBinary(cx, argv)
1.130 + argv = self.generateBinary(cx, argv)
1.131
1.132 - self.outputFile = name
1.133 self.argv = argv
1.134 if self.linker_.pdbSuffix:
1.135 self.pdbFile = self.name_ + self.linker_.pdbSuffix
1.136 else:
1.137 self.pdbFile = None
1.138
1.139 - def generateItem(self, cx, item):
1.140 - fparts = os.path.splitext(item)
1.141 -
1.142 - if fparts[1] == 'c':
1.143 - cenv = self.default_c_env
1.144 - else:
1.145 - cenv = self.default_cxx_env
1.146 - self.used_cxx_ = True
1.147 -
1.148 - # Find or add node for the source input file.
1.149 - if os.path.isabs(item):
1.150 - sourceFile = item
1.151 - else:
1.152 - sourceFile = os.path.join(cx.currentSourcePath, item)
1.153 - sourceFile = os.path.normpath(sourceFile)
1.154 - objName = NameForObjectFile(fparts[0]) + cenv.compiler.objSuffix
1.155 - argv = cenv.argv(sourceFile, objName)
1.156 - return ObjectFile(sourceFile, objName, argv)
1.157 -
1.158 class Program(BinaryBuilder):
1.159 def __init__(self, compiler, name):
1.160 super(Program, self).__init__(compiler, name)
1.161 + self.outputFile = name + util.ExecutableSuffix()
1.162
1.163 def generateBinary(self, cx, argv):
1.164 - name = self.name_ + util.ExecutableSuffix()
1.165 -
1.166 if isinstance(self.linker_, MSVC):
1.167 argv.append('/link')
1.168 argv.extend(LinkFlags(self.compiler))
1.169 if isinstance(self.linker_, MSVC):
1.170 - argv.append('/OUT:' + name)
1.171 + argv.append('/OUT:' + self.outputFile)
1.172 argv.append('/DEBUG')
1.173 argv.append('/nologo')
1.174 argv.append('/PDB:"' + self.name_ + '.pdb"')
1.175 else:
1.176 argv.extend(['-o', name])
1.177
1.178 - return name, argv
1.179 + return argv
1.180
1.181 class Library(BinaryBuilder):
1.182 def __init__(self, compiler, name):
1.183 super(Library, self).__init__(compiler, name)
1.184 + self.outputFile = name + util.SharedLibSuffix()
1.185
1.186 def generateBinary(self, cx, argv):
1.187 - name = self.name_ + util.SharedLibSuffix()
1.188 -
1.189 if isinstance(self.linker_, MSVC):
1.190 argv.append('/link')
1.191 argv.extend(LinkFlags(self.compiler))
1.192 if isinstance(self.linker_, MSVC):
1.193 - argv.append('/OUT:' + name)
1.194 + argv.append('/OUT:' + self.outputFile)
1.195 argv.append('/DEBUG')
1.196 argv.append('/nologo')
1.197 argv.append('/DLL')
1.198 @@ -451,4 +487,4 @@
1.199 argv.append('-shared')
1.200 argv.extend(['-o', name])
1.201
1.202 - return name, argv
1.203 + return argv