Skip to content

Commit 98b2041

Browse files
committed
Keep the CPU provider objects out of the Windows Python bindings
<details><summary>Claude's draft</summary> The /VERBOSE link of the previous commit shows why the Windows bindings still pulled data_types.cc.obj and friends from the static libraries: with MSVC and onnxruntime_BUILD_SHARED_LIB, the CPU provider is the object library onnxruntime_providers_obj, so all of its objects went into the bindings and referenced most of the framework. With onnxruntime_BUILD_INTERNAL_SHARED_LIB they are only in onnxruntime_internal.dll now, and gen_internal_def.py also scans object libraries, so what the bindings call in the provider is exported. The object and library lists go through files written by file(GENERATE), since hundreds of object paths exceed the Windows command line, and dumpbin runs on 64 files at a time. Resume this Claude session: ``` cd /home/mark/git/feedstock claude --resume fdaba65c-5a43-4f26-a32f-d49b747fdbd7 ``` </details> Claude-Session: https://claude.ai/code/session_01R9WZp6UVaiXYyC2hWTNWZY
1 parent 28699fc commit 98b2041

1 file changed

Lines changed: 60 additions & 35 deletions

File tree

‎recipe/patches/0016-Split-libonnxruntime-into-an-internal-and-a-public-library.patch‎

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,10 @@ index a977141..540cd3a 100644
226226

227227
if (winml_is_inbox)
228228
diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake
229-
index 5dfd004..51043a3 100644
229+
index 5dfd004..5f96c8e 100644
230230
--- a/cmake/onnxruntime_python.cmake
231231
+++ b/cmake/onnxruntime_python.cmake
232-
@@ -216,10 +216,50 @@ endif()
232+
@@ -216,16 +216,69 @@ endif()
233233
if(onnxruntime_WEBGPU_LINKED_INTO_HOST)
234234
list(APPEND onnxruntime_pybind11_state_static_providers PRIVATE onnxruntime_providers_webgpu)
235235
endif()
@@ -243,9 +243,12 @@ index 5dfd004..51043a3 100644
243243
+if(onnxruntime_BUILD_INTERNAL_SHARED_LIB)
244244
+ target_link_libraries(onnxruntime_pybind11_state PRIVATE onnxruntime_internal)
245245
+endif()
246+
+set(onnxruntime_pybind11_state_providers_target ${onnxruntime_providers_target})
246247
+if(WIN32 AND onnxruntime_BUILD_INTERNAL_SHARED_LIB)
247-
+ # onnxruntime_internal.dll exports what the objects of the Python bindings take from its static libraries. The
248-
+ # protobuf classes of onnx stay in the Python bindings, as they would need their data imported.
248+
+ # The CPU provider is an object library with MSVC; its objects are in onnxruntime_internal.dll.
249+
+ set(onnxruntime_pybind11_state_providers_target)
250+
+ # onnxruntime_internal.dll exports what the objects of the Python bindings take from its libraries. The protobuf
251+
+ # classes of onnx stay in the Python bindings, as they would need their data imported.
249252
+ target_compile_definitions(onnxruntime_pybind11_state PRIVATE ORT_IMPORT_INTERNAL_DATA)
250253
+ get_filename_component(_onnxruntime_linker_dir "${CMAKE_LINKER}" DIRECTORY)
251254
+ find_program(onnxruntime_DUMPBIN dumpbin HINTS "${_onnxruntime_linker_dir}" REQUIRED)
@@ -261,16 +264,26 @@ index 5dfd004..51043a3 100644
261264
+ else()
262265
+ list(APPEND _onnxruntime_internal_def_libraries $<TARGET_FILE:${_lib}>)
263266
+ endif()
267+
+ elseif(_type STREQUAL "OBJECT_LIBRARY")
268+
+ list(APPEND _onnxruntime_internal_def_libraries $<TARGET_OBJECTS:${_lib}>)
264269
+ endif()
265270
+ endif()
266271
+ endforeach()
267272
+ list(REMOVE_DUPLICATES _onnxruntime_internal_def_libraries)
273+
+ # The object files exceed the length of a command line.
274+
+ set(_onnxruntime_internal_def_inputs ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime_internal_def_inputs)
275+
+ file(GENERATE OUTPUT ${_onnxruntime_internal_def_inputs}/objects.txt
276+
+ CONTENT "$<JOIN:$<TARGET_OBJECTS:onnxruntime_pybind11_state>,\n>\n")
277+
+ file(GENERATE OUTPUT ${_onnxruntime_internal_def_inputs}/libraries.txt
278+
+ CONTENT "$<JOIN:${_onnxruntime_internal_def_libraries},\n>\n")
279+
+ file(GENERATE OUTPUT ${_onnxruntime_internal_def_inputs}/excluded_libraries.txt
280+
+ CONTENT "$<JOIN:${_onnxruntime_internal_def_excluded_libraries},\n>\n")
268281
+ add_custom_command(OUTPUT ${INTERNAL_DEF_FILE}
269282
+ COMMAND ${Python_EXECUTABLE} "${REPO_ROOT}/tools/ci_build/gen_internal_def.py"
270283
+ --dumpbin "${onnxruntime_DUMPBIN}" --public_def "${SYMBOL_FILE}" --output "${INTERNAL_DEF_FILE}"
271-
+ --objects "$<TARGET_OBJECTS:onnxruntime_pybind11_state>"
272-
+ --libraries ${_onnxruntime_internal_def_libraries}
273-
+ --excluded_libraries ${_onnxruntime_internal_def_excluded_libraries}
284+
+ --objects "@${_onnxruntime_internal_def_inputs}/objects.txt"
285+
+ --libraries "@${_onnxruntime_internal_def_inputs}/libraries.txt"
286+
+ --excluded_libraries "@${_onnxruntime_internal_def_inputs}/excluded_libraries.txt"
274287
+ DEPENDS "$<TARGET_OBJECTS:onnxruntime_pybind11_state>" ${_onnxruntime_internal_def_libraries}
275288
+ ${_onnxruntime_internal_def_excluded_libraries} "${SYMBOL_FILE}" "${REPO_ROOT}/tools/ci_build/gen_internal_def.py"
276289
+ COMMENT "Generating the exports of onnxruntime_internal for onnxruntime_pybind11_state"
@@ -281,7 +294,14 @@ index 5dfd004..51043a3 100644
281294
target_link_libraries(onnxruntime_pybind11_state PRIVATE
282295
onnxruntime_session
283296
${onnxruntime_libs}
284-
@@ -854,10 +894,14 @@ add_custom_command(
297+
${onnxruntime_pybind11_state_static_providers}
298+
onnxruntime_optimizer
299+
- ${onnxruntime_providers_target}
300+
+ ${onnxruntime_pybind11_state_providers_target}
301+
onnxruntime_util
302+
onnxruntime_lora
303+
onnxruntime_framework
304+
@@ -854,10 +907,14 @@ add_custom_command(
285305
)
286306

287307
if (onnxruntime_BUILD_SHARED_LIB)
@@ -395,10 +415,10 @@ index 15965a1..5209d65 100755
395415
for c in args.config:
396416
diff --git a/tools/ci_build/gen_internal_def.py b/tools/ci_build/gen_internal_def.py
397417
new file mode 100644
398-
index 0000000..b0f2377
418+
index 0000000..9253dea
399419
--- /dev/null
400420
+++ b/tools/ci_build/gen_internal_def.py
401-
@@ -0,0 +1,97 @@
421+
@@ -0,0 +1,102 @@
402422
+#!/usr/bin/env python3
403423
+# Copyright (c) Microsoft Corporation. All rights reserved.
404424
+# Licensed under the MIT License.
@@ -420,7 +440,8 @@ index 0000000..b0f2377
420440
+
421441
+
422442
+def parse_arguments():
423-
+ parser = argparse.ArgumentParser()
443+
+ parser = argparse.ArgumentParser(fromfile_prefix_chars="@")
444+
+ parser.convert_arg_line_to_args = lambda line: [line.strip()] if line.strip() else []
424445
+ parser.add_argument("--dumpbin", required=True)
425446
+ parser.add_argument("--public_def", required=True, help="module-definition file of the public API")
426447
+ parser.add_argument("--output", required=True)
@@ -430,14 +451,21 @@ index 0000000..b0f2377
430451
+ return parser.parse_args()
431452
+
432453
+
433-
+def external_symbols(dumpbin, path):
434-
+ """Yields (name, defined, is_function) for the external symbols of an object file or static library."""
435-
+ out = subprocess.run([dumpbin, "/nologo", "/SYMBOLS", path], capture_output=True, text=True, errors="replace", check=True)
436-
+ for line in out.stdout.splitlines():
437-
+ m = SYMBOL_RE.match(line)
438-
+ if m:
439-
+ section, function, name = m.groups()
440-
+ yield name, section != "UNDEF", function is not None
454+
+def external_symbols(dumpbin, paths):
455+
+ """Yields (name, defined, is_function) for the external symbols of object files or static libraries."""
456+
+ for i in range(0, len(paths), 64):
457+
+ out = subprocess.run(
458+
+ [dumpbin, "/nologo", "/SYMBOLS", *paths[i : i + 64]],
459+
+ capture_output=True,
460+
+ text=True,
461+
+ errors="replace",
462+
+ check=True,
463+
+ )
464+
+ for line in out.stdout.splitlines():
465+
+ m = SYMBOL_RE.match(line)
466+
+ if m:
467+
+ section, function, name = m.groups()
468+
+ yield name, section != "UNDEF", function is not None
441469
+
442470
+
443471
+args = parse_arguments()
@@ -450,26 +478,23 @@ index 0000000..b0f2377
450478
+ public.append(fields[0])
451479
+
452480
+defined = {}
453-
+for library in args.libraries:
454-
+ for name, is_defined, is_function in external_symbols(args.dumpbin, library):
455-
+ if is_defined:
456-
+ defined.setdefault(name, is_function)
457-
+for library in args.excluded_libraries:
458-
+ for name, is_defined, _ in external_symbols(args.dumpbin, library):
459-
+ if is_defined:
460-
+ defined.pop(name, None)
481+
+for name, is_defined, is_function in external_symbols(args.dumpbin, args.libraries):
482+
+ if is_defined:
483+
+ defined.setdefault(name, is_function)
484+
+for name, is_defined, _ in external_symbols(args.dumpbin, args.excluded_libraries):
485+
+ if is_defined:
486+
+ defined.pop(name, None)
461487
+
462488
+referenced = set()
463489
+imported = set()
464490
+defined_in_objects = set()
465-
+for obj in args.objects:
466-
+ for name, is_defined, _ in external_symbols(args.dumpbin, obj):
467-
+ if is_defined:
468-
+ defined_in_objects.add(name)
469-
+ elif name.startswith("__imp_"):
470-
+ imported.add(name[len("__imp_") :])
471-
+ else:
472-
+ referenced.add(name)
491+
+for name, is_defined, _ in external_symbols(args.dumpbin, args.objects):
492+
+ if is_defined:
493+
+ defined_in_objects.add(name)
494+
+ elif name.startswith("__imp_"):
495+
+ imported.add(name[len("__imp_") :])
496+
+ else:
497+
+ referenced.add(name)
473498
+
474499
+functions = []
475500
+data = []

0 commit comments

Comments
 (0)