class_docstr: CompilerRunner base class.
  
  Parameters
  ==========
  
  sources : list of str
      Paths to sources.
  out : str
  flags : iterable of str
      Compiler flags.
  run_linker : bool
  compiler_name_exe : (str, str) tuple
      Tuple of compiler name &  command to call.
  cwd : str
      Path of root of relative paths.
  include_dirs : list of str
      Include directories.
  libraries : list of str
      Libraries to link against.
  library_dirs : list of str
      Paths to search for shared libraries.
  std : str
      Standard string, e.g. ``'c++11'``, ``'c99'``, ``'f2003'``.
  define: iterable of strings
      macros to define
  undef : iterable of strings
      macros to undefine
  preferred_vendor : string
      name of preferred vendor e.g. 'gnu' or 'intel'
  
  Methods
  =======
  
  run():
      Invoke compilation as a subprocess.
class_docstr_tok: ["CompilerRunner","base","class",".","Parameters","==========","sources",":","list","of","str","Paths","to","sources",".","out",":","str","flags",":","iterable","of","str","Compiler","flags",".","run_linker",":","bool","compiler_name_exe",":","(","str",",","str",")","tuple","Tuple","of","compiler","name","&","command","to","call",".","cwd",":","str","Path","of","root","of","relative","paths",".","include_dirs",":","list","of","str","Include","directories",".","libraries",":","list","of","str","Libraries","to","link","against",".","library_dirs",":","list","of","str","Paths","to","search","for","shared","libraries",".","std",":","str","Standard","string",",","e.g",".","``","'","c++11","'","``",",","``","'c99","'","``",",","``","'f2003","'","``",".","define",":","iterable","of","strings","macros","to","define","undef",":","iterable","of","strings","macros","to","undefine","preferred_vendor",":","string","name","of","preferred","vendor","e.g",".","'gnu","'","or","'intel'","Methods","=======","run","(",")",":","Invoke","compilation","as","a","subprocess","."]
code: def run(self):
      self.flags = unique_list(self.flags)
  
      # Append output flag and name to tail of flags
      self.flags.extend(["-o", self.out])
      env = os.environ.copy()
      env["PWD"] = self.cwd
  
      # NOTE: intel compilers seems to need shell=True
      p = subprocess.Popen(
          " ".join(self.cmd()),
          shell=True,
          cwd=self.cwd,
          stdin=subprocess.PIPE,
          stdout=subprocess.PIPE,
          stderr=subprocess.STDOUT,
          env=env,
      )
      comm = p.communicate()
      try:
          self.cmd_outerr = comm[0].decode("utf-8")
      except UnicodeDecodeError:
          self.cmd_outerr = comm[0].decode("iso-8859-1")  # win32
      self.cmd_returncode = p.returncode
  
      # Error handling
      if self.cmd_returncode != 0:
          msg = "Error executing '{}' in {} (exited status {}):\n {}\n".format(
              " ".join(self.cmd()),
              self.cwd,
              str(self.cmd_returncode),
              self.cmd_outerr,
          )
          raise CompileError(msg)
  
      return self.cmd_outerr, self.cmd_returncode
  
imports: from __future__ import annotations
  from typing import Callable, Optional
  from collections import OrderedDict
  import os
  import re
  import subprocess
  import warnings
  from .util import find_binary_of_command, unique_list, CompileError
label_desc: Use image node_id 4 for calling the CompilerRunner obj's underlying member method code with example usage: obj.run() and returns: self,  self