| 
							 | 
						"""distutils.command.build_clib | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						Implements the Distutils 'build_clib' command, to build a C/C++ library | 
					
					
						
						| 
							 | 
						that is included in the module distribution and needed by an extension | 
					
					
						
						| 
							 | 
						module.""" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						import os | 
					
					
						
						| 
							 | 
						from distutils.core import Command | 
					
					
						
						| 
							 | 
						from distutils.errors import DistutilsSetupError | 
					
					
						
						| 
							 | 
						from distutils.sysconfig import customize_compiler | 
					
					
						
						| 
							 | 
						from distutils import log | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						def show_compilers(): | 
					
					
						
						| 
							 | 
						    from distutils.ccompiler import show_compilers | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    show_compilers() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						class build_clib(Command): | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    description = "build C/C++ libraries used by Python extensions" | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    user_options = [ | 
					
					
						
						| 
							 | 
						        ('build-clib=', 'b', "directory to build C/C++ libraries to"), | 
					
					
						
						| 
							 | 
						        ('build-temp=', 't', "directory to put temporary build by-products"), | 
					
					
						
						| 
							 | 
						        ('debug', 'g', "compile with debugging information"), | 
					
					
						
						| 
							 | 
						        ('force', 'f', "forcibly build everything (ignore file timestamps)"), | 
					
					
						
						| 
							 | 
						        ('compiler=', 'c', "specify the compiler type"), | 
					
					
						
						| 
							 | 
						    ] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    boolean_options = ['debug', 'force'] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    help_options = [ | 
					
					
						
						| 
							 | 
						        ('help-compiler', None, "list available compilers", show_compilers), | 
					
					
						
						| 
							 | 
						    ] | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def initialize_options(self): | 
					
					
						
						| 
							 | 
						        self.build_clib = None | 
					
					
						
						| 
							 | 
						        self.build_temp = None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.libraries = None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.include_dirs = None | 
					
					
						
						| 
							 | 
						        self.define = None | 
					
					
						
						| 
							 | 
						        self.undef = None | 
					
					
						
						| 
							 | 
						        self.debug = None | 
					
					
						
						| 
							 | 
						        self.force = 0 | 
					
					
						
						| 
							 | 
						        self.compiler = None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def finalize_options(self): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        self.set_undefined_options( | 
					
					
						
						| 
							 | 
						            'build', | 
					
					
						
						| 
							 | 
						            ('build_temp', 'build_clib'), | 
					
					
						
						| 
							 | 
						            ('build_temp', 'build_temp'), | 
					
					
						
						| 
							 | 
						            ('compiler', 'compiler'), | 
					
					
						
						| 
							 | 
						            ('debug', 'debug'), | 
					
					
						
						| 
							 | 
						            ('force', 'force'), | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.libraries = self.distribution.libraries | 
					
					
						
						| 
							 | 
						        if self.libraries: | 
					
					
						
						| 
							 | 
						            self.check_library_list(self.libraries) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.include_dirs is None: | 
					
					
						
						| 
							 | 
						            self.include_dirs = self.distribution.include_dirs or [] | 
					
					
						
						| 
							 | 
						        if isinstance(self.include_dirs, str): | 
					
					
						
						| 
							 | 
						            self.include_dirs = self.include_dirs.split(os.pathsep) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def run(self): | 
					
					
						
						| 
							 | 
						        if not self.libraries: | 
					
					
						
						| 
							 | 
						            return | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        from distutils.ccompiler import new_compiler | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.compiler = new_compiler( | 
					
					
						
						| 
							 | 
						            compiler=self.compiler, dry_run=self.dry_run, force=self.force | 
					
					
						
						| 
							 | 
						        ) | 
					
					
						
						| 
							 | 
						        customize_compiler(self.compiler) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        if self.include_dirs is not None: | 
					
					
						
						| 
							 | 
						            self.compiler.set_include_dirs(self.include_dirs) | 
					
					
						
						| 
							 | 
						        if self.define is not None: | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            for (name, value) in self.define: | 
					
					
						
						| 
							 | 
						                self.compiler.define_macro(name, value) | 
					
					
						
						| 
							 | 
						        if self.undef is not None: | 
					
					
						
						| 
							 | 
						            for macro in self.undef: | 
					
					
						
						| 
							 | 
						                self.compiler.undefine_macro(macro) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        self.build_libraries(self.libraries) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def check_library_list(self, libraries): | 
					
					
						
						| 
							 | 
						        """Ensure that the list of libraries is valid. | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        `library` is presumably provided as a command option 'libraries'. | 
					
					
						
						| 
							 | 
						        This method checks that it is a list of 2-tuples, where the tuples | 
					
					
						
						| 
							 | 
						        are (library_name, build_info_dict). | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						        Raise DistutilsSetupError if the structure is invalid anywhere; | 
					
					
						
						| 
							 | 
						        just returns otherwise. | 
					
					
						
						| 
							 | 
						        """ | 
					
					
						
						| 
							 | 
						        if not isinstance(libraries, list): | 
					
					
						
						| 
							 | 
						            raise DistutilsSetupError("'libraries' option must be a list of tuples") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        for lib in libraries: | 
					
					
						
						| 
							 | 
						            if not isinstance(lib, tuple) and len(lib) != 2: | 
					
					
						
						| 
							 | 
						                raise DistutilsSetupError("each element of 'libraries' must a 2-tuple") | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            name, build_info = lib | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            if not isinstance(name, str): | 
					
					
						
						| 
							 | 
						                raise DistutilsSetupError( | 
					
					
						
						| 
							 | 
						                    "first element of each tuple in 'libraries' " | 
					
					
						
						| 
							 | 
						                    "must be a string (the library name)" | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            if '/' in name or (os.sep != '/' and os.sep in name): | 
					
					
						
						| 
							 | 
						                raise DistutilsSetupError( | 
					
					
						
						| 
							 | 
						                    "bad library name '%s': " | 
					
					
						
						| 
							 | 
						                    "may not contain directory separators" % lib[0] | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            if not isinstance(build_info, dict): | 
					
					
						
						| 
							 | 
						                raise DistutilsSetupError( | 
					
					
						
						| 
							 | 
						                    "second element of each tuple in 'libraries' " | 
					
					
						
						| 
							 | 
						                    "must be a dictionary (build info)" | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def get_library_names(self): | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						         | 
					
					
						
						| 
							 | 
						        if not self.libraries: | 
					
					
						
						| 
							 | 
						            return None | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						        lib_names = [] | 
					
					
						
						| 
							 | 
						        for (lib_name, build_info) in self.libraries: | 
					
					
						
						| 
							 | 
						            lib_names.append(lib_name) | 
					
					
						
						| 
							 | 
						        return lib_names | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def get_source_files(self): | 
					
					
						
						| 
							 | 
						        self.check_library_list(self.libraries) | 
					
					
						
						| 
							 | 
						        filenames = [] | 
					
					
						
						| 
							 | 
						        for (lib_name, build_info) in self.libraries: | 
					
					
						
						| 
							 | 
						            sources = build_info.get('sources') | 
					
					
						
						| 
							 | 
						            if sources is None or not isinstance(sources, (list, tuple)): | 
					
					
						
						| 
							 | 
						                raise DistutilsSetupError( | 
					
					
						
						| 
							 | 
						                    "in 'libraries' option (library '%s'), " | 
					
					
						
						| 
							 | 
						                    "'sources' must be present and must be " | 
					
					
						
						| 
							 | 
						                    "a list of source filenames" % lib_name | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            filenames.extend(sources) | 
					
					
						
						| 
							 | 
						        return filenames | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						    def build_libraries(self, libraries): | 
					
					
						
						| 
							 | 
						        for (lib_name, build_info) in libraries: | 
					
					
						
						| 
							 | 
						            sources = build_info.get('sources') | 
					
					
						
						| 
							 | 
						            if sources is None or not isinstance(sources, (list, tuple)): | 
					
					
						
						| 
							 | 
						                raise DistutilsSetupError( | 
					
					
						
						| 
							 | 
						                    "in 'libraries' option (library '%s'), " | 
					
					
						
						| 
							 | 
						                    "'sources' must be present and must be " | 
					
					
						
						| 
							 | 
						                    "a list of source filenames" % lib_name | 
					
					
						
						| 
							 | 
						                ) | 
					
					
						
						| 
							 | 
						            sources = list(sources) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						            log.info("building '%s' library", lib_name) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            macros = build_info.get('macros') | 
					
					
						
						| 
							 | 
						            include_dirs = build_info.get('include_dirs') | 
					
					
						
						| 
							 | 
						            objects = self.compiler.compile( | 
					
					
						
						| 
							 | 
						                sources, | 
					
					
						
						| 
							 | 
						                output_dir=self.build_temp, | 
					
					
						
						| 
							 | 
						                macros=macros, | 
					
					
						
						| 
							 | 
						                include_dirs=include_dirs, | 
					
					
						
						| 
							 | 
						                debug=self.debug, | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						             | 
					
					
						
						| 
							 | 
						            self.compiler.create_static_lib( | 
					
					
						
						| 
							 | 
						                objects, lib_name, output_dir=self.build_clib, debug=self.debug | 
					
					
						
						| 
							 | 
						            ) | 
					
					
						
						| 
							 | 
						
 |