Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
build_clib.py209 linesDownload Raw Back to command
1"""distutils.command.build_clib2 3Implements the Distutils 'build_clib' command, to build a C/C++ library4that is included in the module distribution and needed by an extension5module."""6 7 8# XXX this module has *lots* of code ripped-off quite transparently from9# build_ext.py -- not surprisingly really, as the work required to build10# a static library from a collection of C source files is not really all11# that different from what's required to build a shared object file from12# a collection of C source files.  Nevertheless, I haven't done the13# necessary refactoring to account for the overlap in code between the14# two modules, mainly because a number of subtle details changed in the15# cut 'n paste.  Sigh.16 17import os18from distutils._log import log19 20from ..core import Command21from ..errors import DistutilsSetupError22from ..sysconfig import customize_compiler23 24 25def show_compilers():26    from ..ccompiler import show_compilers27 28    show_compilers()29 30 31class build_clib(Command):32    description = "build C/C++ libraries used by Python extensions"33 34    user_options = [35        ('build-clib=', 'b', "directory to build C/C++ libraries to"),36        ('build-temp=', 't', "directory to put temporary build by-products"),37        ('debug', 'g', "compile with debugging information"),38        ('force', 'f', "forcibly build everything (ignore file timestamps)"),39        ('compiler=', 'c', "specify the compiler type"),40    ]41 42    boolean_options = ['debug', 'force']43 44    help_options = [45        ('help-compiler', None, "list available compilers", show_compilers),46    ]47 48    def initialize_options(self):49        self.build_clib = None50        self.build_temp = None51 52        # List of libraries to build53        self.libraries = None54 55        # Compilation options for all libraries56        self.include_dirs = None57        self.define = None58        self.undef = None59        self.debug = None60        self.force = 061        self.compiler = None62 63    def finalize_options(self):64        # This might be confusing: both build-clib and build-temp default65        # to build-temp as defined by the "build" command.  This is because66        # I think that C libraries are really just temporary build67        # by-products, at least from the point of view of building Python68        # extensions -- but I want to keep my options open.69        self.set_undefined_options(70            'build',71            ('build_temp', 'build_clib'),72            ('build_temp', 'build_temp'),73            ('compiler', 'compiler'),74            ('debug', 'debug'),75            ('force', 'force'),76        )77 78        self.libraries = self.distribution.libraries79        if self.libraries:80            self.check_library_list(self.libraries)81 82        if self.include_dirs is None:83            self.include_dirs = self.distribution.include_dirs or []84        if isinstance(self.include_dirs, str):85            self.include_dirs = self.include_dirs.split(os.pathsep)86 87        # XXX same as for build_ext -- what about 'self.define' and88        # 'self.undef' ?89 90    def run(self):91        if not self.libraries:92            return93 94        # Yech -- this is cut 'n pasted from build_ext.py!95        from ..ccompiler import new_compiler96 97        self.compiler = new_compiler(98            compiler=self.compiler, dry_run=self.dry_run, force=self.force99        )100        customize_compiler(self.compiler)101 102        if self.include_dirs is not None:103            self.compiler.set_include_dirs(self.include_dirs)104        if self.define is not None:105            # 'define' option is a list of (name,value) tuples106            for name, value in self.define:107                self.compiler.define_macro(name, value)108        if self.undef is not None:109            for macro in self.undef:110                self.compiler.undefine_macro(macro)111 112        self.build_libraries(self.libraries)113 114    def check_library_list(self, libraries):115        """Ensure that the list of libraries is valid.116 117        `library` is presumably provided as a command option 'libraries'.118        This method checks that it is a list of 2-tuples, where the tuples119        are (library_name, build_info_dict).120 121        Raise DistutilsSetupError if the structure is invalid anywhere;122        just returns otherwise.123        """124        if not isinstance(libraries, list):125            raise DistutilsSetupError("'libraries' option must be a list of tuples")126 127        for lib in libraries:128            if not isinstance(lib, tuple) and len(lib) != 2:129                raise DistutilsSetupError("each element of 'libraries' must a 2-tuple")130 131            name, build_info = lib132 133            if not isinstance(name, str):134                raise DistutilsSetupError(135                    "first element of each tuple in 'libraries' "136                    "must be a string (the library name)"137                )138 139            if '/' in name or (os.sep != '/' and os.sep in name):140                raise DistutilsSetupError(141                    "bad library name '%s': "142                    "may not contain directory separators" % lib[0]143                )144 145            if not isinstance(build_info, dict):146                raise DistutilsSetupError(147                    "second element of each tuple in 'libraries' "148                    "must be a dictionary (build info)"149                )150 151    def get_library_names(self):152        # Assume the library list is valid -- 'check_library_list()' is153        # called from 'finalize_options()', so it should be!154        if not self.libraries:155            return None156 157        lib_names = []158        for lib_name, _build_info in self.libraries:159            lib_names.append(lib_name)160        return lib_names161 162    def get_source_files(self):163        self.check_library_list(self.libraries)164        filenames = []165        for lib_name, build_info in self.libraries:166            sources = build_info.get('sources')167            if sources is None or not isinstance(sources, (list, tuple)):168                raise DistutilsSetupError(169                    "in 'libraries' option (library '%s'), "170                    "'sources' must be present and must be "171                    "a list of source filenames" % lib_name172                )173 174            filenames.extend(sources)175        return filenames176 177    def build_libraries(self, libraries):178        for lib_name, build_info in libraries:179            sources = build_info.get('sources')180            if sources is None or not isinstance(sources, (list, tuple)):181                raise DistutilsSetupError(182                    "in 'libraries' option (library '%s'), "183                    "'sources' must be present and must be "184                    "a list of source filenames" % lib_name185                )186            sources = list(sources)187 188            log.info("building '%s' library", lib_name)189 190            # First, compile the source code to object files in the library191            # directory.  (This should probably change to putting object192            # files in a temporary build directory.)193            macros = build_info.get('macros')194            include_dirs = build_info.get('include_dirs')195            objects = self.compiler.compile(196                sources,197                output_dir=self.build_temp,198                macros=macros,199                include_dirs=include_dirs,200                debug=self.debug,201            )202 203            # Now "link" the object files together into a static library.204            # (On Unix at least, this isn't really linking -- it just205            # builds an archive.  Whatever.)206            self.compiler.create_static_lib(207                objects, lib_name, output_dir=self.build_clib, debug=self.debug208            )209 
codekingpro/portable-devtools · Team Ai