All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
icarusalg/icarusalg/gallery/helpers/python/cppUtils.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 from __future__ import print_function
4 
5 __doc__ = """
6 Collection of utilities to interface C++ code with Python via PyROOT.
7 
8 This module requires ROOT.
9 """
10 
11 __all__ = [
12  'readHeader',
13  'SourceCode',
14  ]
15 
16 import sys, os
17 from ROOTutils import ROOT
18 
19 
20 ################################################################################
21 def readHeader(headerPath):
22  """Make the ROOT C++ jit compiler read the specified header."""
23  ROOT.gROOT.ProcessLine('#include "%s"' % headerPath)
24 # readHeader()
25 
26 
27 ################################################################################
29  """
30  A class keeping track of the sources and where to look for them.
31  """
32  AllPlatformInfo = {
33  'Linux': {
34  'Name': 'Linux',
35  'LibSuffix': '.so',
36  'LibEnvPath': 'LD_LIBRARY_PATH',
37  },
38  'Darwin': {
39  'Name': 'Darwin',
40  'LibSuffix': '.dylib',
41  'LibEnvPath': 'DYLD_LIBRARY_PATH', # might be not honoured
42  },
43  } # AllPlatformInfo
44  PlatformInfo = AllPlatformInfo[os.uname()[0]]
45 
46  def __init__(self, *includePaths):
47  self.headers = {}
48  self.libraries = {}
49  self.includePaths = []
50  self.addIncPaths(*includePaths)
51  # for
52  # __init__()
53 
54  def addIncPath(self, path, force=False):
55  expPath = os.path.expandvars(path)
56  if not os.path.isdir(expPath):
57  print(
58  "Warning: include path '%s'" % path,
59  (" ( => '%s')" % expPath if path != expPath else ""),
60  " does not exist.",
61  sep='',
62  file=sys.stderr
63  )
64  if force or expPath not in self.includePaths:
65  self.includePaths.append(expPath)
66  # addIncPath()
67 
68  def addIncPathEnv(self, varName, force = False):
69  self.addIncPath(os.environ[varName], force=force)
70 
71  def addIncPaths(self, *paths):
72  for path in paths: self.addIncPath(path)
73 
74  def addIncPathEnvs(self, *varNames):
75  self.addIncPaths(*map((lambda varName: os.environ[varName]), varNames))
76 
77  def find(self, relPath, extraPaths = []):
78  return self.findLibrary(relPath, extraPaths=extraPaths) if self.isLibrary(relPath) else self.findHeader(relPath, extraPaths=extraPaths)
79  # find()
80 
81  def findLibrary(self, libName, extraPaths = []):
82  expLibName = SourceCentral.expandLibraryName(libName)
83  for path in reversed(
84  SourceCentral.LibraryPaths() + list(map(os.path.expandvars, extraPaths))
85  ):
86  candidate = os.path.join(path, expLibName)
87  if os.path.exists(candidate): return candidate
88  else: return None
89  # findLibrary()
90 
91  def findHeader(self, relPath, extraPaths = []):
92  for path in reversed(self.includePaths + list(map(os.path.expandvars, extraPaths))):
93  candidate = os.path.join(path, relPath)
94  if os.path.exists(candidate): return candidate
95  else: return None
96  # findHeader()
97 
98  def loadLibrary(self, relPath, extraPaths = [], force = False):
99  expandedName = self.expandLibraryName(relPath)
100  res = ROOT.gSystem.Load(expandedName)
101  if res == 0: self.libraries[relPath] = expandedName
102  return res
103  # loadLibrary()
104 
105  def loadHeader(self, headerRelPath, extraPaths = [], force = False):
106  try: return self.headers[headerRelPath]
107  except KeyError: pass
108  headerPath = self.findHeader(headerRelPath, extraPaths=extraPaths)
109  if not headerPath: raise RuntimeError("Can't locate header file '%s'" % headerRelPath)
110  readHeader(headerPath)
111  self.headers[headerRelPath] = headerPath
112  return headerPath
113  # loadHeader()
114 
115 
116  def loadHeaderFromUPS(self, headerRelPath, extraPaths = [], force = False):
117  """
118  Loads a C++ header from a UPS product.
119 
120  Assumptions:
121  * the specified relative path of the header is under the include directory
122  of its UPS product
123  * the include directory path is set in a environment variable named with
124  the standard UPS pattern (`PRODUCTNAME_INC`)
125  * the header relative path starts with a directory that reflects the name
126  of the UPS product, `productname/relative/package/path/header.h`
127 
128  For example, for a `headerRelPath` of `larcorealg/Geometry/GeometryCore.h`,
129  the full path must be represented by
130  `${LARCOREALG_INC}/larcorealg/Geometry/GeometryCore.h`, with the content
131  of `LARCOREALG_INC` variable being an absolute path.
132  """
133  # make sure that if there is a INC variable for the package, that one is included
134  return self.loadHeader(
135  headerRelPath,
136  extraPaths
137  =([ '$' + self.packageVarNameFromHeaderPath('INC', headerRelPath) ] + extraPaths),
138  force=force
139  )
140  # loadHeaderFromUPS()
141 
142  def load(self, relPath, extraPaths = [], force = False):
143  return (self.loadLibrary if self.isLibrary(relPath) else self.loadHeaderFromUPS)(relPath, extraPaths=extraPaths, force=force)
144  # load()
145 
146  def isLibrary(self, path):
147  return os.path.splitext(path)[-1] in [ self.PlatformInfo['LibSuffix'], '' ]
148 
149  def expandLibraryName(self, name):
150  if not name.startswith('lib'): name = 'lib' + name
151  LibSuffix = self.PlatformInfo['LibSuffix']
152  if not name.endswith(LibSuffix): name += LibSuffix
153  return name
154  # expandLibraryName()
155 
156  @staticmethod
157  def packageNameFromHeaderPath(headerPath):
158  return os.path.split(os.path.dirname(headerPath))[0]
159 
160  @staticmethod
161  def packageVarNameFromHeaderPath(varSuffix, headerPath):
162  return SourceCentral.packageNameFromHeaderPath(headerPath).upper() + '_' + varSuffix
163 
164  @staticmethod
166  return os.getenv(SourceCentral.PlatformInfo['LibEnvPath']) \
167  .split(SourceCentral.PlatformInfo.get('LibEnvPathSep', ':'))
168  # LibraryPaths()
169 
170 # class SourceCentral
171 
172 ################################################################################
173 
174 # global instance of source tracking class
175 SourceCode = SourceCentral()
176 
177 ################################################################################
do one_file $F done echo for F in find $TOP name CMakeLists txt print
list
Definition: file_to_url.sh:28