Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

CURA-11622 conan v2 #32

Merged
merged 15 commits into from
Dec 4, 2024
Merged
171 changes: 19 additions & 152 deletions .github/workflows/conan-package.yml
Original file line number Diff line number Diff line change
@@ -1,157 +1,24 @@
---
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:
# FIXME: Not yet implemented
conan_id:
required: false
type: string
description: 'The full conan package ID, e.g. "libnest2d/1.2.3@ultimaker/stable"'
create_latest_alias:
required: true
default: false
type: boolean
description: 'Create latest alias'
create_binaries_windows:
required: true
default: false
type: boolean
description: 'create binaries Windows'
create_binaries_linux:
required: true
default: false
type: boolean
description: 'create binaries Linux'
create_binaries_macos:
required: true
default: false
type: boolean
description: 'create binaries Macos'

push:
paths:
- 'python/**'
- 'test_package/**'
- 'cmake/**'
- 'conanfile.py'
- 'conandata.yml'
- 'CMakeLists.txt'
- '.github/workflows/conan-package.yml'
- '.github/workflows/requirements*'
branches:
- main
- 'CURA-*'
- '[0-9]+.[0-9]+'
tags:
- '[0-9]+.[0-9]+.[0-9]*'
push:
paths:
- 'python/**'
- 'test_package/**'
- 'conanfile.py'
- 'conandata.yml'
- 'CMakeLists.txt'
- '.github/workflows/conan-package.yml'
- '.github/workflows/requirements*'
branches:
- main
- 'CURA-*'
- 'PP-*'
- 'NP-*'
- '[0-9].[0-9]*'
- '[0-9].[0-9][0-9]*'

jobs:
conan-recipe-version:
uses: ultimaker/cura/.github/workflows/conan-recipe-version.yml@main
with:
project_name: pynest2d

conan-package-export:
needs: [ conan-recipe-version ]
uses: ultimaker/cura/.github/workflows/conan-recipe-export.yml@main
with:
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }}
runs_on: 'ubuntu-20.04'
python_version: '3.11.x'
conan_logging_level: 'info'
secrets: inherit

conan-package-create-windows:
if: ${{ (github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch)) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_windows) }}
needs: [ conan-recipe-version, conan-package-export ]

uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
with:
project_name: ${{ needs.conan-recipe-version.outputs.project_name }}
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
build_id: 4
build_info: false
runs_on: 'windows-2022'
python_version: '3.11.x'
conan_config_branch: ''
conan_logging_level: 'info'
secrets: inherit

conan-package-create-macos:
if: ${{ (github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch)) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_macos) }}
needs: [ conan-recipe-version, conan-package-export ]

uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
with:
project_name: ${{ needs.conan-recipe-version.outputs.project_name }}
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
build_id: 3
build_info: false
runs_on: 'macos-11'
python_version: '3.11.x'
conan_logging_level: 'info'
secrets: inherit

conan-package-create-linux-modern:
if: ${{ (github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch)) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux) }}
needs: [ conan-recipe-version, conan-package-export ]

uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
with:
project_name: ${{ needs.conan-recipe-version.outputs.project_name }}
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
build_id: 2
build_info: false
runs_on: 'ubuntu-22.04'
python_version: '3.11.x'
conan_logging_level: 'info'
secrets: inherit

conan-package-create-linux:
if: ${{ (github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch)) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux) }}
needs: [ conan-recipe-version, conan-package-export ]

uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
with:
project_name: ${{ needs.conan-recipe-version.outputs.project_name }}
recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
build_id: 1
build_info: false
runs_on: 'ubuntu-20.04'
python_version: '3.11.x'
conan_logging_level: 'info'
secrets: inherit

notify-export:
if: ${{ always() }}
needs: [ conan-recipe-version, conan-package-export ]

uses: ultimaker/cura/.github/workflows/notify.yml@main
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

notify-create:
if: ${{ always() && ((github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch)) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux)) }}
needs: [ conan-recipe-version, conan-package-create-macos, conan-package-create-windows, conan-package-create-linux, conan-package-create-linux-modern ]

uses: ultimaker/cura/.github/workflows/notify.yml@main
with:
success: ${{ contains(join(needs.*.result, ','), 'success') }}
success_title: "New binaries created in ${{ github.repository }}"
success_body: "Created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
failure_title: "Failed to create binaries in ${{ github.repository }}"
failure_body: "Failed to created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
secrets: inherit
conan-package:
uses: ultimaker/cura-workflows/.github/workflows/conan-package.yml@main
secrets: inherit
2 changes: 0 additions & 2 deletions .github/workflows/requirements-conan-package.txt

This file was deleted.

7 changes: 3 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
cmake_policy(SET CMP0091 NEW)
project(pynest2d)
cmake_minimum_required(VERSION 3.20)
project(pynest2d)
cmake_policy(SET CMP0091 NEW)

find_package(Python REQUIRED)
find_package(nest2d REQUIRED)
find_package(cpython REQUIRED)

find_package(standardprojectsettings REQUIRED)
find_package(sipbuildtool REQUIRED)
Expand All @@ -14,4 +14,3 @@ use_threads(pynest2d)
target_link_libraries(pynest2d INTERFACE nest2d::nest2d cpython::cpython)
add_sip_module(pynest2d)
install_sip_module(pynest2d)

3 changes: 3 additions & 0 deletions conandata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
version: "5.4.0-alpha.0"
requirements:
- "nest2d/[>=5.4.0]@ultimaker/stable"
81 changes: 43 additions & 38 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.env import VirtualBuildEnv
from conan.tools.files import copy, mkdir
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout, CMakeDeps
from conan.tools.env import VirtualBuildEnv, VirtualRunEnv
from conan.tools.files import copy, mkdir, update_conandata
from conan.tools.microsoft import check_min_vs, is_msvc, is_msvc_static_runtime
from conan.tools.scm import Version
from conan.tools.scm import Version, Git


required_conan_version = ">=1.56.0"
required_conan_version = ">=2.7.0"


class PyNest2DConan(ConanFile):
Expand All @@ -24,11 +23,10 @@ class PyNest2DConan(ConanFile):
description = "Python bindings for libnest2d"
topics = ("conan", "cura", "prusaslicer", "nesting", "c++", "bin packaging", "python", "sip")
settings = "os", "compiler", "build_type", "arch"
revision_mode = "scm"
exports = "LICENSE*"
generators = "CMakeDeps", "VirtualBuildEnv", "VirtualRunEnv"
package_type = "library"

python_requires = "pyprojecttoolchain/[>=0.1.7]@ultimaker/stable", "sipbuildtool/[>=0.2.4]@ultimaker/stable"
python_requires = "pyprojecttoolchain/[>=0.2.0]@ultimaker/stable", "sipbuildtool/[>=0.3.0]@ultimaker/stable"

options = {
"shared": [True, False],
Expand All @@ -45,7 +43,11 @@ class PyNest2DConan(ConanFile):

def set_version(self):
if not self.version:
self.version = "5.4.0-alpha"
self.version = self.conan_data["version"]

def export(self):
git = Git(self)
update_conandata(self, {"version": self.version, "commit": git.get_commit()})

@property
def _min_cppstd(self):
Expand All @@ -66,8 +68,13 @@ def export_sources(self):
copy(self, "*", path.join(self.recipe_folder, "python"), path.join(self.export_sources_folder, "python"))

def requirements(self):
self.requires("nest2d/5.3.0")
self.requires("cpython/3.10.4")
for req in self.conan_data["requirements"]:
self.requires(req)
self.requires("cpython/3.12.2")
self.requires("nlopt/2.7.1")

# Although not a direct dependency, clipper is for some reason required at link-time
self.requires("clipper/6.4.2@ultimaker/stable")

def validate(self):
if self.settings.compiler.cppstd:
Expand All @@ -81,8 +88,8 @@ def validate(self):
)

def build_requirements(self):
self.test_requires("standardprojectsettings/[>=0.1.0]@ultimaker/stable")
self.test_requires("sipbuildtool/[>=0.2.4]@ultimaker/stable")
self.test_requires("standardprojectsettings/[>=0.2.0]@ultimaker/stable")
self.test_requires("sipbuildtool/[>=0.3.0]@ultimaker/stable")

def config_options(self):
if self.settings.os == "Windows":
Expand All @@ -91,58 +98,56 @@ def config_options(self):
def configure(self):
if self.options.shared:
self.options.rm_safe("fPIC")
self.options["cpython"].shared = True

def generate(self):
pp = self.python_requires["pyprojecttoolchain"].module.PyProjectToolchain(self)
pp.blocks["tool_sip_project"].values["sip_files_dir"] = str(Path("python").as_posix())
pp.blocks["tool_sip_bindings"].values["name"] = "pynest2d"
pp.blocks["tool_sip_metadata"].values["name"] = "pynest2d"
print(pp.blocks["tool_sip_bindings"].context())
pp.blocks.remove("extra_sources")
pp.generate()

tc = CMakeDeps(self)
tc.generate()

tc = CMakeToolchain(self)
if is_msvc(self):
tc.variables["USE_MSVC_RUNTIME_LIBRARY_DLL"] = not is_msvc_static_runtime(self)
tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0077"] = "NEW"
tc.variables["Python_EXECUTABLE"] = self.deps_user_info["cpython"].python.replace("\\", "/")
tc.variables["Python_USE_STATIC_LIBS"] = not self.options["cpython"].shared
tc.variables["Python_ROOT_DIR"] = self.deps_cpp_info["cpython"].rootpath.replace("\\", "/")
tc.variables["Python_FIND_FRAMEWORK"] = "NEVER"
tc.variables["Python_FIND_REGISTRY"] = "NEVER"
tc.variables["Python_FIND_IMPLEMENTATIONS"] = "CPython"
tc.variables["Python_FIND_STRATEGY"] = "LOCATION"
tc.variables["Python_SITEARCH"] = "site-packages"
tc.generate()

vb = VirtualBuildEnv(self)
vb.generate(scope="build")
vb.generate()

vr = VirtualRunEnv(self)
vr.generate(scope="build")

# Generate the Source code from SIP
sip = self.python_requires["sipbuildtool"].module.SipBuildTool(self)
sip.configure()
sip.build()
tc = self.python_requires["sipbuildtool"].module.SipBuildTool(self)
tc.configure()
tc.build()

def layout(self):
cmake_layout(self)

if self.settings.os in ["Linux", "FreeBSD", "Macos"]:
self.cpp.package.system_libs = ["pthread"]

self.cpp.package.lib = ["pynest2d"]
self.cpp.package.libdirs = ["lib"]

self.layouts.build.runenv_info.prepend_path("PYTHONPATH", ".")
self.layouts.package.runenv_info.prepend_path("PYTHONPATH", "lib")

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
copy(self, pattern="LICENSE*", dst="licenses", src=self.source_folder)
for ext in ("*.pyi", "*.so", "*.lib", "*.a", "*.pyd"):
copy(self, ext, src = self.build_folder, dst = path.join(self.package_folder, "lib"), keep_path = False)

for ext in ("*.dll", "*.so", "*.dylib"):
copy(self, ext, src = self.build_folder, dst = path.join(self.package_folder, "bin"), keep_path = False)
for ext in ("*.pyi", "*.so", "*.lib", "*.a", "*.pyd", "*.dll", "*.dylib"):
copy(self, ext, src=self.build_folder, dst=path.join(self.package_folder, "lib"), keep_path=False)

def package_info(self):
self.cpp_info.libdirs = [ os.path.join(self.package_folder, "lib")]
if self.in_local_cache:
self.runenv_info.append_path("PYTHONPATH", os.path.join(self.package_folder, "lib"))
else:
self.runenv_info.append_path("PYTHONPATH", self.build_folder)
self.conf_info.define("user.pysavitar:pythonpath", os.path.join(self.package_folder, "lib"))
13 changes: 3 additions & 10 deletions test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import shutil
from io import StringIO
from pathlib import Path

from conan import ConanFile
from conan.tools.env import VirtualRunEnv
Expand All @@ -11,7 +9,6 @@

class PyNest2DTestConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "VirtualRunEnv"
test_type = "explicit"

def requirements(self):
Expand All @@ -22,19 +19,15 @@ def generate(self):
venv.generate()

cpp_info = self.dependencies[self.tested_reference_str].cpp_info
copy(self, "*.pyd", src = cpp_info.libdirs[0], dst =self.build_folder)
copy(self, "*.pyd", src=cpp_info.libdirs[0], dst=self.build_folder)

for dep in self.dependencies.values():
for bin_dir in dep.cpp_info.bindirs:
copy(self, "*.dll", src = bin_dir, dst = self.build_folder)

def build(self):
if can_run(self):
shutil.copy(Path(self.source_folder).joinpath("test.py"), Path(self.build_folder).joinpath("test.py"))
copy(self, "*.dll", src=bin_dir, dst=self.build_folder)

def test(self):
if can_run(self):
test_buf = StringIO()
self.run(f"python test.py", env = "conanrun", output = test_buf)
self.run(f"python test.py", env="conanrun", stdout=test_buf, scope="run")
if "True" not in test_buf.getvalue():
raise ConanException("pynest2d wasn't build correctly!")
Loading