diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5af4d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,123 @@ +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### CMake template +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +.idea/ +tmp/* +test_package/build/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 82bde89..c0d8cea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,10 @@ cmake_minimum_required(VERSION 3.1) project(Libnest2D) -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED) +# Use C++17 Standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) # Add our own cmake module path. list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/) @@ -160,7 +162,7 @@ install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindClipper.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/Findclipper.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindNLopt.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindTBB.cmake" DESTINATION diff --git a/cmake_modules/FindClipper.cmake b/cmake_modules/Findclipper.cmake similarity index 92% rename from cmake_modules/FindClipper.cmake rename to cmake_modules/Findclipper.cmake index bdc9353..07582d5 100644 --- a/cmake_modules/FindClipper.cmake +++ b/cmake_modules/Findclipper.cmake @@ -74,11 +74,11 @@ MARK_AS_ADVANCED( CLIPPER_LIBRARIES) if(CLIPPER_FOUND) - add_library(Clipper::Clipper UNKNOWN IMPORTED) - set_target_properties(Clipper::Clipper PROPERTIES IMPORTED_LOCATION ${CLIPPER_LIBRARIES}) - set_target_properties(Clipper::Clipper PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CLIPPER_INCLUDE_DIRS}) + add_library(clipper::clipper UNKNOWN IMPORTED) + set_target_properties(clipper::clipper PROPERTIES IMPORTED_LOCATION ${CLIPPER_LIBRARIES}) + set_target_properties(clipper::clipper PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CLIPPER_INCLUDE_DIRS}) if(CLIPPER_LIBRARIES_RELEASE AND CLIPPER_LIBRARIES_DEBUG) - set_target_properties(Clipper::Clipper PROPERTIES + set_target_properties(clipper::clipper PROPERTIES IMPORTED_LOCATION_DEBUG ${CLIPPER_LIBRARIES_DEBUG} IMPORTED_LOCATION_RELWITHDEBINFO ${CLIPPER_LIBRARIES_RELEASE} IMPORTED_LOCATION_RELEASE ${CLIPPER_LIBRARIES_RELEASE} diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..1a079ee --- /dev/null +++ b/conanfile.py @@ -0,0 +1,117 @@ +from typing import Optional + +from conans import ConanFile, tools +from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake +from conan.tools.layout import cmake_layout +from conan.tools.files.packager import AutoPackager +from conans.model.layout import Folders, Infos + +required_conan_version = ">=1.42" + + +class libnest2dConan(ConanFile): + name = "libnest2d" + version = "4.11.0" + license = "LGPL-3.0" + author = "Ultimaker B.V." + url = "https://github.com/Ultimaker/libnest2d" + description = "2D irregular bin packaging and nesting library written in modern C++" + topics = ("conan", "cura", "prusaslicer", "nesting", "c++", "bin packaging") + settings = "os", "compiler", "build_type", "arch" + revision_mode = "scm" + build_policy = "missing" + exports = "LICENSE.txt" + exports_sources = "*", "!cmake-build-*", "!tmp", "test_package" + options = { + "shared": [True, False], + "fPIC": [True, False], + "tests": [True, False], + "header_only": [True, False], + "geometries": ["clipper", "boost", "eigen"], + "optimizer": ["nlopt", "optimlib"], + "threading": ["std", "tbb", "omp", "none"] + } + default_options = { + "shared": True, + "tests": False, + "fPIC": True, + "header_only": False, + "geometries": "clipper", + "optimizer": "nlopt", + "threading": "std" + } + scm = { + "type": "git", + "subfolder": ".", + "url": "auto", + "revision": "auto" + } + + def configure(self): + if self.options.shared or self.settings.compiler == "Visual Studio": + del self.options.fPIC + if self.options.geometries == "clipper": + self.options["clipper"].shared = self.options.shared + self.options["boost"].header_only = True + self.options["boost"].shared = self.options.shared + if self.options.optimizer == "nlopt": + self.options["nlopt"].shared = self.options.shared + + def build_requirements(self): + if self.options.tests: + self.build_requires("catch2/[>=2.13.6]", force_host_context=True) + + def requirements(self): + if self.options.geometries == "clipper": + self.requires("clipper/[>=6.4.2]") + self.requires("boost/1.70.0") + elif self.options.geometries == "eigen": + self.requires("eigen/[>=3.3.7]") + if self.options.optimizer == "nlopt": + self.requires("nlopt/[>=2.7.0]") + + def validate(self): + if self.settings.compiler.get_safe("cppstd"): + tools.check_min_cppstd(self, 17) + + def layout(self): + cmake_layout(self) + self.cpp.package.libs = tools.collect_libs(self) + self.cpp.package.defines = [f"LIBNEST2D_GEOMETRIES_{self.options.geometries}", + f"LIBNEST2D_OPTIMIZERS_{self.options.optimizer}", + f"LIBNEST2D_THREADING_{self.options.threading}"] + self.cpp.package.system_libs = [] + if self.settings.os in ["Linux", "FreeBSD", "Macos"]: + self.cpp.package.system_libs.append("pthread") + + def generate(self): + cmake = CMakeDeps(self) + cmake.generate() + + tc = CMakeToolchain(self) + + # FIXME: This shouldn't be necessary (maybe a bug in Conan????) + if self.settings.compiler == "Visual Studio": + tc.blocks["generic_system"].values["generator_platform"] = None + tc.blocks["generic_system"].values["toolset"] = None + + tc.variables["LIBNEST2D_HEADER_ONLY"] = self.options.header_only + if self.options.header_only: + tc.variables["BUILD_SHARED_LIBS"] = False + else: + tc.variables["BUILD_SHARED_LIBS"] = self.options.shared + tc.variables["LIBNEST2D_BUILD_UNITTESTS"] = self.options.tests + tc.variables["LIBNEST2D_GEOMETRIES"] = self.options.geometries + tc.variables["LIBNEST2D_OPTIMIZER"] = self.options.optimizer + tc.variables["LIBNEST2D_THREADING"] = self.options.threading + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + cmake.install() + + def package(self): + packager = AutoPackager(self) + packager.run() diff --git a/external/+Clipper/CMakeLists.txt b/external/+Clipper/CMakeLists.txt index 6ea945a..db51720 100644 --- a/external/+Clipper/CMakeLists.txt +++ b/external/+Clipper/CMakeLists.txt @@ -1,5 +1,5 @@ -require_dependency(Boost) +require_dependency(boost) -rp_add_cmake_project(Clipper +rp_add_cmake_project(clipper GIT_REPOSITORY https://github.com/tamasmeszaros/libpolyclipping.git ) diff --git a/include/libnest2d/backends/clipper/CMakeLists.txt b/include/libnest2d/backends/clipper/CMakeLists.txt index 031a0a0..2c7d6ad 100644 --- a/include/libnest2d/backends/clipper/CMakeLists.txt +++ b/include/libnest2d/backends/clipper/CMakeLists.txt @@ -1,14 +1,20 @@ add_library(clipperBackend INTERFACE) -require_package(Clipper 6.1 REQUIRED) -target_link_libraries(clipperBackend INTERFACE Clipper::Clipper) +find_package(clipper 6.1 QUIET) +if(NOT TARGET clipper::clipper) + message(STATUS "Using require_package to obtain Clipper") + require_package(Clipper 6.1 REQUIRED) + add_library(clipper::clipper INTERFACE IMPORTED) +endif() +target_link_libraries(clipperBackend INTERFACE clipper::clipper) + # Clipper backend is not enough on its own, it still need some functions # from Boost geometry -require_package(Boost 1.58 REQUIRED) +require_package(boost 1.58 REQUIRED) -if(TARGET Boost::boost) - target_link_libraries(clipperBackend INTERFACE Boost::boost ) +if(TARGET boost::boost) + target_link_libraries(clipperBackend INTERFACE boost::boost ) elseif(Boost_INCLUDE_DIRS_FOUND) target_include_directories(clipperBackend INTERFACE $ ) endif() diff --git a/include/libnest2d/backends/clipper/clipper_polygon.hpp b/include/libnest2d/backends/clipper/clipper_polygon.hpp index 6511fbb..5993221 100644 --- a/include/libnest2d/backends/clipper/clipper_polygon.hpp +++ b/include/libnest2d/backends/clipper/clipper_polygon.hpp @@ -1,7 +1,7 @@ #ifndef CLIPPER_POLYGON_HPP #define CLIPPER_POLYGON_HPP -#include +#include namespace ClipperLib { diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt new file mode 100644 index 0000000..50a416a --- /dev/null +++ b/test_package/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.13) + +project(Libnest2D_example) +set(CMAKE_CXX_STANDARD 17) +find_package(libnest2d REQUIRED) + +add_executable(test main.cpp) + +target_link_libraries(test PRIVATE libnest2d::libnest2d) +target_include_directories(test PRIVATE ${libnest2d_INCLUDE_DIRS}) \ No newline at end of file diff --git a/test_package/conanfile.py b/test_package/conanfile.py new file mode 100644 index 0000000..0f2840e --- /dev/null +++ b/test_package/conanfile.py @@ -0,0 +1,34 @@ +from conans import ConanFile, CMake +from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake + + +class LibNest2DTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + + def build_requirements(self): + self.build_requires("cmake/[>=3.16.2]") + + def requirements(self): + self.requires(f"libnest2d/4.11.0@ultimaker/testing") + + def generate(self): + cmake = CMakeDeps(self) + cmake.generate() + tc = CMakeToolchain(self) + if self.settings.compiler == "Visual Studio": + tc.blocks["generic_system"].values["generator_platform"] = None + tc.blocks["generic_system"].values["toolset"] = None + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def imports(self): + self.copy("*.dll", str(self.settings.build_type), "lib") + self.copy("*.dll", str(self.settings.build_type), "lib") + self.copy("*.dylib", str(self.settings.build_type), "lib") + + def test(self): + pass # only interested in compiling and linking \ No newline at end of file diff --git a/test_package/main.cpp b/test_package/main.cpp new file mode 100644 index 0000000..044700f --- /dev/null +++ b/test_package/main.cpp @@ -0,0 +1,6 @@ +#include + +int main(void /*int argc, char **argv*/) { + auto pi = libnest2d::Pi; + return 0; +} \ No newline at end of file