Skip to content

Commit 859f2ef

Browse files
committed
Added Python Build Steps
Signed-off-by: Justin Williams <Justin.Williams@amd.com>
1 parent b7da296 commit 859f2ef

File tree

8 files changed

+651
-176
lines changed

8 files changed

+651
-176
lines changed

.github/workflows/amdsmi-build.yml

Lines changed: 167 additions & 27 deletions
Large diffs are not rendered by default.

projects/amdsmi/amdsmi_cli/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ message("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
55
# Set CLI Build Directory
66
set(PY_PACKAGE_DIR "amdsmi_cli")
77
set(PY_CLI_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}" CACHE STRING "CLI tool installation directory")
8+
set(PY_LIB_FROM_PKG "${PROJECT_BINARY_DIR}/py-interface/python_package/amdsmi/libamd_smi_python.so")
89

910
# populate version string
1011
configure_file(_version.py.in ${PY_PACKAGE_DIR}/_version.py @ONLY)

projects/amdsmi/amdsmi_cli/amdsmi_init.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,84 @@
2929

3030
from pathlib import Path
3131

32+
from typing import Optional
3233
current_path = os.path.dirname(os.path.abspath(__file__))
3334
python_lib_path = f"{current_path}/../../share/amd_smi"
3435
sys.path.insert(0, python_lib_path)
35-
# Prioritize the library from this installation over any pip-installed version
36+
# Only fallback to the python library if its a compatible version
37+
# multiple amdsmi versions installed on the system could cause issues
38+
# TODO Add version checking & debug to check pathing
39+
# Ideally we want to identify if the installed python library is incompatible and log a solution to the user
40+
# LD library config or reinstall, etc...
41+
# The problem is coming from the switch over between the post install and pypi
42+
43+
44+
def _log_version_and_path_diagnostics():
45+
"""Emit best-effort diagnostics about the amdsmi Python package and the shared library location."""
46+
try:
47+
from amdsmi import _version # type: ignore
48+
pkg_version = getattr(_version, "__version__", "unknown")
49+
except Exception as exc: # pragma: no cover - defensive
50+
pkg_version = f"unavailable ({exc})"
51+
pkg_dir = Path(__file__).resolve().parent
52+
lib_candidate = pkg_dir / "libamd_smi_python.so"
53+
print(f"[amdsmi-cli] Python package version: {pkg_version}")
54+
print(f"[amdsmi-cli] Package dir: {pkg_dir}")
55+
print(f"[amdsmi-cli] Expected Python lib: {lib_candidate} (exists={lib_candidate.exists()})")
56+
print(f"[amdsmi-cli] sys.path[0]: {sys.path[0]}")
57+
58+
59+
def _check_version_compatibility(expected_version: Optional[str] = None) -> None:
60+
"""
61+
Verify that the Python package version matches the expected CLI/lib version (if provided).
62+
If mismatched, log guidance and abort to avoid loading an incompatible library.
63+
"""
64+
lib_locations = []
65+
try:
66+
from amdsmi import _version # type: ignore
67+
pkg_version = getattr(_version, "__version__", None)
68+
except Exception:
69+
_log_version_and_path_diagnostics()
70+
print("[amdsmi-cli] Failed to read amdsmi Python package version; aborting to avoid incompatibility.")
71+
sys.exit(1)
72+
73+
if expected_version and pkg_version and pkg_version != expected_version:
74+
_log_version_and_path_diagnostics()
75+
print(f"[amdsmi-cli] Version mismatch: expected {expected_version}, found {pkg_version}.")
76+
print("[amdsmi-cli] Please install a matching amdsmi wheel from PyPI or reinstall the ROCm package,")
77+
print("[amdsmi-cli] and ensure LD_LIBRARY_PATH/ldconfig points to the matching shared library.")
78+
sys.exit(1)
79+
80+
# If the Python lib is missing, warn early with guidance.
81+
pkg_dir = Path(__file__).resolve().parent
82+
lib_candidate = pkg_dir / "libamd_smi_python.so"
83+
if lib_candidate.exists():
84+
return
85+
lib_locations.append(str(lib_candidate))
86+
87+
# Also consider the shared install path resolved via _find_lib.py
88+
try:
89+
from amdsmi._find_lib import find_smi_library # type: ignore
90+
resolved = find_smi_library()
91+
if resolved.exists():
92+
return
93+
lib_locations.append(str(resolved))
94+
except Exception:
95+
pass
96+
97+
_log_version_and_path_diagnostics()
98+
print("[amdsmi-cli] Unable to locate libamd_smi_python.so in expected locations:")
99+
for loc in lib_locations:
100+
print(f" - {loc}")
101+
print("[amdsmi-cli] Install the amdsmi wheel that bundles the Python shared library,")
102+
print("[amdsmi-cli] or adjust LD_LIBRARY_PATH/ldconfig to point to a compatible lib.")
103+
sys.exit(1)
104+
36105

37106
try:
107+
# TODO Add version checking & debug to check pathing
108+
# The expected version string can be wired in from packaging if desired.
109+
_check_version_compatibility(expected_version=None)
38110
from amdsmi import amdsmi_interface, amdsmi_exception
39111
except ImportError as e:
40112
print(f"Unhandled import error: {e}")

projects/amdsmi/py-interface/CMakeLists.txt

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ set(PY_BUILD_DIR "python_package")
1212
# additionally defined in pyproject.toml
1313
set(PY_PACKAGE_DIR "${PY_BUILD_DIR}/amdsmi")
1414
set(PY_WRAPPER_INSTALL_DIR "${SHARE_INSTALL_PREFIX}" CACHE STRING "Wrapper installation directory")
15+
set(AMDSMI_PYTHON_LIB_NAME "libamd_smi.so")
16+
if(BUILD_PYTHON_LIB)
17+
set(AMDSMI_PYTHON_LIB_NAME "libamd_smi_python.so")
18+
endif()
19+
set(AMDSMI_PYTHON_LIB_PATH "${PROJECT_BINARY_DIR}/src/${AMDSMI_PYTHON_LIB_NAME}")
1520

1621
# try to find clang of the right version
1722
set(GOOD_CLANG_FOUND FALSE)
@@ -35,6 +40,8 @@ if(NOT GOOD_CLANG_FOUND)
3540
AUTHOR_WARNING
3641
"A wrapper will not be re-generated! Using old wrapper instead.\nSet -DBUILD_WRAPPER=ON to re-build the wrapper"
3742
)
43+
# Still need Python3 for building the wheel package
44+
find_package(Python3 3.6 COMPONENTS Interpreter REQUIRED)
3845
add_custom_command(
3946
OUTPUT amdsmi_wrapper.py ${PY_PACKAGE_DIR}/amdsmi_wrapper.py
4047
DEPENDS ${AMD_SMI} ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py
@@ -54,18 +61,22 @@ else()
5461
add_custom_command(
5562
OUTPUT amdsmi.h ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py amdsmi_wrapper.py
5663
${PY_PACKAGE_DIR}/amdsmi_wrapper.py
57-
DEPENDS ${AMD_SMI} python_pre_reqs generator.py ${PROJECT_SOURCE_DIR}/include/amd_smi/amdsmi.h
64+
DEPENDS ${AMD_SMI} $<$<BOOL:${BUILD_PYTHON_LIB}>:${AMD_SMI}_python> python_pre_reqs generator.py ${PROJECT_SOURCE_DIR}/include/amd_smi/amdsmi.h
5865
COMMAND cp ${PROJECT_SOURCE_DIR}/include/amd_smi/amdsmi.h ./
59-
COMMAND ${Python3_EXECUTABLE} generator.py "$<$<BOOL:${ENABLE_ESMI_LIB}>:-e -DENABLE_ESMI_LIB>" -i amdsmi.h -l
60-
${PROJECT_BINARY_DIR}/src/libamd_smi.so -o ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py
66+
COMMAND ${CMAKE_COMMAND} -E env AMDSMI_FIND_LIB_PATH=${CMAKE_CURRENT_BINARY_DIR}/${PY_PACKAGE_DIR}/_find_lib.py
67+
${Python3_EXECUTABLE} generator.py "$<$<BOOL:${ENABLE_ESMI_LIB}>:-e -DENABLE_ESMI_LIB>" -i amdsmi.h -l
68+
${AMDSMI_PYTHON_LIB_PATH} -o ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py
6169
COMMAND mkdir -p ${PY_PACKAGE_DIR}
6270
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py ${PY_PACKAGE_DIR}/)
6371
endif()
6472

6573
# populate version string
6674
configure_file(pyproject.toml.in ${PY_BUILD_DIR}/pyproject.toml @ONLY)
75+
configure_file(setup.cfg.in ${PY_BUILD_DIR}/setup.cfg @ONLY)
6776
configure_file(_version.py.in ${PY_PACKAGE_DIR}/_version.py @ONLY)
68-
configure_file(setup.py.in ${PY_BUILD_DIR}/setup.py @ONLY)
77+
if(BUILD_PYTHON_LIB)
78+
configure_file(_find_lib.py.in ${PY_PACKAGE_DIR}/_find_lib.py @ONLY)
79+
endif()
6980

7081
add_custom_target(python_wrapper DEPENDS amdsmi_wrapper.py)
7182

@@ -81,24 +92,38 @@ add_custom_command(
8192
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_SOURCE_DIR}/LICENSE ${PY_PACKAGE_DIR}/)
8293

8394
# copy libamd_smi.so to allow for a self-contained python package
84-
add_custom_command(OUTPUT ${PY_PACKAGE_DIR}/libamd_smi.so DEPENDS ${PROJECT_BINARY_DIR}/src/libamd_smi.so
85-
COMMAND cp "${PROJECT_BINARY_DIR}/src/libamd_smi.so" ${PY_PACKAGE_DIR}/)
95+
add_custom_command(OUTPUT ${PY_PACKAGE_DIR}/${AMDSMI_PYTHON_LIB_NAME} DEPENDS ${AMDSMI_PYTHON_LIB_PATH}
96+
COMMAND cp "${AMDSMI_PYTHON_LIB_PATH}" ${PY_PACKAGE_DIR}/)
8697

8798
add_custom_target(
8899
python_package ALL
89100
DEPENDS ${PY_BUILD_DIR}/pyproject.toml
90-
${PY_BUILD_DIR}/setup.py
101+
${PY_BUILD_DIR}/setup.cfg
91102
${PY_PACKAGE_DIR}/_version.py
92103
${PY_PACKAGE_DIR}/__init__.py
93104
${PY_PACKAGE_DIR}/amdsmi_exception.py
94105
${PY_PACKAGE_DIR}/amdsmi_interface.py
95106
${PY_PACKAGE_DIR}/README.md
96107
${PY_PACKAGE_DIR}/LICENSE
97-
${PY_PACKAGE_DIR}/libamd_smi.so)
108+
${PY_PACKAGE_DIR}/${AMDSMI_PYTHON_LIB_NAME}
109+
$<$<BOOL:${BUILD_PYTHON_LIB}>:${PY_PACKAGE_DIR}/_find_lib.py>)
110+
if(BUILD_PYTHON_LIB)
111+
add_dependencies(python_package ${AMD_SMI}_python)
112+
endif()
113+
114+
# Build a wheel into the binary dir (no deps, local artifacts only)
115+
add_custom_target(
116+
python_wheel ALL
117+
DEPENDS python_package
118+
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/${PY_BUILD_DIR}
119+
${Python3_EXECUTABLE} -m pip wheel --no-deps -w ${CMAKE_CURRENT_BINARY_DIR}/${PY_BUILD_DIR}
120+
${CMAKE_CURRENT_BINARY_DIR}/${PY_BUILD_DIR}
121+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PY_BUILD_DIR}
122+
COMMENT "Building amdsmi wheel without dependencies")
98123

99124
install(
100125
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PY_BUILD_DIR}/pyproject.toml
101-
${CMAKE_CURRENT_BINARY_DIR}/${PY_BUILD_DIR}/setup.py ${CMAKE_CURRENT_BINARY_DIR}/${PY_PACKAGE_DIR}/_version.py
126+
${CMAKE_CURRENT_BINARY_DIR}/${PY_PACKAGE_DIR}/_version.py
102127
DESTINATION ${PY_WRAPPER_INSTALL_DIR}
103128
COMPONENT dev)
104129

0 commit comments

Comments
 (0)