Skip to content

Commit 19f35fa

Browse files
authored
FEAT: Build process for Mac Support (#68)
This pull request introduces improvements to the Python library detection process, updates dependency handling for macOS dynamic libraries, enhances security in connection string sanitization, and refactors the `setup.py` file to use a different module for wheel building. ### Python library detection improvements: * [`mssql_python/pybind/CMakeLists.txt`](diffhunk://#diff-dbb5892fbbb28149d1639664797cf3adb48ced28ec11aba95f2e2b338ca46badR158-R180): Added logic to handle cases where `PYTHON_LIB_DIR` is not set or is empty on Windows, using Python's `sysconfig` to locate the library directory. Additionally, support for a custom environment variable `CUSTOM_PYTHON_LIB_DIR` was added to override the library directory. ### Dependency handling updates for macOS: * [`mssql_python/pybind/configure_dylibs.sh`](diffhunk://#diff-4cf7dbf7135a58c02b5bf5dc2794aa826d898aeded724d3716f909dd0cede5ffL69-R98): Updated `install_name_tool` commands to use `@loader_path` for dynamic library paths, ensuring better portability. Added commands to set library IDs explicitly using `@loader_path`. ### Security enhancement in connection string sanitization: * [`mssql_python/pybind/ddbc_bindings_mac.cpp`](diffhunk://#diff-5191ba8555f89ff1462b69ab9949c75d79f982904ad2c6bb5c4c9cf90ea0ea34L1086-R1113): Improved the `SanitizeConnectionString` function to perform case-insensitive removal of sensitive parameters (`UID` and `Pwd`) by converting the string to lowercase for comparison. ### Refactor in wheel building: * [`setup.py`](diffhunk://#diff-60f61ab7a8d1910d86d9fda2261620314edcae5894d5aaa236b821c7256badd7L5-R5): Changed the import from `setuptools.command.bdist_wheel` to `wheel.bdist_wheel` for building platform-specific wheels.
1 parent 77238a1 commit 19f35fa

File tree

7 files changed

+55
-8
lines changed

7 files changed

+55
-8
lines changed
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

mssql_python/pybind/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ else()
102102
message(STATUS "Auto-detected pybind11 include directory: ${PYBIND11_INCLUDE_DIR}")
103103
endif()
104104

105+
105106
# Find Python Library for linking
106107
execute_process(
107108
COMMAND python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"
@@ -154,8 +155,29 @@ if(APPLE AND (NOT PYTHON_LIB_DIR OR "${PYTHON_LIB_DIR}" STREQUAL ""))
154155
message(STATUS "Python library not found in standard locations, will try using framework")
155156
# When using a framework, we don't specify the library directly
156157
endif()
158+
elseif(WIN32 AND (NOT PYTHON_LIB_DIR OR "${PYTHON_LIB_DIR}" STREQUAL "" OR "${PYTHON_LIB_DIR}" STREQUAL "None"))
159+
# On Windows, if PYTHON_LIB_DIR is not set, we will try to find it using sysconfig
160+
message(STATUS "PYTHON_LIB_DIR is None or empty for Windows, trying to find it using sysconfig")
161+
# Use Python Executable to find the library directory
162+
execute_process(
163+
COMMAND python -c "import sys, os; print(os.path.dirname(sys.executable))"
164+
OUTPUT_VARIABLE PYTHON_EXEC_DIR
165+
OUTPUT_STRIP_TRAILING_WHITESPACE
166+
)
167+
message(STATUS "Python executable directory: ${PYTHON_EXEC_DIR}")
168+
# Set the library directory based on the executable directory
169+
set(PYTHON_LIB_DIR "${PYTHON_EXEC_DIR}/libs")
170+
message(STATUS "Using Python library directory: ${PYTHON_LIB_DIR}")
157171
endif()
158172

173+
if(DEFINED ENV{CUSTOM_PYTHON_LIB_DIR} AND NOT "$ENV{CUSTOM_PYTHON_LIB_DIR}" STREQUAL "" AND NOT "$ENV{CUSTOM_PYTHON_LIB_DIR}" STREQUAL "None")
174+
message(STATUS "CUSTOM_PYTHON_LIB_DIR is set, using it")
175+
set(PYTHON_LIB_DIR $ENV{CUSTOM_PYTHON_LIB_DIR})
176+
message(STATUS "Using custom Python library directory: ${PYTHON_LIB_DIR}")
177+
endif()
178+
179+
message(STATUS "Final Python library directory: ${PYTHON_LIB_DIR}")
180+
159181
# Determine which source file to use based on platform
160182
if(APPLE)
161183
set(DDBC_SOURCE "ddbc_bindings_mac.cpp")

mssql_python/pybind/configure_dylibs.sh

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,36 @@ done <<< "$OTOOL_LIST"
6666
if [ -n "$OLD_LIBODBCINST_PATH" ]; then
6767
echo "Fixing libmsodbcsql.18.dylib dependency on libodbcinst.2.dylib..."
6868
echo " Changing: $OLD_LIBODBCINST_PATH"
69-
echo " To: $LIBODBCINST_PATH"
70-
install_name_tool -change "$OLD_LIBODBCINST_PATH" "$LIBODBCINST_PATH" "$LIBMSODBCSQL_PATH"
69+
echo " To: @loader_path/libodbcinst.2.dylib"
70+
install_name_tool -change "$OLD_LIBODBCINST_PATH" "@loader_path/libodbcinst.2.dylib" "$LIBMSODBCSQL_PATH"
7171
else
7272
echo "Warning: libodbcinst dependency not found in libmsodbcsql.18.dylib"
7373
fi
7474

7575
if [ -n "$OLD_LIBLTDL_PATH" ] && [ -f "$LIBLTDL_PATH" ]; then
7676
echo "Fixing libodbcinst.2.dylib dependency on libltdl.7.dylib..."
7777
echo " Changing: $OLD_LIBLTDL_PATH"
78-
echo " To: $LIBLTDL_PATH"
79-
install_name_tool -change "$OLD_LIBLTDL_PATH" "$LIBLTDL_PATH" "$LIBODBCINST_PATH"
78+
echo " To: @loader_path/libltdl.7.dylib"
79+
install_name_tool -change "$OLD_LIBLTDL_PATH" "@loader_path/libltdl.7.dylib" "$LIBODBCINST_PATH"
8080
else
8181
echo "Note: libltdl dependency not found or not needed"
8282
fi
8383

8484
# Force codesign the dylibs
85+
86+
# First set the IDs of the libraries using @loader_path
87+
echo "Setting library IDs with @loader_path..."
88+
echo "Setting ID for libmsodbcsql.18.dylib..."
89+
install_name_tool -id "@loader_path/libmsodbcsql.18.dylib" "$LIBMSODBCSQL_PATH"
90+
91+
echo "Setting ID for libodbcinst.2.dylib..."
92+
install_name_tool -id "@loader_path/libodbcinst.2.dylib" "$LIBODBCINST_PATH"
93+
94+
if [ -f "$LIBLTDL_PATH" ]; then
95+
echo "Setting ID for libltdl.7.dylib..."
96+
install_name_tool -id "@loader_path/libltdl.7.dylib" "$LIBLTDL_PATH"
97+
fi
98+
8599
echo "Codesigning libmsodbcsql.18.dylib..."
86100
codesign -s - -f "$LIBMSODBCSQL_PATH" 2>/dev/null
87101

mssql_python/pybind/ddbc_bindings_mac.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,23 +1083,34 @@ ErrorInfo SQLCheckError_Wrap(SQLSMALLINT handleType, intptr_t handle, SQLRETURN
10831083
std::wstring SanitizeConnectionString(const std::wstring& connectionString) {
10841084
// This function will remove the UID and Pwd parameters for security reasons
10851085
std::wstring sanitizedString = connectionString;
1086-
// Remove UID and Pwd parameters
1087-
size_t uidPos = sanitizedString.find(L"UID=");
1086+
std::wstring lowerCaseString = sanitizedString;
1087+
// Convert the string to lowercase for case-insensitive search
1088+
// Using lowerCaseString to avoid modifying the original string
1089+
// This is necessary because towlower works on wide characters
1090+
std::transform(lowerCaseString.begin(), lowerCaseString.end(), lowerCaseString.begin(),
1091+
::towlower);
1092+
// Can be UID or uid or UID, test only on lowercase uid
1093+
size_t uidPos = lowerCaseString.find(L"uid=");
10881094
if (uidPos != std::wstring::npos) {
10891095
size_t endPos = sanitizedString.find(L';', uidPos);
10901096
if (endPos != std::wstring::npos) {
10911097
sanitizedString.erase(uidPos, endPos - uidPos + 1);
1098+
lowerCaseString.erase(uidPos, endPos - uidPos + 1);
10921099
} else {
10931100
sanitizedString.erase(uidPos);
1101+
lowerCaseString.erase(uidPos);
10941102
}
10951103
}
1096-
size_t pwdPos = sanitizedString.find(L"Pwd=");
1104+
// Can be Pwd or pwd or PWD, test only on lowercase pwd
1105+
size_t pwdPos = lowerCaseString.find(L"pwd=");
10971106
if (pwdPos != std::wstring::npos) {
10981107
size_t endPos = sanitizedString.find(L';', pwdPos);
10991108
if (endPos != std::wstring::npos) {
11001109
sanitizedString.erase(pwdPos, endPos - pwdPos + 1);
1110+
lowerCaseString.erase(pwdPos, endPos - pwdPos + 1);
11011111
} else {
11021112
sanitizedString.erase(pwdPos);
1113+
lowerCaseString.erase(pwdPos);
11031114
}
11041115
}
11051116
return sanitizedString;

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33
from setuptools import setup, find_packages
44
from setuptools.dist import Distribution
5-
from setuptools.command.bdist_wheel import bdist_wheel
5+
from wheel.bdist_wheel import bdist_wheel
66

77
# Custom distribution to force platform-specific wheel
88
class BinaryDistribution(Distribution):

0 commit comments

Comments
 (0)