ambuild2/frontend/cpp.py
changeset 190 ac8f25935d84
parent 189 5cbcf2a49ddf
child 191 591aacecffa3
     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