Skip to content
Snippets Groups Projects
Unverified Commit eb41756a authored by Nick Draper's avatar Nick Draper Committed by GitHub
Browse files

Merge pull request #26742 from martyngigg/python-pkg-install-rules

Fix add_python_package for mantid package 
parents 7fcfd176 08bef95c
No related branches found
No related tags found
No related merge requests found
......@@ -107,7 +107,8 @@
0,
1,
2,
3
3,
4
],
"enable_markup": true,
"first_comment_is_literal": false,
......
......@@ -112,7 +112,13 @@ add_subdirectory(mantid)
include ( PythonPackageTargetFunctions )
# Adds `mantid` as a target in the `MantidFramework/Python` folder
add_python_package ( PythonInterface EGGLINKNAME mantid )
if(APPLE)
set(_install_lib_dirs "${LIB_DIR};${WORKBENCH_LIB_DIR}")
else()
set(_install_lib_dirs "${WORKBENCH_LIB_DIR}")
endif()
add_python_package ( PythonInterface EGGLINKNAME mantid
INSTALL_LIB_DIRS ${_install_lib_dirs} )
set_property ( TARGET PythonInterface PROPERTY FOLDER "MantidFramework/Python" )
add_dependencies ( PythonInterface PythonInterfaceCore PythonKernelModule
PythonGeometryModule PythonAPIModule PythonDataObjectsModule
......
......@@ -14,7 +14,7 @@ from setuptools import find_packages, setup
setup(
name='mantid',
version='@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@',
packages=find_packages(exclude=['*.test']),
packages=find_packages(exclude=['*.test', 'plugins*']),
package_data={'': ['*.ui']},
@SETUPTOOLS_BUILD_COMMANDS_USE@
)
# Defines functions to help deal with python packages
# ~~~
# Function to create links to python packages in the source tree
# Optional keyword arguments:
# - EXECUTABLE: If this option provided then it is assumed the package contains a
......@@ -7,16 +8,23 @@
# directory
# - EGGLINKNAME: Pass in a new name for the egg link, e.g. EGGLINKNAME mylink,
# creates a new egg link called mylink
# - INSTALL_LIB_DIRS: A list of install directories.
# - INSTALL_BIN_DIR: Destination for an executable to be installed
# - EXCLUDE_ON_INSTALL: Specifies a regex of files to exclude from the install
# - command
function ( add_python_package pkg_name )
# ~~~
function(
add_python_package
pkg_name
)
# Create a setup.py file if necessary
set ( _setup_py ${CMAKE_CURRENT_SOURCE_DIR}/setup.py )
set ( _setup_py_build_root ${CMAKE_CURRENT_BINARY_DIR} )
set(_setup_py ${CMAKE_CURRENT_SOURCE_DIR}/setup.py)
set(_setup_py_build_root ${CMAKE_CURRENT_BINARY_DIR})
if ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in" )
set ( SETUPTOOLS_BUILD_COMMANDS_DEF
"def patch_setuptools_command(cmd_cls_name):
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
set(
SETUPTOOLS_BUILD_COMMANDS_DEF
"def patch_setuptools_command(cmd_cls_name):
import importlib
cmd_module = importlib.import_module('setuptools.command.' + cmd_cls_name)
setuptools_command_cls = getattr(cmd_module, cmd_cls_name)
......@@ -34,106 +42,150 @@ function ( add_python_package pkg_name )
CustomBuildPy = patch_setuptools_command('build_py')
CustomInstall = patch_setuptools_command('install')
CustomInstallLib = patch_setuptools_command('install_lib')
" )
set ( SETUPTOOLS_BUILD_COMMANDS_USE "cmdclass={'build_py': CustomBuildPy, 'install': CustomInstall, 'install-lib': CustomInstallLib }" )
configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${_setup_py} @ONLY )
endif ()
"
)
set(
SETUPTOOLS_BUILD_COMMANDS_USE
"cmdclass={'build_py': CustomBuildPy, 'install': CustomInstall, 'install-lib': CustomInstallLib }"
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in
${_setup_py}
@ONLY
)
endif()
set ( _egg_link_dir ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR} )
set(_egg_link_dir ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR})
# Create variables for additional arguments
cmake_parse_arguments(_parsed_arg
"EXECUTABLE"
"EGGLINKNAME;EXCLUDE_FROM_INSTALL"
"" ${ARGN})
cmake_parse_arguments(
_parsed_arg
"EXECUTABLE"
"EGGLINKNAME;EXCLUDE_FROM_INSTALL;INSTALL_BIN_DIR"
"INSTALL_LIB_DIRS"
${ARGN}
)
# If a custom egg-link name was specified use that for the link
if (_parsed_arg_EGGLINKNAME)
set ( _egg_link ${_egg_link_dir}/${_parsed_arg_EGGLINKNAME}.egg-link )
if(_parsed_arg_EGGLINKNAME)
set(_egg_link ${_egg_link_dir}/${_parsed_arg_EGGLINKNAME}.egg-link)
else()
# if no egg-link name is specified, then use the target name
set ( _egg_link ${_egg_link_dir}/${pkg_name}.egg-link )
set(_egg_link ${_egg_link_dir}/${pkg_name}.egg-link)
endif()
if ( _parsed_arg_EXECUTABLE )
if ( WIN32 )
# add .exe in the executable name for Windows, otherwise it can't find it during the install step
set ( _executable_name ${pkg_name}.exe )
set ( _startup_script_full_name ${pkg_name}-script.pyw )
set ( _startup_script ${_egg_link_dir}/${_startup_script_full_name} )
else ()
set ( _startup_script_full_name )
set ( _startup_script )
set ( _executable_name ${pkg_name} )
endif ()
set ( _startup_exe ${_egg_link_dir}/${_executable_name} )
endif ()
if(_parsed_arg_EXECUTABLE)
if(WIN32)
# add .exe in the executable name for Windows, otherwise it can't find it
# during the install step
set(_executable_name ${pkg_name}.exe)
set(_startup_script_full_name ${pkg_name}-script.pyw)
set(_startup_script ${_egg_link_dir}/${_startup_script_full_name})
else()
set(_startup_script_full_name)
set(_startup_script)
set(_executable_name ${pkg_name})
endif()
set(_startup_exe ${_egg_link_dir}/${_executable_name})
endif()
# create the developer setup which just creates a pth file rather than copying things over
set ( _outputs ${_egg_link} ${_startup_script} ${_startup_exe} )
add_custom_command ( OUTPUT ${_outputs}
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${_egg_link_dir}
${PYTHON_EXECUTABLE} ${_setup_py} develop
--install-dir ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}
--script-dir ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}
# create the developer setup which just creates a pth file rather than copying
# things over
set(
_outputs
${_egg_link}
${_startup_script}
${_startup_exe}
)
add_custom_command(
OUTPUT ${_outputs}
COMMAND
${CMAKE_COMMAND}
-E
env
PYTHONPATH=${_egg_link_dir}
${PYTHON_EXECUTABLE}
${_setup_py}
develop
--install-dir
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}
--script-dir
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${_setup_py}
)
add_custom_target ( ${pkg_name} ALL
add_custom_target(
${pkg_name}
ALL
DEPENDS ${_outputs}
)
if ( ${ENABLE_WORKBENCH} )
# setuptools by default wants to build into a directory called 'build' relative the to the working directory. We have overridden
# commands in setup.py.in to force the build directory to take place out of source. The install directory is specified here and then
# --install-scripts=bin --install-lib=lib removes any of the platform/distribution specific install directories so we can have a flat
# structure
install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${_setup_py} install -O1 --single-version-externally-managed --root=${_setup_py_build_root}/install --install-scripts=bin --install-lib=lib WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})")
# setuptools by default wants to build into a directory called 'build'
# relative the to the working directory. We have overridden commands in
# setup.py.in to force the build directory to take place out of source. The
# install directory is specified here and then --install-scripts=bin
# --install-lib=lib removes any of the platform/distribution specific install
# directories so we can have a flat structure
install(
CODE
"execute_process(COMMAND ${PYTHON_EXECUTABLE} ${_setup_py} install -O1 --single-version-externally-managed --root=${_setup_py_build_root}/install --install-scripts=bin --install-lib=lib WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})"
)
# Specify the installation directory based on OS
if ( WIN32 OR APPLE)
# The / after lib tells cmake to copy over the _CONTENTS_ of the lib directory
# placing the installed files inside the DESTINATION folder. This copies the
# installed Python package inside the bin directory of Mantid's installation
set ( _package_source_directory ${_setup_py_build_root}/install/lib/ )
set ( _package_install_destination ${WORKBENCH_BIN_DIR} )
else ()
# NOTE the lack of slash at the end - this means the _whole_ lib directory will be moved
set ( _package_source_directory ${_setup_py_build_root}/install/lib )
set ( _package_install_destination . )
endif ()
# Registers the "installed" components with CMake so it will carry them over
if(_parsed_arg_EXCLUDE_FROM_INSTALL)
foreach(
_dest
${_parsed_arg_INSTALL_LIB_DIRS}
)
install(
DIRECTORY ${_setup_py_build_root}/install/lib/
DESTINATION ${_dest}
PATTERN
"test"
EXCLUDE
REGEX
"${_parsed_arg_EXCLUDE_FROM_INSTALL}"
EXCLUDE
)
endforeach()
else()
foreach(
_dest
${_parsed_arg_INSTALL_LIB_DIRS}
)
install(
DIRECTORY ${_setup_py_build_root}/install/lib/
DESTINATION ${_dest}
PATTERN
"test"
EXCLUDE
)
endforeach()
endif()
# Registers the "installed" components with CMake so it will carry them over
if ( _parsed_arg_EXCLUDE_FROM_INSTALL )
install(DIRECTORY ${_package_source_directory}
DESTINATION ${_package_install_destination}
PATTERN "test" EXCLUDE
REGEX "${_parsed_arg_EXCLUDE_FROM_INSTALL}" EXCLUDE)
else ()
install(DIRECTORY ${_package_source_directory}
DESTINATION ${_package_install_destination}
PATTERN "test" EXCLUDE)
endif()
if(APPLE AND "${pkg_name}" STREQUAL "mantidqt")
# Horrible hack to get mantidqt into the MantidPlot.app bundle too. Remove
# this when MantidPlot is removed!! Registers the "installed" components
# with CMake so it will carry them over
install(
DIRECTORY ${_setup_py_build_root}/install/lib/
DESTINATION ${BIN_DIR}
PATTERN
"test"
EXCLUDE
)
endif()
if (APPLE AND "${pkg_name}" STREQUAL "mantidqt")
# Horrible hack to get mantidqt into the MantidPlot.app bundle too.
# Remove this when MantidPlot is removed!!
set ( _package_install_destination ${BIN_DIR} )
# Registers the "installed" components with CMake so it will carry them over
install(DIRECTORY ${_package_source_directory}
DESTINATION ${_package_install_destination}
PATTERN "test" EXCLUDE )
# install the generated executable - only tested with "workbench"
if(_parsed_arg_EXECUTABLE)
# On UNIX systems install the workbench executable directly. The Windows
# case is handled with a custom startup script installed in WindowsNSIS
if(NOT WIN32)
install(
PROGRAMS ${_setup_py_build_root}/install/bin/${pkg_name}
DESTINATION ${_parsed_arg_INSTALL_BIN_DIR}
RENAME workbench-script
)
endif()
# install the generated executable - only tested with "workbench"
if ( _parsed_arg_EXECUTABLE )
# On UNIX systems install the workbench executable directly.
# The Windows case is handled with a custom startup script installed in WindowsNSIS
if ( NOT WIN32 )
install(PROGRAMS ${_setup_py_build_root}/install/bin/${pkg_name}
DESTINATION ${WORKBENCH_BIN_DIR}
RENAME workbench-script)
endif()
endif()
endif()
endfunction ()
endfunction()
......@@ -8,6 +8,8 @@ endif()
add_python_package(workbench
EXECUTABLE
EXCLUDE_FROM_INSTALL ${_exclude_on_install}
INSTALL_LIB_DIRS "${WORKBENCH_LIB_DIR}"
INSTALL_BIN_DIR "${WORKBENCH_BIN_DIR}"
)
set(_images_qrc_file ${CMAKE_CURRENT_LIST_DIR}/resources.qrc)
......@@ -32,7 +34,7 @@ if (WIN32)
# Write resources.qrc.BUILD_TYPE
file (WRITE ${_paths_qrc_file} ${_qrc_file_contents})
# Add command to generate resources.py file
add_custom_command(OUTPUT ${_output_res_py}
COMMAND ${PYRCC5_CMD} -o ${_output_res_py} ${_images_qrc_file} ${_paths_qrc_file}
......
......@@ -9,7 +9,7 @@ if(ENABLE_MANTIDPLOT)
endif()
# mantidqt
if(ENABLE_WORKBENCH)
if(ENABLE_WORKBENCH OR ENABLE_WORKBENCH)
# The default value is just an empty string - this prevents a Python syntax
# error when not on Windows Configure utils.qt.plugins file for build. It is
# placed in the source directory and added to the .gitignore for simplicity.
......@@ -21,7 +21,13 @@ if(ENABLE_WORKBENCH)
# plugins
configure_file(mantidqt/utils/qt/plugins.py.in
${CMAKE_CURRENT_SOURCE_DIR}/mantidqt/utils/qt/plugins.py)
add_python_package(mantidqt)
if(APPLE)
set(_install_lib_dirs "${LIB_DIR};${WORKBENCH_LIB_DIR}")
else()
set(_install_lib_dirs "${WORKBENCH_LIB_DIR}")
endif()
add_python_package(mantidqt
INSTALL_LIB_DIRS ${_install_lib_dirs})
# Configure resources data in place for ease of development. The output file
# is added to the toplevel gitignore
......@@ -40,23 +46,25 @@ if(ENABLE_WORKBENCH)
# Setup dependency chain
add_dependencies(mantidqt
mantidqt_resources
mantidqt_commonqt5
mantidqt_instrumentviewqt5
mantidqt_iconsqt5
PythonInterface)
if(ENABLE_MANTIDPLOT)
add_dependencies(mantidqt mantidqt_commonqt4 mantidqt_iconsqt4)
endif()
if(MSVC)
# Debug builds need libraries that are linked with MSVC debug runtime
add_custom_command(
TARGET mantidqt POST_BUILD
COMMAND if 1==$<CONFIG:Debug> ${CMAKE_COMMAND} -E copy_directory
${PYTHON_DIR}/msvc-site-packages/debug/PyQt5
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/PyQt5
COMMENT "Copying debug PyQt5 to bin/Debug")
if(ENABLE_WORKBENCH)
add_dependencies(mantidqt
mantidqt_commonqt5
mantidqt_instrumentviewqt5
mantidqt_iconsqt5)
if(MSVC)
# Debug builds need libraries that are linked with MSVC debug runtime
add_custom_command(
TARGET mantidqt POST_BUILD
COMMAND if 1==$<CONFIG:Debug> ${CMAKE_COMMAND} -E copy_directory
${PYTHON_DIR}/msvc-site-packages/debug/PyQt5
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/PyQt5
COMMENT "Copying debug PyQt5 to bin/Debug")
endif()
endif()
# Testing
......@@ -102,53 +110,57 @@ if(ENABLE_WORKBENCH)
mantidqt/widgets/embedded_find_replace_dialog/test/test_embedded_find_replace_dialog_presenter.py
)
# ctest target for widgets that only get tested in qt5, because they are only
# used in the workbench
set(
PYTHON_WIDGET_QT5_ONLY_TESTS
mantidqt/widgets/algorithmselector/test/observer_test.py
mantidqt/widgets/algorithmselector/test/test_algorithmselector.py
mantidqt/widgets/codeeditor/test/test_interpreter_view.py
mantidqt/widgets/codeeditor/test/test_multifileinterpreter.py
mantidqt/widgets/codeeditor/test/test_multifileinterpreter_view.py
mantidqt/widgets/codeeditor/tab_widget/test/test_codeeditor_tab_presenter.py
mantidqt/widgets/codeeditor/tab_widget/test/test_codeeditor_tab_view.py
mantidqt/widgets/instrumentview/test/test_instrumentview_io.py
mantidqt/widgets/instrumentview/test/test_instrumentview_view.py
mantidqt/widgets/plotconfigdialog/axestabwidget/test/test_axestabwidgetpresenter.py
mantidqt/widgets/plotconfigdialog/curvestabwidget/test/test_curveproperties.py
mantidqt/widgets/plotconfigdialog/curvestabwidget/test/test_curvestabwidgetpresenter.py
mantidqt/widgets/plotconfigdialog/test/test_apply_all_properties.py
mantidqt/widgets/plotconfigdialog/imagestabwidget/test/test_imagestabwidgetpresenter.py
mantidqt/widgets/plotconfigdialog/test/test_plotconfigdialogpresenter.py
mantidqt/widgets/samplelogs/test/test_samplelogs_view.py
mantidqt/widgets/test/test_jupyterconsole.py
mantidqt/widgets/workspacedisplay/test/test_data_copier.py
mantidqt/widgets/workspacedisplay/test/test_user_notifier.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_model.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_presenter.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_table_view_model.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_view.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_io.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_error_column.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_marked_columns.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_workbench_table_widget_item.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_model.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_presenter.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_view.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_io.py
mantidqt/widgets/workspacewidget/test/test_workspacetreewidget.py
mantidqt/icons/test/test_icons.py
)
if(ENABLE_WORKBENCH)
# ctest target for widgets that only get tested in qt5, because they are only
# used in the workbench
set(
PYTHON_WIDGET_QT5_ONLY_TESTS
mantidqt/widgets/algorithmselector/test/observer_test.py
mantidqt/widgets/algorithmselector/test/test_algorithmselector.py
mantidqt/widgets/codeeditor/test/test_interpreter_view.py
mantidqt/widgets/codeeditor/test/test_multifileinterpreter.py
mantidqt/widgets/codeeditor/test/test_multifileinterpreter_view.py
mantidqt/widgets/codeeditor/tab_widget/test/test_codeeditor_tab_presenter.py
mantidqt/widgets/codeeditor/tab_widget/test/test_codeeditor_tab_view.py
mantidqt/widgets/instrumentview/test/test_instrumentview_io.py
mantidqt/widgets/instrumentview/test/test_instrumentview_view.py
mantidqt/widgets/plotconfigdialog/axestabwidget/test/test_axestabwidgetpresenter.py
mantidqt/widgets/plotconfigdialog/curvestabwidget/test/test_curveproperties.py
mantidqt/widgets/plotconfigdialog/curvestabwidget/test/test_curvestabwidgetpresenter.py
mantidqt/widgets/plotconfigdialog/test/test_apply_all_properties.py
mantidqt/widgets/plotconfigdialog/imagestabwidget/test/test_imagestabwidgetpresenter.py
mantidqt/widgets/plotconfigdialog/test/test_plotconfigdialogpresenter.py
mantidqt/widgets/samplelogs/test/test_samplelogs_view.py
mantidqt/widgets/test/test_jupyterconsole.py
mantidqt/widgets/workspacedisplay/test/test_data_copier.py
mantidqt/widgets/workspacedisplay/test/test_user_notifier.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_model.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_presenter.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_table_view_model.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_view.py
mantidqt/widgets/workspacedisplay/matrix/test/test_matrixworkspacedisplay_io.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_error_column.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_marked_columns.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_workbench_table_widget_item.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_model.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_presenter.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_view.py
mantidqt/widgets/workspacedisplay/table/test/test_tableworkspacedisplay_io.py
mantidqt/widgets/workspacewidget/test/test_workspacetreewidget.py
mantidqt/icons/test/test_icons.py
)
# Tests
set(PYUNITTEST_QT_API pyqt5)
pyunittest_add_test(${CMAKE_CURRENT_SOURCE_DIR}
mantidqt_qt5
${PYTHON_TEST_FILES}
${PYTHON_WIDGET_QT5_ONLY_TESTS})
set(PYUNITTEST_QT_API pyqt)
pyunittest_add_test(${CMAKE_CURRENT_SOURCE_DIR} mantidqt_qt4
${PYTHON_TEST_FILES})
unset(PYUNITTEST_QT_API)
# Tests
set(PYUNITTEST_QT_API pyqt5)
pyunittest_add_test(${CMAKE_CURRENT_SOURCE_DIR}
mantidqt_qt5
${PYTHON_TEST_FILES}
${PYTHON_WIDGET_QT5_ONLY_TESTS})
endif()
if(ENABLE_MANTIDPLOT)
set(PYUNITTEST_QT_API pyqt)
pyunittest_add_test(${CMAKE_CURRENT_SOURCE_DIR} mantidqt_qt4
${PYTHON_TEST_FILES})
unset(PYUNITTEST_QT_API)
endif()
endif()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment