Skip to content

Commit b1634d2

Browse files
committed
Allow install of parasail without building C library.
Fixes #26. Fixes #44. Fixes #47.
1 parent 3162c3f commit b1634d2

File tree

6 files changed

+137
-10
lines changed

6 files changed

+137
-10
lines changed

CHANGELOG.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Unreleased_
1010
-----------
1111
The Unreleased section will be empty for tagged releases. Unreleased functionality appears in the develop branch.
1212

13+
--------------------
14+
1.1.18_ - 2019-12-11
15+
--------------------
16+
- Allow install without downloading and building C library, set evn var PARASAIL_SKIP_BUILD=1 to enable.
17+
1318
--------------------
1419
1.1.17_ - 2019-29-04
1520
--------------------
@@ -120,7 +125,8 @@ The Unreleased section will be empty for tagged releases. Unreleased functionali
120125
-------------------
121126
First tagged release. The 'master' branch always represents the latest stable code. Tagged releases correspond to pypi releases.
122127

123-
.. _Unreleased: https://github.com/jeffdaily/parasail-python/compare/v1.1.17...master
128+
.. _Unreleased: https://github.com/jeffdaily/parasail-python/compare/v1.1.18...master
129+
.. _1.1.18: https://github.com/jeffdaily/parasail-python/compare/v1.1.17...v1.1.18
124130
.. _1.1.17: https://github.com/jeffdaily/parasail-python/compare/v1.1.16...v1.1.17
125131
.. _1.1.16: https://github.com/jeffdaily/parasail-python/compare/v1.1.15...v1.1.16
126132
.. _1.1.15: https://github.com/jeffdaily/parasail-python/compare/v1.1.14...v1.1.15

README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ The second approach is to let the setup.py script attempt to download and compil
7373

7474
The bdist_wheel target will first look for the shared library. If it exists, it will happily install it as package data. Otherwise, the latest parasail master branch from github will be downloaded, unzipped, configured, made, and the shared library will be copied into the appropriate location for package data installation.
7575

76+
The downloading and building of the parasail C library can be skipped if you set the environment variable PARASAIL_SKIP_BUILD to any value prior to running setup.py or pip install. At runtime during import, the parasail bindings will search for the parasail C library first in the package data location, then in standard system locations, and lastly by searching through the environment variables PARASAIL_LIBPATH, LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, and PATH.. For verbose output during this search, set PARASAIL_VERBOSE=1.
77+
7678
Quick Example
7779
-------------
7880

parasail/__init__.py

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import ctypes
22
import platform
33
import os
4+
import re
45
import sys
56

67
import numpy
@@ -23,11 +24,50 @@
2324
_libname = "parasail.dll"
2425
_libpath = os.path.join(os.path.dirname(__file__), _libname)
2526

27+
_verbose = os.environ.get("PARASAIL_VERBOSE", False)
28+
29+
# attempt to load library from package location
2630
_lib = None
27-
if os.path.exists(_libpath):
31+
try:
2832
_lib = ctypes.CDLL(_libpath)
29-
else:
30-
_lib = ctypes.CDLL(_libname)
33+
except:
34+
if _verbose: print("failed to open '{}' in package location".format(_libname))
35+
36+
if not _lib:
37+
try:
38+
_lib = ctypes.CDLL(_libname)
39+
except:
40+
if _verbose: print("failed to open '{}' using ctypes.CDLL defaults".format(_libname))
41+
42+
def _lib_search():
43+
global _lib
44+
global _libpath
45+
_libpath = None
46+
for env_var in ["PARASAIL_LIBPATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "PATH"]:
47+
if env_var in os.environ:
48+
if _verbose: print("searching {} for {}".format(env_var,_libname))
49+
for path in re.split("[:;]", os.environ[env_var]):
50+
if _verbose: print("searching {}".format(path))
51+
for attempt in [os.path.join(root,_libname) for root,dirs,files in os.walk(path) if _libname in files]:
52+
try:
53+
_lib = ctypes.CDLL(attempt)
54+
_libpath = attempt
55+
# shortcut the search during bindings import
56+
os.environ["PARASAIL_LIBPATH"] = os.path.dirname(attempt)
57+
if _verbose: print("found '{}'".format(attempt))
58+
return
59+
except:
60+
if _verbose: print("attempted but failed to load '{}'".format(attempt))
61+
else:
62+
if _verbose: print("env var {} not set".format(env_var))
63+
64+
# if library load failed, search for it
65+
if not _lib:
66+
_lib_search()
67+
68+
# library load still failed, hard error
69+
if not _lib:
70+
raise Exception("failed to locate and open '{}'".format(_libname))
3171

3272
c_int_p = ctypes.POINTER(ctypes.c_int)
3373

parasail/bindings_v2.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import ctypes
33
import platform
44
import os
5+
import re
56
import sys
67

78
import numpy
@@ -13,11 +14,48 @@
1314
_libname = "parasail.dll"
1415
_libpath = os.path.join(os.path.dirname(__file__), _libname)
1516

17+
_verbose = os.environ.get("PARASAIL_VERBOSE", False)
18+
19+
# attempt to load library from package location
1620
_lib = None
17-
if os.path.exists(_libpath):
21+
try:
1822
_lib = ctypes.CDLL(_libpath)
19-
else:
20-
_lib = ctypes.CDLL(_libname)
23+
except:
24+
if _verbose: print("failed to open '{}' in package location".format(_libname))
25+
26+
if not _lib:
27+
try:
28+
_lib = ctypes.CDLL(_libname)
29+
except:
30+
if _verbose: print("failed to open '{}' using ctypes.CDLL defaults".format(_libname))
31+
32+
def _lib_search():
33+
global _lib
34+
global _libpath
35+
_libpath = None
36+
for env_var in ["PARASAIL_LIBPATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "PATH"]:
37+
if env_var in os.environ:
38+
if _verbose: print("searching {} for {}".format(env_var,_libname))
39+
for path in re.split("[:;]", os.environ[env_var]):
40+
if _verbose: print("searching {}".format(path))
41+
for attempt in [os.path.join(root,_libname) for root,dirs,files in os.walk(path) if _libname in files]:
42+
try:
43+
_lib = ctypes.CDLL(attempt)
44+
_libpath = attempt
45+
if _verbose: print("found '{}'".format(attempt))
46+
return
47+
except:
48+
if _verbose: print("attempted but failed to load '{}'".format(attempt))
49+
else:
50+
if _verbose: print("env var {} not set".format(env_var))
51+
52+
# if library load failed, search for it
53+
if not _lib:
54+
_lib_search()
55+
56+
# library load still failed, hard error
57+
if not _lib:
58+
raise Exception("failed to locate and open '{}'".format(_libname))
2159

2260
_case_sensitive = False
2361
def set_case_sensitive(case):

setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,9 @@ def prepare_shared_lib():
409409
libname = get_libname()
410410
libpath = os.path.join("parasail", libname)
411411
if not os.path.exists(libpath):
412+
if "PARASAIL_SKIP_BUILD" in os.environ:
413+
print("{} not found, but PARASAIL_SKIP_BUILD set by env var, skipping download and build".format(libpath))
414+
return
412415
print("{} not found, attempting to build".format(libpath))
413416
if platform.system() == "Windows":
414417
download_windows_dll()

tools/ctypesgen2.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def myprint(arg):
1111
import ctypes
1212
import platform
1313
import os
14+
import re
1415
import sys
1516
1617
import numpy
@@ -22,11 +23,48 @@ def myprint(arg):
2223
_libname = "parasail.dll"
2324
_libpath = os.path.join(os.path.dirname(__file__), _libname)
2425
26+
_verbose = os.environ.get("PARASAIL_VERBOSE", False)
27+
28+
# attempt to load library from package location
2529
_lib = None
26-
if os.path.exists(_libpath):
30+
try:
2731
_lib = ctypes.CDLL(_libpath)
28-
else:
29-
_lib = ctypes.CDLL(_libname)
32+
except:
33+
if _verbose: print("failed to open '{}' in package location".format(_libname))
34+
35+
if not _lib:
36+
try:
37+
_lib = ctypes.CDLL(_libname)
38+
except:
39+
if _verbose: print("failed to open '{}' using ctypes.CDLL defaults".format(_libname))
40+
41+
def _lib_search():
42+
global _lib
43+
global _libpath
44+
_libpath = None
45+
for env_var in ["PARASAIL_LIBPATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "PATH"]:
46+
if env_var in os.environ:
47+
if _verbose: print("searching {} for {}".format(env_var,_libname))
48+
for path in re.split("[:;]", os.environ[env_var]):
49+
if _verbose: print("searching {}".format(path))
50+
for attempt in [os.path.join(root,_libname) for root,dirs,files in os.walk(path) if _libname in files]:
51+
try:
52+
_lib = ctypes.CDLL(attempt)
53+
_libpath = attempt
54+
if _verbose: print("found '{}'".format(attempt))
55+
return
56+
except:
57+
if _verbose: print("attempted but failed to load '{}'".format(attempt))
58+
else:
59+
if _verbose: print("env var {} not set".format(env_var))
60+
61+
# if library load failed, search for it
62+
if not _lib:
63+
_lib_search()
64+
65+
# library load still failed, hard error
66+
if not _lib:
67+
raise Exception("failed to locate and open '{}'".format(_libname))
3068
3169
_case_sensitive = False
3270
def set_case_sensitive(case):

0 commit comments

Comments
 (0)