Custom openssl location
roederja opened this issue · 14 comments
It appears libmsodbcql tries to dynamically load openssl from /usr/local/opt/openssl/lib . Is it possible to override this location?
Do you have a specific use-case in mind for this?
https://trac.macports.org/ticket/60560 - trying to install it with macports which installs the openssl libraries somewhere else.
Since we support homebrew, the driver needs to specifically load from the homebrew install location for openssl. Apparently the dynamic loader on macOS does not include the homebrew path, so it had to be set in the driver. I'll note this as a feature request for the driver on macOS. Note, it has a simple workaround of creating a link in the location the driver looks for the library, though, and this is the first time we've had this issue reported.
Yes, I have found this workaround. However, it's not an option when we install it from macports because macports is not supposed to create files or links outside of its install prefix.
Currently, only hombrew is supported.
In the latest release it seems that the path to the library is hard-coded and the openssl libraries are not dynamically linked:
$ otool -L msodbcsql-17.6.1.1/lib/libmsodbcsql.17.dylib
msodbcsql-17.6.1.1/lib/libmsodbcsql.17.dylib:
libmsodbcsql.17.dylib (compatibility version 0.0.1, current version 6.1.1)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1259.11.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/lib/libodbcinst.2.dylib (compatibility version 3.0.0, current version 3.0.0)
/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
(papertrack-mast) casper:homebrew-mssql-release sweissman$
But in previous releases the openssl libraries were dynamically linked, so you could load them from different locations using DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH. Or change them to rpath/loader_path with install_name_tool if you were packaging them with something else:
$ otool -L msodbcsql-17.3.1.1/lib/libmsodbcsql.17.dylib
msodbcsql-17.3.1.1/lib/libmsodbcsql.17.dylib:
/Users/bamboo/bamboo-agent-home/xml-data/build-dir/LO-MBT-BR/msodbcsql.build/retail/Darwin/amd64/Sql/Ntdbms/sqlncli/libmsodbcsql.dylib (compatibility version 0.0.1, current version 3.1.1)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1259.11.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/lib/libodbcinst.2.dylib (compatibility version 3.0.0, current version 3.0.0)
/usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)
/usr/local/opt/openssl/lib/libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
I know my team has experienced some trouble with this as we don't by default have permissions to install brew in /usr/local. I had built brew in my home directory and the latest release broke my setup because my libraries were in $HOME/lib. It seems like it would be better to dynamically link these libraries and default the path to /usr/local/opt/openssl/lib rather than just assume that everyone using this driver has openssl installed on a specific path.
It is dynamically linked, just not in the import table. Driver will automatically use latest version of OpenSSL available, 1.1.x now, whereas before it was hardcoded to 1.0.x.
Why does it not use standard mechanisms to locate libraries?
It does, but needs to load it dynamically since it does not know what version of OpenSSL is available on the system.
If this is using the dyld env vars in a standard way, then the answer to the original question should be that you can override the library path by setting DYLD_LIBRARY_PATH, correct? It might be good to have some documentation on how this driver finds openssl. Admittedly, I'm not an expert on packaging and dynamic libraries, but It was quite confusing to me that it was able to find the openssl libraries in /usr/local/opt when the libraries weren't linked in a way that was viewable with otool and I hadn't set an env variable to tell it to look in any non-standard location. Should I have been able to figure this out?
There is a note in the official docs about that, but it doesn't say where the driver looks for those libs.
https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/programming-guidelines?view=sql-server-ver15#bkmk-openssl
Perhaps we should add more details to make loading logic more clear, including default directories and such since it's hard to figure it out.
P.S.
To see which dynamic libraries something loads you can use DYLD_PRINT_LIBRARIES=1, followed by the command, so
DYLD_PRINT_LIBRARIES=1 isql -k "DRIVER={ODBC Driver 17 for SQL Server};SERVER=...;UID=...;PWD=..."
although that wouldn't tell you how to make it load one from a different location, but it does give a better picture of what's happening.
The default location where Homebrew installs the libraries is not in the (hardcoded in the dyld) list of paths the dynamic linker uses either, hence the need for the driver to include the path directly when it is searching for the libs.
17.7 has been released with additional path for MacPorts: /opt/local/lib
. Please give it a try.
Thanks! It works now when macports is installed in /opt/local/lib. Not sure what happens when you install it in a non-standard location. Is there an env variable you can set so it can find open ssl?