diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index d25d71bcc9..0000000000 --- a/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -.git -.github -resources/materials -CuraEngine \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 6dbe51a09e..0000000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: CI -on: - push: - branches: - - master - - 'WIP**' - - '4.*' - - 'CURA-*' - pull_request: -jobs: - build: - runs-on: ubuntu-latest - container: ultimaker/cura-build-environment - steps: - - name: Checkout Cura - uses: actions/checkout@v2 - - name: Build - run: docker/build.sh - - name: Test - run: docker/test.sh diff --git a/.github/workflows/conan-package-create.yml b/.github/workflows/conan-package-create.yml new file mode 100644 index 0000000000..ca9248cfd6 --- /dev/null +++ b/.github/workflows/conan-package-create.yml @@ -0,0 +1,114 @@ +name: Create and Upload Conan package + +on: + workflow_call: + inputs: + recipe_id_full: + required: true + type: string + + runs_on: + required: true + type: string + + python_version: + required: true + type: string + + conan_config_branch: + required: false + type: string + + conan_logging_level: + required: false + type: string + + conan_clean_local_cache: + required: false + type: boolean + default: false + +env: + CONAN_LOGIN_USERNAME_CURA: ${{ secrets.CONAN_USER }} + CONAN_PASSWORD_CURA: ${{ secrets.CONAN_PASS }} + CONAN_LOGIN_USERNAME_CURA_CE: ${{ secrets.CONAN_USER }} + CONAN_PASSWORD_CURA_CE: ${{ secrets.CONAN_PASS }} + CONAN_LOG_RUN_TO_OUTPUT: 1 + CONAN_LOGGING_LEVEL: ${{ inputs.conan_logging_level }} + CONAN_NON_INTERACTIVE: 1 + +jobs: + conan-package-create: + runs-on: ${{ inputs.runs_on }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Python and pip + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python_version }} + cache: 'pip' + cache-dependency-path: .github/workflows/requirements-conan-package.txt + + - name: Install Python requirements and Create default Conan profile + run: | + pip install -r .github/workflows/requirements-conan-package.txt + conan profile new default --detect + + - name: Use Conan download cache (Bash) + if: ${{ runner.os != 'Windows' }} + run: conan config set storage.download_cache="$HOME/.conan/conan_download_cache" + + - name: Use Conan download cache (Powershell) + if: ${{ runner.os == 'Windows' }} + run: conan config set storage.download_cache="C:\Users\runneradmin\.conan\conan_download_cache" + + - name: Cache Conan local repository packages (Bash) + uses: actions/cache@v3 + if: ${{ runner.os != 'Windows' }} + with: + path: | + $HOME/.conan/data + $HOME/.conan/conan_download_cache + key: conan-${{ runner.os }}-${{ runner.arch }} + + - name: Cache Conan local repository packages (Powershell) + uses: actions/cache@v3 + if: ${{ runner.os == 'Windows' }} + with: + path: | + C:\Users\runneradmin\.conan\data + C:\.conan + C:\Users\runneradmin\.conan\conan_download_cache + key: conan-${{ runner.os }}-${{ runner.arch }} + + - name: Install MacOS system requirements + if: ${{ runner.os == 'Macos' }} + run: brew install autoconf automake ninja + + - name: Install Linux system requirements + if: ${{ runner.os == 'Linux' }} + run: sudo apt install build-essential checkinstall zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev -y + + - name: Clean Conan local cache + if: ${{ inputs.conan_clean_local_cache }} + run: conan remove "*" -f + + - name: Get Conan configuration from branch + if: ${{ inputs.conan_config_branch != '' }} + run: conan config install https://github.com/Ultimaker/conan-config.git -a "-b ${{ inputs.conan_config_branch }}" + + - name: Get Conan configuration + if: ${{ inputs.conan_config_branch == '' }} + run: conan config install https://github.com/Ultimaker/conan-config.git + + - name: Create the Packages + run: conan install ${{ inputs.recipe_id_full }} --build=missing --update + + - name: Upload the Package(s) + if: always() + run: | + conan upload "*" -r cura --all -c + conan upload "*" -r cura-ce -c diff --git a/.github/workflows/conan-package.yml b/.github/workflows/conan-package.yml new file mode 100644 index 0000000000..7f8790fcf7 --- /dev/null +++ b/.github/workflows/conan-package.yml @@ -0,0 +1,105 @@ +--- +name: conan-package + +# Exports the recipe, sources and binaries for Mac, Windows and Linux and upload these to the server such that these can +# be used downstream. +# +# It should run on pushes against main or CURA-* branches, but it will only create the binaries for main and release branches + +on: + workflow_dispatch: + inputs: + create_binaries_windows: + required: true + default: false + description: 'create binaries Windows' + create_binaries_linux: + required: true + default: false + description: 'create binaries Linux' + create_binaries_macos: + required: true + default: false + description: 'create binaries Macos' + + push: + paths: + - 'plugins/**' + - 'resources/**' + - 'cura/**' + - 'icons/**' + - 'tests/**' + - '.github/workflows/conan-*.yml' + - '.github/workflows/notify.yml' + - '.github/workflows/requirements-conan-package.txt' + - 'requirements*.txt' + - 'conanfile.py' + - 'conandata.yml' + - 'GitVersion.yml' + branches: + - main + - 'CURA-*' + - '[1-9]+.[0-9]+' + tags: + - '[1-9]+.[0-9]+.[0-9]+' + +jobs: + conan-recipe-version: + uses: ultimaker/cura/.github/workflows/conan-recipe-version.yml@5.1 + with: + project_name: cura + + conan-package-export-macos: + needs: [ conan-recipe-version ] + uses: ultimaker/cura/.github/workflows/conan-recipe-export.yml@5.1 + with: + recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }} + recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }} + recipe_id_pr: ${{ needs.conan-recipe-version.outputs.recipe_id_pr }} + runs_on: 'macos-10.15' + python_version: '3.10.4' + conan_config_branch: 'master' + conan_logging_level: 'info' + conan_export_binaries: true + secrets: inherit + + conan-package-export-linux: + needs: [ conan-recipe-version ] + uses: ultimaker/cura/.github/workflows/conan-recipe-export.yml@5.1 + with: + recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }} + recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }} + recipe_id_pr: ${{ needs.conan-recipe-version.outputs.recipe_id_pr }} + runs_on: 'ubuntu-20.04' + python_version: '3.10.4' + conan_config_branch: 'master' + conan_logging_level: 'info' + conan_export_binaries: true + secrets: inherit + + conan-package-export-windows: + needs: [ conan-recipe-version ] + uses: ultimaker/cura/.github/workflows/conan-recipe-export.yml@5.1 + with: + recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }} + recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }} + recipe_id_pr: ${{ needs.conan-recipe-version.outputs.recipe_id_pr }} + runs_on: 'windows-2022' + python_version: '3.10.4' + conan_config_branch: 'master' + conan_logging_level: 'info' + conan_export_binaries: true + secrets: inherit + + notify-export: + if: ${{ always() }} + needs: [ conan-package-export-linux, conan-package-export-macos, conan-package-export-windows ] + + uses: ultimaker/cura/.github/workflows/notify.yml@5.1 + with: + success: ${{ contains(join(needs.*.result, ','), 'success') }} + success_title: "New Conan recipe exported in ${{ github.repository }}" + success_body: "Exported ${{ needs.conan-recipe-version.outputs.recipe_id_full }}" + failure_title: "Failed to export Conan Export in ${{ github.repository }}" + failure_body: "Failed to exported ${{ needs.conan-recipe-version.outputs.recipe_id_full }}" + secrets: inherit diff --git a/.github/workflows/conan-recipe-export.yml b/.github/workflows/conan-recipe-export.yml new file mode 100644 index 0000000000..a53059f52a --- /dev/null +++ b/.github/workflows/conan-recipe-export.yml @@ -0,0 +1,101 @@ +name: Export Conan Recipe to server + +on: + workflow_call: + inputs: + recipe_id_full: + required: true + type: string + + recipe_id_latest: + required: false + type: string + + recipe_id_pr: + required: false + type: string + + runs_on: + required: true + type: string + + python_version: + required: true + type: string + + conan_config_branch: + required: false + type: string + + conan_logging_level: + required: false + type: string + + conan_export_binaries: + required: false + type: boolean + +env: + CONAN_LOGIN_USERNAME_CURA: ${{ secrets.CONAN_USER }} + CONAN_PASSWORD_CURA: ${{ secrets.CONAN_PASS }} + CONAN_LOGIN_USERNAME_CURA_CE: ${{ secrets.CONAN_USER }} + CONAN_PASSWORD_CURA_CE: ${{ secrets.CONAN_PASS }} + CONAN_LOG_RUN_TO_OUTPUT: 1 + CONAN_LOGGING_LEVEL: ${{ inputs.conan_logging_level }} + CONAN_NON_INTERACTIVE: 1 + +jobs: + package-export: + runs-on: ${{ inputs.runs_on }} + + steps: + - name: Checkout project + uses: actions/checkout@v3 + + - name: Setup Python and pip + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python_version }} + cache: 'pip' + cache-dependency-path: .github/workflows/requirements-conan-package.txt + + - name: Install Python requirements and Create default Conan profile + run: | + pip install -r .github/workflows/requirements-conan-package.txt + conan profile new default --detect + + - name: Cache Conan local repository packages + uses: actions/cache@v3 + with: + path: $HOME/.conan/data + key: ${{ runner.os }}-conan + + - name: Get Conan configuration from branch + if: ${{ inputs.conan_config_branch != '' }} + run: conan config install https://github.com/Ultimaker/conan-config.git -a "-b ${{ inputs.conan_config_branch }}" + + - name: Get Conan configuration + if: ${{ inputs.conan_config_branch == '' }} + run: conan config install https://github.com/Ultimaker/conan-config.git + + - name: Export the Package (binaries) + if: ${{ inputs.conan_export_binaries == 'true' }} + run: conan export-pkg . ${{ inputs.recipe_id_full }} + + - name: Export the Package + if: ${{ inputs.conan_export_binaries != 'true' && github.event_name != 'pull_request' }} + run: conan export . ${{ inputs.recipe_id_full }} + + - name: Create the latest alias + if: ${{ inputs.recipe_id_latest != '' && github.event_name != 'pull_request' }} + run: conan alias ${{ inputs.recipe_id_latest }} ${{ inputs.recipe_id_full }} + + - name: Create the pull request alias + if: ${{ inputs.recipe_id_pr != '' && github.event_name == 'pull_request' }} + run: conan alias ${{ inputs.recipe_id_latest }} ${{ inputs.recipe_id_full }} + + - name: Upload the Package(s) + run: | + # Only use --all (upload binaries) for the cura repository + conan upload "*" -r cura --all -c + conan upload "*" -r cura-ce -c diff --git a/.github/workflows/conan-recipe-version.yml b/.github/workflows/conan-recipe-version.yml new file mode 100644 index 0000000000..6b04354de3 --- /dev/null +++ b/.github/workflows/conan-recipe-version.yml @@ -0,0 +1,99 @@ +name: Get Conan Recipe Version + +on: + workflow_call: + inputs: + project_name: + required: true + type: string + + outputs: + recipe_id_full: + description: "The full Conan recipe id: /@/" + value: ${{ jobs.get-semver.outputs.recipe_id_full }} + + recipe_id_latest: + description: "The full Conan recipe aliased (latest) id: /(latest)@/" + value: ${{ jobs.get-semver.outputs.recipe_id_latest }} + + recipe_semver_full: + description: "The full semver ..-+" + value: ${{ jobs.get-semver.outputs.semver_full }} + +jobs: + get-semver: + + runs-on: ubuntu-latest + + outputs: + recipe_id_full: ${{ inputs.project_name }}/${{ steps.git-tool.outputs.Major }}.${{ steps.git-tool.outputs.Minor }}.${{ steps.git-tool.outputs.Patch }}-${{ steps.git-tool.outputs.PreReleaseLabel }}+${{ steps.git-tool.outputs.BuildMetaData }}@${{ steps.get-conan-broadcast-data.outputs.user }}/${{ steps.get-conan-broadcast-data.outputs.channel }} + recipe_id_latest: ${{ steps.latest-alias.outputs.recipe_id_latest }} + recipe_id_pr: ${{ steps.pr-alias.outputs.recipe_id_pr }} + semver_full: ${{ steps.git-tool.outputs.Major }}.${{ steps.git-tool.outputs.Minor }}.${{ steps.git-tool.outputs.Patch }}-${{ steps.git-tool.outputs.PreReleaseLabel }}+${{ steps.git-tool.outputs.BuildMetaData }} + user: ${{ steps.get-conan-broadcast-data.outputs.user }} + channel: ${{ steps.get-conan-broadcast-data.outputs.channel }} + + steps: + - name: Checkout repo + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + fetch-depth: 0 + + - name: Install GitVersion + uses: gittools/actions/gitversion/setup@v0.9.13 + with: + versionSpec: '5.x' + + - name: GitTools + id: git-tool + uses: gittools/actions/gitversion/execute@v0.9.13 + + - id: get-conan-broadcast-data + name: Get Conan broadcast data + run: | + if [ "${{ github.ref_type == 'tag' && github.ref_name == '5.1' }}" = "true" ]; then + # tagged commits on a release branch are actual released version and should have no user and channel + # name/major.minor.patch@_/_ + # FIXME: For release branches: maybe rename the branch to release/** + echo '::set-output name=user::_' + echo '::set-output name=channel::_' + elif [ "${{ github.ref_name == 'main' }}" = "true" ]; then + # commits on main are alpha's (nightlies) and are considered stable + # name/major.minor.patch-alpha+build@ultimaker/stable + echo ${{ github.repository_owner }} | awk '{print "::set-output name=user::"tolower($0)}' + echo '::set-output name=channel::stable' + elif [ "${{ github.ref_name == '5.1' }}" = "true" ]; then + # commits on release branches are beta's and are considered stable + # name/major.minor.patch-beta+build@ultimaker/stable + # FIXME: For release branches: maybe rename the branch to release/** + echo ${{ github.repository_owner }} | awk '{print "::set-output name=user::"tolower($0)}' + echo '::set-output name=channel::stable' + else + # commits on other branches are considered unstable and for development purposes only + # Use the Cura branch naming scheme CURA-1234_foo_bar + # we use the first 9 characters of the branch name + # name/major.minor.patch-beta+build@ultimaker/cura_ + echo ${{ github.repository_owner }} | awk '{print "::set-output name=user::"tolower($0)}' + branch=${{ github.ref_name }} + sanitized_branch="${branch//-/_}" + echo $sanitized_branch | awk '{print "::set-output name=channel::"substr(tolower($0),0,9)}' + fi + + - name: Get pull request alias + id: pr-alias + run: | + if [ "${{ github.event_name == 'pull_request' }}" = "true" ]; then + # pull request events are considered unstable and are for testing purposes + # name/latest@ultimaker/pr_ + echo "::set-output name=recipe_id_pr::${{ inputs.project_name }}/latest@${{ steps.get-conan-broadcast-data.outputs.user }}/pr_$PR_NUMBER" + else + echo "::set-output name=recipe_id_pr::''" + fi + env: + PR_NUMBER: ${{ github.event.issue.number }} + + - name: Get latest alias + id: latest-alias + run: | + echo "::set-output name=recipe_id_latest::${{ inputs.project_name }}/latest@${{ steps.get-conan-broadcast-data.outputs.user }}/${{ steps.get-conan-broadcast-data.outputs.channel }}" diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml index 776aa1c652..b22c825c8c 100644 --- a/.github/workflows/no-response.yml +++ b/.github/workflows/no-response.yml @@ -7,7 +7,7 @@ on: types: [created] schedule: # Schedule for ten minutes after the hour, every hour - - cron: '10 * * * *' + - cron: '* */12 * * *' # By specifying the access of one of the scopes, all of those that are not # specified are set to 'none'. diff --git a/.github/workflows/notify.yml b/.github/workflows/notify.yml new file mode 100644 index 0000000000..3d421905d0 --- /dev/null +++ b/.github/workflows/notify.yml @@ -0,0 +1,54 @@ +name: Get Conan Recipe Version + +on: + workflow_call: + inputs: + success: + required: true + type: boolean + + success_title: + required: true + type: string + + success_body: + required: true + type: string + + failure_title: + required: true + type: string + + failure_body: + required: true + type: string + + +jobs: + slackNotification: + name: Slack Notification + + runs-on: ubuntu-latest + + steps: + - name: Slack notify on-success + if: ${{ inputs.success }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_USERNAME: ${{ github.repository }} + SLACK_COLOR: #00ff00 + SLACK_ICON: https://github.com/Ultimaker/Cura/blob/main/icons/cura-128.png?raw=true + SLACK_TITLE: ${{ inputs.success_title }} + SLACK_MESSAGE: ${{ inputs.success_body }} + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} + + - name: Slack notify on-failure + if: ${{ !inputs.success }} + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_USERNAME: ${{ github.repository }} + SLACK_COLOR: #ff0000 + SLACK_ICON: https://github.com/Ultimaker/Cura/blob/main/icons/cura-128.png?raw=true + SLACK_TITLE: ${{ inputs.failure_title }} + SLACK_MESSAGE: ${{ inputs.failure_body }} + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/requirements-conan-package.txt b/.github/workflows/requirements-conan-package.txt new file mode 100644 index 0000000000..674ef437c2 --- /dev/null +++ b/.github/workflows/requirements-conan-package.txt @@ -0,0 +1,2 @@ +conan +sip==6.5.1 \ No newline at end of file diff --git a/.gitignore b/.gitignore index c1fd5477d9..6412843522 100644 --- a/.gitignore +++ b/.gitignore @@ -89,4 +89,13 @@ CuraEngine #Prevents import failures when plugin running tests plugins/__init__.py -/venv +venv/ +build/ +dist/ +conaninfo.txt +conan.lock +conan_imports_manifest.txt +conanbuildinfo.txt +graph_info.json +Ultimaker-Cura.spec +/.run/ diff --git a/CMakeLists.txt b/CMakeLists.txt index f61737fbcf..9d6e3c709b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ # Copyright (c) 2022 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +# For MSVC flags, will be ignored on non-Windows OS's and this project in general. Only needed for cura-build-environment. +cmake_policy(SET CMP0091 NEW) project(cura) cmake_minimum_required(VERSION 3.18) diff --git a/CuraVersion.py.jinja b/CuraVersion.py.jinja new file mode 100644 index 0000000000..1c30a0b5af --- /dev/null +++ b/CuraVersion.py.jinja @@ -0,0 +1,13 @@ +# Copyright (c) 2022 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +CuraAppName = "{{ cura_app_name }}" +CuraAppDisplayName = "{{ cura_app_display_name }}" +CuraVersion = "{{ cura_version }}" +CuraBuildType = "{{ cura_build_type }}" +CuraDebugMode = {{ cura_debug_mode }} +CuraCloudAPIRoot = "{{ cura_cloud_api_root }}" +CuraCloudAPIVersion = "{{ cura_cloud_api_version }}" +CuraCloudAccountAPIRoot = "{{ cura_cloud_account_api_root }}" +CuraMarketplaceRoot = "{{ cura_marketplace_root }}" +CuraDigitalFactoryURL = "{{ cura_digital_factory_url }}" diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 68255c56b9..0000000000 --- a/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -FROM ultimaker/cura-build-environment:1 - -# Environment vars for easy configuration -ENV CURA_APP_DIR=/srv/cura - -# Ensure our sources dir exists -RUN mkdir $CURA_APP_DIR - -# Setup CuraEngine -ENV CURA_ENGINE_BRANCH=master -WORKDIR $CURA_APP_DIR -RUN git clone -b $CURA_ENGINE_BRANCH --depth 1 https://github.com/Ultimaker/CuraEngine -WORKDIR $CURA_APP_DIR/CuraEngine -RUN mkdir build -WORKDIR $CURA_APP_DIR/CuraEngine/build -RUN cmake3 .. -RUN make -RUN make install - -# TODO: setup libCharon - -# Setup Uranium -ENV URANIUM_BRANCH=master -WORKDIR $CURA_APP_DIR -RUN git clone -b $URANIUM_BRANCH --depth 1 https://github.com/Ultimaker/Uranium - -# Setup materials -ENV MATERIALS_BRANCH=master -WORKDIR $CURA_APP_DIR -RUN git clone -b $MATERIALS_BRANCH --depth 1 https://github.com/Ultimaker/fdm_materials materials - -# Setup Cura -WORKDIR $CURA_APP_DIR/Cura -ADD . . -RUN mv $CURA_APP_DIR/materials resources/materials - -# Make sure Cura can find CuraEngine -RUN ln -s /usr/local/bin/CuraEngine $CURA_APP_DIR/Cura - -# Run Cura -WORKDIR $CURA_APP_DIR/Cura -ENV PYTHONPATH=${PYTHONPATH}:$CURA_APP_DIR/Uranium -RUN chmod +x ./CuraEngine -RUN chmod +x ./run_in_docker.sh -CMD "./run_in_docker.sh" diff --git a/GitVersion.yml b/GitVersion.yml new file mode 100644 index 0000000000..b46d102dcf --- /dev/null +++ b/GitVersion.yml @@ -0,0 +1,42 @@ +mode: ContinuousDelivery +next-version: 5.1 +branches: + main: + regex: ^main$ + mode: ContinuousDelivery + tag: alpha + increment: None + prevent-increment-of-merged-branch-version: true + track-merge-target: false + source-branches: [ ] + tracks-release-branches: false + is-release-branch: false + is-mainline: true + pre-release-weight: 55000 + develop: + regex: ^CURA-.*$ + mode: ContinuousDelivery + tag: alpha + increment: None + prevent-increment-of-merged-branch-version: false + track-merge-target: true + source-branches: [ 'main' ] + tracks-release-branches: true + is-release-branch: false + is-mainline: false + pre-release-weight: 0 + release: + regex: ^[\d].[\d]$ + mode: ContinuousDelivery + tag: beta + increment: None + prevent-increment-of-merged-branch-version: true + track-merge-target: false + source-branches: [ 'main' ] + tracks-release-branches: false + is-release-branch: true + is-mainline: false + pre-release-weight: 30000 +ignore: + sha: [ ] +merge-message-formats: { } diff --git a/README.md b/README.md index 1090d13aa7..8ec3101ef6 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,64 @@ -Cura -==== -Ultimaker Cura is a state-of-the-art slicer application to prepare your 3D models for printing with a 3D printer. With hundreds of settings and hundreds of community-managed print profiles, Ultimaker Cura is sure to lead your next project to a success. +# Cura + +

+ + + + + + + + + + + + + + + + +

+ +Ultimaker Cura is a state-of-the-art slicer application to prepare your 3D models for printing with a 3D printer. With hundreds of settings +and hundreds of community-managed print profiles, Ultimaker Cura is sure to lead your next project to a success. ![Screenshot](cura-logo.PNG) -Logging Issues ------------- +## Logging Issues + For crashes and similar issues, please attach the following information: * (On Windows) The log as produced by dxdiag (start -> run -> dxdiag -> save output) * The Cura GUI log file, located at - * `%APPDATA%\cura\\cura.log` (Windows), or usually `C:\Users\\AppData\Roaming\cura\\cura.log` - * `$HOME/Library/Application Support/cura//cura.log` (OSX) - * `$HOME/.local/share/cura//cura.log` (Ubuntu/Linux) + * `%APPDATA%\cura\\cura.log` (Windows), or usually `C:\Users\\AppData\Roaming\cura\\cura.log` + * `$HOME/Library/Application Support/cura//cura.log` (OSX) + * `$HOME/.local/share/cura//cura.log` (Ubuntu/Linux) -If the Cura user interface still starts, you can also reach this directory from the application menu in Help -> Show settings folder +If the Cura user interface still starts, you can also reach this directory from the application menu in Help -> Show settings folder. +An alternative is to install the [ExtensiveSupportLogging plugin](https://marketplace.ultimaker.com/app/cura/plugins/UltimakerPackages/ExtensiveSupportLogging) +this creates a zip folder of the relevant log files. If you're experiencing performance issues, we might ask you to connect the CPU profiler +in this plugin and attach the collected data to your support ticket. -For additional support, you could also ask in the [#cura channel](https://web.libera.chat/#cura) on [libera.chat](https://libera.chat/). For help with development, there is also the [#cura-dev channel](https://web.libera.chat/#cura-dev). - -Dependencies ------------- -* [Uranium](https://github.com/Ultimaker/Uranium) Cura is built on top of the Uranium framework. -* [CuraEngine](https://github.com/Ultimaker/CuraEngine) This will be needed at runtime to perform the actual slicing. -* [fdm_materials](https://github.com/Ultimaker/fdm_materials) Required to load a printer that has swappable material profiles. -* [PySerial](https://github.com/pyserial/pyserial) Only required for USB printing support. -* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers. - -For a list of required Python packages, with their recommended version, see `requirements.txt`. - -This list is not exhaustive at the moment, please check the links in the next section for more details. - -Build scripts -------------- -Please check out [cura-build](https://github.com/Ultimaker/cura-build) for detailed building instructions. - -If you want to build the entire environment from scratch before building Cura as well, [cura-build-environment](https://github.com/Ultimaker/cura-build-environment) might be a starting point before cura-build. (Again, see cura-build for more details.) - -Running from Source -------------- +## Running from Source Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Running-Cura-from-Source) for details about running Cura from source. -Plugins -------------- +## Plugins Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Plugin-Directory) for details about creating and using plugins. -Supported printers -------------- -Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura) for guidelines about adding support for new machines. +## Supported printers +Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura) for guidelines about adding support +for new machines. -Configuring Cura ----------------- +## Configuring Cura Please check out [Wiki page](https://github.com/Ultimaker/Cura/wiki/Cura-Settings) about configuration options for developers. -Translating Cura ----------------- +## Translating Cura Please check out [Wiki page](https://github.com/Ultimaker/Cura/wiki/Translating-Cura) about how to translate Cura into other languages. -License ----------------- -Cura is released under the terms of the LGPLv3 or higher. A copy of this license should be included with the software. +## License +![License](https://img.shields.io/github/license/ultimaker/cura?style=flat) +Cura is released under terms of the LGPLv3 or higher. A copy of this license should be included with the software. Terms of the license can be found in the LICENSE file. Or at +http://www.gnu.org/licenses/lgpl.html + +> But in general it boils down to: +> **You need to share the source of any Cura modifications** diff --git a/Ultimaker-Cura.spec.jinja b/Ultimaker-Cura.spec.jinja new file mode 100644 index 0000000000..ae0636a4cf --- /dev/null +++ b/Ultimaker-Cura.spec.jinja @@ -0,0 +1,60 @@ +# -*- mode: python ; coding: utf-8 -*- +from PyInstaller.utils.hooks import collect_all + +datas = {{ datas }} +binaries = {{ binaries }} + +hiddenimports = {{ hiddenimports }} + +{% for value in collect_all %}tmp_ret = collect_all('{{ value }}') +datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] +{% endfor %} + +block_cipher = None + + +a = Analysis( + ['{{ entrypoint }}'], + pathex=[], + binaries=binaries, + datas=datas, + hiddenimports=hiddenimports, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False +) +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='{{ name }}', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon='{{ icon }}' +) +coll = COLLECT( + exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='{{ name }}' +) diff --git a/build.sh b/build.sh deleted file mode 100644 index 7da99d0de5..0000000000 --- a/build.sh +++ /dev/null @@ -1,34 +0,0 @@ -set -e -set -u - -export OLD_PWD=`pwd` -export CMAKE=/c/software/PCL/cmake-3.0.1-win32-x86/bin/cmake.exe -export MAKE=mingw32-make.exe -export PATH=/c/mingw-w64/i686-4.9.2-posix-dwarf-rt_v3-rev1/mingw32/bin:$PATH - -mkdir -p /c/software/protobuf/_build -cd /c/software/protobuf/_build -$CMAKE ../ -$MAKE install - -mkdir -p /c/software/libArcus/_build -cd /c/software/libArcus/_build -$CMAKE ../ -$MAKE install - -mkdir -p /c/software/PinkUnicornEngine/_build -cd /c/software/PinkUnicornEngine/_build -$CMAKE ../ -$MAKE - -cd $OLD_PWD -export PYTHONPATH=`pwd`/../libArcus/python:/c/Software/Uranium/ -/c/python34/python setup.py py2exe - -cp /c/software/PinkUnicornEngine/_build/CuraEngine.exe dist/ -cp /c/software/libArcus/_install/bin/libArcus.dll dist/ -cp /c/mingw-w64/i686-4.9.2-posix-dwarf-rt_v3-rev1/mingw32/bin/libgcc_s_dw2-1.dll dist/ -cp /c/mingw-w64/i686-4.9.2-posix-dwarf-rt_v3-rev1/mingw32/bin/libwinpthread-1.dll dist/ -cp /c/mingw-w64/i686-4.9.2-posix-dwarf-rt_v3-rev1/mingw32/bin/libstdc++-6.dll dist/ - -/c/program\ files\ \(x86\)/NSIS/makensis.exe installer.nsi diff --git a/conandata.yml b/conandata.yml new file mode 100644 index 0000000000..948922aa0b --- /dev/null +++ b/conandata.yml @@ -0,0 +1,360 @@ +"None": + requirements: + - "arcus/(latest)@ultimaker/stable" + - "curaengine/(latest)@ultimaker/stable" + - "savitar/(latest)@ultimaker/stable" + - "pynest2d/(latest)@ultimaker/stable" + - "uranium/(latest)@ultimaker/stable" + - "fdm_materials/(latest)@ultimaker/stable" + - "cura_binary_data/(latest)@ultimaker/stable" + - "cpython/3.10.4" + runinfo: + entrypoint: "cura_app.py" + pyinstaller: + datas: + cura_plugins: + package: "cura" + src: "plugins" + dst: "share/cura/plugins" + cura_resources: + package: "cura" + src: "resources" + dst: "share/cura/resources" + uranium_plugins: + package: "uranium" + src: "plugins" + dst: "share/uranium/plugins" + uranium_resources: + package: "uranium" + src: "resources" + dst: "share/uranium/resources" + uranium_um_qt_qml_um: + package: "uranium" + src: "site-packages/UM/Qt/qml/UM" + dst: "PyQt6/Qt6/qml/UM" + cura_binary_data: + package: "cura_binary_data" + src: "resources/cura/resources" + dst: "share/cura/resources" + uranium_binary_data: + package: "cura_binary_data" + src: "resources/uranium/resources" + dst: "share/uranium/resources" + windows_binary_data: + package: "cura_binary_data" + src: "windows" + dst: "share/windows" + fdm_materials: + package: "fdm_materials" + src: "materials" + dst: "share/cura/resources/materials" + tcl: + package: "tcl" + src: "lib/tcl8.6" + dst: "tcl" + tk: + package: "tk" + src: "lib/tk8.6" + dst: "tk" + binaries: + curaengine: + package: "curaengine" + src: "bin" + dst: "." + binary: "CuraEngine" + hiddenimports: + - "pySavitar" + - "pyArcus" + - "pynest2d" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "logging.handlers" + - "zeroconf" + - "fcntl" + - "stl" + collect_all: + - "cura" + - "UM" + - "serial" + - "Charon" + - "sqlite3" + - "trimesh" + - "win32ctypes" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + icon: + Windows: "./icons/Cura.ico" + Macos: "./icons/cura.icns" + Linux: "./icons/cura-128.png" +"5.1.0": + requirements: + - "arcus/5.1.0" + - "curaengine/5.1.0" + - "savitar/5.1.0" + - "pynest2d/5.1.0" + - "uranium/5.1.0" + - "fdm_materials/5.1.0" + - "cura_binary_data/5.1.0" + - "cpython/3.10.4" + runinfo: + entrypoint: "cura_app.py" + pyinstaller: + datas: + cura_plugins: + package: "cura" + src: "plugins" + dst: "share/cura/plugins" + cura_resources: + package: "cura" + src: "resources" + dst: "share/cura/resources" + uranium_plugins: + package: "uranium" + src: "plugins" + dst: "share/uranium/plugins" + uranium_resources: + package: "uranium" + src: "resources" + dst: "share/uranium/resources" + uranium_um_qt_qml_um: + package: "uranium" + src: "site-packages/UM/Qt/qml/UM" + dst: "PyQt6/Qt6/qml/UM" + cura_binary_data: + package: "cura_binary_data" + src: "resources/cura/resources" + dst: "share/cura/resources" + uranium_binary_data: + package: "cura_binary_data" + src: "resources/uranium/resources" + dst: "share/uranium/resources" + windows_binary_data: + package: "cura_binary_data" + src: "windows" + dst: "share/windows" + fdm_materials: + package: "fdm_materials" + src: "materials" + dst: "share/cura/resources/materials" + tcl: + package: "tcl" + src: "lib/tcl8.6" + dst: "tcl" + tk: + package: "tk" + src: "lib/tk8.6" + dst: "tk" + binaries: + curaengine: + package: "curaengine" + src: "bin" + dst: "." + binary: "CuraEngine" + hiddenimports: + - "pySavitar" + - "pyArcus" + - "pynest2d" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "logging.handlers" + - "zeroconf" + - "fcntl" + - "stl" + collect_all: + - "cura" + - "UM" + - "serial" + - "Charon" + - "sqlite3" + - "trimesh" + - "win32ctypes" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + icon: + Windows: "./icons/Cura.ico" + Macos: "./icons/cura.icns" + Linux: "./icons/cura-128.png" +"5.1.0-beta": + requirements: + - "arcus/(latest)@ultimaker/stable" + - "curaengine/(latest)@ultimaker/stable" + - "savitar/(latest)@ultimaker/stable" + - "pynest2d/(latest)@ultimaker/stable" + - "uranium/(latest)@ultimaker/stable" + - "fdm_materials/(latest)@ultimaker/stable" + - "cura_binary_data/(latest)@ultimaker/stable" + - "cpython/3.10.4" + runinfo: + entrypoint: "cura_app.py" + pyinstaller: + datas: + cura_plugins: + package: "cura" + src: "plugins" + dst: "share/cura/plugins" + cura_resources: + package: "cura" + src: "resources" + dst: "share/cura/resources" + uranium_plugins: + package: "uranium" + src: "plugins" + dst: "share/uranium/plugins" + uranium_resources: + package: "uranium" + src: "resources" + dst: "share/uranium/resources" + uranium_um_qt_qml_um: + package: "uranium" + src: "site-packages/UM/Qt/qml/UM" + dst: "PyQt6/Qt6/qml/UM" + cura_binary_data: + package: "cura_binary_data" + src: "resources/cura/resources" + dst: "share/cura/resources" + uranium_binary_data: + package: "cura_binary_data" + src: "resources/uranium/resources" + dst: "share/uranium/resources" + windows_binary_data: + package: "cura_binary_data" + src: "windows" + dst: "share/windows" + fdm_materials: + package: "fdm_materials" + src: "materials" + dst: "share/cura/resources/materials" + tcl: + package: "tcl" + src: "lib/tcl8.6" + dst: "tcl" + tk: + package: "tk" + src: "lib/tk8.6" + dst: "tk" + binaries: + curaengine: + package: "curaengine" + src: "bin" + dst: "." + binary: "CuraEngine" + hiddenimports: + - "pySavitar" + - "pyArcus" + - "pynest2d" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "logging.handlers" + - "zeroconf" + - "fcntl" + - "stl" + collect_all: + - "cura" + - "UM" + - "serial" + - "Charon" + - "sqlite3" + - "trimesh" + - "win32ctypes" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + icon: + Windows: "./icons/Cura.ico" + Macos: "./icons/cura.icns" + Linux: "./icons/cura-128.png" +"5.1.0-alpha": + requirements: + - "arcus/(latest)@ultimaker/cura_9365" + - "curaengine/(latest)@ultimaker/cura_9365" + - "savitar/(latest)@ultimaker/cura_9365" + - "pynest2d/(latest)@ultimaker/cura_9365" + - "uranium/(latest)@ultimaker/cura_9365" + - "fdm_materials/(latest)@ultimaker/cura_9365" + - "cura_binary_data/(latest)@ultimaker/cura_9365" + - "cpython/3.10.4" + runinfo: + entrypoint: "cura_app.py" + pyinstaller: + datas: + cura_plugins: + package: "cura" + src: "plugins" + dst: "share/cura/plugins" + cura_resources: + package: "cura" + src: "resources" + dst: "share/cura/resources" + uranium_plugins: + package: "uranium" + src: "plugins" + dst: "share/uranium/plugins" + uranium_resources: + package: "uranium" + src: "resources" + dst: "share/uranium/resources" + uranium_um_qt_qml_um: + package: "uranium" + src: "site-packages/UM/Qt/qml/UM" + dst: "PyQt6/Qt6/qml/UM" + cura_binary_data: + package: "cura_binary_data" + src: "resources/cura/resources" + dst: "share/cura/resources" + uranium_binary_data: + package: "cura_binary_data" + src: "resources/uranium/resources" + dst: "share/uranium/resources" + windows_binary_data: + package: "cura_binary_data" + src: "windows" + dst: "share/windows" + fdm_materials: + package: "fdm_materials" + src: "materials" + dst: "share/cura/resources/materials" + tcl: + package: "tcl" + src: "lib/tcl8.6" + dst: "tcl" + tk: + package: "tk" + src: "lib/tk8.6" + dst: "tk" + binaries: + curaengine: + package: "curaengine" + src: "bin" + dst: "." + binary: "CuraEngine" + hiddenimports: + - "pySavitar" + - "pyArcus" + - "pynest2d" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + - "logging.handlers" + - "zeroconf" + - "fcntl" + - "stl" + collect_all: + - "cura" + - "UM" + - "serial" + - "Charon" + - "sqlite3" + - "trimesh" + - "win32ctypes" + - "PyQt6" + - "PyQt6.QtNetwork" + - "PyQt6.sip" + icon: + Windows: "./icons/Cura.ico" + Macos: "./icons/cura.icns" + Linux: "./icons/cura-128.png" diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000000..533b631abf --- /dev/null +++ b/conanfile.py @@ -0,0 +1,332 @@ +import os +import sys +from pathlib import Path + +from io import StringIO + +from platform import python_version + +from jinja2 import Template + +from conans import tools +from conan import ConanFile +from conan.tools import files +from conan.tools.env import VirtualRunEnv +from conan.errors import ConanInvalidConfiguration + +required_conan_version = ">=1.47.0" + + +class CuraConan(ConanFile): + name = "cura" + license = "LGPL-3.0" + author = "Ultimaker B.V." + url = "https://github.com/Ultimaker/cura" + description = "3D printer / slicing GUI built on top of the Uranium framework" + topics = ("conan", "python", "pyqt5", "qt", "qml", "3d-printing", "slicer") + build_policy = "missing" + exports = "LICENSE*", "Ultimaker-Cura.spec.jinja", "CuraVersion.py.jinja" + settings = "os", "compiler", "build_type", "arch" + no_copy_source = True # We won't build so no need to copy sources to the build folder + + # FIXME: Remove specific branch once merged to main + # Extending the conanfile with the UMBaseConanfile https://github.com/Ultimaker/conan-ultimaker-index/tree/CURA-9177_Fix_CI_CD/recipes/umbase + python_requires = "umbase/0.1.2@ultimaker/testing" + python_requires_extend = "umbase.UMBaseConanfile" + + options = { + "enterprise": ["True", "False", "true", "false"], # Workaround for GH Action passing boolean as lowercase string + "staging": ["True", "False", "true", "false"], # Workaround for GH Action passing boolean as lowercase string + "devtools": [True, False], # FIXME: Split this up in testing and (development / build (pyinstaller) / system installer) tools + "cloud_api_version": "ANY", + "display_name": "ANY", # TODO: should this be an option?? + "cura_debug_mode": [True, False] # FIXME: Use profiles + } + default_options = { + "enterprise": "False", + "staging": "False", + "devtools": False, + "cloud_api_version": "1", + "display_name": "Ultimaker Cura", + "cura_debug_mode": False # Not yet implemented + } + scm = { + "type": "git", + "subfolder": ".", + "url": "auto", + "revision": "auto" + } + + @property + def _staging(self): + return self.options.staging in ["True", 'true'] + + @property + def _enterprise(self): + return self.options.enterprise in ["True", 'true'] + + @property + def _cloud_api_root(self): + return "https://api-staging.ultimaker.com" if self._staging else "https://api.ultimaker.com" + + @property + def _cloud_account_api_root(self): + return "https://account-staging.ultimaker.com" if self._staging else "https://account.ultimaker.com" + + @property + def _marketplace_root(self): + return "https://marketplace-staging.ultimaker.com" if self._staging else "https://marketplace.ultimaker.com" + + @property + def _digital_factory_url(self): + return "https://digitalfactory-staging.ultimaker.com" if self._staging else "https://digitalfactory.ultimaker.com" + + @property + def requirements_txts(self): + if self.options.devtools: + return ["requirements.txt", "requirements-ultimaker.txt", "requirements-dev.txt"] + return ["requirements.txt", "requirements-ultimaker.txt"] + + @property + def _base_dir(self): + if self.install_folder is None: + if self.build_folder is not None: + return Path(self.build_folder) + return Path(os.getcwd(), "venv") + + return Path(self.install_folder) # TODO: add base dir for running from source + + @property + def _share_dir(self): + return self._base_dir.joinpath("share") + + @property + def _script_dir(self): + if self.settings.os == "Windows": + return self._base_dir.joinpath("Scripts") + return self._base_dir.joinpath("bin") + + @property + def _site_packages(self): + if self.settings.os == "Windows": + return self._base_dir.joinpath("Lib", "site-packages") + py_version = tools.Version(self.deps_cpp_info["cpython"].version) + return self._base_dir.joinpath("lib", f"python{py_version.major}.{py_version.minor}", "site-packages") + + @property + def _py_interp(self): + py_interp = self._script_dir.joinpath(Path(self.deps_user_info["cpython"].python).name) + if self.settings.os == "Windows": + py_interp = Path(*[f'"{p}"' if " " in p else p for p in py_interp.parts]) + return py_interp + + def _generate_cura_version(self, location): + with open(Path(__file__).parent.joinpath("CuraVersion.py.jinja"), "r") as f: + cura_version_py = Template(f.read()) + + with open(Path(location, "CuraVersion.py"), "w") as f: + f.write(cura_version_py.render( + cura_app_name = self.name, + cura_app_display_name = self.options.display_name, + cura_version = self.version, + cura_build_type = "Enterprise" if self._enterprise else "", + cura_debug_mode = self.options.cura_debug_mode, + cura_cloud_api_root = self._cloud_api_root, + cura_cloud_api_version = self.options.cloud_api_version, + cura_cloud_account_api_root = self._cloud_account_api_root, + cura_marketplace_root = self._marketplace_root, + cura_digital_factory_url = self._digital_factory_url)) + + def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path): + pyinstaller_metadata = self._um_data(self.version)["pyinstaller"] + datas = [] + for data in pyinstaller_metadata["datas"].values(): + if "package" in data: # get the paths from conan package + if data["package"] == self.name: + src_path = Path(self.package_folder, data["src"]) + else: + src_path = Path(self.deps_cpp_info[data["package"]].rootpath, data["src"]) + elif "root" in data: # get the paths relative from the sourcefolder + src_path = Path(self.source_folder, data["root"], data["src"]) + else: + continue + if src_path.exists(): + datas.append((str(src_path), data["dst"])) + + binaries = [] + for binary in pyinstaller_metadata["binaries"].values(): + if "package" in binary: # get the paths from conan package + src_path = Path(self.deps_cpp_info[binary["package"]].rootpath, binary["src"]) + elif "root" in binary: # get the paths relative from the sourcefolder + src_path = Path(self.source_folder, binary["root"], binary["src"]) + else: + continue + if not src_path.exists(): + continue + for bin in src_path.glob(binary["binary"] + ".*[exe|dll|so|dylib]"): + binaries.append((str(bin), binary["dst"])) + for bin in src_path.glob(binary["binary"]): + binaries.append((str(bin), binary["dst"])) + + with open(Path(__file__).parent.joinpath("Ultimaker-Cura.spec.jinja"), "r") as f: + pyinstaller = Template(f.read()) + + with open(Path(location, "Ultimaker-Cura.spec"), "w") as f: + f.write(pyinstaller.render( + name = str(self.options.display_name).replace(" ", "-"), + entrypoint = entrypoint_location, + datas = datas, + binaries = binaries, + hiddenimports = pyinstaller_metadata["hiddenimports"], + collect_all = pyinstaller_metadata["collect_all"], + icon = icon_path + )) + + def source(self): + self._generate_cura_version(Path(self.source_folder, "cura")) + + def configure(self): + self.options["arcus"].shared = True + self.options["savitar"].shared = True + self.options["pynest2d"].shared = True + self.options["cpython"].shared = True + + def validate(self): + if self.version and tools.Version(self.version) <= tools.Version("4"): + raise ConanInvalidConfiguration("Only versions 5+ are support") + + def requirements(self): + for req in self._um_data(self.version)["requirements"]: + self.requires(req) + + def layout(self): + self.folders.source = "." + self.folders.build = "venv" + self.folders.generators = Path(self.folders.build, "conan") + + self.cpp.package.libdirs = [os.path.join("site-packages", "cura")] + self.cpp.package.bindirs = ["bin"] + self.cpp.package.resdirs = ["resources", "plugins", "packaging", "pip_requirements"] # pip_requirements should be the last item in the list + + def generate(self): + vr = VirtualRunEnv(self) + vr.generate() + + if self.options.devtools: + self._generate_pyinstaller_spec(self.generators_folder, + Path(self.source_folder, self._um_data(self.version)["runinfo"]["entrypoint"]), + Path(self.source_folder, "packaging", self._um_data(self.version)["pyinstaller"]["icon"][str(self.settings.os)])) + + def imports(self): + self.copy("CuraEngine.exe", root_package = "curaengine", src = "@bindirs", dst = "", keep_path = False) + self.copy("CuraEngine", root_package = "curaengine", src = "@bindirs", dst = "", keep_path = False) + + files.rmdir(self, "resources/materials") + self.copy("*.fdm_material", root_package = "fdm_materials", src = "@resdirs", dst = "resources/materials", keep_path = False) + self.copy("*.sig", root_package = "fdm_materials", src = "@resdirs", dst = "resources/materials", keep_path = False) + + # Copy resources of cura_binary_data + self.copy("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[0], + dst = "venv/share/cura", keep_path = True) + self.copy("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[1], + dst = "venv/share/uranium", keep_path = True) + + self.copy("*.dll", src = "@bindirs", dst = self._site_packages) + self.copy("*.pyd", src = "@libdirs", dst = self._site_packages) + self.copy("*.pyi", src = "@libdirs", dst = self._site_packages) + self.copy("*.dylib", src = "@libdirs", dst = self._script_dir) + + def deploy(self): + # Copy CuraEngine.exe to bindirs of Virtual Python Environment + # TODO: Fix source such that it will get the curaengine relative from the executable (Python bindir in this case) + self.copy_deps("CuraEngine.exe", root_package = "curaengine", src = self.deps_cpp_info["curaengine"].bindirs[0], + dst = self._base_dir, + keep_path = False) + self.copy_deps("CuraEngine", root_package = "curaengine", src = self.deps_cpp_info["curaengine"].bindirs[0], dst = self._base_dir, + keep_path = False) + + # Copy resources of Cura (keep folder structure) + self.copy("*", src = self.cpp_info.bindirs[0], dst = self._base_dir, keep_path = False) + self.copy("*", src = self.cpp_info.libdirs[0], dst = self._site_packages.joinpath("cura"), keep_path = True) + self.copy("*", src = self.cpp_info.resdirs[0], dst = self._share_dir.joinpath("cura", "resources"), keep_path = True) + self.copy("*", src = self.cpp_info.resdirs[1], dst = self._share_dir.joinpath("cura", "plugins"), keep_path = True) + + # Copy materials (flat) + self.copy_deps("*.fdm_material", root_package = "fdm_materials", src = self.deps_cpp_info["fdm_materials"].resdirs[0], + dst = self._share_dir.joinpath("cura", "resources", "materials"), keep_path = False) + self.copy_deps("*.sig", root_package = "fdm_materials", src = self.deps_cpp_info["fdm_materials"].resdirs[0], + dst = self._share_dir.joinpath("cura", "resources", "materials"), keep_path = False) + + # Copy resources of Uranium (keep folder structure) + self.copy_deps("*", root_package = "uranium", src = self.deps_cpp_info["uranium"].resdirs[0], + dst = self._share_dir.joinpath("uranium", "resources"), keep_path = True) + self.copy_deps("*", root_package = "uranium", src = self.deps_cpp_info["uranium"].resdirs[1], + dst = self._share_dir.joinpath("uranium", "plugins"), keep_path = True) + self.copy_deps("*", root_package = "uranium", src = self.deps_cpp_info["uranium"].libdirs[0], + dst = self._site_packages.joinpath("UM"), + keep_path = True) + self.copy_deps("*", root_package = "uranium", src = str(Path(self.deps_cpp_info["uranium"].libdirs[0], "Qt", "qml", "UM")), + dst = self._site_packages.joinpath("PyQt6", "Qt6", "qml", "UM"), + keep_path = True) + + # Copy resources of cura_binary_data + self.copy_deps("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[0], + dst = self._share_dir.joinpath("cura"), keep_path = True) + self.copy_deps("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[1], + dst = self._share_dir.joinpath("uranium"), keep_path = True) + if self.settings.os == "Windows": + self.copy_deps("*", root_package = "cura_binary_data", src = self.deps_cpp_info["cura_binary_data"].resdirs[2], + dst = self._share_dir.joinpath("windows"), keep_path = True) + + self.copy_deps("*.dll", src = "@bindirs", dst = self._site_packages) + self.copy_deps("*.pyd", src = "@libdirs", dst = self._site_packages) + self.copy_deps("*.pyi", src = "@libdirs", dst = self._site_packages) + self.copy_deps("*.dylib", src = "@libdirs", dst = self._script_dir) + + # Copy requirements.txt's + self.copy("*.txt", src = self.cpp_info.resdirs[-1], dst = self._base_dir.joinpath("pip_requirements")) + + self._generate_cura_version(Path(self._site_packages, "cura")) + self._generate_pyinstaller_spec(self._base_dir, + Path(self.cpp_info.bin_paths[0], self._um_data(self.version)["runinfo"]["entrypoint"]), + Path(self.cpp_info.res_paths[2], self._um_data(self.version)["pyinstaller"]["icon"][str(self.settings.os)])) + + + def package(self): + self.copy("cura_app.py", src = ".", dst = self.cpp.package.bindirs[0]) + self.copy("*", src = "cura", dst = self.cpp.package.libdirs[0]) + self.copy("*", src = "resources", dst = self.cpp.package.resdirs[0]) + self.copy("*", src = "plugins", dst = self.cpp.package.resdirs[1]) + self.copy("requirement*.txt", src = ".", dst = self.cpp.package.resdirs[-1]) + self.copy("*", src = "packaging", dst = self.cpp.package.resdirs[2]) + + def package_info(self): + self.user_info.pip_requirements = "requirements.txt" + self.user_info.pip_requirements_git = "requirements-ultimaker.txt" + self.user_info.pip_requirements_build = "requirements-dev.txt" + + if self.in_local_cache: + self.runenv_info.append_path("PYTHONPATH", str(Path(self.cpp_info.lib_paths[0]).parent)) + self.runenv_info.append_path("PYTHONPATH", self.cpp_info.res_paths[1]) # Add plugins to PYTHONPATH + else: + self.runenv_info.append_path("PYTHONPATH", self.source_folder) + self.runenv_info.append_path("PYTHONPATH", os.path.join(self.source_folder, "plugins")) + + def package_id(self): + del self.info.settings.os + del self.info.settings.compiler + del self.info.settings.build_type + del self.info.settings.arch + + # The following options shouldn't be used to determine the hash, since these are only used to set the CuraVersion.py + # which will als be generated by the deploy method during the `conan install cura/5.1.0@_/_` + del self.info.options.enterprise + del self.info.options.staging + del self.info.options.devtools + del self.info.options.cloud_api_version + del self.info.options.display_name + del self.info.options.cura_debug_mode + + # TODO: Use the hash of requirements.txt and requirements-ultimaker.txt, Because changing these will actually result in a different + # Cura. This is needed because the requirements.txt aren't managed by Conan and therefor not resolved in the package_id. This isn't + # ideal but an acceptable solution for now. diff --git a/cura/ApplicationMetadata.py b/cura/ApplicationMetadata.py index cb80c12416..981d80e4d3 100644 --- a/cura/ApplicationMetadata.py +++ b/cura/ApplicationMetadata.py @@ -6,7 +6,7 @@ # --------- DEFAULT_CURA_APP_NAME = "cura" DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura" -DEFAULT_CURA_VERSION = "master" +DEFAULT_CURA_VERSION = "dev" DEFAULT_CURA_BUILD_TYPE = "" DEFAULT_CURA_DEBUG_MODE = False diff --git a/cura/Backups/Backup.py b/cura/Backups/Backup.py index a5fc3044ce..19655df531 100644 --- a/cura/Backups/Backup.py +++ b/cura/Backups/Backup.py @@ -136,7 +136,7 @@ class Backup: return False current_version = Version(self._application.getVersion()) - version_to_restore = Version(self.meta_data.get("cura_release", "master")) + version_to_restore = Version(self.meta_data.get("cura_release", "dev")) if current_version < version_to_restore: # Cannot restore version newer than current because settings might have changed. diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e1805584b0..dd67e48c20 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -355,8 +355,14 @@ class CuraApplication(QtApplication): Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources")) if not hasattr(sys, "frozen"): - resource_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources") - Resources.addSecureSearchPath(resource_path) + Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources")) + + # local Conan cache + Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "..", "resources")) + Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "..", "plugins")) + + # venv site-packages + Resources.addSearchPath(os.path.join(os.path.dirname(sys.executable), "..", "share", "cura", "resources")) @classmethod def _initializeSettingDefinitions(cls): diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index 24724ed46a..4937618917 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -100,6 +100,7 @@ class CuraPackageManager(PackageManager): return package_id Logger.error("Could not find package_id for file: {} with GUID: {} ".format(file_name, guid)) + Logger.error(f"Bundled paths searched: {list(Resources.getSecureSearchPaths())}") return "" def getMachinesUsingPackage(self, package_id: str) -> Tuple[List[Tuple[GlobalStack, str, str]], List[Tuple[GlobalStack, str, str]]]: diff --git a/cura/CuraVersion.py.in b/cura/CuraVersion.py.in deleted file mode 100644 index ce2264f5fc..0000000000 --- a/cura/CuraVersion.py.in +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2020 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -CuraAppName = "@CURA_APP_NAME@" -CuraAppDisplayName = "@CURA_APP_DISPLAY_NAME@" -CuraVersion = "@CURA_VERSION@" -CuraBuildType = "@CURA_BUILDTYPE@" -CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False -CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@" -CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@" -CuraCloudAccountAPIRoot = "@CURA_CLOUD_ACCOUNT_API_ROOT@" -CuraMarketplaceRoot = "@CURA_MARKETPLACE_ROOT@" -CuraDigitalFactoryURL = "@CURA_DIGITAL_FACTORY_URL@" diff --git a/docker/build.sh b/docker/build.sh deleted file mode 100755 index 1092ba4852..0000000000 --- a/docker/build.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env bash - -# Abort at the first error. -set -e - -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -PROJECT_DIR="$( cd "${SCRIPT_DIR}/.." && pwd )" - -# Make sure that environment variables are set properly -export PATH="${CURA_BUILD_ENV_PATH}/bin:${PATH}" -export PKG_CONFIG_PATH="${CURA_BUILD_ENV_PATH}/lib/pkgconfig:${PKG_CONFIG_PATH}" -export LD_LIBRARY_PATH="${CURA_BUILD_ENV_PATH}/lib:${LD_LIBRARY_PATH}" - -cd "${PROJECT_DIR}" - - - -# -# Clone Uranium and set PYTHONPATH first -# - -# Check the branch to use for Uranium. -# It tries the following branch names and uses the first one that's available. -# - GITHUB_HEAD_REF: the branch name of a PR. If it's not a PR, it will be empty. -# - GITHUB_BASE_REF: the branch a PR is based on. If it's not a PR, it will be empty. -# - GITHUB_REF: the branch name if it's a branch on the repository; -# refs/pull/123/merge if it's a pull_request. -# - master: the master branch. It should always exist. - -# For debugging. -echo "GITHUB_REF: ${GITHUB_REF}" -echo "GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" -echo "GITHUB_BASE_REF: ${GITHUB_BASE_REF}" - -GIT_REF_NAME_LIST=( "${GITHUB_HEAD_REF}" "${GITHUB_BASE_REF}" "${GITHUB_REF}" "master" ) -for git_ref_name in "${GIT_REF_NAME_LIST[@]}" -do - if [ -z "${git_ref_name}" ]; then - continue - fi - git_ref_name="$(basename "${git_ref_name}")" - # Skip refs/pull/1234/merge as pull requests use it as GITHUB_REF - if [[ "${git_ref_name}" == "merge" ]]; then - echo "Skip [${git_ref_name}]" - continue - fi - URANIUM_BRANCH="${git_ref_name}" - output="$(git ls-remote --heads https://github.com/Ultimaker/Uranium.git "${URANIUM_BRANCH}")" - if [ -n "${output}" ]; then - echo "Found Uranium branch [${URANIUM_BRANCH}]." - break - else - echo "Could not find Uranium branch [${URANIUM_BRANCH}], try next." - fi -done - -echo "Using Uranium branch ${URANIUM_BRANCH} ..." -git clone --depth=1 -b "${URANIUM_BRANCH}" https://github.com/Ultimaker/Uranium.git "${PROJECT_DIR}"/Uranium -export PYTHONPATH="${PROJECT_DIR}/Uranium:.:${PYTHONPATH}" - -mkdir build -cd build -cmake \ - -DCMAKE_BUILD_TYPE=Debug \ - -DCMAKE_PREFIX_PATH="${CURA_BUILD_ENV_PATH}" \ - -DURANIUM_DIR="${PROJECT_DIR}/Uranium" \ - -DBUILD_TESTS=ON \ - -DPRINT_PLUGIN_LIST=OFF \ - -DGENERATE_TRANSLATIONS=OFF \ - .. -make diff --git a/docker/test.sh b/docker/test.sh deleted file mode 100755 index bae2bf785e..0000000000 --- a/docker/test.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash -cd build -ctest -j4 --output-on-failure -T Test diff --git a/docs/resources/deps.dot b/docs/resources/deps.dot new file mode 100644 index 0000000000..dbfe8f4530 --- /dev/null +++ b/docs/resources/deps.dot @@ -0,0 +1,54 @@ +digraph { + "cpython/3.10.4@ultimaker/testing" -> "zlib/1.2.12" + "cpython/3.10.4@ultimaker/testing" -> "openssl/1.1.1l" + "cpython/3.10.4@ultimaker/testing" -> "expat/2.4.1" + "cpython/3.10.4@ultimaker/testing" -> "libffi/3.2.1" + "cpython/3.10.4@ultimaker/testing" -> "mpdecimal/2.5.0@ultimaker/testing" + "cpython/3.10.4@ultimaker/testing" -> "libuuid/1.0.3" + "cpython/3.10.4@ultimaker/testing" -> "libxcrypt/4.4.25" + "cpython/3.10.4@ultimaker/testing" -> "bzip2/1.0.8" + "cpython/3.10.4@ultimaker/testing" -> "gdbm/1.19" + "cpython/3.10.4@ultimaker/testing" -> "sqlite3/3.36.0" + "cpython/3.10.4@ultimaker/testing" -> "tk/8.6.10" + "cpython/3.10.4@ultimaker/testing" -> "ncurses/6.2" + "cpython/3.10.4@ultimaker/testing" -> "xz_utils/5.2.5" + "pynest2d/5.1.0-beta+3@ultimaker/stable" -> "libnest2d/5.1.0-beta+3@ultimaker/stable" + "pynest2d/5.1.0-beta+3@ultimaker/stable" -> "cpython/3.10.4@ultimaker/testing" + "freetype/2.12.1" -> "libpng/1.6.37" + "freetype/2.12.1" -> "zlib/1.2.12" + "freetype/2.12.1" -> "bzip2/1.0.8" + "freetype/2.12.1" -> "brotli/1.0.9" + "savitar/5.1.0-beta+3@ultimaker/stable" -> "pugixml/1.12.1" + "savitar/5.1.0-beta+3@ultimaker/stable" -> "cpython/3.10.4@ultimaker/testing" + "arcus/5.1.0-beta+3@ultimaker/stable" -> "protobuf/3.17.1" + "arcus/5.1.0-beta+3@ultimaker/stable" -> "cpython/3.10.4@ultimaker/testing" + "arcus/5.1.0-beta+3@ultimaker/stable" -> "zlib/1.2.12" + "libpng/1.6.37" -> "zlib/1.2.12" + "curaengine/5.1.0-beta+3@ultimaker/stable" -> "clipper/6.4.2" + "curaengine/5.1.0-beta+3@ultimaker/stable" -> "boost/1.78.0" + "curaengine/5.1.0-beta+3@ultimaker/stable" -> "rapidjson/1.1.0" + "curaengine/5.1.0-beta+3@ultimaker/stable" -> "stb/20200203" + "curaengine/5.1.0-beta+3@ultimaker/stable" -> "protobuf/3.17.1" + "curaengine/5.1.0-beta+3@ultimaker/stable" -> "arcus/5.1.0-beta+3@ultimaker/stable" + "tcl/8.6.10" -> "zlib/1.2.12" + "uranium/5.1.0-beta+3@ultimaker/stable" -> "arcus/5.1.0-beta+3@ultimaker/stable" + "uranium/5.1.0-beta+3@ultimaker/stable" -> "cpython/3.10.4@ultimaker/testing" + "libnest2d/5.1.0-beta+3@ultimaker/stable" -> "boost/1.78.0" + "libnest2d/5.1.0-beta+3@ultimaker/stable" -> "clipper/6.4.2" + "libnest2d/5.1.0-beta+3@ultimaker/stable" -> "nlopt/2.7.0" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "arcus/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "curaengine/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "savitar/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "pynest2d/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "uranium/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "fdm_materials/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "cura_binary_data/5.1.0-beta+3@ultimaker/stable" + "conanfile.py (cura/5.1.0-beta+3@ultimaker/testing)" -> "cpython/3.10.4@ultimaker/testing" + "fontconfig/2.13.93" -> "freetype/2.12.1" + "fontconfig/2.13.93" -> "expat/2.4.1" + "fontconfig/2.13.93" -> "libuuid/1.0.3" + "tk/8.6.10" -> "tcl/8.6.10" + "tk/8.6.10" -> "fontconfig/2.13.93" + "tk/8.6.10" -> "xorg/system" + "protobuf/3.17.1" -> "zlib/1.2.12" +} diff --git a/icons/cura.icns b/icons/cura.icns deleted file mode 100644 index 51d8ea71e8..0000000000 Binary files a/icons/cura.icns and /dev/null differ diff --git a/packaging/AppRun b/packaging/AppRun new file mode 100644 index 0000000000..5a134fa12d --- /dev/null +++ b/packaging/AppRun @@ -0,0 +1,16 @@ +#!/bin/sh + +scriptdir=$(dirname $0) + +export PYTHONPATH="$scriptdir/lib/python3.10" +export LD_LIBRARY_PATH=$scriptdir +export QT_PLUGIN_PATH="$scriptdir/qt/plugins" +export QML2_IMPORT_PATH="$scriptdir/qt/qml" +export QT_QPA_FONTDIR=/usr/share/fonts +export QT_QPA_PLATFORMTHEME=xdgdesktopportal +export QT_XKB_CONFIG_ROOT=/usr/share/X11/xkb + +# Use the openssl.cnf packaged in the AppImage +export OPENSSL_CONF="$scriptdir/openssl.cnf" + +$scriptdir/Ultimaker-Cura "$@" diff --git a/packaging/create_appimage.py b/packaging/create_appimage.py new file mode 100644 index 0000000000..33f8482065 --- /dev/null +++ b/packaging/create_appimage.py @@ -0,0 +1,75 @@ +# Copyright (c) 2022 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +import argparse # Command line arguments parsing and help. +from jinja2 import Template +import os # Finding installation directory. +import os.path # Finding files. +import shutil # Copying files. +import stat # For setting file permissions. +import subprocess # For calling system commands. + +def build_appimage(dist_path, version): + """ + Creates an AppImage file from the build artefacts created so far. + """ + copy_metadata_files(dist_path, version) + + appimage_filename = f"Ultimaker-Cura_{version}.AppImage" + try: + os.remove(os.path.join(dist_path, appimage_filename)) # Ensure any old file is removed, if it exists. + except FileNotFoundError: + pass # If it didn't exist, that's even better. + + generate_appimage(dist_path, appimage_filename) + + sign_appimage(dist_path, appimage_filename) + +def copy_metadata_files(dist_path, version): + """ + Copy metadata files for the metadata of the AppImage. + """ + copied_files = { + "cura-icon_256x256.png": "cura-icon.png", + "cura.appdata.xml": "cura.appdata.xml", + "AppRun": "AppRun" + } + + packaging_dir = os.path.dirname(__file__) + for source, dest in copied_files.items(): + print("Copying", os.path.join(packaging_dir, source), "to", os.path.join(dist_path, dest)) + shutil.copyfile(os.path.join(packaging_dir, source), os.path.join(dist_path, dest)) + + # Ensure that AppRun has the proper permissions: 755 (user reads, writes and executes, group reads and executes, world reads and executes). + print("Changing permissions for AppRun") + os.chmod(os.path.join(dist_path, "AppRun"), stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + + # Provision the Desktop file with the correct version number. + template_path = os.path.join(packaging_dir, "cura.desktop.jinja") + desktop_path = os.path.join(dist_path, "cura.desktop") + print("Provisioning desktop file from", template_path, "to", desktop_path) + with open(template_path, "r") as f: + desktop_file = Template(f.read()) + with open(desktop_path, "w") as f: + f.write(desktop_file.render(cura_version = version)) + +def generate_appimage(dist_path, appimage_filename): + appimage_path = os.path.join(dist_path, appimage_filename) + command = ["appimagetool", "--appimage-extract-and-run", f"{dist_path}/", appimage_path] + result = subprocess.call(command) + if result != 0: + raise RuntimeError(f"The AppImageTool command returned non-zero: {result}") + +def sign_appimage(dist_path, appimage_filename): + appimage_path = os.path.join(dist_path, appimage_filename) + command = ["gpg", "--yes", "--armor", "--detach-sig", appimage_path] + result = subprocess.call(command) + if result != 0: + raise RuntimeError(f"The GPG command returned non-zero: {result}") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description = "Create AppImages of Cura.") + parser.add_argument("dist_path", type=str, help="Path to where PyInstaller installed the distribution of Cura.") + parser.add_argument("version", type=str, help="Full version number of Cura (e.g. '5.1.0-beta')") + args = parser.parse_args() + build_appimage(args.dist_path, args.version) diff --git a/packaging/cura.appdata.xml b/packaging/cura.appdata.xml new file mode 100644 index 0000000000..de940af939 --- /dev/null +++ b/packaging/cura.appdata.xml @@ -0,0 +1,18 @@ + + + com.ultimaker.cura + CC0-1.0 + LGPL-3.0 + Ultimaker Cura + Slicer to prepare your 3D printing projects + +

Ultimaker Cura is a slicer, an application that prepares your model for 3D printing. Optimized, expert-tested profiles for 3D printers and materials mean you can start printing reliably in no time. And with industry-standard software integration, you can streamline your workflow for maximum efficiency.

+
+ https://ultimaker.com/en/software/ultimaker-cura + + + Print preparation screen + https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png + + +
diff --git a/packaging/cura.desktop.jinja b/packaging/cura.desktop.jinja new file mode 100644 index 0000000000..1026d10cb0 --- /dev/null +++ b/packaging/cura.desktop.jinja @@ -0,0 +1,15 @@ +[Desktop Entry] +Name=Ultimaker Cura +Name[de]=Ultimaker Cura +GenericName=3D Printing Software +GenericName[de]=3D-Druck-Software +GenericName[nl]=3D-Print Software +Comment=Cura converts 3D models into paths for a 3D printer. It prepares your print for maximum accuracy, minimum printing time and good reliability with many extra features that make your print come out great. +Exec=Ultimaker-Cura %F +Icon=cura-icon +Terminal=false +Type=Application +MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;image/bmp;image/gif;image/jpeg;image/png;text/x-gcode;application/x-amf;application/x-ply;application/x-ctm;model/vnd.collada+xml;model/gltf-binary;model/gltf+json;model/vnd.collada+xml+zip; +Categories=Graphics; +Keywords=3D;Printing; +X-AppImage-Version={{ cura_version }} diff --git a/packaging/cura_license.txt b/packaging/cura_license.txt new file mode 100644 index 0000000000..07b1d92c0e --- /dev/null +++ b/packaging/cura_license.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/packaging/dmg_sign_noterize.py b/packaging/dmg_sign_noterize.py new file mode 100644 index 0000000000..46a3e1374a --- /dev/null +++ b/packaging/dmg_sign_noterize.py @@ -0,0 +1,71 @@ +import os +import subprocess +import shutil + +SOURCE_DIR = os.environ.get("SOURCE_DIR", ".") +DIST_DIR = os.environ.get("DIST_DIR", os.path.join(SOURCE_DIR, "dist")) +DMG_PATH = "Ultimaker-Cura.dmg" +APP_PATH = "Ultimaker-Cura.app" +ULTIMAKER_CURA_DOMAIN = os.environ.get("ULTIMAKER_CURA_DOMAIN", "nl.ultimaker.cura") + + +def build_dmg() -> None: + create_dmg_executable = os.environ.get("CREATE_DMG_EXECUTABLE", "create-dmg") + + arguments = [create_dmg_executable, + "--window-pos", "640", "360", + "--window-size", "690", "503", + "--app-drop-link", "520", "272", + "--volicon", f"{SOURCE_DIR}/packaging/icons/VolumeIcons_Cura.icns", + "--icon-size", "90", + "--icon", "Ultimaker-Cura.app", "169", "272", + "--eula", f"{SOURCE_DIR}/packaging/cura_license.txt", + "--background", f"{SOURCE_DIR}/packaging/icons/cura_background_dmg.png", + DMG_PATH, + APP_PATH] + + subprocess.run(arguments) + + +def sign(file_path: str) -> None: + codesign_executable = os.environ.get("CODESIGN", "codesign") + codesign_identity = os.environ.get("CODESIGN_IDENTITY", "A831301292FC30F84F3C137F2141401620EE5FA0") + + arguments = [codesign_executable, + "-s", codesign_identity, + "--timestamp", + "-i", f"{ULTIMAKER_CURA_DOMAIN}.dmg", + file_path] + + subprocess.run(arguments) + + +def notarize() -> None: + notarize_user = os.environ.get("NOTARIZE_USER") + notarize_password = os.environ.get("NOTARIZE_PASSWORD") + altool_executable = os.environ.get("ALTOOL_EXECUTABLE", "altool") + + arguments = [ + "xcrun", altool_executable, + "--notarize-app", + "--primary-bundle-id", ULTIMAKER_CURA_DOMAIN, + "--username", notarize_user, + "--password", notarize_password, + "--file", DMG_PATH + ] + + subprocess.run(arguments) + + +if __name__ == "__main__": + try: + os.rename(os.path.join(DIST_DIR, "Ultimaker-Cura"), os.path.join(DIST_DIR, "Ultimaker-Cura.app")) + except: + pass + sign(APP_PATH) + build_dmg() + sign(DMG_PATH) + + # notarize_dmg = bool(os.environ.get("NOTARIZE_DMG", "TRUE")) + # if notarize_dmg: + # notarize() diff --git a/icons/cura.ico b/packaging/icons/Cura.ico similarity index 100% rename from icons/cura.ico rename to packaging/icons/Cura.ico diff --git a/packaging/icons/VolumeIcons_Cura.icns b/packaging/icons/VolumeIcons_Cura.icns new file mode 100644 index 0000000000..6ea4526293 Binary files /dev/null and b/packaging/icons/VolumeIcons_Cura.icns differ diff --git a/icons/cura-128.png b/packaging/icons/cura-128.png similarity index 100% rename from icons/cura-128.png rename to packaging/icons/cura-128.png diff --git a/icons/cura-32.png b/packaging/icons/cura-32.png similarity index 100% rename from icons/cura-32.png rename to packaging/icons/cura-32.png diff --git a/icons/cura-48.png b/packaging/icons/cura-48.png similarity index 100% rename from icons/cura-48.png rename to packaging/icons/cura-48.png diff --git a/icons/cura-64.png b/packaging/icons/cura-64.png similarity index 100% rename from icons/cura-64.png rename to packaging/icons/cura-64.png diff --git a/packaging/icons/cura-icon_128x128.png b/packaging/icons/cura-icon_128x128.png new file mode 100644 index 0000000000..7f70fe330e Binary files /dev/null and b/packaging/icons/cura-icon_128x128.png differ diff --git a/packaging/icons/cura-icon_256x256.png b/packaging/icons/cura-icon_256x256.png new file mode 100644 index 0000000000..a9ddbd94c4 Binary files /dev/null and b/packaging/icons/cura-icon_256x256.png differ diff --git a/packaging/icons/cura-icon_64x64.png b/packaging/icons/cura-icon_64x64.png new file mode 100644 index 0000000000..5bfbf782ce Binary files /dev/null and b/packaging/icons/cura-icon_64x64.png differ diff --git a/packaging/icons/cura.icns b/packaging/icons/cura.icns new file mode 100644 index 0000000000..8e8e09b389 Binary files /dev/null and b/packaging/icons/cura.icns differ diff --git a/packaging/icons/cura_background_dmg.png b/packaging/icons/cura_background_dmg.png new file mode 100644 index 0000000000..e838608293 Binary files /dev/null and b/packaging/icons/cura_background_dmg.png differ diff --git a/packaging/signing/cura.entitlements b/packaging/signing/cura.entitlements new file mode 100644 index 0000000000..3b95f077c9 --- /dev/null +++ b/packaging/signing/cura.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-executable-page-protection + + com.apple.security.cs.disable-library-validation + + + diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000000..190ef82926 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,3 @@ +pytest +pyinstaller +sip==6.5.1 diff --git a/requirements-ultimaker.txt b/requirements-ultimaker.txt new file mode 100644 index 0000000000..ae158516f2 --- /dev/null +++ b/requirements-ultimaker.txt @@ -0,0 +1 @@ +git+https://github.com/ultimaker/libcharon@master#egg=charon diff --git a/requirements.txt b/requirements.txt index dc14e2e041..c759d97a79 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,36 +1,188 @@ -appdirs==1.4.3 -certifi==2019.11.28 -cffi==1.14.1 -chardet==3.0.4 -colorlog -cryptography==3.4.8 -decorator==4.4.0 -idna==2.8 -importlib-metadata==4.10.0 -keyring==23.0.1 -lxml==4.7.1 -mypy==0.740 -netifaces==0.10.9 -networkx==2.6.2 -numpy==1.21.5 -numpy-stl==2.10.1 -packaging==18.0 -pyclipper==1.3.0.post2 -pycollada==0.6 -pycparser==2.20 -pyparsing==2.4.2 -PyQt5==5.15.6 -PyQt5-sip==12.9.0 -pyserial==3.4 -pytest -python-dateutil==2.8.0 -python-utils==2.3.0 -pywin32==303 -scipy==1.8.0rc2 -sentry-sdk==0.13.5 -six==1.12.0 -trimesh==3.9.36 -twisted==21.2.0 -typing -urllib3==1.25.9 -zeroconf==0.31.0 +### Direct requirements for Cura, Uranium and libCharon ### +PyQt6-sip==13.2.1 \ + --hash=sha256:b7bce59900b2e0a04f70246de2ccf79ee7933036b6b9183cf039b62eeae2b858 \ + --hash=sha256:8b52d42e42e6e9f934ac7528cd154ac0210a532bb33fa1edfb4a8bbfb73ff88b \ + --hash=sha256:0314d011633bc697e99f3f9897b484720e81a5f4ba0eaa5f05c5811e2e74ea53 \ + --hash=sha256:226e9e349aa16dc1132f106ca01fa99cf7cb8e59daee29304c2fea5fa33212ec +PyQt6==6.2.3 \ + --hash=sha256:a9bfcac198fe4b703706f809bb686c7cef5f60a7c802fc145c6b57929c7a6a34 \ + --hash=sha256:11c039b07962b29246de2da0912f4f663786185fd74d48daac7a270a43c8d92a \ + --hash=sha256:8a2f357b86fec8598f52f16d5f93416931017ca1986d5f68679c9565bfc21fff \ + --hash=sha256:577334c9d4518022a4cb6f9799dfbd1b996167eb31404b5a63d6c43d603e6418 +PyQt6-Qt6==6.2.4 \ + --hash=sha256:42c37475a50ec7e06e0445ac9ce39465f69a86af407ad9b28b183da178d401ee \ + --hash=sha256:b68543e5d5a4f5d24c26b517569da3cd30b0fbe75390b841e142c160399b3c0a \ + --hash=sha256:0aa93581b92e01deaf2dcaad88ed6718996a6d84de59ee88316bcba143f008c9 \ + --hash=sha256:48bc5b7400d6bca13d8c0a145f82295a6da317952ee1a3f107f1cd7d078c8140 +PyQt6-NetworkAuth==6.2.0 \ + --hash=sha256:23e730cc0d6b828bec2f92d9fac3607871e6033a8af4620e5d4e3afc13bd6c3c \ + --hash=sha256:b85ee25b01d6cb38d6141df0052b96de2df7f6e69066eaddb22ae238f56be40b \ + --hash=sha256:e637781a00dd2032d0fd2025af09274898335033763e1dc765a5a99348f60c3b \ + --hash=sha256:542e9d9a8a5bb78e1f26fa3d35ee01f45209bcf5a35b0cc367aaa85932c29750 +PyQt6-NetworkAuth-Qt6==6.2.4 \ + --hash=sha256:c7996a9d8c4ce024529ec37981fbfd525ab1a2d497af1281f81f2b6054452d2e \ + --hash=sha256:1ae9e08e03bd9d5ebdb42dfaccf484a9cc62eeea7504621fe42c005ff1745e66 \ + --hash=sha256:8ed4e5e0eaaa42a6f91aba6745eea23fb3ffcbddc6b162016936530ed28dd0ad +PyQt6-sip==13.2.1 \ + --hash=sha256:b7bce59900b2e0a04f70246de2ccf79ee7933036b6b9183cf039b62eeae2b858 \ + --hash=sha256:8b52d42e42e6e9f934ac7528cd154ac0210a532bb33fa1edfb4a8bbfb73ff88b \ + --hash=sha256:0314d011633bc697e99f3f9897b484720e81a5f4ba0eaa5f05c5811e2e74ea53 \ + --hash=sha256:226e9e349aa16dc1132f106ca01fa99cf7cb8e59daee29304c2fea5fa33212ec +certifi==2021.10.8 \ + --hash=sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872 \ + --hash=sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569 +cryptography==3.4.8; \ + --hash=sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14 \ + --hash=sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc \ + --hash=sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b +zeroconf==0.31.0 \ + --hash=sha256:53a180248471c6f81bd1fffcbce03ed93d7d8eaf10905c9121ac1ea996d19844 \ + --hash=sha256:5a468da018bc3f04bbce77ae247924d802df7aeb4c291bbbb5a9616d128800b0 +importlib-metadata==4.10.0 \ + --hash=sha256:b7cf7d3fef75f1e4c80a96ca660efbd51473d7e8f39b5ab9210febc7809012a4 \ + --hash=sha256:92a8b58ce734b2a4494878e0ecf7d79ccd7a128b5fc6014c401e0b61f006f0f6 +keyring==23.0.1 \ + --hash=sha256:045703609dd3fccfcdb27da201684278823b72af515aedec1a8515719a038cb8 \ + --hash=sha256:8f607d7d1cc502c43a932a275a56fe47db50271904513a379d39df1af277ac48 + +# Use Numpy wheel that is compiled with Intel optimizations (MKL). Obtained from https://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy +# We cache this at software.ultimaker.com since this website tends to remove older versions rather quickly. +https://software.ultimaker.com/cura-binary-dependencies/numpy-1.21.5+mkl-cp310-cp310-win_amd64.whl; \ + sys_platform=="win32" \ + --hash=sha256:fbd5d5126b730a151134d21994a951fe28df06464e0c9a2cba2a4132e542a5fc +numpy==1.21.5; \ + sys_platform!="win32" \ + --hash=sha256:301e408a052fdcda5cdcf03021ebafc3c6ea093021bf9d1aa47c54d48bdad166 \ + --hash=sha256:a7e8f6216f180f3fd4efb73de5d1eaefb5f5a1ee5b645c67333033e39440e63a \ + --hash=sha256:fc7a7d7b0ed72589fd8b8486b9b42a564f10b8762be8bd4d9df94b807af4a089 \ + --hash=sha256:58ca1d7c8aef6e996112d0ce873ac9dfa1eaf4a1196b4ff7ff73880a09923ba7 \ + --hash=sha256:dc4b2fb01f1b4ddbe2453468ea0719f4dbb1f5caa712c8b21bb3dd1480cd30d9 \ + --hash=sha256:6a5928bc6241264dce5ed509e66f33676fc97f464e7a919edc672fb5532221ee +pyclipper==1.3.0.post2; \ + --hash=sha256:c096703dc32f2e4700a1f7054e8b58c29fe86212fa7a2c2adecb0102cb639fb2 \ + --hash=sha256:a1525051ced1ab74e8d32282299c24c68f3e31cd4b64e0b368720b5da65aad67 \ + --hash=sha256:5960aaa012cb925ef44ecabe69528809564a3c95ceac874d95c6600f207138d3 \ + --hash=sha256:d3954330c02a19f7566651a909ec4bc5733ba6c62a228ab26db4a90305748430 \ + --hash=sha256:5175ee50772a7dcc0feaab19ccf5b979b6066f4753edb330700231cf70d0c918 \ + --hash=sha256:19a6809d9cbd535d0fe922e9315babb8d70b5c7dcd43e0f89740d09c406b40f8 \ + --hash=sha256:5c5d50498e335d7f969ca5ad5886e77c40088521dcabab4feb2f93727140251e +scipy==1.8.1; \ + --hash=sha256:9e3fb1b0e896f14a85aa9a28d5f755daaeeb54c897b746df7a55ccb02b340f33 \ + --hash=sha256:4e53a55f6a4f22de01ffe1d2f016e30adedb67a699a310cdcac312806807ca81 \ + --hash=sha256:a0aa8220b89b2e3748a2836fbfa116194378910f1a6e78e4675a095bcd2c762d \ + --hash=sha256:02b567e722d62bddd4ac253dafb01ce7ed8742cf8031aea030a41414b86c1125 \ + --hash=sha256:65b77f20202599c51eb2771d11a6b899b97989159b7975e9b5259594f1d35ef4 \ + --hash=sha256:9dd4012ac599a1e7eb63c114d1eee1bcfc6dc75a29b589ff0ad0bb3d9412034f \ + --hash=sha256:70de2f11bf64ca9921fda018864c78af7147025e467ce9f4a11bc877266900a6 \ + --hash=sha256:83606129247e7610b58d0e1e93d2c5133959e9cf93555d3c27e536892f1ba1f2 \ + --hash=sha256:f3e7a8867f307e3359cc0ed2c63b61a1e33a19080f92fe377bc7d49f646f2ec1 +trimesh==3.9.36 \ + --hash=sha256:f01e8edab14d1999700c980c21a1546f37417216ad915a53be649d263130181e \ + --hash=sha256:8ac8bea693b3ee119f11b022fc9b9481c9f1af06cb38bc859bf5d16bbbe49b23 +sentry-sdk==0.13.5 \ + --hash=sha256:05285942901d38c7ce2498aba50d8e87b361fc603281a5902dda98f3f8c5e145 \ + --hash=sha256:c6b919623e488134a728f16326c6f0bcdab7e3f59e7f4c472a90eea4d6d8fe82 +mypy==0.931 \ + --hash=sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce \ + --hash=sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d \ + --hash=sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069 \ + --hash=sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c \ + --hash=sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d \ + --hash=sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714 \ + --hash=sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a \ + --hash=sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d \ + --hash=sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05 \ + --hash=sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266 \ + --hash=sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697 \ + --hash=sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc \ + --hash=sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799 \ + --hash=sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd \ + --hash=sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00 \ + --hash=sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7 \ + --hash=sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a \ + --hash=sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0 \ + --hash=sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0 \ + --hash=sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166 +pyserial==3.4 \ + --hash=sha256:6e2d401fdee0eab996cf734e67773a0143b932772ca8b42451440cfed942c627 \ + --hash=sha256:e0770fadba80c31013896c7e6ef703f72e7834965954a78e71a3049488d4d7d8 + +### Indirect requirements ### +numpy-stl==2.10.1 \ + --hash=sha256:f6b529b8a8112dfe456d4f7697c7aee0aca62be5a873879306afe4b26fca963c +python-utils==2.3.0 \ + --hash=sha256:34aaf26b39b0b86628008f2ae0ac001b30e7986a8d303b61e1357dfcdad4f6d3 \ + --hash=sha256:e25f840564554eaded56eaa395bca507b0b9e9f0ae5ecb13a8cb785305c56d25 +six==1.12.0 \ + --hash=sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c \ + --hash=sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73 +shapely==1.8.2 \ + --hash=sha256:572af9d5006fd5e3213e37ee548912b0341fb26724d6dc8a4e3950c10197ebb6 \ + --hash=sha256:c60f3758212ec480675b820b13035dda8af8f7cc560d2cc67999b2717fb8faef \ + --hash=sha256:6bdc7728f1e5df430d8c588661f79f1eed4a2728c8b689e12707cfec217f68f8 \ + --hash=sha256:ce0b5c5f7acbccf98b3460eecaa40e9b18272b2a734f74fcddf1d7696e047e95 \ + --hash=sha256:7c9e3400b716c51ba43eea1678c28272580114e009b6c78cdd00c44df3e325fa \ + --hash=sha256:3423299254deec075e79fb7dc7909d702104e4167149de7f45510c3a6342eeea \ + --hash=sha256:3423299254deec075e79fb7dc7909d702104e4167149de7f45510c3a6342eeea \ + --hash=sha256:44d2832c1b706bf43101fda92831a083467cc4b4923a7ed17319ab599c1025d8 \ + --hash=sha256:44d2832c1b706bf43101fda92831a083467cc4b4923a7ed17319ab599c1025d8 \ + --hash=sha256:75042e8039c79dd01f102bb288beace9dc2f49fc44a2dea875f9b697aa8cd30d \ + --hash=sha256:75042e8039c79dd01f102bb288beace9dc2f49fc44a2dea875f9b697aa8cd30d \ + --hash=sha256:5254240eefc44139ab0d128faf671635d8bdd9c23955ee063d4d6b8f20073ae0 +cython==0.29.26 \ + --hash=sha256:af377d543a762867da11fcf6e558f7a4a535ff8693f30cce123fab10c00fa312 \ + --hash=sha256:f5e15ff892c8afad64931ee3dd723c4755c2c516606f9aae7613bebfac62b0f6 \ + --hash=sha256:2b834ff6e4d10ba6d7a0d676dd71c1b427a181ddbbbbf79e91d1861557aab59f \ + --hash=sha256:c813799d533194b7d85203d881d8b4f567a8c644a67f50d47f1ffbf316df412f \ + --hash=sha256:6773cce9d4b3b6168d8feb2b6f06b658ef1e11cbfec075041745666d8e2a5e45 \ + --hash=sha256:362fbb9cb4627c7786231429768b54aaba5459a2a0e46c25e59f202ca6155437 +pybind11==2.6.2 \ + --hash=sha256:2d8aebe1709bc367e34e3b23d8eccbf3f387ee9d5640548c6260d33b59f02405 \ + --hash=sha256:d0e0aed9279656f21501243b707eb6e3b951e89e10c3271dedf3ae41c365e5ed +wheel==0.37.1 \ + --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4 \ + --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a +setuptools==62.0.0 \ + --hash=sha256:7999cbd87f1b6e1f33bf47efa368b224bed5e27b5ef2c4d46580186cbcb1a86a \ + --hash=sha256:a65e3802053e99fc64c6b3b29c11132943d5b8c8facbcc461157511546510967 +ifaddr==0.1.7 \ + --hash=sha256:1f9e8a6ca6f16db5a37d3356f07b6e52344f6f9f7e806d618537731669eb1a94 \ + --hash=sha256:d1f603952f0a71c9ab4e705754511e4e03b02565bc4cec7188ad6415ff534cd3 +pycparser==2.20 \ + --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 +zipp==3.5.0 \ + --hash=sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3 \ + --hash=sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4 +cffi==1.15.0 \ + --hash=sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954 \ + --hash=sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0 \ + --hash=sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3 \ + --hash=sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2 +urllib3==1.26.9 \ + --hash=sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e \ + --hash=sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14 +mypy-extensions==0.4.3 \ + --hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \ + --hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8 +tomli==2.0.1 \ + --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \ + --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f +typing-extensions==3.10.0.2 \ + --hash=sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e \ + --hash=sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34 +jeepney==0.7.1; \ + --hash=sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac \ + --hash=sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f +SecretStorage==3.3.1 \ + --hash=sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f \ + --hash=sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195 +keyring==23.0.1 \ + --hash=sha256:045703609dd3fccfcdb27da201684278823b72af515aedec1a8515719a038cb8 \ + --hash=sha256:8f607d7d1cc502c43a932a275a56fe47db50271904513a379d39df1af277ac48 +pywin32==303; \ + sys_platform=="win32" \ + --hash=sha256:51cb52c5ec6709f96c3f26e7795b0bf169ee0d8395b2c1d7eb2c029a5008ed51 +pywin32-ctypes==0.2.0; \ + sys_platform=="win32" \ + --hash=sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942 \ + --hash=sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98 diff --git a/run_in_docker.sh b/run_in_docker.sh deleted file mode 100644 index eb364fd887..0000000000 --- a/run_in_docker.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -Xvfb :1 -screen 0 1280x800x16 & -export DISPLAY=:1.0 -python3 cura_app.py --headless \ No newline at end of file diff --git a/test-in-docker.sh b/test-in-docker.sh deleted file mode 100755 index e5a1116646..0000000000 --- a/test-in-docker.sh +++ /dev/null @@ -1,5 +0,0 @@ -sudo rm -rf ./build ./Uranium -sudo docker run -it --rm \ - -v "$(pwd):/srv/cura" ultimaker/cura-build-environment \ - /srv/cura/docker/build.sh -sudo rm -rf ./build ./Uranium