Skip to content

Commit ed7f480

Browse files
authored
Merge branch 'main' into jahnvi/perf-fetch-optimization
2 parents 1d4c178 + 89aee60 commit ed7f480

6 files changed

Lines changed: 43 additions & 26 deletions

File tree

‎OneBranchPipelines/stages/build-odbc-all-stage.yml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ stages:
133133
# wheel that packaged the wrong (or an incomplete) subtree would still pass
134134
# `twine check`. This is the single-host cross-build's safety net: it proves
135135
# the ODBC_TARGET_* overrides selected the right libs/ subtree per tag and
136-
# that no foreign-platform binaries leaked in.
136+
# that no foreign-platform, foreign-architecture, or foreign-libc binaries leaked in.
137137
- powershell: |
138138
$ErrorActionPreference = "Stop"
139139
Add-Type -AssemblyName System.IO.Compression.FileSystem
@@ -149,10 +149,10 @@ stages:
149149
'win_amd64' = @{ Must = @('libs/windows/x64/', 'msodbcsql18.dll', 'mssql-auth.dll', 'libs/LICENSING'); Forbid = @('libs/linux/', 'libs/macos/', 'libs/windows/arm64/') }
150150
'win_arm64' = @{ Must = @('libs/windows/arm64/', 'msodbcsql18.dll', 'mssql-auth.dll', 'libs/LICENSING'); Forbid = @('libs/linux/', 'libs/macos/', 'libs/windows/x64/') }
151151
'macosx_15_0_universal2' = @{ Must = @('libs/macos/arm64/', 'libs/macos/x86_64/', 'libmsodbcsql.18.dylib', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/linux/') }
152-
'manylinux_2_28_x86_64' = @{ Must = @('libs/linux/debian_ubuntu/x86_64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/arm64/') }
153-
'manylinux_2_28_aarch64' = @{ Must = @('libs/linux/debian_ubuntu/arm64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/x86_64/') }
154-
'musllinux_1_2_x86_64' = @{ Must = @('libs/linux/alpine/x86_64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/arm64/') }
155-
'musllinux_1_2_aarch64' = @{ Must = @('libs/linux/alpine/arm64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/x86_64/') }
152+
'manylinux_2_28_x86_64' = @{ Must = @('libs/linux/debian_ubuntu/x86_64/', 'libs/linux/rhel/x86_64/', 'libs/linux/suse/x86_64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/arm64/', 'libs/linux/alpine/') }
153+
'manylinux_2_28_aarch64' = @{ Must = @('libs/linux/debian_ubuntu/arm64/', 'libs/linux/rhel/arm64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/x86_64/', 'libs/linux/alpine/') }
154+
'musllinux_1_2_x86_64' = @{ Must = @('libs/linux/alpine/x86_64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/arm64/', 'libs/linux/debian_ubuntu/', 'libs/linux/rhel/', 'libs/linux/suse/') }
155+
'musllinux_1_2_aarch64' = @{ Must = @('libs/linux/alpine/arm64/', 'libmsodbcsql-18', 'libs/LICENSING'); Forbid = @('libs/windows/', 'libs/macos/', '/x86_64/', 'libs/linux/debian_ubuntu/', 'libs/linux/rhel/', 'libs/linux/suse/') }
156156
}
157157
158158
$failed = $false

‎PyPI_Description_ODBC.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ This package ships the platform-specific **Microsoft ODBC Driver 18 for SQL Serv
77
(and the supporting runtime libraries they depend on) as a standalone, pure-data wheel, so that
88
`mssql-python` does not have to bundle them inside its own wheel.
99

10+
Linux wheels are specific to both CPU architecture and libc family: `manylinux` wheels
11+
include the glibc-based Debian/Ubuntu, RHEL, and available SUSE driver variants, while
12+
`musllinux` wheels include only the Alpine/musl variant. Each retains the supporting
13+
libraries and resources for its included drivers.
14+
1015
## Not intended for direct use
1116

1217
Do **not** install this package directly. Install

‎eng/conda_tools/__main__.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
caught too;
3838
* no ``krb5``/``openssl``/``libltdl`` is VENDORED inside the payload (they are
3939
serviced by conda, never bundled).
40-
* the complete supported driver inventory is present: alpine/debian_ubuntu/rhel/suse
41-
for x86_64 and alpine/debian_ubuntu/rhel for arm64 (no SUSE ARM64 driver is shipped).
40+
* the complete glibc driver inventory is present: debian_ubuntu/rhel/suse for x86_64
41+
and debian_ubuntu/rhel for arm64 (no SUSE ARM64 driver is shipped).
4242
4343
Non-Linux packages (``win-*`` / ``osx-*``) have no such ELF payload and are skipped.
4444
An unreadable/malformed package FAILS (it is never silently treated as non-Linux).

‎eng/conda_tools/contracts.py‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,11 @@
4242
_MACHINE_NAME = {_EM_X86_64: "x86_64", _EM_AARCH64: "aarch64"}
4343
_REQUIRED_DRIVER_TREES = {
4444
"linux-64": {
45-
("alpine", "x86_64"),
4645
("debian_ubuntu", "x86_64"),
4746
("rhel", "x86_64"),
4847
("suse", "x86_64"),
4948
},
5049
"linux-aarch64": {
51-
("alpine", "arm64"),
5250
("debian_ubuntu", "arm64"),
5351
("rhel", "arm64"),
5452
},
@@ -655,9 +653,9 @@ def validate_elf(
655653
)
656654
# musl/alpine variants (NEEDED libc.musl*) link differently -- their libodbcinst
657655
# statically resolves libltdl, so the glibc DT_NEEDED requirements below do not
658-
# apply. There is no musl conda subdir (conda Linux is glibc-only); these variants
659-
# ride along in the payload but are never the conda load target. The climb /
660-
# presence / no-vendored checks still apply to them.
656+
# apply. Older ODBC wheels also carry these variants, but they are never a
657+
# conda load target (conda Linux is glibc-only). The climb / presence /
658+
# no-vendored checks still apply when auditing those older payloads.
661659
is_musl = any("libc.musl" in n for n in needed)
662660
want = expected_climb_entry(name)
663661

@@ -725,8 +723,8 @@ def validate_elf(
725723
)
726724
# Require the supported distro inventory for this architecture, then require EVERY
727725
# discovered driver lib dir to ship BOTH a driver and libodbcinst.so.2. The x86_64
728-
# ODBC wheel supports alpine/debian_ubuntu/rhel/suse; the arm64 wheel supports
729-
# alpine/debian_ubuntu/rhel (Microsoft does not ship a SUSE ARM64 driver tree).
726+
# manylinux ODBC wheel supports debian_ubuntu/rhel/suse; the arm64 wheel supports
727+
# debian_ubuntu/rhel (Microsoft does not ship a SUSE ARM64 driver tree).
730728
missing_trees = _REQUIRED_DRIVER_TREES[subdir] - driver_trees
731729
if missing_trees:
732730
errors.append(

‎setup_odbc.py‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
full release matrix.
1717
1818
Each wheel ships ONLY its own platform's ``libs/`` subtree (see
19-
``_target_libs_globs``). Because the package contains no compiled extension, a
19+
``_target_libs_globs``); manylinux and musllinux wheels also select only their
20+
own libc family. Because the package contains no compiled extension, a
2021
single build host can produce EVERY platform's wheel by setting
2122
``ODBC_TARGET_PLATFORM_TAG`` / ``ODBC_TARGET_ARCH`` (see ``get_platform_info``),
2223
e.g. build all 7 release wheels on one Windows agent.
@@ -151,7 +152,8 @@ def _target_libs_globs(platform_tag: str, arch: str) -> list:
151152
the minimal set of ``libs/`` globs. Combined with ``include_package_data=False``
152153
this guarantees a Windows wheel never carries Linux/macOS binaries (and vice
153154
versa), whether the build runs on the native OS or is cross-built on a single
154-
host via the ``ODBC_TARGET_*`` overrides.
155+
host via the ``ODBC_TARGET_*`` overrides. Linux's manylinux and musllinux
156+
tags additionally restrict the payload to glibc and musl, respectively.
155157
"""
156158
# LICENSING travels with every wheel (it is a file at the libs/ root).
157159
globs = ["libs/LICENSING"]
@@ -173,9 +175,14 @@ def _subtree(root: str) -> None:
173175
if arch in ("x86_64", "amd64")
174176
else "arm64" if arch in ("aarch64", "arm64") else arch
175177
)
176-
# A single Linux wheel serves all distro families for its arch; the driver
177-
# is selected at runtime via /etc/*-release detection.
178-
for distro in ("alpine", "debian_ubuntu", "rhel", "suse"):
178+
# Keep the distro-specific layout used by the runtime resolver, but do
179+
# not ship a different libc's binaries in manylinux/musllinux wheels.
180+
distros = ("alpine", "debian_ubuntu", "rhel", "suse")
181+
if tag.startswith("manylinux"):
182+
distros = ("debian_ubuntu", "rhel", "suse")
183+
elif tag.startswith("musllinux"):
184+
distros = ("alpine",)
185+
for distro in distros:
179186
_subtree(f"libs/linux/{distro}/{libs_arch}")
180187
else:
181188
raise OSError(f"Cannot determine libs subtree for platform tag {platform_tag!r}")

‎tests/test_029_bundled_binary_audit.py‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ def add_str(s):
138138
_CORE = "lib/python3.12/site-packages/mssql_py_core/mssql_py_core.cpython-312-x86_64-linux-gnu.so"
139139
_CORE_INIT = "lib/python3.12/site-packages/mssql_py_core/__init__.py"
140140
_DISTROS_BY_SUBDIR = {
141-
"linux-64": ("alpine", "debian_ubuntu", "rhel", "suse"),
142-
"linux-aarch64": ("alpine", "debian_ubuntu", "rhel"),
141+
"linux-64": ("debian_ubuntu", "rhel", "suse"),
142+
"linux-aarch64": ("debian_ubuntu", "rhel"),
143143
}
144144

145145

@@ -512,14 +512,22 @@ def test_malformed_required_core_elf_cannot_pass(tmp_path, damage):
512512

513513

514514
def test_audit_fails_when_entire_required_distro_tree_is_missing(tmp_path):
515-
package = _make_pkg(tmp_path, distros=("debian_ubuntu", "rhel", "suse"))
515+
package = _make_pkg(tmp_path, distros=("debian_ubuntu", "suse"))
516516
errors = audit.audit_package(package, "elf").violations
517517
assert any(
518-
"missing required Linux driver trees" in error and "alpine/x86_64" in error
518+
"missing required Linux driver trees" in error and "rhel/x86_64" in error
519519
for error in errors
520520
)
521521

522522

523+
@pytest.mark.parametrize("subdir,machine", [("linux-64", 62), ("linux-aarch64", 183)])
524+
def test_audit_accepts_glibc_only_driver_trees(tmp_path, subdir, machine):
525+
package = _make_pkg(
526+
tmp_path, subdir=subdir, machine=machine, distros=_DISTROS_BY_SUBDIR[subdir]
527+
)
528+
assert audit.audit_package(package, "elf").violations == []
529+
530+
523531
# --- N1: wrong climb variants must all FAIL --------------------------------
524532

525533

@@ -733,9 +741,8 @@ def add(name, data):
733741

734742

735743
def test_audit_allows_musl_variant_without_libltdl(tmp_path):
736-
# The alpine/musl libodbcinst NEEDs libc.musl* and statically links ltdl, so the
737-
# glibc libltdl DT_NEEDED requirement must NOT fail it. Package has a complete glibc
738-
# debian_ubuntu variant plus an alpine/musl variant.
744+
# Legacy manylinux wheels also carry Alpine. Its libodbcinst statically links
745+
# libltdl, so glibc-specific DT_NEEDED requirements must not reject that payload.
739746
alpine_lib = "lib/python3.12/site-packages/mssql_python_odbc/libs/linux/alpine/x86_64/lib"
740747
p = tmp_path / "mssql-python-1.13.0-py312_0.tar.bz2"
741748
with tarfile.open(p, "w:bz2") as tf:

0 commit comments

Comments
 (0)