diff --git a/CMakeLists.txt b/CMakeLists.txt index ca62c09c..79928a82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,22 +116,28 @@ if(BUILD_PACKAGE) add_custom_target(packaging ALL DEPENDS projects COMMENT "Packaging Projects...") if(BUILD_OS_WINDOWS) - if(${Python3_VERSION} VERSION_LESS 3.7) - include(packaging/windows.cmake) - else() + if(${Python3_VERSION} VERSION_GREATER_EQUAL 3.8) + include(packaging/python3.8/windows.cmake) + elseif(${Python3_VERSION} VERSION_GREATER_EQUAL 3.7) include(packaging/python3.7/windows.cmake) + else() + include(packaging/windows.cmake) endif() elseif(BUILD_OS_OSX) - if(${Python3_VERSION} VERSION_LESS 3.7) - include(packaging/osx.cmake) - else() + if(${Python3_VERSION} VERSION_GREATER_EQUAL 3.8) + include(packaging/python3.8/osx.cmake) + elseif(${Python3_VERSION} VERSION_GREATER_EQUAL 3.7) include(packaging/python3.7/osx.cmake) + else() + include(packaging/osx.cmake) endif() elseif(BUILD_OS_LINUX) - if(${Python3_VERSION} VERSION_LESS 3.7) - include(packaging/linux.cmake) - else() + if(${Python3_VERSION} VERSION_GREATER_EQUAL 3.8) + include(packaging/python3.8/linux.cmake) + elseif(${Python3_VERSION} VERSION_GREATER_EQUAL 3.7) include(packaging/python3.7/linux.cmake) + else() + include(packaging/linux.cmake) endif() else() message(STATUS "Do not know how to build an executable for the current platform! You will have to create it manually.") diff --git a/packaging/osx.cmake b/packaging/osx.cmake index ec3793bc..3399dc4a 100644 --- a/packaging/osx.cmake +++ b/packaging/osx.cmake @@ -1,4 +1,4 @@ -find_package(cx_freeze 5.0 REQUIRED) +find_package(cx_Freeze 5.0 REQUIRED) configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_osx.py.in setup.py @ONLY) configure_file(${CMAKE_CURRENT_LIST_DIR}/Info.plist.in Info.plist @ONLY) diff --git a/packaging/python3.7/osx.cmake b/packaging/python3.7/osx.cmake index 76957615..bde7b804 100644 --- a/packaging/python3.7/osx.cmake +++ b/packaging/python3.7/osx.cmake @@ -1,4 +1,4 @@ -find_package(cx_freeze 5.0 REQUIRED) +find_package(cx_Freeze 5.0 REQUIRED) configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_osx.py.in setup.py @ONLY) configure_file(${CMAKE_CURRENT_LIST_DIR}/../Info.plist.in Info.plist @ONLY) diff --git a/packaging/python3.7/windows.cmake b/packaging/python3.7/windows.cmake index 59d2c7de..e7399047 100644 --- a/packaging/python3.7/windows.cmake +++ b/packaging/python3.7/windows.cmake @@ -1,4 +1,4 @@ -find_package(cx_freeze 5.0 REQUIRED) +find_package(cx_Freeze 5.0 REQUIRED) configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_win32.py.in setup.py @ONLY) add_custom_target(build_bundle) diff --git a/packaging/python3.8/cura.sh b/packaging/python3.8/cura.sh new file mode 100755 index 00000000..8a8d4ae6 --- /dev/null +++ b/packaging/python3.8/cura.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +scriptdir="$(dirname $0)" + +export PYTHONPATH=$scriptdir/../lib +#export QT_PLUGIN_PATH=$scriptdir/qt/plugins +export QML2_IMPORT_PATH=$scriptdir/../lib/UM/Qt/qml +#export QT_QPA_FONTDIR=/usr/share/fonts +#export QT_XKB_CONFIG_ROOT=/usr/share/X11/xkb + +# Use the openssl.cnf packaged in the AppImage +#export OPENSSL_CONF=$scriptdir/openssl.cnf + +"$scriptdir/../cura" "$@" diff --git a/packaging/python3.8/linux.cmake b/packaging/python3.8/linux.cmake new file mode 100644 index 00000000..e656cf12 --- /dev/null +++ b/packaging/python3.8/linux.cmake @@ -0,0 +1,82 @@ +find_package(cx_Freeze 5.0 REQUIRED) +find_package(AppImageKit REQUIRED) + +configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_linux.py.in setup.py @ONLY) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/package + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Cleaning old package directory..." +) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND env "LD_LIBRARY_PATH=${CMAKE_PREFIX_PATH}/lib" ${Python3_EXECUTABLE} setup.py build + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running cx_Freeze to generate executable..." +) + +set(PACKAGE_DIR ${CMAKE_BINARY_DIR}/package) + +configure_file(${CMAKE_CURRENT_LIST_DIR}/../cura.desktop.in ${CMAKE_CURRENT_LIST_DIR}/../cura.desktop @ONLY) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND mkdir -p ${PACKAGE_DIR}/usr/share/applications/ + COMMAND ${CMAKE_COMMAND} -E copy ../cura.desktop ${PACKAGE_DIR}/usr/share/applications/cura.desktop + COMMAND ln -s -r ${PACKAGE_DIR}/usr/share/applications/cura.desktop ${PACKAGE_DIR}/cura.desktop + COMMENT "Copying desktop file ..." + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ../cura-icon_256x256.png ${PACKAGE_DIR}/cura-icon.png + COMMAND mkdir -p ${PACKAGE_DIR}/usr/share/icons/hicolor/64x64/apps/ + COMMAND ${CMAKE_COMMAND} -E copy ../cura-icon_64x64.png ${PACKAGE_DIR}/usr/share/icons/hicolor/64x64/apps/cura-icon.png + COMMAND mkdir -p ${PACKAGE_DIR}/usr/share/icons/hicolor/128x128/apps/ + COMMAND ${CMAKE_COMMAND} -E copy ../cura-icon_128x128.png ${PACKAGE_DIR}/usr/share/icons/hicolor/128x128/apps/cura-icon.png + COMMAND mkdir -p ${PACKAGE_DIR}/usr/share/icons/hicolor/256x256/apps/ + COMMAND ${CMAKE_COMMAND} -E copy ../cura-icon_256x256.png ${PACKAGE_DIR}/usr/share/icons/hicolor/256x256/apps/cura-icon.png + COMMENT "Copying icon files ..." + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND mkdir -p ${PACKAGE_DIR}/usr/bin/ + COMMAND ${CMAKE_COMMAND} -E copy cura.sh ${PACKAGE_DIR}/usr/bin/ + COMMENT "Copying shell script..." + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND ${CMAKE_CURRENT_LIST_DIR}/../linux_mod_rpath.sh ${PACKAGE_DIR}/usr/bin + COMMENT "Modify RPATH for ELFs..." + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND mkdir -p ${PACKAGE_DIR}/usr/share/metainfo/ + COMMAND ${CMAKE_COMMAND} -E copy ../cura.appdata.xml ${PACKAGE_DIR}/usr/share/metainfo/ + COMMENT "Installing AppStream metadata..." + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +add_custom_command( + TARGET packaging PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${APPIMAGEKIT_APPRUN_EXECUTABLE} ${PACKAGE_DIR} + COMMENT "Copying AppRun executable..." +) + +set(APPIMAGE_FILENAME "Cura-${CURA_VERSION}.AppImage") + +add_custom_command( + TARGET packaging POST_BUILD + COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/${APPIMAGE_FILENAME} + COMMAND ${APPIMAGEKIT_APPIMAGETOOL_EXECUTABLE} --appimage-extract-and-run ${CMAKE_BINARY_DIR}/package ${APPIMAGE_FILENAME} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) diff --git a/packaging/python3.8/osx.cmake b/packaging/python3.8/osx.cmake new file mode 100644 index 00000000..bde7b804 --- /dev/null +++ b/packaging/python3.8/osx.cmake @@ -0,0 +1,11 @@ +find_package(cx_Freeze 5.0 REQUIRED) + +configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_osx.py.in setup.py @ONLY) +configure_file(${CMAKE_CURRENT_LIST_DIR}/../Info.plist.in Info.plist @ONLY) + +add_custom_command( + TARGET packaging POST_BUILD + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/build + COMMAND ${Python3_EXECUTABLE} setup.py bdist_mac + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) diff --git a/packaging/python3.8/setup_linux.py.in b/packaging/python3.8/setup_linux.py.in new file mode 100644 index 00000000..d15968be --- /dev/null +++ b/packaging/python3.8/setup_linux.py.in @@ -0,0 +1,158 @@ +import sys +import os.path + +from cx_Freeze import setup, Executable, hooks + +def load_scipy(finder, module): + finder.IncludePackage("scipy._lib") + finder.IncludePackage("scipy.misc") + finder.IncludePackage("scipy.sparse.csgraph._validation") + finder.IncludePackage("scipy.sparse._csparsetools") + +hooks.load_scipy = load_scipy + +def load_pyqt5_qtgui(finder, module): + finder.IncludeModule("PyQt5.QtCore") + +hooks.load_PyQt5_QtGui = load_pyqt5_qtgui + +def load_pyqt5_qtquick(finder, module): + finder.IncludeModule("PyQt5.QtCore") + finder.IncludeModule("PyQt5.QtGui") + finder.IncludeModule("PyQt5.QtQml") + finder.IncludeModule("PyQt5.QtNetwork") + finder.IncludeModule("PyQt5.QtWebSockets") + finder.IncludeModule("PyQt5._QOpenGLFunctions_2_0") + finder.IncludeModule("PyQt5._QOpenGLFunctions_4_1_Core") + +hooks.load_PyQt5_QtQuick = load_pyqt5_qtquick + +search_path = sys.path.copy() +if os.path.exists("/etc/debian_version"): + python_externalproject_dir = "@EXTERNALPROJECT_INSTALL_PREFIX@/lib/python3/dist-packages/" + python_install_dir = "@CMAKE_INSTALL_PREFIX@/lib/python3/dist-packages/" +else: + python_externalproject_dir = "@EXTERNALPROJECT_INSTALL_PREFIX@/lib/python3.8/site-packages/" + python_install_dir = "@CMAKE_INSTALL_PREFIX@/lib/python3.8/site-packages/" +search_path.insert(1, python_externalproject_dir) +search_path.insert(2, python_install_dir) + +# Dependencies are automatically detected, but it might need +# fine tuning. +build_options = { + "build_exe": "package/usr", + "path": search_path, + "packages": [ + "appdirs", + "packaging", + "cryptography", + "xml.etree", + "uuid", + "UM", + "cura", + "zeroconf", + "pkg_resources", + "requests", + "idna", + "stl", + "serial", + "shapely", + "networkx", + "trimesh", + "Savitar", + "Charon", + "logging", + "logging.config", + "logging.handlers", + ], + "include_files": [ + ("@EXTERNALPROJECT_INSTALL_PREFIX@/bin/CuraEngine", "bin/CuraEngine"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/cura/plugins", "share/cura/plugins"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/uranium/plugins", "share/uranium/plugins"), + (os.path.join(python_externalproject_dir, "UM/Qt/qml/UM"), "share/uranium/resources/qml/UM"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/share/cura/resources", "share/cura/resources"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/share/uranium/resources", "share/uranium/resources"), + ("@CMAKE_PREFIX_PATH@/lib/libprotobuf.so.3.9.2.0", "lib/libprotobuf.so.3.9.2.0"), + ("@CMAKE_PREFIX_PATH@/lib/libArcus.so.3", "lib/libArcus.so.3"), + ("@CMAKE_PREFIX_PATH@/lib/libSavitar.so.0", "lib/libSavitar.so.0"), + ], + + # Known issue, see https://github.com/numpy/numpy/issues/13248 + # If "optimize" is set to 2, the packaged Cura will raise the following exception when it runs: + # """ TypeError: add_docstring() argument 2 must be str, not None """ + # Setting "optimize" to 0 is a workaround. + "optimize": 0, + + "bin_path_includes": [ + "@CMAKE_PREFIX_PATH@/lib", + "/lib", + "/usr/lib", + "/usr/lib/x86_64-linux-gnu", + "/usr/local/lib", + ], + "bin_includes": [ + "libopenctm.so.1.0.3", + ], + "bin_excludes": [ + "linux-vdso.so.1", + "libpthread.so.0", + "libdl.so.2", + "librt.so.1", + "libstdc++.so.6", + "libm.so.6", + "libgcc_s.so.1", + "libc.so.6", + "ld-linux-x86-64.so.2", + "libz.so.1", + "libgcc_s.so.1", + "libglib-2.0", + "librt.so.1", + "libcap.so.2", + "libGL.so.1", + "libGLX.so.0", + "libGLdispatch.so.0", + "libglapi.so.0", + "libXext.so.6", + "libXdamage.so.1", + "libXfixes.so.3", + "libX11-xcb.so.1", + "libX11.so.6", + "libxcb-glx.so.0", + "libxcb-dri2.so.0", + "libxcb.so.1", + "libXxf86vm.so.1", + "libdrm.so.2", + "libexpat.so.1", + "libXau.so.6", + "libglib-2.0.so.0", + "libgssapi_krb5.so.", + "libgthread-2.0.so.0", + "libk5crypto.so.3", + "libkeyutils.so.1", + "libkrb5.so.3", + "libkrb5support.so.0", + "libresolv.so.2", + "libutil.so.1", + "libXrender.so.1", + "libcom_err.so.2", + "libgssapi_krb5.so.2", + ] +} + +base = "Win32GUI" if sys.platform == "win32" else None + +executables = [ + Executable(os.path.join("@EXTERNALPROJECT_INSTALL_PREFIX@", "bin", "cura"), base = base) +] + +setup( + name = "Ultimaker Cura", + version = "@CURA_MAJOR_VERSION@.@CURA_MINOR_VERSION@.@CURA_PATCH_VERSION@", + author = "Ultimaker B.V.", + url="http://software.ultimaker.com/", + description = "3D Slicer Software", + license="GNU LESSER GENERAL PUBLIC LICENSE (LGPL)", + + options = { "build_exe": build_options }, + executables = executables +) diff --git a/packaging/python3.8/setup_osx.py.in b/packaging/python3.8/setup_osx.py.in new file mode 100644 index 00000000..3c1d73ad --- /dev/null +++ b/packaging/python3.8/setup_osx.py.in @@ -0,0 +1,104 @@ +import sys +import os.path + +from cx_Freeze import setup, Executable, hooks + +def load_scipy(finder, module): + finder.IncludePackage("scipy._lib") + finder.IncludePackage("scipy.misc") + finder.IncludePackage("scipy.sparse.csgraph._validation") + finder.IncludePackage("scipy.sparse._csparsetools") + +hooks.load_scipy = load_scipy + +def load_pyqt5_qtquick(finder, module): + finder.IncludeModule("PyQt5.QtCore") + finder.IncludeModule("PyQt5.QtGui") + finder.IncludeModule("PyQt5.QtQml") + finder.IncludeModule("PyQt5.QtNetwork") + finder.IncludeModule("PyQt5.QtWebSockets") + finder.IncludeModule("PyQt5._QOpenGLFunctions_2_0") + finder.IncludeModule("PyQt5._QOpenGLFunctions_4_1_Core") + +hooks.load_PyQt5_QtQuick = load_pyqt5_qtquick + +search_path = sys.path.copy() +search_path.insert(1, "@EXTERNALPROJECT_INSTALL_PREFIX@/lib/python3.8/site-packages/") +search_path.insert(2, "@CMAKE_PREFIX_PATH@/lib/python3.8/site-packages/") +search_path.insert(3, "@CMAKE_PREFIX_PATH@/lib") + +# Dependencies are automatically detected, but it might need +# fine tuning. +build_options = { +# "build_exe": "package", + "path": search_path, + "packages": [ + "appdirs", + "packaging", + "cryptography", + "xml.etree", + "uuid", + "serial", + "zeroconf", + "requests", + "idna", + "UM", + "cura", + "stl", + "shapely", + "netifaces", + "networkx", + "trimesh", + "Savitar", + "PyQt5", + "PyQt5.QtDBus", + "Charon", + "logging", + "logging.config", + "logging.handlers", + ], + "include_files": [ + ("@EXTERNALPROJECT_INSTALL_PREFIX@/bin/CuraEngine", ""), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/cura", "plugins"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/uranium", "plugins"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/python3.8/site-packages/UM/Qt/qml/UM", "qml/UM"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/share/cura/resources", "resources"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/share/uranium/resources", "resources"), + #("@CMAKE_PREFIX_PATH@/lib/qml/Qt", "qml/Qt"), + #("@CMAKE_PREFIX_PATH@/lib/qml/QtQml", "qml/QtQml"), + #("@CMAKE_PREFIX_PATH@/lib/qml/QtQuick", "qml/QtQuick"), + #("@CMAKE_PREFIX_PATH@/lib/qml/QtQuick.2", "qml/QtQuick.2"), + #("@CMAKE_PREFIX_PATH@/lib/qml/QtCharts", "qml/QtCharts"), + #("@CMAKE_PREFIX_PATH@/lib/qml/QtDataVisualization", "qml/QtDataVisualization"), + #("@CMAKE_PREFIX_PATH@/lib/qml/QtGraphicalEffects", "qml/QtGraphicalEffects"), + #("@CMAKE_PREFIX_PATH@/lib/libgeos.dylib", "lib/python3.8/shapely/.dylibs/libgeos.dylib"), + #("@CMAKE_PREFIX_PATH@/lib/libgeos_c.1.dylib", "lib/python3.8/shapely/.dylibs/libgeos_c.1.dylib"), + #("@CMAKE_PREFIX_PATH@/lib/libopenctm.dylib", ""), # For opening .CTM files + ], + "excludes": [ ], + "bin_path_includes": [ + "@CMAKE_PREFIX_PATH@/lib", + ], +} + +bdist_mac_options = { + "iconfile": "@CMAKE_SOURCE_DIR@/packaging/cura.icns", + "custom_info_plist": "@CMAKE_BINARY_DIR@/Info.plist", + "bundle_name": "Ultimaker Cura" +} + +executables = [ + Executable("@EXTERNALPROJECT_INSTALL_PREFIX@/bin/cura_app.py", targetName = "cura") +] + +setup( + name = "Ultimaker Cura", + version = "@CURA_VERSION_MAJOR@.@CURA_VERSION_MINOR@.@CURA_VERSION_PATCH@", + description = "3D Printing Software", + author = "Ultimaker B.V.", + url = "http://software.ultimaker.com/", + license = "GNU LESSER GENERAL PUBLIC LICENSE (LGPL)", + + options = {"build_exe": build_options, "bdist_mac": bdist_mac_options }, + executables = executables +) diff --git a/packaging/python3.8/setup_win32.py.in b/packaging/python3.8/setup_win32.py.in new file mode 100644 index 00000000..2bc0537e --- /dev/null +++ b/packaging/python3.8/setup_win32.py.in @@ -0,0 +1,216 @@ +# Needed build-ins +import sys +import os.path +import platform + +# Importing preinstalled modules to get their paths +import PyQt5 +import numpy +import trimesh +import shapely + +from cx_Freeze import setup, Executable, hooks + + +zip_includes = [] + + +def load_numpy(finder, module): + finder.IncludePackage("numpy.core._methods") + finder.IncludePackage("numpy._globals") + finder.IncludePackage("numpy.lib.format") + finder.IncludePackage("numpy.linalg._umath_linalg") + + # Include all MKL files that are needed to get Numpy with MKL working. + npy_core_dir = os.path.join(module.path[0], "DLLs") + required_mkl_files = [ + "libifcoremd.dll", + "libifportmd.dll", + "libimalloc.dll", + "libiomp5md.dll", + "libiompstubs5md.dll", + "libmmd.dll", + "libopenblas.dll", + "mkl_avx.dll", + "mkl_avx2.dll", + "mkl_avx512.dll", + "mkl_core.dll", + "mkl_def.dll", + "mkl_intel_thread.dll", + "mkl_sequential.dll", + "mkl_tbb_thread.dll", + "mkl_vml_avx.dll", + "mkl_vml_avx2.dll", + "mkl_vml_avx512.dll", + "mkl_vml_cmpt.dll", + "mkl_vml_def.dll", + "mkl_vml_mc.dll", + "mkl_vml_mc2.dll", + "mkl_vml_mc3.dll", + "tbb.dll", + "tbbmalloc.dll", + ] + + if platform.architecture()[0] == "32bit": + required_mkl_files.extend([ + "mkl_p4.dll", + "mkl_p4m.dll", + "mkl_p4m3.dll", + ]) + else: + required_mkl_files.extend([ + "mkl_def.dll", + "mkl_mc.dll", + "mkl_mc3.dll", + ]) + + for file in required_mkl_files: + finder.IncludeFiles(os.path.join(npy_core_dir, file), file) + +hooks.load_numpy = load_numpy + +def load_scipy(finder, module): + finder.IncludePackage("scipy._lib") + finder.IncludePackage("scipy.misc") + finder.IncludePackage("scipy.sparse.csgraph._validation") + finder.IncludePackage("scipy.sparse._csparsetools") + finder.IncludePackage("scipy.special._ufuncs_cxx") + finder.IncludePackage("scipy.special.specfun") + +hooks.load_scipy = load_scipy + +# Trimesh data files +trimesh_resources_path = os.path.join(os.path.dirname(trimesh.__file__), "resources") +trimesh_resources_required_files = [ + "blender.py.template", + "collada.dae.template", + "dxf.json.template", + "ply.template", + "svg.xml.template", + "units_to_inches.json", + "viewer.html.template", + "yafaray.xml.template", +] +for file_name in trimesh_resources_required_files: + item = (os.path.join(trimesh_resources_path, file_name), os.path.join("trimesh", "resources", file_name)) + zip_includes.append(item) + +def load_pyqt5_qtquick(finder, module): + finder.IncludeModule("PyQt5.QtCore") + finder.IncludeModule("PyQt5.QtGui") + finder.IncludeModule("PyQt5.QtQml") + finder.IncludeModule("PyQt5.QtNetwork") + finder.IncludeModule("PyQt5.QtWebSockets") + finder.IncludeModule("PyQt5._QOpenGLFunctions_2_0") + finder.IncludeModule("PyQt5._QOpenGLFunctions_2_1") + finder.IncludeModule("PyQt5._QOpenGLFunctions_4_1_Core") + +hooks.load_PyQt5_QtQuick = load_pyqt5_qtquick + +def load_pyqt5_qtnetwork(finder, module): + finder.IncludeModule("PyQt5.QtCore") + + qt_path = os.path.join(os.path.dirname(PyQt5.QtCore.__file__), "Qt", "bin") + required_ssl_files = [ + "libeay32.dll", + "ssleay32.dll", + ] + for file_name in required_ssl_files: + finder.IncludeFiles(os.path.join(qt_path, file_name), file_name) + +hooks.load_PyQt5_QtNetwork = load_pyqt5_qtnetwork + +def load_shapely(finder, module): + finder.IncludeModule("shapely") + shapely_path = os.path.join(os.path.dirname(shapely.__file__), "DLLs") + required_dll_files = [ + "geos_c.dll", + ] + for file_name in required_dll_files: + finder.IncludeFiles(os.path.join(shapely_path, file_name), file_name) + +hooks.load_shapely = load_shapely + +search_path = sys.path.copy() +search_path.insert(1, "@EXTERNALPROJECT_INSTALL_PREFIX@/lib/python3.8/site-packages/") +search_path.insert(2, "@CMAKE_PREFIX_PATH@/lib/python3.8/site-packages/") + +# Dependencies are automatically detected, but it might need +# fine tuning. +build_options = { + "build_exe": "package", + "zip_include_packages": "*", + "zip_exclude_packages": "certifi", + "path": search_path, + "packages": [ + "appdirs", + "packaging", + "cryptography", + "xml.etree", + "uuid", + "serial", + "zeroconf", + "requests", + "idna", + "UM", + "cura", + "stl", + "shapely", + "netifaces", + "networkx", + "trimesh", + "trimesh.resources", + "Savitar", + "PyQt5.QtDBus", + "comtypes", + "Charon", + "logging", + "logging.config", + "logging.handlers", + ], + "include_files": [ + ("@EXTERNALPROJECT_INSTALL_PREFIX@/bin/CuraEngine.exe", ""), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/cura/plugins", ""), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/uranium/plugins", ""), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/lib/python3.8/site-packages/UM/Qt/qml/UM", "qml/UM"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/share/cura/resources", "resources"), + ("@EXTERNALPROJECT_INSTALL_PREFIX@/share/uranium/resources", "resources"), + #("@CMAKE_PREFIX_PATH@/bin/openctm.dll", ""), # For opening .CTM files + # Preinstalled PyQt5 installation + (PyQt5.__path__[0] + "/Qt/qml/Qt", "qml/Qt"), + (PyQt5.__path__[0] + "/Qt/qml/QtQml", "qml/QtQml"), + (PyQt5.__path__[0] + "/Qt/qml/QtQuick", "qml/QtQuick"), + (PyQt5.__path__[0] + "/Qt/qml/QtQuick.2", "qml/QtQuick.2"), + (PyQt5.__path__[0] + "/Qt/qml/QtGraphicalEffects", "qml/QtGraphicalEffects"), + ], + "zip_includes": zip_includes, + "excludes": [ ], + "replace_paths": [("*", "")], +} + +executables = [ + Executable(script="@EXTERNALPROJECT_INSTALL_PREFIX@/bin/cura_app.py", + base="Win32GUI", + targetName = os.path.join("@CMAKE_BINARY_DIR@", "package", "Cura.exe"), + icon="@CMAKE_SOURCE_DIR@/packaging/cura.ico" + ), + Executable(script="@EXTERNALPROJECT_INSTALL_PREFIX@/bin/cura_app.py", + base="Console", + targetName = os.path.join("@CMAKE_BINARY_DIR@", "package", "CuraCLI.exe"), + icon="@CMAKE_SOURCE_DIR@/packaging/cura.ico" + ), + +] + +setup( + name = "Ultimaker Cura", + version = "@CURA_VERSION_MAJOR@.@CURA_VERSION_MINOR@.@CURA_VERSION_PATCH@", + description = "Ultimaker Cura", + long_description = "Ultimaker Cura - 3D Printing Software", + author = "Ultimaker B.V.", + url = "http://software.ultimaker.com/", + license = "GNU LESSER GENERAL PUBLIC LICENSE (LGPL)", + + options = {"build_exe": build_options}, + executables = executables +) diff --git a/packaging/python3.8/windows.cmake b/packaging/python3.8/windows.cmake new file mode 100644 index 00000000..e7399047 --- /dev/null +++ b/packaging/python3.8/windows.cmake @@ -0,0 +1,78 @@ +find_package(cx_Freeze 5.0 REQUIRED) + +configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_win32.py.in setup.py @ONLY) +add_custom_target(build_bundle) +add_dependencies(packaging build_bundle) +add_dependencies(build_bundle projects) + +add_custom_command( + TARGET build_bundle PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/package + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/package + COMMENT "cleaning old package/ directory" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +add_custom_command( + TARGET build_bundle POST_BUILD + COMMAND ${Python3_EXECUTABLE} setup.py build_exe + COMMENT "running cx_Freeze" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +add_custom_command( + TARGET build_bundle POST_BUILD + # NOTE: Needs testing here, whether CPACK_SYSTEM_NAME is working good for 64bit builds, too. + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/packaging/cura.ico ${CMAKE_BINARY_DIR}/package/ + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_BINARY_DIR}/package/cura.ico ${CMAKE_BINARY_DIR}/package/Cura.ico + COMMENT "copying cura.ico as Cura.ico into package/" +) + +# +# CURA-6074 +# QTBUG-57832 +# Patch Qt dialogplugin.dll to avoid adding all available drives as shortcuts for FileDialog. +# +if(BUILD_OS_WINDOWS) + add_custom_command( + TARGET build_bundle POST_BUILD + # NOTE: Needs testing here, whether CPACK_SYSTEM_NAME is working good for 64bit builds, too. + COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/packaging/patch_qt5.10_dialogplugin.py ${CMAKE_BINARY_DIR}/package + COMMENT "CURA-6074 Patching dialogplugin.dll in ${CMAKE_BINARY_DIR}/package" + ) +endif() + +install(DIRECTORY ${CMAKE_BINARY_DIR}/package/ + DESTINATION "." + USE_SOURCE_PERMISSIONS + COMPONENT "_cura" # Note: _ prefix is necessary to make sure the Cura component is always listed first +) + +if(CPACK_GENERATOR MATCHES "NSIS64" OR CPACK_GENERATOR MATCHES "NSIS") + # Only NSIS needs to have arduino and vcredist + install(DIRECTORY ${EXTERNALPROJECT_INSTALL_PREFIX}/arduino + DESTINATION "." + COMPONENT "arduino" + ) + + install(FILES ${EXTERNALPROJECT_INSTALL_PREFIX}/vcredist_x64.exe + DESTINATION "." + COMPONENT "vcredist" + ) + + set(CPACK_NSIS_PACKAGE_ARCHITECTURE "64") + + include(packaging/cpackconfig_nsis.cmake) + include(CPack) + + add_custom_command( + TARGET build_bundle POST_BUILD + # NOTE: Needs testing here, whether CPACK_SYSTEM_NAME is working good for 64bit builds, too. + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/NSIS "${CMAKE_CURRENT_BINARY_DIR}/_CPack_Packages/${CPACK_SYSTEM_NAME}/NSIS" + COMMENT "Copying NSIS scripts from [${CMAKE_SOURCE_DIR}/NSIS] to [${CMAKE_CURRENT_BINARY_DIR}/_CPack_Packages/${CPACK_SYSTEM_NAME}/NSIS]" + ) + +elseif(CPACK_GENERATOR MATCHES "WIX") + include(packaging/cpackconfig_wix.cmake) + include(CPack) +endif() diff --git a/packaging/windows.cmake b/packaging/windows.cmake index f561d617..78113dbe 100644 --- a/packaging/windows.cmake +++ b/packaging/windows.cmake @@ -1,4 +1,4 @@ -find_package(cx_freeze 5.0 REQUIRED) +find_package(cx_Freeze 5.0 REQUIRED) configure_file(${CMAKE_CURRENT_LIST_DIR}/setup_win32.py.in setup.py @ONLY) add_custom_target(build_bundle)