docstr: Returns a class that can be used as a replacement for the
  ``build_ext`` command in ``setuptools`` and that will compile the C core
  of igraph before compiling the Python extension.
docstr_tok: ["Returns","a","class","that","can","be","used","as","a","replacement","for","the","``","build_ext","``","command","in","``","setuptools","``","and","that","will","compile","the","C","core","of","igraph","before","compiling","the","Python","extension","."]
code: def build_ext(self) -> Command:
      """Returns a class that can be used as a replacement for the
      ``build_ext`` command in ``setuptools`` and that will compile the C core
      of igraph before compiling the Python extension.
      """
      from setuptools.command.build_ext import build_ext
  
      buildcfg = self
  
      class custom_build_ext(build_ext):
          def run(self):
              # Bail out if we don't have the Python include files
              include_dir = sysconfig.get_path("include")
              if not os.path.isfile(
                  os.path.join(include_dir, "Python.h")
              ):
                  fail(
                      "You will need the Python headers to compile this extension."
                  )
  
              # Check whether the user asked us to discover a pre-built igraph
              # with pkg-config
              detected = False
              if buildcfg.use_pkgconfig:
                  detected = buildcfg.detect_from_pkgconfig()
                  if not detected:
                      fail(
                          "Cannot find the C core of igraph on this system using pkg-config."
                      )
              else:
                  # Build the C core from the vendored igraph source
                  self.run_command("build_c_core")
                  if not buildcfg.c_core_built:
                      # Fall back to an educated guess if everything else failed
                      if not detected:
                          if buildcfg.allow_educated_guess:
                              buildcfg.use_educated_guess()
                          else:
                              fail("Cannot build the C core of igraph.")
  
              # Add any extra library paths if needed; this is needed for the
              # Appveyor CI build
              if "IGRAPH_EXTRA_LIBRARY_PATH" in os.environ:
                  buildcfg.library_dirs = (
                      list(
                          os.environ["IGRAPH_EXTRA_LIBRARY_PATH"].split(
                              os.pathsep
                          )
                      )
                      + buildcfg.library_dirs
                  )
  
              # Add extra libraries that may have been specified
              if "IGRAPH_EXTRA_LIBRARIES" in os.environ:
                  extra_libraries = os.environ[
                      "IGRAPH_EXTRA_LIBRARIES"
                  ].split(",")
                  buildcfg.libraries.extend(extra_libraries)
  
              # Override build configuration based on environment variables
              if "IGRAPH_STATIC_EXTENSION" in os.environ:
                  buildcfg.static_extension = is_envvar_on(
                      "IGRAPH_STATIC_EXTENSION"
                  )
              buildcfg.use_sanitizers = building_with_sanitizers()
  
              # Replaces library names with full paths to static libraries
              # where possible. libm.a is excluded because it caused problems
              # on Sabayon Linux where libm.a is probably not compiled with
              # -fPIC
              if buildcfg.static_extension:
                  if buildcfg.static_extension == "only_igraph":
                      buildcfg.replace_static_libraries(only=["igraph"])
                  else:
                      buildcfg.replace_static_libraries(
                          exclusions=["m"]
                      )
  
              # Add sanitizer flags
              if buildcfg.use_sanitizers:
                  buildcfg.extra_link_args += [
                      "-fsanitize=address",
                      "-fsanitize=undefined",
                  ]
                  buildcfg.extra_compile_args += [
                      "-g",
                      "-Og",
                      "-fno-omit-frame-pointer",
                      "-fdiagnostics-color",
                  ]
  
              # Add extra libraries that may have been specified
              if "IGRAPH_EXTRA_DYNAMIC_LIBRARIES" in os.environ:
                  extra_libraries = os.environ[
                      "IGRAPH_EXTRA_DYNAMIC_LIBRARIES"
                  ].split(",")
                  buildcfg.libraries.extend(extra_libraries)
  
              # Remove C++ standard library as we will use the C++ linker
              for lib in ("c++", "stdc++"):
                  if lib in buildcfg.libraries:
                      buildcfg.libraries.remove(lib)
  
              # Prints basic build information
              buildcfg.print_build_info()
  
              # Find the igraph extension and configure it with the settings
              # of this build configuration
              ext = first(
                  extension
                  for extension in self.extensions
                  if extension.name == "igraph._igraph"
              )
              buildcfg.configure(ext)
  
              # Run the original build_ext command
              build_ext.run(self)
  
      return custom_build_ext
  
imports: import os
  import platform
  import sys
  from setuptools import find_packages, setup, Command, Extension
  import glob
  import shlex
  import shutil
  import subprocess
  import sysconfig
  from contextlib import contextmanager
  from pathlib import Path
  from select import select
  from shutil import which
  from time import sleep
  from typing import List, Iterable, Iterator, Optional, Tuple, TypeVar, Union
label_desc: Use image node_id 4 for calling the BuildConfiguration obj's underlying member method code with example usage: obj.build_ext() and returns: custom_build_ext