1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
|
# SPDX-FileCopyrightInfo: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
# SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
# This cmake module provides infrastructure for cmake installation rules concerning python packages.
#
# .. cmake_function:: dune_python_configure_dependencies
#
# .. cmake_param:: PATH
# :required:
# :single:
#
# Path to the python package source code containing a valid setup.py file.
# In case of a relative path, it will be evaluated with respect to the :CMAKE_CURRENT_SOURCE_DIR:.
#
# .. cmake_param:: RESULT
# :single:
#
# Variable where to store the result of the dependency configuration.
# A non-zero result stands for a failure on the configuration of the dependencies.
#
# .. cmake_param:: INSTALL_CONCRETE_DEPENDENCIES
# :option:
#
# This option forces the package dependencies to be installed with concrete dependencies
# listed in the requirements.txt file
#
# This function installs the dependencies of a python package at configure time.
# The dependencies are extracted from the :setup.py: and :requiements.txt: file
# A failure on the installation of the dependencies does will no trigger a
# CMake fatal error but it will be reflected on the :RESULT: variable.
#
#
# .. cmake_function:: dune_link_dune_py
#
# .. cmake_param:: PATH
# :required:
# :single:
#
# Absolute path to the python package source code where to generate metadata.
#
# .. cmake_param:: INSTALL_TARGET
# :required:
# :single:
#
# Name of the target that generates the package metadata and triggers the :dune-py:
# module configuration at installation time. This target will only be generated if
# the build system is setup to install python packages :ref:`DUNE_PYTHON_INSTALL_LOCATION`.
#
# .. cmake_param:: CMAKE_METADATA_FLAGS
# :multi:
#
# A list of cmake flags to add to meta data file. For each flag given
# an entry of the form "flagname:=value" is added. These flags are
# then set in the CMakeLists.txt file of a generated dune-py module.
#
# This function generates the metadata required for Python package in order to be
# used by the dune-py module. It essentially glues together python code generation
# of dune-py (via CMake) with a python package. This is achiieved by generating a
# filename that CMake should export some meta data about this build to.
# The file will be installed together with the Python package. This mechanism
# is used by the Python bindings to transport information from CMake to
# the installed Python package. A module dune-mymodule that provides a Python
# package dune.mymodule should set this to dune/mymodule/metadata.cmake
#
# For historic reasons, this function installs the package at configure time rather than at
# build time. This distinction is important because it means that the package dependencies
# will be available to be used during configuration time.
#
# .. cmake_function:: dune_python_configure_package
#
# .. cmake_param:: PATH
# :required:
# :single:
#
# Path to the python package. In case of a relative path, it will be
# evaluated with respect to the :CMAKE_CURRENT_SOURCE_DIR:.
#
# .. cmake_param:: INSTALL_TARGET
# :single:
#
# Name of the target that installs the package on the install directory.
#
# .. cmake_param:: RESULT
# :single:
#
# Variable where to store the result of the package configuration.
# A non-zero result stands for a failure on the configuration of the package.
#
# .. cmake_param:: ADDITIONAL_PIP_PARAMS
# :multi:
# :argname: param
#
# Parameters to add to any :code:`pip install` call (appended).
#
# .. cmake_param:: INSTALL_CONCRETE_DEPENDENCIES
# :option:
#
# See :dune_python_configure_dependencies:
#
# This function installs the python package located at the given path:
#
# * installs it to the location specified with :ref:`DUNE_PYTHON_INSTALL_LOCATION` during
# :code:`make install_python` and during :code:`make install`.
# * installs a wheel into the Dune wheelhouse during :code:`make install`.
# This is necessary for mixing installed and non-installed Dune modules.
#
# The package at the given location is expected to be a pip-installable package.
# This function installs the package at configure time. This distinction is
# important because it means that the package will be available to be used during
# other CMake configureation tasks.
#
#
#
# .. cmake_function:: dune_python_configure_bindings
#
# .. cmake_param:: PATH
# :required:
# :single:
#
# Relative path to the given python package source code.
#
# .. cmake_param:: PACKAGENAME
# :single:
#
# Name of the python package.
#
# .. cmake_param:: ADDITIONAL_PIP_PARAMS
# :multi:
# :argname: param
#
# Parameters to add to any :code:`pip install` call (appended).
#
# .. cmake_param:: CMAKE_METADATA_FLAGS
# :multi:
#
# A list of cmake flags to add to meta data file. For each flag given
# an entry of the form "flagname:=value" is added. These flags are
# then set in the CMakeLists.txt file of a generated dune-py module.
#
# This is a convenience function that performs the tasks of
# :dune_python_configure_dependencies:, :dune_link_dune_py:, and :dune_python_configure_package:.
# Additionally, it makes sure that a 'setup.py' is available with the following procedure:
#
# 1. If PATH contains a `setup.py` file, such file will be used to make a `pip install` from the source directory
# 2. If PATH contains a `setup.py.in` file, such file will be configured and used to `pip install` the package from the binary directory
# 3. Otherwise, this script will provide a template for `setup.py.in` and continue with 2.
#
# .. cmake_function:: dune_python_install_package
#
# This function is deprecated, use :dune_python_configure_bindings: or
# :dune_python_configure_package: according to the needed behavior.
#
# .. cmake_variable:: DUNE_PYTHON_ADDITIONAL_PIP_PARAMS
#
# Use this variable to set additional flags for pip in this build. This can e.g.
# be used to point pip to alternative package indices in restricted environments.
#
include_guard(GLOBAL)
function(dune_python_configure_dependencies)
# Parse Arguments
set(OPTION)
set(SINGLE PATH RESULT INSTALL_CONCRETE_DEPENDENCIES)
cmake_parse_arguments(PYCONFDEPS "${OPTION}" "${SINGLE}" "${MULTI}" ${ARGN})
if(PYCONFDEPS_UNPARSED_ARGUMENTS)
message(WARNING "Unparsed arguments in dune_python_configure_dependencies: This often indicates typos!")
endif()
# Check for the presence of the pip package
if(NOT DUNE_PYTHON_pip_FOUND)
message(WARNING "dune_python_configure_dependencies: Requested installations, but pip was not found!")
set(DUNE_PYTHON_VENVSETUP FALSE CACHE BOOL "The internal venv setup failed due to missing pip")
return()
endif()
if(NOT IS_ABSOLUTE "${PYCONFDEPS_PATH}")
set(PYCONFDEPS_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PYCONFDEPS_PATH}")
endif()
if(NOT EXISTS "${PYCONFDEPS_PATH}/setup.py")
message(FATAL_ERROR "Directory '${PYCONFDEPS_PATH}' does not contain a configuration file 'setup.py'")
endif()
if(IS_DIRECTORY ${DUNE_PYTHON_WHEELHOUSE})
set(WHEEL_OPTION "--find-links=file://${DUNE_PYTHON_WHEELHOUSE}")
endif()
if(PYCONFDEPS_INSTALL_CONCRETE_DEPENDENCIES)
# if requirements file exists, install them directly
message(STATUS "Installing python package concrete requirements at ${PYPKGCONF_PATH}/requirements.txt")
# Install requirements (e.g. not dune packages) once at configure stage
dune_execute_process(COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pip install
"${WHEEL_OPTION}"
# we can't use the same additional parameters for both internal
# install and normal install so not including these flags at the moment
"${DUNE_PIP_INDEX}" # stopgap solution until ci repo fixed
-r requirements.txt
WORKING_DIRECTORY "${PYCONFDEPS_PATH}"
RESULT_VARIABLE INSTALL_FAILED
ERROR_VARIABLE DEPENDENCIES_ERROR
WARNING_MESSAGE "python package requirements could not be installed - possibly connection to the python package index failed\n${DEPENDENCIES_ERROR}"
)
if(NOT OPTIONAL_PACKAGE)
if(INSTALL_FAILED)
set(${PYCONFDEPS_RESULT} ${INSTALL_FAILED} PARENT_SCOPE)
set(DUNE_PYTHON_VENVSETUP FALSE CACHE BOOL "The internal venv setup failed: some required packages could not be installed")
return()
else()
set(DUNE_PYTHON_VENVSETUP TRUE CACHE BOOL "The internal venv setup successful")
endif()
endif()
endif()
# generate egg_info requirement file from setup.py
string(MD5 PACKAGE_HASH "${PYCONFDEPS_PATH}")
set(EGG_INFO_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_HASH}")
file(MAKE_DIRECTORY "${EGG_INFO_PATH}")
dune_execute_process(COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} setup.py
egg_info --egg-base "${EGG_INFO_PATH}"
WORKING_DIRECTORY "${PYCONFDEPS_PATH}"
RESULT_VARIABLE REQUIREMENTS_FAILED
ERROR_VARIABLE DEPENDENCIES_ERROR
WARNING_MESSAGE "python package requirements could not be generated\n${DEPENDENCIES_ERROR}"
)
if(REQUIREMENTS_FAILED)
set(${PYCONFDEPS_RESULT} ${REQUIREMENTS_FAILED} PARENT_SCOPE)
set(DUNE_PYTHON_VENVSETUP FALSE CACHE BOOL "The internal venv setup failed: some required packages could not be installed")
return()
else()
set(DUNE_PYTHON_VENVSETUP TRUE CACHE BOOL "The internal venv setup successful")
endif()
# find the generated egg-info folder and install each dependency listed on the requires.txt file
file(GLOB EGG_INFO_PATH LIST_DIRECTORIES TRUE "${EGG_INFO_PATH}/*.egg-info")
if(EXISTS "${EGG_INFO_PATH}/requires.txt")
file(READ "${EGG_INFO_PATH}/requires.txt" PACKAGE_REQUIREMENTS)
string(REPLACE "\n" ";" PACKAGE_REQUIREMENTS ${PACKAGE_REQUIREMENTS})
string(REPLACE ";" " " PACKAGE_REQUIREMENTS_STR "${PACKAGE_REQUIREMENTS}")
message(STATUS "Installing python package abstract requirements: " ${PACKAGE_REQUIREMENTS_STR})
foreach(requirement IN LISTS PACKAGE_REQUIREMENTS)
if("${requirement}" STREQUAL "")
continue()
endif()
if (requirement MATCHES "^\\[")
# sections (e.g. "[<section>]") in setuptools define the start of optional requirements
set(OPTIONAL_PACKAGE ON)
set(PYCONFDEPS_OPT "(optional) ")
continue()
endif()
# Install requirements (e.g. not dune packages) once at configure stage
dune_execute_process(COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pip install
"${WHEEL_OPTION}"
# we can't use the same additional parameters for both internal
# install and normal install so not including these flags at the moment
"${DUNE_PIP_INDEX}" # stopgap solution until ci repo fixed
"${requirement}"
RESULT_VARIABLE INSTALL_FAILED
ERROR_VARIABLE DEPENDENCIES_ERROR
WARNING_MESSAGE "Python ${PYCONFDEPS_OPT}package requirement '${requirement}' could not be installed - possibly connection to the python package index failed\n${DEPENDENCIES_ERROR}"
)
if(NOT OPTIONAL_PACKAGE)
if(INSTALL_FAILED)
set(${PYCONFDEPS_RESULT} ${INSTALL_FAILED} PARENT_SCOPE)
set(DUNE_PYTHON_VENVSETUP FALSE CACHE BOOL "The internal venv setup failed: some required packages could not be installed")
return()
else()
set(DUNE_PYTHON_VENVSETUP TRUE CACHE BOOL "The internal venv setup successful")
endif()
endif()
endforeach()
endif()
set(${PYCONFDEPS_RESULT} 0 PARENT_SCOPE)
endfunction()
function(dune_link_dune_py)
# Parse Arguments
set(OPTION)
set(SINGLE PATH INSTALL_TARGET PACKAGENAME)
set(MULTI CMAKE_METADATA_FLAGS)
cmake_parse_arguments(LINKDUNEPY "${OPTION}" "${SINGLE}" "${MULTI}" ${ARGN})
if(LINKDUNEPY_UNPARSED_ARGUMENTS)
message(WARNING "Unparsed arguments in dune_python_install_package: This often indicates typos!")
endif()
# check the package name argument
if("${LINKDUNEPY_PACKAGENAME}" STREQUAL "")
message(FATAL_ERROR "PACKAGENAME cannot be empty!")
endif()
# set the meta data file path for this package
set(LINKDUNEPY_CMAKE_METADATA_FILE "${LINKDUNEPY_PACKAGENAME}/data/${ProjectName}.cmake")
# Locate the cmake/scripts directory of dune-common
dune_module_path(MODULE dune-common
RESULT scriptdir
SCRIPT_DIR)
if(NOT IS_ABSOLUTE "${LINKDUNEPY_PATH}")
message(FATAL_ERROR "'PATH=${LINKDUNEPY_PATH}' argument is not an absulte path")
endif()
if(NOT EXISTS "${LINKDUNEPY_PATH}/setup.py")
message(Warning "Directory '${LINKDUNEPY_PATH}' does not contain a configuration file 'setup.py'. Link for dune-py module may not work properly")
endif()
# Add the metadata file to MANIFEST.in to enable its installation
file(
APPEND "${LINKDUNEPY_PATH}/MANIFEST.in"
"include ${LINKDUNEPY_CMAKE_METADATA_FILE}\n"
)
# Determine full path of the meta data file
set(metadatafile ${LINKDUNEPY_PATH}/${LINKDUNEPY_CMAKE_METADATA_FILE})
# Collect some variables that we would like to export
set(_deps ${ProjectName})
set(_export_builddirs "${CMAKE_BINARY_DIR}")
foreach(mod ${ALL_DEPENDENCIES})
string(APPEND _deps " ${mod}")
string(APPEND _export_builddirs "\;${${mod}_DIR}")
endforeach()
# add the list of HAVE_{MODULE} flags to the meta data
set(_cmake_flags "")
foreach(_dep ${ProjectName} ${ALL_DEPENDENCIES})
dune_module_to_uppercase(upper ${_dep})
if(DEFINED HAVE_${upper})
list(APPEND _cmake_flags "HAVE_${upper}:=${HAVE_${upper}}")
endif()
endforeach()
# automatically add DUNE_OPTS_FILE
list(APPEND _cmake_flags "DUNE_OPTS_FILE:=${DUNE_OPTS_FILE}")
# handle all manually added flags
foreach(flags_loop IN ITEMS ${LINKDUNEPY_CMAKE_METADATA_FLAGS})
if(${flags_loop})
set(value ${${flags_loop}})
# need to make sure not to use the script generated by the CXX_OVERWRITE
# because dune-py should not depend on a file in the build dir
if(DEFINED DEFAULT_CXX_COMPILER AND "${flags_loop}" STREQUAL "CMAKE_CXX_COMPILER")
set(value "${DEFAULT_CXX_COMPILER}")
endif()
if(DEFINED DEFAULT_CXXFLAGS AND "${flags_loop}" STREQUAL "CMAKE_CXX_FLAGS")
set(value "${DEFAULT_CXXFLAGS}")
endif()
list(APPEND _cmake_flags "${flags_loop}:=\"${value}\"")
endif()
endforeach()
# transform the list into an escaped string
string(REPLACE ";" "<SEP>" _cmake_flags "${_cmake_flags}")
#
# Generate metadata - note that there is a metadata target for the
# build stage and one for the install stage so changes need to be made
# to both.
#
# check consistency of the builddir when using an external venv
if(DUNE_PYTHON_SYSTEM_IS_VIRTUALENV)
message(STATUS "Checking if the modules used to confiugre this module match those from any installed dune packages")
dune_execute_process(COMMAND "${CMAKE_COMMAND}" -E echo "configured for interpreter ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE}"
COMMAND "${DUNE_PYTHON_VIRTUALENV_EXECUTABLE}" "${scriptdir}/checkvenvconf.py"
checkbuilddirs \"${PROJECT_NAME};${ALL_DEPENDENCIES}\" "${_export_builddirs}"
)
endif()
# Make sure to generate the metadata for the build stage
# Issue: parameter forwarding fails when using dune_execute_process so
# reverting to 'execute_process' for now. Alternative would be to extra escape the ';':
# e.g. string(REPLACE ";" "\\\\\\\;" _export_builddirs # "${_export_builddirs}")
# and the same for the DEPS argument.
if(SKBUILD)
# this is the only version of the metadata we need for the package installation
message(STATUS "Generating the CMake metadata file at ${LINKDUNEPY_CMAKE_METADATA_FILE}")
execute_process(
COMMAND ${CMAKE_COMMAND}
-Dmetadatafile=${metadatafile}
-DDEPS=${_deps}
-DMODULENAME=${PROJECT_NAME}
-DCMAKE_FLAGS=${_cmake_flags}
-P ${scriptdir}/WritePythonCMakeMetadata.cmake
)
# don't need an 'install' target for the metadata since we can use the build version
# but we need to make sure that skbuild correctly installs the
# existing metadata file into the site-package
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LINKDUNEPY_CMAKE_METADATA_FILE} DESTINATION python/dune/data)
else()
# this is the build version - keep in mind there is an install version further down
message(STATUS "Generating the CMake metadata file at ${LINKDUNEPY_CMAKE_METADATA_FILE}")
execute_process(
COMMAND ${CMAKE_COMMAND}
-Dmetadatafile=${metadatafile}
-DDEPBUILDDIRS=${_export_builddirs}
-DDEPS=${_deps}
-DMODULENAME=${PROJECT_NAME}
-DCMAKE_FLAGS=${_cmake_flags}
-DINSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-P ${scriptdir}/WritePythonCMakeMetadata.cmake
)
# WARNING_MESSAGE "Writing metadata failed"
if(NOT "${DUNE_PYTHON_INSTALL_LOCATION}" STREQUAL "none")
add_custom_target(
metadata_${LINKDUNEPY_INSTALL_TARGET}
COMMAND ${CMAKE_COMMAND}
-Dmetadatafile=${metadatafile}
-DDEPS=${_deps}
-DMODULENAME=${PROJECT_NAME}
-DCMAKE_FLAGS="${_cmake_flags}"
-DINSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-P ${scriptdir}/WritePythonCMakeMetadata.cmake
COMMENT "Generating the CMake metadata file at ${LINKDUNEPY_CMAKE_METADATA_FILE}"
)
endif()
endif()
# Trigger the configuration of dune-py
dune_execute_process(COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m dune configure)
# Add a custom command that triggers the configuration of dune-py when installing package
if(NOT "${DUNE_PYTHON_INSTALL_LOCATION}" STREQUAL "none")
dune_execute_process(COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m dune configure)
endif()
endfunction()
function(dune_python_configure_package)
# Parse Arguments
set(SINGLE PATH RESULT INSTALL_TARGET INSTALL_CONCRETE_DEPENDENCIES)
set(MULTI ADDITIONAL_PIP_PARAMS)
cmake_parse_arguments(PYPKGCONF "${OPTION}" "${SINGLE}" "${MULTI}" ${ARGN})
if(PYPKGCONF_UNPARSED_ARGUMENTS)
message(WARNING "Unparsed arguments in dune_python_install_package: This often indicates typos!")
endif()
if(NOT IS_ABSOLUTE "${PYPKGCONF_PATH}")
set(PYPKGCONF_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${PYPKGCONF_PATH})
endif()
dune_python_configure_dependencies(
PATH ${PYPKGCONF_PATH}
RESULT PYTHON_DEPENDENCIES_FAILED
${PYPKGCONF_INSTALL_CONCRETE_DEPENDENCIES}
)
if (PYTHON_DEPENDENCIES_FAILED)
set(${PYPKGCONF_RESULT} ${PYTHON_DEPENDENCIES_FAILED} PARENT_SCOPE)
return()
endif()
if(IS_DIRECTORY ${DUNE_PYTHON_WHEELHOUSE})
set(WHEEL_OPTION "--find-links=file://${DUNE_PYTHON_WHEELHOUSE}")
endif()
# installation command for dune package into local env - external requirements are already sorted and we want this step to not require
# internet access. Dune packages need to be installed at this stage and should not be obtained from pypi (those packages include the C++ part
# of the module which we don't want to install. So only use available wheels.
if(NOT SKBUILD)
message(STATUS "Installing python package at ${PYPKGCONF_PATH} into Dune virtual environment ${DUNE_PIP_INDEX}")
dune_execute_process(
COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pip install
--no-build-isolation # avoid looking for packages during 'make' if they in the internal venv from previous 'make'
--no-warn-script-location # suppress warnings that dune-env/bin is not in path
--no-index
"${WHEEL_OPTION}"
# we can't use the same additional parameters for both internal
# install and normal install so not including these flags at the moment
# ${PYPKGCONF_ADDITIONAL_PIP_PARAMS} ${DUNE_PYTHON_ADDITIONAL_PIP_PARAMS}
--editable # Installations into the internal env are always editable
.
WORKING_DIRECTORY "${PYPKGCONF_PATH}"
RESULT_VARIABLE PYTHON_INSTALL_FAILED
ERROR_VARIABLE PYTHON_INSTALL_ERROR
WARNING_MESSAGE "python package at '${PYPKGCONF_PATH}' could not be installed - possibly connection to the python package index failed\n${PYTHON_INSTALL_ERROR}"
)
set(${PYPKGCONF_RESULT} ${PYTHON_INSTALL_FAILED} PARENT_SCOPE)
if (PYTHON_INSTALL_FAILED)
return()
endif()
endif()
#
# Now define rules for `make install_python`.
#
# Only add installation rules if it was requested
if(NOT "${DUNE_PYTHON_INSTALL_LOCATION}" STREQUAL "none")
# Construct the installation location option string
set(USER_INSTALL_OPTION "")
if("${DUNE_PYTHON_INSTALL_LOCATION}" STREQUAL "user")
set(USER_INSTALL_OPTION "--user")
endif()
if("${DUNE_PYTHON_INSTALL_LOCATION}" MATCHES "--target")
set(USER_INSTALL_OPTION "${DUNE_PYTHON_INSTALL_LOCATION}")
endif()
# Add a custom target that globally installs this package if requested
if (NOT PYPKGCONF_INSTALL_TARGET)
string(REPLACE "/" "_" PYPKGCONF_INSTALL_TARGET "install_python_${CMAKE_CURRENT_SOURCE_DIR}_${PYPKGCONF_PATH}")
endif()
# TODO this creates an egg-info folder in the source directory
add_custom_target(${PYPKGCONF_INSTALL_TARGET}
COMMAND ${Python3_EXECUTABLE} -m pip install
"${USER_INSTALL_OPTION}"
"${DUNE_PIP_INDEX}"
# --use-feature=in-tree-build
--upgrade
"${WHEEL_OPTION}"
${PYPKGCONF_ADDITIONAL_PIP_PARAMS} ${DUNE_PYTHON_ADDITIONAL_PIP_PARAMS}
.
WORKING_DIRECTORY "${PYPKGCONF_PATH}"
COMMENT "Installing the python package at ${PYPKGCONF_PATH} (location ${USER_INSTALL_OPTION})"
)
# during package installation we don't want the package to be installed
# since skbuild takes care of that.
if(NOT SKBUILD)
add_dependencies(install_python ${PYPKGCONF_INSTALL_TARGET})
endif()
endif()
# Construct the wheel installation commandline
# TODO should the wheel be build for the internal env setup or for the external one?
set(WHEEL_COMMAND ${DUNE_PYTHON_VIRTUALENV_EXECUTABLE} -m pip wheel -w ${DUNE_PYTHON_WHEELHOUSE}
"${DUNE_PIP_INDEX}"
# --use-feature=in-tree-build
"${WHEEL_OPTION}"
${PYPKGCONF_ADDITIONAL_PIP_PARAMS} ${DUNE_PYTHON_ADDITIONAL_PIP_PARAMS}
"${PYPKGCONF_PATH}")
#
# Have make install do the same as make install_python plus
# install a wheel into a central wheelhouse
# NB: This is necessary, to allow mixing installed and non-installed modules
# with python packages. The wheelhouse will allow to install any missing
# python packages into a virtual environment.
#
if(NOT SKBUILD)
install(CODE "set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
set(DUNE_PYTHON_WHEELHOUSE ${DUNE_PYTHON_WHEELHOUSE})
include(DuneExecuteProcess)
message(\"Installing python package\")
dune_execute_process(COMMAND \"${CMAKE_COMMAND}\" --build . --target install_python --config $<CONFIG>
WARNING_MESSAGE \"python package installation failed - ignored\")
message(\"Installing wheel for python package at ${PYPKGCONF_PATH} into ${DUNE_PYTHON_WHEELHOUSE}...\")
dune_execute_process(COMMAND ${WHEEL_COMMAND}
WARNING_MESSAGE \"wheel installation failed - ignored\")"
)
endif()
endfunction()
function(dune_python_configure_bindings)
# Parse Arguments
set(SINGLE PATH PACKAGENAME)
set(MULTI ADDITIONAL_PIP_PARAMS CMAKE_METADATA_FLAGS)
cmake_parse_arguments(PYCONFBIND "${OPTION}" "${SINGLE}" "${MULTI}" ${ARGN})
if(PYCONFBIND_UNPARSED_ARGUMENTS)
message(WARNING "Unparsed arguments in dune_python_configure_bindings: This often indicates typos!")
endif()
# set the new package name
if("${PYCONFBIND_PACKAGENAME}" STREQUAL "")
set(PYCONFBIND_PACKAGENAME "dune")
endif()
if ("${DUNE_BINDINGS_PACKAGENAME}" STREQUAL "")
set(DUNE_BINDINGS_PACKAGENAME ${PYCONFBIND_PACKAGENAME})
else()
message(FATAL_ERROR "DUNE Python bindings can only be configured once per project!")
endif()
if(IS_ABSOLUTE "${PYCONFBIND_PATH}")
message(FATAL_ERROR "'PATH=${PYCONFBIND_PATH}' is not a relative path")
endif()
# try to find setup.py. if not found, provide it from a template
set(PYCONFBIND_FULLPATH ${CMAKE_CURRENT_SOURCE_DIR}/${PYCONFBIND_PATH})
if(NOT EXISTS ${PYCONFBIND_FULLPATH}/setup.py)
# 'RequiredPythonModules' is added to the builddir/python/setup.py.in
# This also contains the dependent dune modules which can be available
# in the dune wheelhouse (e.g. used in the nightly-build)
set(RequiredPythonModules "${ProjectPythonRequires}")
foreach(mod ${ALL_DEPENDENCIES})
if(${${mod}_HASPYTHON}) # module found and has python bindings
string(APPEND RequiredPythonModules " ${mod}")
endif()
endforeach()
# Configure setup.py.in if present
if(EXISTS ${PYCONFBIND_FULLPATH}/setup.py.in)
configure_file(${PYCONFBIND_PATH}/setup.py.in ${PYCONFBIND_PATH}/setup.py)
set(PYCONFBIND_FULLPATH ${CMAKE_CURRENT_BINARY_DIR}/${PYCONFBIND_PATH})
else()
configure_file(${scriptdir}/setup.py.in ${PYCONFBIND_PATH}/setup.py)
set(PYCONFBIND_FULLPATH ${CMAKE_CURRENT_BINARY_DIR}/${PYCONFBIND_PATH})
endif()
endif()
if(NOT EXISTS ${PYCONFBIND_FULLPATH})
message(FATAL_ERROR "dune_python_install_package: ${PYCONFBIND_FULLPATH} does not exists")
endif()
dune_python_configure_package(
PATH ${PYCONFBIND_FULLPATH}
ADDITIONAL_PIP_PARAMS ${PYCONFBIND_ADDITIONAL_PIP_PARAMS}
RESULT PYTHON_PACKAGE_FAILED
INSTALL_TARGET install_python_package_${PYCONFBIND_PACKAGENAME}
)
# we could actually add metadata even if the configuration of the venv
# failed - some people set the PYTHON_PATH env variable instead of using
# a venv.
# At the moment the metadata is added to target that only exists if
# configuration succeeded. When moving to pure configure time this could
# be changed.
if(NOT PYTHON_PACKAGE_FAILED)
dune_link_dune_py(
PATH ${CMAKE_CURRENT_BINARY_DIR}/${PYCONFBIND_PATH}
PACKAGENAME ${PYCONFBIND_PACKAGENAME}
INSTALL_TARGET install_python_package_${PYCONFBIND_PACKAGENAME}
CMAKE_METADATA_FLAGS ${PYCONFBIND_CMAKE_METADATA_FLAGS}
)
else()
message(WARNING "python binding configuration failed - no linking done")
endif()
endfunction()
function(dune_python_install_package)
# Parse Arguments
set(SINGLE PATH PACKAGENAME)
set(MULTI ADDITIONAL_PIP_PARAMS DEPENDS CMAKE_METADATA_FLAGS)
cmake_parse_arguments(PYINST "${OPTION}" "${SINGLE}" "${MULTI}" ${ARGN})
if(PYINST_UNPARSED_ARGUMENTS)
message(WARNING "Unparsed arguments in dune_python_install_package: This often indicates typos!")
endif()
message(DEPRECATION "This function is deprecated. Use 'dune_python_configure_bindings' for python binding packages or 'dune_python_configure_package' for installable python packages")
if(PYINST_DEPENDS)
message(DEPRECATION "Argument DEPENDS is deprecated and will be ignored!")
endif()
dune_python_configure_bindings(
PATH ${PYINST_PATH}
PACKAGENAME ${PYINST_PACKAGENAME}
ADDITIONAL_PIP_PARAMS ${PYINST_ADDITIONAL_PIP_PARAMS}
CMAKE_METADATA_FLAGS ${PYINST_CMAKE_METADATA_FLAGS}
INSTALL_TARGET install_python_package_${PYINST_PACKAGENAME}
)
endfunction()
|