This patch provides support for finding the Oracle Instant Client
libraries (and sdk) delivered via IPS. It also forces the specification
of an RPATH so that the cx_Oracle module links against the IPS-
delivered Instant Client packages.
This patch has not yet been integrated with upstream.
--- cx_Oracle-5.2/setup.py.orig Fri Apr 3 21:10:29 2015
+++ cx_Oracle-5.2/setup.py Fri Sep 11 17:23:39 2015
@@ -61,9 +61,17 @@
# define the list of files to be included as documentation for bdist_rpm
docFiles = "README.txt BUILD.txt samples test"
+# Globalize some variables
+subDirs = []
+versions = []
+if struct.calcsize("P") == 4:
+ bitness = 32
+else:
+ bitness = 64
+
# method for checking a potential Oracle home
def CheckOracleHome(directoryToCheck):
- global oracleHome, oracleVersion, oracleLibDir
+ global oracleHome, oracleVersion, oracleLibDir, subDirs, versions
import os
import struct
import sys
@@ -81,8 +89,19 @@
("11g", "libclntsh.dylib.11.1"),
("10g", "libclntsh.dylib.10.1")
]
+ elif sys.platform == "sunos5":
+ if bitness == 32:
+ # 32bit
+ subDirs = ["lib"]
+ else:
+ subDirs = ["lib/64", "lib"]
+ filesToCheck = [
+ ("12c", "libclntsh.so.12.1"),
+ ("11g", "libclntsh.so.11.1"),
+ ("10g", "libclntsh.so.10.1")
+ ]
else:
- if struct.calcsize("P") == 4:
+ if bitness == 32:
subDirs = ["lib", "lib32"]
else:
subDirs = ["lib", "lib64"]
@@ -124,7 +143,7 @@
# Older Instant Client dirs have the form:
# /usr/lib/oracle/10.2.0.5/client[64]/lib
def FindInstantClientRPMLib():
- versions = []
+ global versions
for path in glob.glob(os.path.join(rpmBaseLibDir, "[0-9.]*")):
versions.append(os.path.basename(path))
versions.sort(key = lambda x: [int(s) for s in x.split(".")])
@@ -147,26 +166,68 @@
# define Linux Instant Client RPM path components
# Assume 64 bit builds if the platform is 64 bit
rpmBaseLibDir = "/usr/lib/oracle"
-if struct.calcsize("P") == 4:
+if bitness == 32:
rpmClientDir = "client"
else:
rpmClientDir = "client64"
instantClientRPMLib = None
+#
+# Solaris 11.x and later make use of the Image Packaging System, IPS,
+# and can install Instant Client 12.1 (and later versions) using that
+# format. IPS-delivered versions exist under
+# /usr/oracle/instantclient/[version]
+# which allows us to bake an rpath into this module and remove the need
+# for setting LD_LIBRARY_PATH in a wrapper.
+def FindInstantClientIPSLib():
+ global versions
+ for path in glob.glob(os.path.join(ipsBaseLibDir, "[0-9.]*")):
+ versions.append(os.path.basename(path))
+ versions.sort(key = lambda x: [int(s) for s in x.split(".")])
+ versions.reverse()
+ for version in versions:
+ path = os.path.join(ipsBaseLibDir, version)
+ if os.path.exists(path) and CheckOracleHome(path):
+ return path
+
+# If the lib dir appears to be an Instant Client IPS dir, then look only
+# for matching SDK headers
+def FindInstantClientIPSInclude(libDir):
+ includeDir = os.path.join("/usr/include/oracle", versions[0])
+ return [includeDir]
+ raise DistutilsSetupError("cannot locate Oracle Instant Client " \
+ "SDK RPM header files")
+
+# Now we can define path components for the Solaris 11.x++ Instant Client
+# delivered via IPS.
+#
+# We build cx_Oracle as 32bit if we're running python2.7, and
+# 64bit if we're running python3.4 or later. That, however,
+# doesn't matter when finding the libraries since the IPS package
+# ships with both 32- and 64-bit libraries.
+ipsBaseLibDir = "/usr/oracle/instantclient"
+instantClientIPSLib = None
+
+
# try to determine the Oracle home
userOracleHome = os.environ.get("ORACLE_HOME")
if userOracleHome is not None:
if not CheckOracleHome(userOracleHome):
messageFormat = "Oracle home (%s) does not refer to an " \
- "10g, 11g or 12c installation."
+ "10g, 11g or 12c installation.\n"
raise DistutilsSetupError(messageFormat % userOracleHome)
else:
for path in os.environ["PATH"].split(os.pathsep):
if CheckOracleHome(path):
break
- if oracleHome is None and sys.platform.startswith("linux"):
- instantClientRPMLib = FindInstantClientRPMLib()
if oracleHome is None:
+ if sys.platform.startswith("linux"):
+ instantClientRPMLib = FindInstantClientRPMLib()
+ elif sys.platform.startswith("sunos5"):
+ instantClientIPSLib = FindInstantClientIPSLib()
+ else:
+ # oracleHome is None
raise DistutilsSetupError("cannot locate an Oracle software " \
"installation")
@@ -199,6 +260,8 @@
libs = ["clntsh"]
if instantClientRPMLib is not None:
includeDirs = FindInstantClientRPMInclude(instantClientRPMLib)
+ elif instantClientIPSLib is not None:
+ includeDirs = FindInstantClientIPSInclude(instantClientIPSLib)
else:
"sdk/include"]
@@ -238,12 +301,19 @@
elif sys.platform == "darwin":
extraLinkArgs.append("-shared-libgcc")
-# force the inclusion of an RPATH linker directive if desired; this will
-# eliminate the need for setting LD_LIBRARY_PATH but it also means that this
-# location will be the only location searched for the Oracle client library
-if "FORCE_RPATH" in os.environ or instantClientRPMLib:
+# Eliminate the need for setting LD_LIBRARY_PATH in a wrapper script
+# by baking in a RUNPATH (aka RPATH)
+if sys.platform.startswith("sunos5"):
+ extraLinkArgs.append("-R%s" % oracleLibDir)
+else:
extraLinkArgs.append("-Wl,-rpath,%s" % oracleLibDir)
+# If we're running as a 64bit python interpreter, we need to ensure that
+# we get the compiler and linker to generate 64bit code too.
+if bitness == 64:
+ extraCompileArgs.append("-m64")
+ extraLinkArgs.append("-m64")
+
# tweak distribution full name to include the Oracle version
class Distribution(distutils.dist.Distribution):