Changeset 30

Show
Ignore:
Timestamp:
08/08/06 14:17:39 (2 years ago)
Author:
KirkMcDonald
Message:

Inroads on Linux support.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dcompiler.py

    r29 r30  
    1414 
    1515from distutils import ccompiler as cc 
     16from distutils.ccompiler import gen_lib_options 
    1617from distutils.errors import ( 
    1718    DistutilsExecError, DistutilsFileError, DistutilsPlatformError, 
    1819    CompileError, LibError, LinkError, UnknownFileError 
    19  
     20
    2021 
    2122 
     
    4445 
    4546class DCompiler(cc.CCompiler): 
    46     # YYY: This class exists because in the long term, a GDCDCompiler class 
    47     # should be created (selectable with 'python setup.py build -cgdc') and 
    48     # common code should be factored into the common superclass DCompiler. 
    49     pass 
    50  
    51  
    52 class DMDDCompiler(DCompiler): 
    53     compiler_type = 'dmd' 
    54  
    55     executables = { 
    56         'preprocessor' : None, 
    57         'compiler'     : ['dmd'], 
    58         'compiler_so'  : ['dmd'], 
    59         'linker_so'    : ['dmd', '-shared'], # XXX? 
    60         'linker_exe'   : ['dmd'], 
    61       } 
    6247 
    6348    src_extensions = ['.d'] 
     
    7055 
    7156    def __init__(self, *args, **kwargs): 
    72         DCompiler.__init__(self, *args, **kwargs) 
    73         self._initialized = False 
    74  
    75  
    76     def _initialize(self, debug): 
    77         # Would like to determine whether optimization was requested in a more 
    78         # proper manner (by checking the 'optimize' attribute of the Command 
    79         # object under which we're operating), but can't figure out how to get 
    80         # a reference to that Command object without burdening client 
    81         # programmers by forcing them to pass a cmd_class argument to setup(). 
    82         args = [a.lower() for a in sys.argv[1:]] 
    83         optimize = ('-o' in args or '--optimize' in args) 
    84  
    85         dmdExeFilename = (_isPlatWin and 'dmd.exe') or 'dmd' 
    86  
    87         # Require environment variable D_ROOT: 
     57        cc.CCompiler.__init__(self, *args, **kwargs) 
     58        # Get DMD/GDC specific info 
     59        self._initialize() 
     60        # _binpath 
    8861        try: 
    89             dRoot = os.environ['D_ROOT'] 
     62            dBin = os.environ[self._env_var] 
     63            if not os.path.isfile(dBin): 
     64                self.warn("Environment variable %s provided, but file '%s' does not exist." % (self._env_var, dBin)) 
     65                raise KeyError 
    9066        except KeyError: 
    9167            if _isPlatWin: 
    92                 exampleDMDPath = os.path.join( 
    93                     os.path.dirname(os.path.dirname(sys.executable)), 
    94                     'd', 'dmd', 'bin', dmdExeFilename 
    95                   ) 
     68                # The environment variable wasn't supplied, so search the PATH. 
     69                # Windows requires the full path for reasons that escape me at 
     70                # the moment. 
     71                dBin = _findInPath(self.compiler_type + self.exe_extension) 
     72                if dBin is None: 
     73                    raise DistutilsFileError('You must either set the %s' 
     74                        ' environment variable to the full path of the %s' 
     75                        ' executable, or place the executable on the PATH.' % 
     76                        (self._env_var, self.compiler_type) 
     77                    ) 
    9678            else: 
    97                 exampleDMDPath = '/opt/d/dmd/bin/' + dmdExeFilename 
    98  
    99             raise DistutilsFileError('You must set the D_ROOT environment' 
    100                 ' variable to the great-grandparent directory of the dmd' 
    101                 ' executable.' 
    102                 '\n(If the dmd executable were at\n  "%s", D_ROOT should be' 
    103                 '\n  "%s".)' 
    104                 % (exampleDMDPath, 
    105                    os.path.dirname(os.path.dirname( 
    106                        os.path.dirname(exampleDMDPath) 
    107                      )) 
    108                   ) 
    109               ) 
    110  
    111         # Find the DMD executable: 
    112         dmdExePath = _findInPath(dmdExeFilename, 
    113             startIn=os.path.join(dRoot, 'dmd', 'bin') 
    114           ) 
    115         if not dmdExePath: 
    116             dmdExeSubPath = os.path.join('dmd', 'bin', 
    117                 'dmd' + ((_isPlatWin and '.exe') or '') 
    118               ) 
    119             dmdExePath = os.path.join(dRoot, dmdExeSubPath) 
    120             if not os.path.isfile(dmdExePath): 
    121                 dmdExePathRepr = os.path.join( 
    122                     ((_isPlatWin and '%D_ROOT%') or '$D_ROOT'), 
    123                     dmdExeSubPath 
    124                   ) 
    125                 raise DistutilsFileError('Could not find dmd executable.  It' 
    126                     ' should be located at "%s".' % dmdExePathRepr 
    127                   ) 
    128  
    129         # Store in instance variables the info we'll need later: 
    130         self._dRoot = dRoot 
    131         self._dmdExePath = dmdExePath 
    132         self._unicodeOpt = ('-version=Python_Unicode_UCS' 
    133             + ((sys.maxunicode == 0xFFFF and '2') or '4') 
    134           ) 
    135  
    136         # Set optimization-versus-safety options (conservatively by default; 
    137         # as aggressively optimized as possible when the user specifies 
    138         # 'python setup.py build -O'). 
    139         conservativeOpts = ['-debug', '-unittest'] 
    140         if debug: 
    141             # Conservative checking AND symbolic debugging information: 
    142             self._optimizationOpts = conservativeOpts + ['-g'] 
    143         elif optimize: 
    144             self._optimizationOpts = ['-version=Optimized', 
    145                 '-release', '-O', '-inline', 
    146               ] 
    147         else: 
    148             # The default is conservative in that it generates validation code, 
    149             # but it does not include symbolic debugging information: 
    150             self._optimizationOpts = conservativeOpts 
    151  
    152  
    153         self._initialized = True 
    154  
     79                # Just run it via the PATH directly in Linux 
     80                dBin = self.compiler_type 
     81        self._binpath = dBin 
     82        # _unicodeOpt 
     83        self._unicodeOpt = self._versionOpt % ('Python_Unicode_UCS' + ((sys.maxunicode == 0xFFFF and '2') or '4')) 
     84 
     85    def _initialize(self): 
     86        # It is intended that this method be implemented by subclasses. 
     87        raise NotImplementedError, "Cannot initialize DCompiler, use DMDDCompiler or GDCDCompiler instead." 
     88 
     89    def _def_file(self, output_dir, output_filename): 
     90        """A list of options used to tell the linker how to make a dll/so. In 
     91        DMD, it is the .def file. In GDC, it is 
     92        ['-shared', '-Wl,-soname,blah.so'] or similar.""" 
     93        raise NotImplementedError, "Cannot initialize DCompiler, use DMDDCompiler or GDCDCompiler instead." 
     94 
     95    def _lib_file(self, libraries): 
     96        return '' 
     97 
     98    def find_library_file(self, dirs, lib, debug=0): 
     99        shared_f = self.library_filename(lib, lib_type='shared') 
     100        static_f = self.library_filename(lib, lib_type='static') 
     101 
     102        for dir in dirs: 
     103            shared = os.path.join(dir, shared_f) 
     104            static = os.path.join(dir, static_f) 
     105 
     106            if os.path.exists(shared): 
     107                return shared 
     108            elif os.path.exists(static): 
     109                return static 
     110 
     111        return None 
    155112 
    156113    def compile(self, sources, 
    157114        output_dir=None, macros=None, include_dirs=None, debug=0, 
    158115        extra_preargs=None, extra_postargs=None, depends=None 
    159       ): 
    160         if not self._initialized: self._initialize(debug) 
    161  
    162         # Distutils defaults to None for "unspecified option list"; we want 
    163         # empty lists in that case (this substitution is done here in the body 
    164         # rather than by changing the default parameters in case distutils 
    165         # passes None explicitly). 
     116    ): 
    166117        macros = macros or [] 
    167118        include_dirs = include_dirs or [] 
     
    172123            os.makedirs(output_dir) 
    173124 
    174         dmdExeOpt = _qp(self._dmdExePath) 
    175         compileOnlyOpt = '-c' # In this stage, we don't want to link. 
    176  
    177         outputDirOpt = '-od' + _qp(output_dir) 
    178  
     125        binpath = _qp(self._binpath) 
     126        compileOpts = self._compileOpts 
     127        #outputOpts = self._outputOpts 
     128 
     129        includePathOpts = [] 
     130         
    179131        # To sources, add the appropriate D header file python.d, as well as 
    180132        # any platform-specific boilerplate. 
    181133        pythonHeaderPath = os.path.join(_infraDir, 'python', 'headers', 'python.d') 
     134        # Add the python header's directory to the include path 
     135        includePathOpts += self._includeOpts 
     136        includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir, 'python', 'headers') 
    182137        if not os.path.isfile(pythonHeaderPath): 
    183138            raise DistutilsPlatformError('Required D translation of Python' 
    184139                ' header files "%s" is missing.' % pythonHeaderPath 
    185              
    186         sources.append(_qp(pythonHeaderPath)
     140           
     141        sources.append(pythonHeaderPath
    187142 
    188143        # And Pyd! 
     
    194149                    " missing." % filePath 
    195150                ) 
    196             sources.append(_qp(filePath)) 
     151            sources.append(filePath) 
     152        # Add the pyd directory to the include path 
     153        includePathOpts += self._includeOpts 
     154        includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir) 
    197155         
     156        # Add DLL/SO boilerplate code file. 
    198157        if _isPlatWin: 
    199             pdwbPath = os.path.join(_infraDir, 'd', 
     158            boilerplatePath = os.path.join(_infraDir, 'd', 
    200159                'python_dll_windows_boilerplate.d' 
    201               ) 
    202             if not os.path.isfile(pdwbPath): 
    203                 raise DistutilsFileError('Required supporting code file "%s"' 
    204                     ' is missing.' % pdwbPath 
    205                   ) 
    206             sources.append(_qp(pdwbPath)) 
    207  
    208  
    209         quotedSourceFiles = [_qp(sf) for sf in sources] 
     160            ) 
     161        else: 
     162            boilerplatePath = os.path.join(_infraDir, 'd', 
     163                'python_so_linux_boilerplate.d' 
     164            ) 
     165        if not os.path.isfile(boilerplatePath): 
     166            raise DistutilsFileError('Required supporting code file "%s"' 
     167                ' is missing.' % boilerplatePath 
     168            ) 
     169        sources.append(boilerplatePath) 
    210170 
    211171        # Extension subclass DExtension will have packed any user-supplied 
    212172        # version and debug flags into macros; we extract them and convert them 
    213         # into the appropriate DMD command-line args. 
     173        # into the appropriate command-line args. 
    214174        versionFlags = [name for (name, category) in macros if category == 'version'] 
    215175        debugFlags = [name for (name, category) in macros if category == 'debug'] 
    216176        userVersionAndDebugOpts = ( 
    217               ['-version=%s' % v for v in versionFlags] 
    218             + ['-debug=%s' % v for v in debugFlags] 
    219          
     177              [self._versionOpt % v for v in versionFlags] + 
     178              [self._debugOpt  % v for v in debugFlags] 
     179       
    220180 
    221181        # Python version option allows extension writer to take advantage of 
     
    227187        #     // Do it the hard way... 
    228188        #   } 
    229         pythonVersionOpt = '-version=Python_%d_%d_Or_Later' % sys.version_info[:2] 
    230  
    231         # Generate a complete list of all command-line arguments, excluding any 
    232         # that turned out to be blank: 
    233         cmdElements = ([dmdExeOpt] + extra_preargs 
    234             + [compileOnlyOpt, pythonVersionOpt, self._unicodeOpt] 
    235             + self._optimizationOpts + [outputDirOpt] 
    236             + userVersionAndDebugOpts + quotedSourceFiles + extra_postargs 
    237           ) 
     189        pythonVersionOpt = self._versionOpt % ('Python_%d_%d_Or_Later' % sys.version_info[:2]) 
     190 
     191        # Optimization opts 
     192        args = [a.lower() for a in sys.argv[1:]] 
     193        optimize = ('-o' in args or '--optimize' in args) 
     194        if debug: 
     195            optimizationOpts = self._debugOptimizeOpts 
     196        elif optimize: 
     197            optimizationOpts = self._releaseOptimizeOpts 
     198        else: 
     199            optimizationOpts = self._defaultOptimizeOpts 
     200 
     201        #for source in sources: 
     202            #outOpts = outputOpts[:] 
     203            #objName = self.object_filenames([os.path.split(source)[1]], 0, output_dir)[0] 
     204            #outOpts[-1] = outOpts[-1] % _qp(objName) 
     205            #cmdElements = ( 
     206            #    [binpath] + extra_preargs + compileOpts + 
     207            #    [pythonVersionOpt, self._unicodeOpt] + optimizationOpts + 
     208            #    includePathOpts + outOpts + userVersionAndDebugOpts + 
     209            #    [_qp(source)] + extra_postargs 
     210            #) 
     211        # gdc/gcc doesn't support the idea of an output directory, so we 
     212        # compile from the destination 
     213        sources = [_qp(os.path.abspath(s)) for s in sources] 
     214        cwd = os.getcwd() 
     215        os.chdir(output_dir) 
     216        cmdElements = ( 
     217            [binpath] + extra_preargs + compileOpts + 
     218            [pythonVersionOpt, self._unicodeOpt] + optimizationOpts + 
     219            includePathOpts + userVersionAndDebugOpts + 
     220            sources + extra_postargs 
     221        ) 
    238222        cmdElements = [el for el in cmdElements if el] 
    239223 
    240         # Invoke the compiler: 
    241224        try: 
    242225            self.spawn(cmdElements) 
    243226        except DistutilsExecError, msg: 
     227            os.chdir(cwd) 
    244228            raise CompileError(msg) 
    245  
    246         # Return a list of paths to the object files generated by the 
    247         # compilation process: 
    248         return [os.path.join(output_dir, fn) for fn in os.listdir(output_dir)] 
    249  
     229        os.chdir(cwd) 
     230 
     231        return [os.path.join(output_dir, fn) for fn in os.listdir(output_dir) if fn.endswith(self.obj_extension)] 
    250232 
    251233    def link (self, 
     
    256238        extra_preargs=None, extra_postargs=None, 
    257239        build_temp=None, target_lang=None 
    258       ): 
    259         if not self._initialized: self._initialize(debug) 
    260  
     240    ): 
    261241        # Distutils defaults to None for "unspecified option list"; we want 
    262242        # empty lists in that case (this substitution is done here in the body 
     
    270250        extra_postargs = extra_postargs or [] 
    271251 
     252        binpath = self._binpath 
     253        outputOpts = self._outputOpts[:] 
     254        objectOpts = [_qp(fn) for fn in objects] 
     255 
    272256        (objects, output_dir) = self._fix_object_args (objects, output_dir) 
    273257        (libraries, library_dirs, runtime_library_dirs) = \ 
     
    276260            self.warn('This CCompiler implementation does nothing with' 
    277261                ' "runtime_library_dirs": ' + str(runtime_library_dirs) 
    278               ) 
    279  
    280         # Determine output_dir from output_filename or vice versa, depending 
    281         # on which was supplied: 
     262            ) 
     263 
    282264        if output_dir and os.path.basename(output_filename) == output_filename: 
    283265            output_filename = os.path.join(output_dir, output_filename) 
    284266        else: 
    285267            if not output_filename: 
    286                 raise DistutilsFileError('Neither output_dir nor' 
     268                raise DistutilsFileError, 'Neither output_dir nor' \ 
    287269                    ' output_filename was specified.' 
    288                   ) 
    289270            output_dir = os.path.dirname(output_filename) 
    290271            if not output_dir: 
    291                 raise DistutilsFileError('Unable to guess output_dir on the' 
    292                     ' basis of output_filename "%s" alone.' % output_filename 
    293                   ) 
     272                raise DistutilsFileError, 'Unable to guess output_dir on the'\ 
     273                    ' bases of output_filename "%s" alone.' % output_filename 
     274 
     275        # Format the output filename option 
     276        # (-offilename in DMD, -o filename in GDC) 
     277        outputOpts[-1] = outputOpts[-1] % _qp(output_filename) 
    294278 
    295279        if not os.path.exists(output_dir): 
     
    297281 
    298282        if not self._need_link(objects, output_filename): 
    299             print ('The distutils infrastructure indicated that all binary' 
    300                 ' output files are up to date.' 
    301               ) 
     283            print "All binary output files are up to date." 
    302284            return 
    303285 
     286        # The .def file (on Windows) or -shared and -soname (on Linux) 
     287        sharedOpts = self._def_file(build_temp, output_filename) 
     288 
     289        # The python .lib file, if needed 
     290        pythonLibOpt = self._lib_file(libraries) 
     291        if pythonLibOpt: 
     292            pythonLibOpt = _qp(pythonLibOpt) 
     293 
     294        if target_desc != cc.CCompiler.SHARED_OBJECT: 
     295            raise LinkError('This CCompiler implementation does not know' 
     296                ' how to link anything except an extension module (that is, a' 
     297                ' shared object file).' 
     298            ) 
     299 
     300        # Library linkage options 
     301        print "library_dirs:", library_dirs 
     302        print "runtime_library_dirs:", runtime_library_dirs 
     303        print "libraries:", libraries 
     304        libOpts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) 
     305 
     306        # Optimization opts 
     307        args = [a.lower() for a in sys.argv[1:]] 
     308        optimize = ('-o' in args or '--optimize' in args) 
     309        if debug: 
     310            optimizationOpts = self._debugOptimizeOpts 
     311        elif optimize: 
     312            optimizationOpts = self._releaseOptimizeOpts 
     313        else: 
     314            optimizationOpts = self._defaultOptimizeOpts 
     315 
     316        cmdElements = ( 
     317            [binpath] + extra_preargs + self._linkOpts + optimizationOpts + 
     318            outputOpts + [pythonLibOpt] + objectOpts + libOpts + sharedOpts + 
     319            extra_postargs 
     320        ) 
     321        cmdElements = [el for el in cmdElements if el] 
     322 
     323        try: 
     324            self.spawn(cmdElements) 
     325        except DistutilsExecError, msg: 
     326            raise CompileError(msg) 
     327 
     328class DMDDCompiler(DCompiler): 
     329    compiler_type = 'dmd' 
     330 
     331    executables = { 
     332        'preprocessor' : None, 
     333        'compiler'     : ['dmd'], 
     334        'compiler_so'  : ['dmd'], 
     335        'linker_so'    : ['dmd'], 
     336        'linker_exe'   : ['dmd'], 
     337    } 
     338 
     339    _env_var = 'DMD_BIN' 
     340 
     341    def _initialize(self): 
     342        # _compileOpts 
     343        self._compileOpts = ['-c'] 
     344        # _outputOpts 
     345        self._outputOpts = ['-of%s'] 
     346        # _linkOpts 
     347        self._linkOpts = [] 
     348        # _includeOpts 
     349        self._includeOpts = ['-I%s'] 
     350        # _versionOpt 
     351        self._versionOpt = '-version=%s' 
     352        # _debugOpt 
     353        self._debugOpt = '-debug=%s' 
     354        # _defaultOptimizeOpts 
     355        self._defaultOptimizeOpts = ['-debug', '-unittest'] 
     356        # _debugOptimizeOpts 
     357        self._debugOptimizeOpts = self._defaultOptimizeOpts + ['-g'] 
     358        # _releaseOptimizeOpts 
     359        self._releaseOptimizeOpts = ['-version=Optimized', '-release', '-O', '-inline'] 
     360 
     361    #def link_opts(self,  
     362 
     363    def _def_file(self, output_dir, output_filename): 
    304364        if _isPlatWin: 
    305365            # Automatically create a .def file: 
    306366            defTemplatePath = os.path.join(_infraDir, 'd', 
    307367                'python_dll_def.def_template' 
    308              
     368           
    309369            if not os.path.isfile(defTemplatePath): 
    310370                raise DistutilsFileError('Required def template file "%s" is' 
    311371                    ' missing.' % defTemplatePath 
    312                  
     372               
    313373            f = file(defTemplatePath, 'rb') 
    314374            try: 
     
    318378 
    319379            defFileContents = defTemplate % os.path.basename(output_filename) 
    320             defFilePath = os.path.join(build_temp, 'python_dll_def.def') 
     380            defFilePath = os.path.join(output_dir, 'python_dll_def.def') 
    321381            f = file(defFilePath, 'wb') 
    322382            try: 
     
    325385                f.close() 
    326386 
    327             objects.append(defFilePath) 
    328  
    329         if target_desc != cc.CCompiler.SHARED_OBJECT: 
    330             raise LinkError('This CCompiler implementation does not know' 
    331                 ' how to link anything except an extension module (that is, a' 
    332                 ' shared object file).' 
    333               ) 
    334  
    335         dmdExeOpt = _qp(self._dmdExePath) 
    336         outputDirOpt = '-od' + _qp(output_dir) 
    337         outputObjOpt = '-of' + _qp(output_filename) 
    338         inputObjectOpts = [_qp(oFN) for oFN in objects] 
    339  
    340         if not _isPlatWin: 
    341             # DMD uses the GNU linker on non-Windows platforms, so there's no 
    342             # need for us to change the distutils defaults. 
    343             pythonLibOpt = '' 
    344         else: 
     387            return [defFilePath] 
     388        else: 
     389            return [] 
     390 
     391    def _lib_file(self, libraries): 
     392        if _isPlatWin: 
    345393            # The DMD-compatible .lib file can be generated with implib.exe 
    346394            # (from the Digital Mars "Basic Utilities" package) using a command 
     
    355403            pythonDMDLibPath = _qp(os.path.join(_infraDir, 'python', 'libs', 
    356404                _pyVerXDotY, 'python%s_digitalmars.lib' % _pyVerXY 
    357               )) 
     405            )) 
    358406            if not os.path.isfile(pythonDMDLibPath): 
    359407                raise DistutilsFileError('The DMD-compatible Python .lib file' 
     
    362410                    ' contains a .lib file appropriate for your Python version.' 
    363411                    % pythonDMDLibPath 
    364                  
     412               
    365413            pythonLibOpt = _qp(pythonDMDLibPath) 
    366414 
     
    372420            if 'python' + _pyVerXY in libraries: 
    373421                libraries.remove('python' + _pyVerXY) 
    374  
    375         # Find the paths of any requested library files: 
    376         explicitLibOpts = [] 
    377         if libraries: 
    378             if not _isPlatWin: 
    379                 # Pass through library requests to the GNU linker via DMD's -L 
    380                 # option. 
    381                 explicitLibOpts.extend('-L-l' + libName for libName in libraries) 
    382             else: 
    383                 # On Windows, the linker that DMD uses doesn't seem to have an 
    384                 # equivalent of GCC's -LsearchDirectory and -llibraryName 
    385                 # arguments, so we try to find the exact paths for the 
    386                 # libraries mentioned and pass those paths to DMD. 
    387                 # XXX: What about OptLink's /scanlib option and the LIB env var? 
    388                 explicitLibFilenames = [ 
    389                     libName + DMDDCompiler.static_lib_extension 
    390                     for libName in libraries 
    391                   ] 
    392                 if not library_dirs: 
    393                     explicitLibOpts.extend(explicitLibFilenames) 
    394                 else: 
    395                     curDir = os.path.abspath(os.curdir) 
    396                     if curDir not in library_dirs: 
    397                         library_dirs.insert(0, curDir) 
    398  
    399                     libFound = [False] * len(libraries) 
    400                     for libIndex, libFilename in enumerate(explicitLibFilenames): 
    401                         for libDir in library_dirs: 
    402                             probeLibPath = os.path.join(libDir, libFilename) 
    403                             if os.path.isfile(probeLibPath): 
    404                                 explicitLibOpts.append(_qp(probeLibPath)) 
    405                                 libFound[libIndex] = True 
    406                                 break 
    407  
    408                     libsNotFound = [] 
    409                     for libIndex, found in enumerate(libFound): 
    410                         if not found: 
    411                             libsNotFound.append( 
    412                                 (libraries[libIndex], explicitLibFilenames[libIndex]) 
    413                               ) 
    414                     if libsNotFound: 
    415                         raise LinkError('Unable to find the following libraries' 
    416                             ' in the specified library search directories:\n  ' 
    417                             + '\n  '.join( 
    418                                   '%s  (filename "%s")' % (libName, libFilename) 
    419                                   for (libName, libFilename) in libsNotFound 
    420                                 ) 
    421                             + '\nSearched the following directories:\n  ' 
    422                             + '\n  '.join(library_dirs) 
    423                           ) 
    424  
    425         # Generate a complete list of all command-line arguments, excluding any 
    426         # that turned out to be blank: 
    427         cmdElements = ([dmdExeOpt] + extra_preargs + self._optimizationOpts 
    428             + [outputDirOpt, outputObjOpt, pythonLibOpt, self._unicodeOpt] 
    429             + inputObjectOpts + explicitLibOpts + extra_postargs 
    430           ) 
    431         cmdElements = [el for el in cmdElements if el] 
    432  
    433         # Invoke the linker indirectly by calling the compiler: 
    434         try: 
    435             self.spawn(cmdElements) 
    436         except DistutilsExecError, msg: 
    437             raise CompileError(msg) 
    438  
     422            return pythonLibOpt 
     423        else: 
     424            return '' 
     425 
     426    def library_dir_option(self, dir): 
     427        self.warn("Don't know how to set library search path for DMD.") 
     428        #raise DistutilsPlatformError, "Don't know how to set library search path for DMD." 
     429 
     430    def runtime_library_dir_option(self, dir): 
     431        self.warn("Don't know how to set runtime library search path for DMD.") 
     432        #raise DistutilsPlayformError, "Don't know how to set runtime library search path for DMD." 
     433 
     434    def library_option(self, lib): 
     435        if _isPlatWin: 
     436            return self.library_filename(lib) 
     437        else: 
     438            return '-L-l' + lib 
     439 
     440class GDCDCompiler(DCompiler): 
     441    compiler_type = 'gdc' 
     442 
     443    executables = { 
     444        'preprocessor' : None, 
     445        'compiler'     : ['gdc'], 
     446        'compiler_so'  : ['gdc'], 
     447        'linker_so'    : ['gdc'], 
     448        'linker_exe'   : ['gdc'], 
     449    } 
     450 
     451    _env_var = 'GDC_BIN' 
     452 
     453    def _initialize(self): 
     454        # _compileOpts 
     455        self._compileOpts = ['-fPIC', '-c'] 
     456        # _outputOpts 
     457        self._outputOpts = ['-o', '%s'] 
     458        # _linkOpts 
     459        self._linkOpts = ['-fPIC', '-nostartfiles', '-shared'] 
     460        # _includeOpts 
     461        self._includeOpts = ['-I', '%s'] 
     462        # _versionOpt 
     463        self._versionOpt = '-fversion=%s' 
     464        # _debugOpt 
     465        self._debugOpt = '-fdebug=%s' 
     466        # _defaultOptimizeOpts 
     467        self._defaultOptimizeOpts = ['-fdebug', '-funittest'] 
     468        # _debugOptimizeOpts 
     469        self._debugOptimizeOpts = self._defaultOptimizeOpts + ['-g'] 
     470        # _releaseOptimizeOpts 
     471        self._releaseOptimizeOpts = ['-fversion=Optimized', '-frelease', '-O3', '-finline-functions'] 
     472 
     473    def _def_file(self, output_dir, output_filename): 
     474        return ['-Wl,-soname,' + os.path.basename(output_filename)] 
     475 
     476    def library_dir_option(self, dir): 
     477        return '-L' + dir 
     478 
     479    def runtime_library_dir_option(self, dir): 
     480        return '-Wl,-R' + dir 
     481 
     482    def library_option(self, lib): 
     483        return '-l' + lib 
    439484 
    440485# Utility functions: 
  • trunk/patch_distutils.py

    r24 r30  
    1818 
    1919cc.compiler_class['dmd'] = ('celerid.dcompiler', 'DMDDCompiler', 'Digital Mars D') 
     20cc.compiler_class['gdc'] = ('celerid.dcompiler', 'GDCDCompiler', 'GCC D Compiler') 
    2021 
    2122_old_new_compiler = cc.new_compiler 
     
    2526        compiler = compiler.lower() 
    2627 
    27     if compiler not in (None, 'dmd'): 
     28    if compiler is None: 
     29        if dcompiler._isPlatWin: 
     30            compiler = 'dmd' 
     31        else: 
     32            compiler = 'gdc' 
     33 
     34    if compiler not in ('dmd', 'gdc'): 
    2835        return _old_new_compiler(compiler=compiler, 
    2936            dry_run=dry_run, force=force, **kwargs 
    3037          ) 
     38    elif compiler == 'dmd': 
     39        return dcompiler.DMDDCompiler(None, dry_run, force) 
     40    elif compiler == 'gdc': 
     41        return dcompiler.GDCDCompiler(None, dry_run, force) 
    3142    else: 
    32         return dcompiler.DMDDCompiler(None, dry_run, force) 
     43        raise RuntimeError, "Couldn't get a compiler..." 
    3344 
    3445cc.new_compiler = new_compiler 
     
    4253#   python setup.py build --compiler=dmd 
    4354def get_default_compiler(*args, **kwargs): 
    44     return 'dmd' 
     55    if dcompiler._isPlatWin: 
     56        return 'dmd' 
     57    else: 
     58        return 'gdc' 
    4559 
    4660cc.get_default_compiler = get_default_compiler 
  • trunk/pydmdvars.bat

    r24 r30  
    33Set D_ROOT=C:\dmd 
    44Set PY_ROOT=C:\Python24 
    5 Set PATH=%D_ROOT%\dmd\bin;%D_ROOT%\dm\bin;%PY_ROOT%;%PATH% 
     5Set PATH=%D_ROOT%\dmd\bin;%D_ROOT%\dm\bin;%D_ROOT%\gdc\bin;%PY_ROOT%;%PATH% 
    66Set LIB=%D_ROOT%\dmd\lib;%D_ROOT%\dm\lib;%LIB% 
    77 
    8 echo Environment configured for Python and DMD 
     8echo Environment configured for Python and D 
    99