[python] fix get_library()
[oota-llvm.git] / bindings / python / llvm / common.py
1 #===- common.py - Python LLVM Bindings -----------------------*- python -*--===#
2 #
3 #                     The LLVM Compiler Infrastructure
4 #
5 # This file is distributed under the University of Illinois Open Source
6 # License. See LICENSE.TXT for details.
7 #
8 #===------------------------------------------------------------------------===#
9
10 from ctypes import POINTER
11 from ctypes import c_void_p
12 from ctypes import cdll
13
14 import ctypes.util
15 import platform
16
17 # LLVM_VERSION: sync with PACKAGE_VERSION in autoconf/configure.ac and CMakeLists.txt
18 #               but leave out the 'svn' suffix.
19 LLVM_VERSION = '3.3'
20
21 __all__ = [
22     'c_object_p',
23     'get_library',
24 ]
25
26 c_object_p = POINTER(c_void_p)
27
28 class LLVMObject(object):
29     """Base class for objects that are backed by an LLVM data structure.
30
31     This class should never be instantiated outside of this package.
32     """
33     def __init__(self, ptr, ownable=True, disposer=None):
34         assert isinstance(ptr, c_object_p)
35
36         self._ptr = self._as_parameter_ = ptr
37
38         self._self_owned = True
39         self._ownable = ownable
40         self._disposer = disposer
41
42         self._owned_objects = []
43
44     def take_ownership(self, obj):
45         """Take ownership of another object.
46
47         When you take ownership of another object, you are responsible for
48         destroying that object. In addition, a reference to that object is
49         placed inside this object so the Python garbage collector will not
50         collect the object while it is still alive in libLLVM.
51
52         This method should likely only be called from within modules inside
53         this package.
54         """
55         assert isinstance(obj, LLVMObject)
56
57         self._owned_objects.append(obj)
58         obj._self_owned = False
59
60     def from_param(self):
61         """ctypes function that converts this object to a function parameter."""
62         return self._as_parameter_
63
64     def __del__(self):
65         if not hasattr(self, '_self_owned') or not hasattr(self, '_disposer'):
66             return
67
68         if self._self_owned and self._disposer:
69             self._disposer(self)
70
71 class CachedProperty(object):
72     """Decorator that caches the result of a property lookup.
73
74     This is a useful replacement for @property. It is recommended to use this
75     decorator on properties that invoke C API calls for which the result of the
76     call will be idempotent.
77     """
78     def __init__(self, wrapped):
79         self.wrapped = wrapped
80         try:
81             self.__doc__ = wrapped.__doc__
82         except: # pragma: no cover
83             pass
84
85     def __get__(self, instance, instance_type=None):
86         if instance is None:
87             return self
88
89         value = self.wrapped(instance)
90         setattr(instance, self.wrapped.__name__, value)
91
92         return value
93
94 def get_library():
95     """Obtain a reference to the llvm library."""
96
97     # On Linux, ctypes.cdll.LoadLibrary() respects LD_LIBRARY_PATH
98     # while ctypes.util.find_library() doesn't.
99     # See http://docs.python.org/2/library/ctypes.html#finding-shared-libraries
100     #
101     # To make it possible to run the unit tests without installing the LLVM shared
102     # library into a default linker search path.  Always Try ctypes.cdll.LoadLibrary()
103     # with all possible library names first, then try ctypes.util.find_library().
104
105     names = ['LLVM-' + LLVM_VERSION, 'LLVM-' + LLVM_VERSION + 'svn']
106     t = platform.system()
107     if t == 'Darwin':
108         pfx, ext = 'lib', '.dylib'
109     elif t == 'Windows':
110         pfx, ext = '', '.dll'
111     else:
112         pfx, ext = 'lib', '.so'
113
114     for i in names:
115         try:
116             lib = cdll.LoadLibrary(pfx + i + ext)
117         except OSError:
118             pass
119         else:
120             return lib
121
122     for i in names:
123         t = ctypes.util.find_library(i)
124         if t:
125             return cdll.LoadLibrary(t)
126     raise Exception('LLVM shared library not found!')