Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cmake python utils #4

Merged
merged 3 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions everest-cmake-config-version.cmake
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
set(PACKAGE_VERSION 0.2.1)
set(PACKAGE_VERSION 0.3)

if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
set(PACKAGE_VERSION_EXACT TRUE)
elseif (PACKAGE_FIND_VERSION_MAJOR STREQUAL "0")
if (PACKAGE_FIND_VERSION_MINOR GREATER "2")
if (PACKAGE_FIND_VERSION_MINOR GREATER "3")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
else ()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
Expand Down
2 changes: 2 additions & 0 deletions everest-cmake-config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ if (everest_cmake_FOUND)
endif()

include("${CMAKE_CURRENT_LIST_DIR}/edm.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/python-package-helpers.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/python-virtualenv.cmake")

macro (evc_include FILE)
include("${everest-cmake_DIR}/3rd_party/${FILE}.cmake")
Expand Down
128 changes: 128 additions & 0 deletions python-package-helpers.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
function (ev_create_pip_install_dist_target)
cmake_parse_arguments(
"EV_CREATE_PIP_INSTALL_DIST_TARGET"
""
"PACKAGE_NAME"
"DEPENDS"
${ARGN}
)

add_custom_target(${EV_CREATE_PIP_INSTALL_DIST_TARGET_PACKAGE_NAME}_pip_install_dist
# Remove build dir from pip
COMMAND
${CMAKE_COMMAND} -E remove_directory build
COMMAND
${Python3_EXECUTABLE} -m pip install --force-reinstall .
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
${EV_CREATE_PIP_INSTALL_DIST_TARGET_DEPENDS}
COMMENT
"Installing ${EV_CREATE_PIP_INSTALL_DIST_TARGET_PACKAGE_NAME} from distribution"
)
endfunction()

function (ev_create_pip_install_local_target)
cmake_parse_arguments(
"EV_CREATE_PIP_INSTALL_LOCAL_TARGET"
""
"PACKAGE_NAME"
"DEPENDS"
${ARGN}
)

add_custom_target(${EV_CREATE_PIP_INSTALL_LOCAL_TARGET_PACKAGE_NAME}_pip_install_local
# Remove build dir from pip
COMMAND
${CMAKE_COMMAND} -E remove_directory build
COMMAND
${Python3_EXECUTABLE} -m pip install --force-reinstall -e .
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
${EV_CREATE_PIP_INSTALL_LOCAL_TARGET_DEPENDS}
COMMENT
"Installing ${EV_CREATE_PIP_INSTALL_LOCAL_TARGET_PACKAGE_NAME} via user-mode from build"
)
endfunction()

function(ev_create_pip_install_targets)
cmake_parse_arguments(
"EV_CREATE_PIP_INSTALL_TARGETS"
""
"PACKAGE_NAME"
"DIST_DEPENDS;LOCAL_DEPENDS"
${ARGN}
)
ev_create_pip_install_dist_target(
PACKAGE_NAME ${EV_CREATE_PIP_INSTALL_TARGETS_PACKAGE_NAME}
DEPENDS ${EV_CREATE_PIP_INSTALL_TARGETS_DIST_DEPENDS}
)
ev_create_pip_install_local_target(
PACKAGE_NAME ${EV_CREATE_PIP_INSTALL_TARGETS_PACKAGE_NAME}
DEPENDS ${EV_CREATE_PIP_INSTALL_TARGETS_LOCAL_DEPENDS}
)
endfunction()

function (ev_create_python_wheel_targets)
cmake_parse_arguments(
"EV_CREATE_PYTHON_WHEEL_TARGETS"
""
"PACKAGE_NAME"
"DEPENDS;INSTALL_PREFIX"
${ARGN}
)

if (NOT DEFINED ${EV_CREATE_PYTHON_WHEEL_TARGETS_INSTALL_PREFIX})
if ("${${PROJECT_NAME}_WHEEL_INSTALL_PREFIX}" STREQUAL "")
message(FATAL_ERROR
"No install prefix for wheel specified, please set ${PROJECT_NAME}_WHEEL_INSTALL_PREFIX, use the INSTALL_PREFIX argument or use macro ev_setup_cmake_variables_python_wheel() to set a default value."
)
else()
set(EV_CREATE_PYTHON_WHEEL_TARGETS_INSTALL_PREFIX ${${PROJECT_NAME}_WHEEL_INSTALL_PREFIX})
endif()
endif()

set(WHEEL_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/dist)
add_custom_target(${EV_CREATE_PYTHON_WHEEL_TARGETS_PACKAGE_NAME}_build_wheel
# Remove build dir from pip
COMMAND
${CMAKE_COMMAND} -E remove_directory build
COMMAND
${Python3_EXECUTABLE} -m build --wheel --outdir ${WHEEL_OUTDIR} .
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
${EV_CREATE_PYTHON_WHEEL_TARGETS_DEPENDS}
COMMENT
"Building wheel for ${EV_CREATE_PYTHON_WHEEL_TARGETS_PACKAGE_NAME}"
)

add_custom_target(${EV_CREATE_PYTHON_WHEEL_TARGETS_PACKAGE_NAME}_install_wheel
COMMAND
${CMAKE_COMMAND} -E make_directory ${EV_CREATE_PYTHON_WHEEL_TARGETS_INSTALL_PREFIX}
COMMAND
${CMAKE_COMMAND} -E copy_directory ${WHEEL_OUTDIR} ${EV_CREATE_PYTHON_WHEEL_TARGETS_INSTALL_PREFIX}/
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS
${EV_CREATE_PYTHON_WHEEL_TARGETS_PACKAGE_NAME}_build_wheel
COMMENT
"Copy wheel for ${EV_CREATE_PYTHON_WHEEL_TARGETS_PACKAGE_NAME} to ${EV_CREATE_PYTHON_WHEEL_TARGETS_INSTALL_PREFIX}"
)
endfunction()

macro(ev_setup_cmake_variables_python_wheel)
set(${PROJECT_NAME}_WHEEL_INSTALL_PREFIX "" CACHE PATH "Path to install python wheels to")
if (${PROJECT_NAME}_WHEEL_INSTALL_PREFIX STREQUAL "")
if(${WHEEL_INSTALL_PREFIX})
set(${PROJECT_NAME}_DEFAULT_WHEEL_INSTALL_PREFIX "${WHEEL_INSTALL_PREFIX}")
message(STATUS "${PROJET_NAME}_WHEEL_INSTALL_PREFIX not set, using default: WHEEL_INSTALL_PREFIX=${${PROJECT_NAME}_DEFAULT_WHEEL_INSTALL_PREFIX}")
else()
set(${PROJECT_NAME}_DEFAULT_WHEEL_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/../dist-wheels")
message(STATUS "${PROJECT_NAME}_WHEEL_INSTALL_PREFIX not set, using default: \${CMAKE_INSTALL_PREFIX}/../dist-wheels=${${PROJECT_NAME}_DEFAULT_WHEEL_INSTALL_PREFIX}")
endif()
set(${PROJECT_NAME}_WHEEL_INSTALL_PREFIX "${${PROJECT_NAME}_DEFAULT_WHEEL_INSTALL_PREFIX}" CACHE PATH "Path to install python wheels to" FORCE)
endif()
message(STATUS "${PROJECT_NAME}_WHEEL_INSTALL_PREFIX=${${PROJECT_NAME}_WHEEL_INSTALL_PREFIX}")
endmacro()
143 changes: 143 additions & 0 deletions python-virtualenv.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
macro(ev_create_python_venv)
cmake_parse_arguments(
"EV_CREATE_PYTHON_VENV"
"INCLUDE_SYSTEM_SITE_PACKAGES"
"PATH_TO_VENV"
""
${ARGN}
)
ev_is_directory_python_venv(
DIRECTORY "${EV_CREATE_PYTHON_VENV_PATH_TO_VENV}"
RESULT_VAR "EV_CREATE_PYTHON_VENV_IS_DIRECTORY_PYTHON_VENV"
)
if(${EV_CREATE_PYTHON_VENV_IS_DIRECTORY_PYTHON_VENV})
message(FATAL_ERROR "Directory is already a python venv: ${EV_CREATE_PYTHON_VENV_PATH_TO_VENV}")
endif()
find_package(Python3
REQUIRED
COMPONENTS
Interpreter
Development
)
set(EV_CREATE_PYTHON_VENV_SYSTEM_SITE_PACKAGES_FLAG "")
if(${EV_CREATE_PYTHON_VENV_INCLUDE_SYSTEM_SITE_PACKAGES})
set(EV_CREATE_PYTHON_VENV_SYSTEM_SITE_PACKAGES_FLAG "--system-site-packages")
endif()
execute_process(
COMMAND
${Python3_EXECUTABLE} -m venv ${EV_CREATE_PYTHON_VENV_SYSTEM_SITE_PACKAGES_FLAG} ${EV_CREATE_PYTHON_VENV_PATH_TO_VENV}
)
message(STATUS "Created python venv: ${EV_CREATE_PYTHON_VENV_PATH_TO_VENV}")
endmacro()

macro(ev_activate_python_venv)
cmake_parse_arguments(
"EV_ACTIVATE_PYTHON_VENV"
""
"PATH_TO_VENV"
""
${ARGN}
)
ev_is_directory_python_venv(
DIRECTORY "${EV_ACTIVATE_PYTHON_VENV_PATH_TO_VENV}"
RESULT_VAR "EV_CREATE_PYTHON_VENV_IS_DIRECTORY_PYTHON_VENV"
)
if(NOT ${EV_CREATE_PYTHON_VENV_IS_DIRECTORY_PYTHON_VENV})
message(FATAL_ERROR "Directory is not a python venv: ${EV_ACTIVATE_PYTHON_VENV_PATH_TO_VENV}")
endif()
set(ENV{VIRTUAL_ENV} "${EV_ACTIVATE_PYTHON_VENV_PATH_TO_VENV}")
set(Python3_FIND_VIRTUALENV FIRST)
unset(Python3_EXECUTABLE)
find_package(Python3
REQUIRED
COMPONENTS
Interpreter
Development
)
message(STATUS "Activated python venv: Python3_EXECUTABLE: ${Python3_EXECUTABLE}")
endmacro()

macro(ev_deactivate_python_venv)
unset(ENV{VIRTUAL_ENV})
unset(Python3_EXECUTABLE)
set(Python3_FIND_VIRTUALENV STANDARD)
find_package(Python3
REQUIRED
COMPONENTS
Interpreter
Development
)
message(STATUS "Deactivated python venv: Python3_EXECUTABLE: ${Python3_EXECUTABLE}")
endmacro()

function(ev_is_directory_python_venv)
cmake_parse_arguments(
"EV_IS_DIRECTORY_PYTHON_VENV"
""
"DIRECTORY;RESULT_VAR"
""
${ARGN}
)
message(DEBUG "Checking if directory is a python venv: ${EV_IS_DIRECTORY_PYTHON_VENV_DIRECTORY}")
if(EXISTS "${EV_IS_DIRECTORY_PYTHON_VENV_DIRECTORY}/pyvenv.cfg")
message(DEBUG "Directory is a python venv: ${EV_IS_DIRECTORY_PYTHON_VENV_DIRECTORY}")
set(${EV_IS_DIRECTORY_PYTHON_VENV_RESULT_VAR} TRUE PARENT_SCOPE)
return()
else()
message(DEBUG "Directory is not a python venv: ${EV_IS_DIRECTORY_PYTHON_VENV_DIRECTORY}")
set(${EV_IS_DIRECTORY_PYTHON_VENV_RESULT_VAR} FALSE PARENT_SCOPE)
return()
endif()
endfunction()

function(ev_is_python_venv_active)
cmake_parse_arguments(
"EV_IS_PYTHON_VENV_ACTIVE"
""
"RESULT_VAR"
""
${ARGN}
)
if(DEFINED ENV{VIRTUAL_ENV})
message(DEBUG "Python venv is active: $ENV{VIRTUAL_ENV}")
set(${EV_IS_PYTHON_VENV_ACTIVE_RESULT_VAR} TRUE PARENT_SCOPE)
return()
else()
message(DEBUG "Python venv is not active")
set(${EV_IS_PYTHON_VENV_ACTIVE_RESULT_VAR} FALSE PARENT_SCOPE)
return()
endif()
endfunction()

macro(ev_setup_python_executable)
cmake_parse_arguments(
"EV_SETUP_PYTHON_EXECUTABLE"
""
"USE_PYTHON_VENV;PYTHON_VENV_PATH"
""
${ARGN}
)
if(NOT ${EV_SETUP_PYTHON_EXECUTABLE_USE_PYTHON_VENV})
find_package(Python3
REQUIRED
COMPONENTS
Interpreter
Development
)
else()
message(STATUS "Using python venv: ${${PROJECT_NAME}_PYTHON_VENV_PATH}")
ev_is_directory_python_venv(
DIRECTORY ${${PROJECT_NAME}_PYTHON_VENV_PATH}
RESULT_VAR IS_DIRECTORY_PYTHON_VENV
)
if(NOT ${IS_DIRECTORY_PYTHON_VENV})
ev_create_python_venv(
PATH_TO_VENV
"${${PROJECT_NAME}_PYTHON_VENV_PATH}"
INCLUDE_SYSTEM_SITE_PACKAGES
)
endif()
ev_activate_python_venv(PATH_TO_VENV "${${PROJECT_NAME}_PYTHON_VENV_PATH}")
endif()
message(STATUS "Set up python executable with Python3_EXECUTABLE=${Python3_EXECUTABLE}")
endmacro()