Skip to content

Commit 75ae846

Browse files
[mlir] Make Python bindings installable.
* Links against libMLIR.so if the project is built for DYLIBs. * Puts things in the right place in build and install time python/ trees so that RPaths line up. * Adds install actions to install both the extension and sources. * Copies py source files to the build directory to match (consistent layout between build/install time and one place to point a PYTHONPATH for tests and interactive use). * Finally, "import mlir" from an installed LLVM just works. Differential Revision: https://reviews.llvm.org/D89167
1 parent a324d8f commit 75ae846

File tree

3 files changed

+103
-19
lines changed

3 files changed

+103
-19
lines changed

mlir/lib/Bindings/Python/CMakeLists.txt

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,46 @@
1+
################################################################################
2+
# Copy python source tree.
3+
################################################################################
4+
5+
set(PY_SRC_FILES
6+
mlir/__init__.py
7+
)
8+
9+
add_custom_target(MLIRBindingsPythonSources ALL
10+
DEPENDS ${PY_SRC_FILES}
11+
)
12+
13+
foreach(PY_SRC_FILE ${PY_SRC_FILES})
14+
set(PY_DEST_FILE "${PROJECT_BINARY_DIR}/python/${PY_SRC_FILE}")
15+
add_custom_command(
16+
TARGET MLIRBindingsPythonSources PRE_BUILD
17+
COMMENT "Copying python source ${PY_SRC_FILE} -> ${PY_DEST_FILE}"
18+
DEPENDS "${PY_SRC_FILE}"
19+
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
20+
"${CMAKE_CURRENT_SOURCE_DIR}/${PY_SRC_FILE}" "${PY_DEST_FILE}"
21+
)
22+
endforeach()
23+
24+
################################################################################
25+
# Build python extension
26+
################################################################################
27+
128
# Normally on unix-like platforms, extensions are built as "MODULE" libraries
229
# and do not explicitly link to the python shared object. This allows for
330
# some greater deployment flexibility since the extension will bind to
431
# symbols in the python interpreter on load. However, it also keeps the
532
# linker from erroring on undefined symbols, leaving this to (usually obtuse)
633
# runtime errors. Building in "SHARED" mode with an explicit link to the
734
# python libraries allows us to build with the expectation of no undefined
8-
# symbols, which is better for development.
9-
if(MLIR_PYTHON_BINDINGS_VERSION_LOCKED)
10-
set(PYEXT_LINK_MODE SHARED)
11-
set(PYEXT_LIBADD ${PYTHON_LIBRARIES})
12-
else()
35+
# symbols, which is better for development. Note that not all python
36+
# configurations provide build-time libraries to link against, in which
37+
# case, we fall back to MODULE linking.
38+
if(PYTHON_LIBRARIES STREQUAL "" OR NOT MLIR_PYTHON_BINDINGS_VERSION_LOCKED)
1339
set(PYEXT_LINK_MODE MODULE)
1440
set(PYEXT_LIBADD)
41+
else()
42+
set(PYEXT_LINK_MODE SHARED)
43+
set(PYEXT_LIBADD ${PYTHON_LIBRARIES})
1544
endif()
1645

1746
# The actual extension library produces a shared-object or DLL and has
@@ -47,7 +76,14 @@ target_compile_options(MLIRBindingsPythonExtension PRIVATE
4776
# Configure the output to match python expectations.
4877
set_target_properties(
4978
MLIRBindingsPythonExtension PROPERTIES
50-
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
79+
# Build-time RPath layouts require to be a directory one up from the
80+
# binary root.
81+
# TODO: Don't reference the LLVM_BINARY_DIR here: the invariant is that
82+
# the output directory must be at the same level of the lib directory
83+
# where libMLIR.so is installed. This is presently not optimal from a
84+
# project separation perspective and a discussion on how to better
85+
# segment MLIR libraries needs to happen.
86+
LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/python
5187
OUTPUT_NAME "_mlir"
5288
PREFIX "${PYTHON_MODULE_PREFIX}"
5389
SUFFIX "${PYTHON_MODULE_SUFFIX}${PYTHON_MODULE_EXTENSION}"
@@ -61,15 +97,62 @@ set_target_properties(
6197
# TODO: Add a Windows .def file and figure out the right thing to do on MacOS.
6298
set_target_properties(
6399
MLIRBindingsPythonExtension PROPERTIES CXX_VISIBILITY_PRESET "hidden")
64-
if(NOT MSVC AND NOT APPLE)
65-
set_target_properties(MLIRBindingsPythonExtension
66-
PROPERTIES LINK_FLAGS
67-
"-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/unix_version.lds")
100+
101+
set(PYEXT_DEPS)
102+
if(LLVM_BUILD_LLVM_DYLIB)
103+
list(APPEND PYEXT_DEPS
104+
# Depend on libMLIR.so first so that deps primarily come from the shared
105+
# library.
106+
MLIR
107+
)
68108
endif()
69109

70-
target_link_libraries(MLIRBindingsPythonExtension
71-
PRIVATE
110+
# Full static dependencies are also added and will augment what is in the
111+
# shared lib if needed (or in fully static builds, will result in mondo-built
112+
# extension).
113+
list(APPEND PYEXT_DEPS
114+
# Depend only on the MLIR C-API.
72115
MLIRCAPIIR
73116
MLIRCAPIRegistration
117+
)
118+
119+
target_link_libraries(MLIRBindingsPythonExtension
120+
PRIVATE
121+
${PYEXT_DEPS}
74122
${PYEXT_LIBADD}
75123
)
124+
125+
add_dependencies(MLIRBindingsPythonExtension MLIRBindingsPythonSources)
126+
llvm_setup_rpath(MLIRBindingsPythonExtension)
127+
128+
################################################################################
129+
# Install
130+
################################################################################
131+
132+
install(TARGETS MLIRBindingsPythonExtension
133+
COMPONENT MLIRBindingsPythonExtension
134+
LIBRARY DESTINATION python
135+
ARCHIVE DESTINATION python
136+
# NOTE: Even on DLL-platforms, extensions go in the lib directory tree.
137+
RUNTIME DESTINATION python)
138+
139+
# Note that we copy from the source tree just like for headers because
140+
# it will not be polluted with py_cache runtime artifacts (from testing and
141+
# such).
142+
install(
143+
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mlir
144+
DESTINATION python
145+
COMPONENT MLIRBindingsPythonSources
146+
FILES_MATCHING PATTERN "*.py"
147+
)
148+
149+
if (NOT LLVM_ENABLE_IDE)
150+
add_llvm_install_targets(
151+
install-MLIRBindingsPythonExtension
152+
DEPENDS MLIRBindingsPythonExtension
153+
COMPONENT MLIRBindingsPythonExtension)
154+
add_llvm_install_targets(
155+
install-MLIRBindingsPythonSources
156+
DEPENDS MLIRBindingsPythonSources
157+
COMPONENT MLIRBindingsPythonSources)
158+
endif()

mlir/lib/Bindings/Python/unix_version.lds

Lines changed: 0 additions & 4 deletions
This file was deleted.

mlir/test/lit.cfg.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464

6565
# The following tools are optional
6666
tools.extend([
67-
ToolSubst('%PYTHON', config.python_executable),
67+
ToolSubst('%PYTHON', config.python_executable, unresolved='ignore'),
6868
ToolSubst('toy-ch1', unresolved='ignore'),
6969
ToolSubst('toy-ch2', unresolved='ignore'),
7070
ToolSubst('toy-ch3', unresolved='ignore'),
@@ -99,6 +99,11 @@
9999
# by copying/linking sources to build.
100100
if config.enable_bindings_python:
101101
llvm_config.with_environment('PYTHONPATH', [
102-
os.path.join(config.mlir_src_root, "lib", "Bindings", "Python"),
103-
os.path.join(config.mlir_obj_root, "lib", "Bindings", "Python"),
102+
# TODO: Don't reference the llvm_obj_root here: the invariant is that
103+
# the python/ must be at the same level of the lib directory
104+
# where libMLIR.so is installed. This is presently not optimal from a
105+
# project separation perspective and a discussion on how to better
106+
# segment MLIR libraries needs to happen. See also
107+
# lib/Bindings/Python/CMakeLists.txt for where this is set up.
108+
os.path.join(config.llvm_obj_root, 'python'),
104109
], append_path=True)

0 commit comments

Comments
 (0)