Improve python wrapper generation
- Add "BUILD_PACKAGE" option that is OFF by default (CI issues)
- Optionally package wrapper if python3.7 or above is present (hack for CI)
- Optionally build wrapper if clang is present (hack for CI)
- Improve dependency resolution for wrapper
- Use python venv
- Use pyproject.toml instead of setup.py
- Use CMake install path to search for libamd_smi.so
- Move python-specific CMakeLists into py-interface
- Search for libamd_smi.so more aggressively
Change-Id: Ie7dad676b0d4a5f58ad2b887db7fecf5b1297e3b
Signed-off-by: Galantsev, Dmitrii <dmitrii.galantsev@amd.com>
[ROCm/amdsmi commit: 74479187d0]
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
# Generate py-interface and package targets
|
||||
|
||||
# match this version to your clang
|
||||
# too new won't work, too old won't work either
|
||||
set(clang_ver 14.0)
|
||||
set(ctypeslib_ver 2.3.2)
|
||||
|
||||
set(PY_BUILD_DIR "python_package" CACHE STRING "")
|
||||
# amdsmi part of this string is the directory containing all python files
|
||||
# additionally defined in pyproject.toml
|
||||
set(PY_PACKAGE_DIR "${PY_BUILD_DIR}/amdsmi" CACHE STRING "")
|
||||
|
||||
# if Python3 is found but the version is below 3.7 - Python3_FOUND is set to FALSE
|
||||
find_package(Python3 3.7 COMPONENTS Interpreter)
|
||||
|
||||
# WARN: This is a HACK to pass compile on AMD rhel8 CI systems!
|
||||
# Those still use python3.6 which is too old for this project!
|
||||
# TODO: drop python3.6 support
|
||||
if(NOT Python3_FOUND)
|
||||
message(AUTHOR_WARNING "Python3 DOESN'T EXIST OR VERSION IS TOO OLD!: ${Python3_VERSION}")
|
||||
message(AUTHOR_WARNING "The wrapper will not be created and the project will not be packaged!")
|
||||
# WARN: EXIT CURRENT CMAKE FILE
|
||||
return()
|
||||
endif()
|
||||
|
||||
# check if virtualenv is installed
|
||||
execute_process(COMMAND "${Python3_EXECUTABLE}" -m pip show virtualenv
|
||||
ERROR_VARIABLE VIRTUALENV_NOT_FOUND)
|
||||
if(VIRTUALENV_NOT_FOUND)
|
||||
message(FATAL_ERROR "Python virtualenv is not installed!
|
||||
${VIRTUALENV_NOT_FOUND}
|
||||
Please run:
|
||||
${Python3_EXECUTABLE} -m pip install virtualenv")
|
||||
endif()
|
||||
|
||||
|
||||
# set up the Python environment
|
||||
execute_process(COMMAND "${Python3_EXECUTABLE}" -m venv "${CMAKE_CURRENT_BINARY_DIR}/venv")
|
||||
|
||||
# venv trick borrowed from:
|
||||
# https://discourse.cmake.org/t/possible-to-create-a-python-virtual-env-from-cmake-and-then-find-it-with-findpython3/1132
|
||||
# update the environment with VIRTUAL_ENV variable(mimic the activate script)
|
||||
set(ENV{VIRTUAL_ENV} "${CMAKE_CURRENT_BINARY_DIR}/venv")
|
||||
# change the context of the search
|
||||
set(Python3_FIND_VIRTUALENV FIRST)
|
||||
# unset Python3_EXECUTABLE because it is also an input variable(see documentation, Artifacts Specification section)
|
||||
unset(Python3_EXECUTABLE)
|
||||
# launch a new search
|
||||
find_package(Python3 3.7 COMPONENTS Interpreter Development REQUIRED)
|
||||
|
||||
add_custom_target(
|
||||
python_pre_reqs
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip install clang==${clang_ver} ctypeslib2==${ctypeslib_ver})
|
||||
|
||||
# TODO: Figure out how python-clang and clang are related
|
||||
# Currently only a very specific combination works
|
||||
|
||||
# try to find clang of the right version
|
||||
set(GOOD_CLANG_FOUND FALSE)
|
||||
find_program(clang NAMES clang)
|
||||
if(clang STREQUAL "clang-NOTFOUND")
|
||||
message(AUTHOR_WARNING "NO CLANG FOUND!")
|
||||
else()
|
||||
# extract clang version manually because find_package(clang) doesn't work
|
||||
execute_process(COMMAND ${clang} --version OUTPUT_VARIABLE clang_full_version_string)
|
||||
string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
|
||||
if(CLANG_VERSION_STRING VERSION_EQUAL 14.0)
|
||||
message("GOOD CLANG VERSION: ${CLANG_VERSION_STRING}")
|
||||
set(GOOD_CLANG_FOUND TRUE)
|
||||
else()
|
||||
message(AUTHOR_WARNING "CLANG VERSION TOO OLD!: ${CLANG_VERSION_STRING}")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT GOOD_CLANG_FOUND)
|
||||
# keep old wrapper because no clang found
|
||||
message(AUTHOR_WARNING "A wrapper will not be generated! Using old wrapper instead.")
|
||||
add_custom_command(
|
||||
OUTPUT amdsmi_wrapper.py
|
||||
${PY_PACKAGE_DIR}/amdsmi_wrapper.py
|
||||
DEPENDS ${AMD_SMI}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py
|
||||
COMMAND cp -f ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py ${CMAKE_CURRENT_BINARY_DIR}/
|
||||
# hacky alternative to configure_file that will run at MAKE compile instead of CMake configure
|
||||
COMMAND sed -i
|
||||
s:"@CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@":"${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}":g
|
||||
${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper.py
|
||||
COMMAND mkdir -p ${PY_PACKAGE_DIR}
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper.py ${PY_PACKAGE_DIR}/)
|
||||
else()
|
||||
# generate new wrapper
|
||||
configure_file(${PROJECT_SOURCE_DIR}/tools/generator.py generator.py @ONLY COPYONLY)
|
||||
add_custom_command(
|
||||
OUTPUT amdsmi.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py
|
||||
amdsmi_wrapper.py
|
||||
${PY_PACKAGE_DIR}/amdsmi_wrapper.py
|
||||
DEPENDS ${AMD_SMI}
|
||||
python_pre_reqs
|
||||
generator.py
|
||||
${PROJECT_SOURCE_DIR}/include/amd_smi/amdsmi.h
|
||||
COMMAND cp ${PROJECT_SOURCE_DIR}/include/amd_smi/amdsmi.h ./
|
||||
COMMAND ${Python3_EXECUTABLE} generator.py -i amdsmi.h -l ${PROJECT_BINARY_DIR}/src/libamd_smi.so -o ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py
|
||||
COMMAND cp -f ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py ${CMAKE_CURRENT_BINARY_DIR}/
|
||||
# hacky alternative to configure_file that will run at MAKE compile instead of CMake configure
|
||||
COMMAND sed -i
|
||||
s:"@CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@":"${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}":g
|
||||
${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper.py
|
||||
COMMAND mkdir -p ${PY_PACKAGE_DIR}
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/amdsmi_wrapper.py ${PY_PACKAGE_DIR}/)
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
python_wrapper
|
||||
DEPENDS amdsmi_wrapper.py)
|
||||
|
||||
# symlinking instead of copying avoids unnecessarry regeneration of packaged files
|
||||
add_custom_command(
|
||||
OUTPUT ${PY_BUILD_DIR}/pyproject.toml
|
||||
${PY_PACKAGE_DIR}/__init__.py
|
||||
${PY_PACKAGE_DIR}/amdsmi_exception.py
|
||||
${PY_PACKAGE_DIR}/amdsmi_interface.py
|
||||
${PY_PACKAGE_DIR}/README.md
|
||||
${PY_PACKAGE_DIR}/LICENSE
|
||||
DEPENDS python_wrapper
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml ${PY_BUILD_DIR}/
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${PY_PACKAGE_DIR}/
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_exception.py ${PY_PACKAGE_DIR}/
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_interface.py ${PY_PACKAGE_DIR}/
|
||||
COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${PY_PACKAGE_DIR}/
|
||||
COMMAND ln -sf ${PROJECT_SOURCE_DIR}/LICENSE ${PY_PACKAGE_DIR}/)
|
||||
|
||||
# NOTE: changing this does not change the generated file!
|
||||
# it WILL break
|
||||
set(PY_PACKAGE "${PY_BUILD_DIR}/amdsmi-0.1-py3-none-any.whl")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PY_PACKAGE}
|
||||
DEPENDS ${PY_BUILD_DIR}/pyproject.toml
|
||||
${PY_PACKAGE_DIR}/__init__.py
|
||||
${PY_PACKAGE_DIR}/amdsmi_exception.py
|
||||
${PY_PACKAGE_DIR}/amdsmi_interface.py
|
||||
${PY_PACKAGE_DIR}/README.md
|
||||
${PY_PACKAGE_DIR}/LICENSE
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip install wheel
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip wheel ./${PY_BUILD_DIR} --wheel-dir=${PY_BUILD_DIR})
|
||||
|
||||
add_custom_target(
|
||||
python_package ALL
|
||||
DEPENDS ${PY_PACKAGE})
|
||||
|
||||
install(
|
||||
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PY_PACKAGE}
|
||||
DESTINATION ${SHARE_INSTALL_PREFIX})
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
import os
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# TARGET arch is: ['-I/usr/lib/llvm-6.0/lib/clang/6.0.0/include']
|
||||
# TARGET arch is: ['-I/usr/lib/llvm-14/lib/clang/14.0.0/include']
|
||||
# WORD_SIZE is: 8
|
||||
# POINTER_SIZE is: 8
|
||||
# LONGDOUBLE_SIZE is: 16
|
||||
@@ -167,7 +167,17 @@ def char_pointer_cast(string, encoding='utf-8'):
|
||||
|
||||
|
||||
_libraries = {}
|
||||
_libraries['libamd_smi.so'] = ctypes.CDLL(os.path.join(os.path.dirname(__file__), 'libamd_smi.so'))
|
||||
|
||||
if os.path.isfile('@CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/libamd_smi.so'):
|
||||
# try to find library in install directory provided by CMake
|
||||
_libraries['libamd_smi.so'] = ctypes.CDLL(os.path.join('@CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@', 'libamd_smi.so'))
|
||||
elif os.path.isfile('/opt/rocm/lib/libamd_smi.so'):
|
||||
# try /opt/rocm/lib as a fallback
|
||||
_libraries['libamd_smi.so'] = ctypes.CDLL(os.path.join('/opt/rocm/lib', 'libamd_smi.so'))
|
||||
else:
|
||||
# lastly - search in current directory
|
||||
_libraries['libamd_smi.so'] = ctypes.CDLL(os.path.join(os.path.dirname(__file__), 'libamd_smi.so'))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -697,6 +707,16 @@ amdsmi_process_handle = ctypes.c_uint32
|
||||
class struct_c__SA_amdsmi_proc_info_t(Structure):
|
||||
pass
|
||||
|
||||
class struct_c__SA_amdsmi_proc_info_t_1(Structure):
|
||||
pass
|
||||
|
||||
struct_c__SA_amdsmi_proc_info_t_1._pack_ = 1 # source:False
|
||||
struct_c__SA_amdsmi_proc_info_t_1._fields_ = [
|
||||
('gtt_mem', ctypes.c_uint64),
|
||||
('cpu_mem', ctypes.c_uint64),
|
||||
('vram_mem', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
class struct_c__SA_amdsmi_proc_info_t_0(Structure):
|
||||
pass
|
||||
|
||||
@@ -709,16 +729,6 @@ struct_c__SA_amdsmi_proc_info_t_0._fields_ = [
|
||||
('dec', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
class struct_c__SA_amdsmi_proc_info_t_1(Structure):
|
||||
pass
|
||||
|
||||
struct_c__SA_amdsmi_proc_info_t_1._pack_ = 1 # source:False
|
||||
struct_c__SA_amdsmi_proc_info_t_1._fields_ = [
|
||||
('gtt_mem', ctypes.c_uint64),
|
||||
('cpu_mem', ctypes.c_uint64),
|
||||
('vram_mem', ctypes.c_uint64),
|
||||
]
|
||||
|
||||
struct_c__SA_amdsmi_proc_info_t._pack_ = 1 # source:False
|
||||
struct_c__SA_amdsmi_proc_info_t._fields_ = [
|
||||
('name', ctypes.c_char * 32),
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# for details see:
|
||||
# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "amdsmi"
|
||||
authors = [
|
||||
{name = "AMD", email = "amd-smi.support@amd.com"},
|
||||
]
|
||||
version = '0.1'
|
||||
license = {file = "amdsmi/LICENSE"}
|
||||
readme = {file = "amdsmi/README.md", content-type = "text/markdown"}
|
||||
description = "SMI LIB - AMD GPU Monitoring Library"
|
||||
requires-python = ">=3.7"
|
||||
|
||||
[project.urls]
|
||||
"Homepage" = "https://github.com/RadeonOpenCompute/amdsmi"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["amdsmi"]
|
||||
@@ -1,16 +0,0 @@
|
||||
from setuptools import setup
|
||||
|
||||
with open("amdsmi/README.md", "r", encoding="utf-8") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setup(
|
||||
name='amdsmi',
|
||||
version='0.1',
|
||||
description="SMI LIB - AMD GPU Monitoring Library",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/markdown",
|
||||
packages=['amdsmi'],
|
||||
package_data={'': ['LICENSE']},
|
||||
include_package_data=True,
|
||||
python_requires=">=3.6",
|
||||
)
|
||||
Reference in New Issue
Block a user