code: def build_extension(self, ext):
      sources = ext.sources
      if sources is None or not isinstance(sources, (list, tuple)):
          raise DistutilsSetupError(
              "in 'ext_modules' option (extension '%s'), "
              "'sources' must be present and must be "
              "a list of source filenames" % ext.name
          )
      # sort to make the resulting .so file build reproducible
      sources = sorted(sources)
  
      ext_path = self.get_ext_fullpath(ext.name)
      depends = sources + ext.depends
      if not (self.force or newer_group(depends, ext_path, "newer")):
          log.debug("skipping '%s' extension (up-to-date)", ext.name)
          return
      else:
          log.info("building '%s' extension", ext.name)
  
      # First, scan the sources for SWIG definition files (.i), run
      # SWIG on 'em to create .c files, and modify the sources list
      # accordingly.
      sources = self.swig_sources(sources, ext)
  
      # Next, compile the source code to object files.
  
      # XXX not honouring 'define_macros' or 'undef_macros' -- the
      # CCompiler API needs to change to accommodate this, and I
      # want to do one thing at a time!
  
      # Two possible sources for extra compiler arguments:
      #   - 'extra_compile_args' in Extension object
      #   - CFLAGS environment variable (not particularly
      #     elegant, but people seem to expect it and I
      #     guess it's useful)
      # The environment variable should take precedence, and
      # any sensible compiler will give precedence to later
      # command line args.  Hence we combine them in order:
      extra_args = ext.extra_compile_args or []
  
      macros = ext.define_macros[:]
      for undef in ext.undef_macros:
          macros.append((undef,))
  
      objects = self.compiler.compile(
          sources,
          output_dir=self.build_temp,
          macros=macros,
          include_dirs=ext.include_dirs,
          debug=self.debug,
          extra_postargs=extra_args,
          depends=ext.depends,
      )
  
      # XXX outdated variable, kept here in case third-part code
      # needs it.
      self._built_objects = objects[:]
  
      # Now link the object files together into a "shared object" --
      # of course, first we have to figure out all the other things
      # that go into the mix.
      if ext.extra_objects:
          objects.extend(ext.extra_objects)
      extra_args = ext.extra_link_args or []
  
      # Detect target language, if not provided
      language = ext.language or self.compiler.detect_language(sources)
  
      self.compiler.link_shared_object(
          objects,
          ext_path,
          libraries=self.get_libraries(ext),
          library_dirs=ext.library_dirs,
          runtime_library_dirs=ext.runtime_library_dirs,
          extra_postargs=extra_args,
          export_symbols=self.get_export_symbols(ext),
          debug=self.debug,
          build_temp=self.build_temp,
          target_lang=language,
      )
  
imports: import contextlib
  import os
  import re
  import sys
  from ..core import Command
  from ..errors import DistutilsOptionError, DistutilsSetupError, CCompilerError, DistutilsError, CompileError, DistutilsPlatformError
  from ..sysconfig import customize_compiler, get_python_version
  from ..sysconfig import get_config_h_filename
  from .._modified import newer_group
  from ..extension import Extension
  from ..util import get_platform
  from distutils._log import log
  from .None import py37compat
  from site import USER_BASE
label_desc: Use image node_id 11 for calling the build_ext obj's underlying member method code with example usage: obj.build_extension(ext) without return types