From 4296fd8b6e8c56351601a7a100b27ac5be0ab1d1 Mon Sep 17 00:00:00 2001 From: "j.spijker@ultimaker.com" Date: Thu, 5 Aug 2021 18:09:20 +0200 Subject: [PATCH 1/6] Added Conan support - Added conanfile.py with build recipe - Use StandardProjectSettings - Remove find_packages Clipper and NLopt these are dependencies of libnest2d not pynest2d - Added .gitignore (usefull to have in a project) --- .gitignore | 262 ++++++++++++++++++++++++++++ CMakeLists.txt | 68 +++----- cmake/FindClipper.cmake | 88 ---------- cmake/FindNLopt.cmake | 83 --------- cmake/FindSIP.cmake | 94 +++++----- cmake/Findlibnest2d.cmake | 19 +- cmake/SIPMacros.cmake | 32 ++-- cmake/StandardProjectSettings.cmake | 166 ++++++++++++++++++ conanfile.py | 97 ++++++++++ 9 files changed, 631 insertions(+), 278 deletions(-) create mode 100644 .gitignore delete mode 100644 cmake/FindClipper.cmake delete mode 100644 cmake/FindNLopt.cmake create mode 100644 cmake/StandardProjectSettings.cmake create mode 100644 conanfile.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d38b206 --- /dev/null +++ b/.gitignore @@ -0,0 +1,262 @@ +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +### 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 + +### 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 + +tmp/ +.idea/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 962a3d4..c565d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,45 +1,12 @@ -# Copyright (c) 2020 Ultimaker B.V. +# Copyright (c) 2021 Ultimaker B.V. # pynest2d is released under the terms of the LGPLv3 or higher. project(pynest2d) -cmake_minimum_required(VERSION 3.6) # Lowest version it's been tested with. +cmake_minimum_required(VERSION 3.13) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +include(cmake/StandardProjectSettings.cmake) -# Requirements. -# FIXME: Remove the code for CMake <3.12 once we have switched over completely. -# FindPython3 is a new module since CMake 3.12. It deprecates FindPythonInterp and FindPythonLibs. -if(${CMAKE_VERSION} VERSION_LESS 3.12) - # FIXME: Use FindPython3 to find Python, new in CMake 3.12. - # However currently on our CI server it finds the wrong Python version and then doesn't find the headers. - find_package(PythonInterp 3.5 REQUIRED) - find_package(PythonLibs 3.5 REQUIRED) - -else() - # Use FindPython3 for CMake >=3.12 - find_package(Python3 3.5 REQUIRED COMPONENTS Interpreter Development) -endif() - -find_package(SIP REQUIRED) # To create Python bindings. -find_package(libnest2d REQUIRED) # The library we're creating bindings for. -find_package(Clipper REQUIRED) # Dependency of libnest2d. -find_package(NLopt REQUIRED) # Dependency of libnest2d. -find_package(Boost REQUIRED) # Dependency of libnest2d. -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLIBNEST2D_GEOMETRIES_clipper -DLIBNEST2D_OPTIMIZERS_nlopt -DLIBNEST2D_THREADING_std") # Tell libnest2d to use Clipper and NLopt, and standard threads. - -# Some build options. -set(CMAKE_CXX_STANDARD 17) -if(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -endif() -if(UNIX) - # Want to be able to move symbols from the Clipper library. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") -endif() -if(NOT DEFINED LIB_SUFFIX) - set(LIB_SUFFIX "") -endif() +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # Building and linking. set(SIP_EXTRA_FILES_DEPEND @@ -55,6 +22,27 @@ set(SIP_EXTRA_FILES_DEPEND src/String.sip ) -set(SIP_EXTRA_OPTIONS -g -n PyQt5.sip) # Always release the GIL before calling C++ methods. -n PyQt5.sip is required to not get the PyCapsule error -include_directories(src/ ${SIP_INCLUDE_DIRS} ${Python3_INCLUDE_DIRS} ${CLIPPER_INCLUDE_DIRS} ${NLopt_INCLUDE_DIRS} ${LIBNEST2D_INCLUDE_DIRS}) -add_sip_python_module(pynest2d src/Pynest2D.sip ${CLIPPER_LIBRARIES} ${NLopt_LIBRARIES}) +find_package(SIP REQUIRED) +set(SIP_EXTRA_OPTIONS -y pynest2d.pyi -o -g -n PyQt5.sip) # Always release the GIL before calling C++ methods. -n PyQt5.sip is required to not get the PyCapsule error +add_sip_python_module(pynest2d src/Pynest2D.sip) + +set_project_standards(python_module_pynest2d) +set_project_warnings(python_module_pynest2d) + +use_python(python_module_pynest2d Interpreter Development) +find_package(libnest2d REQUIRED) # The library we're creating bindings for. + +target_link_libraries(python_module_pynest2d PUBLIC libnest2d::libnest2d SIP::SIP) + +target_compile_definitions(python_module_pynest2d + PRIVATE + LIBNEST2D_GEOMETRIES_clipper + LIBNEST2D_OPTIMIZERS_nlopt + LIBNEST2D_THREADING_std + ) + +target_include_directories(python_module_pynest2d + PRIVATE + $ + $ + ) \ No newline at end of file diff --git a/cmake/FindClipper.cmake b/cmake/FindClipper.cmake deleted file mode 100644 index a399dfd..0000000 --- a/cmake/FindClipper.cmake +++ /dev/null @@ -1,88 +0,0 @@ -#Find Clipper library (http://www.angusj.com/delphi/clipper.php). -#The following variables are set -# -#CLIPPER_FOUND -#CLIPPER_INCLUDE_DIRS -#CLIPPER_LIBRARIES -# -#It searches the environment variable $CLIPPER_PATH automatically. - -unset(CLIPPER_FOUND CACHE) -unset(CLIPPER_INCLUDE_DIRS CACHE) -unset(CLIPPER_LIBRARIES CACHE) -unset(CLIPPER_LIBRARIES_RELEASE CACHE) -unset(CLIPPER_LIBRARIES_DEBUG CACHE) - -if($ EQUAL "debug") - set(CLIPPER_BUILD_TYPE DEBUG) -else() - set(CLIPPER_BUILD_TYPE RELEASE) -endif() - -find_path(CLIPPER_INCLUDE_DIRS clipper.hpp - $ENV{CLIPPER_PATH} - $ENV{CLIPPER_PATH}/cpp/ - $ENV{CLIPPER_PATH}/include/ - $ENV{CLIPPER_PATH}/include/polyclipping/ - ${PROJECT_SOURCE_DIR}/python/pymesh/third_party/include/ - ${PROJECT_SOURCE_DIR}/python/pymesh/third_party/include/polyclipping/ - ${CMAKE_PREFIX_PATH}/include/polyclipping - ${CMAKE_PREFIX_PATH}/include/ - /opt/local/include/ - /opt/local/include/polyclipping/ - /usr/local/include/ - /usr/local/include/polyclipping/ - /usr/include - /usr/include/polyclipping/ -) - -set(LIB_SEARCHDIRS - $ENV{CLIPPER_PATH} - $ENV{CLIPPER_PATH}/cpp/ - $ENV{CLIPPER_PATH}/cpp/build/ - $ENV{CLIPPER_PATH}/lib/ - $ENV{CLIPPER_PATH}/lib/polyclipping/ - ${PROJECT_SOURCE_DIR}/python/pymesh/third_party/lib/ - ${PROJECT_SOURCE_DIR}/python/pymesh/third_party/lib/polyclipping/ - ${CMAKE_PREFIX_PATH}/lib/ - ${CMAKE_PREFIX_PATH}/lib/polyclipping/ - /opt/local/lib/ - /opt/local/lib/polyclipping/ - /usr/local/lib/ - /usr/local/lib/polyclipping/ - /usr/lib/polyclipping -) - -set(_deb_postfix "d") - -find_library(CLIPPER_LIBRARIES_RELEASE polyclipping ${LIB_SEARCHDIRS}) -find_library(CLIPPER_LIBRARIES_DEBUG polyclipping${_deb_postfix} ${LIB_SEARCHDIRS}) - -if(CLIPPER_LIBRARIES_${CLIPPER_BUILD_TYPE}) - set(CLIPPER_LIBRARIES "${CLIPPER_LIBRARIES_${CLIPPER_BUILD_TYPE}}") -else() - set(CLIPPER_LIBRARIES "${CLIPPER_LIBRARIES_RELEASE}") -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Clipper - "Clipper library cannot be found. Consider set CLIPPER_PATH environment variable" - CLIPPER_INCLUDE_DIRS - CLIPPER_LIBRARIES -) - -mark_as_advanced(CLIPPER_INCLUDE_DIRS 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}) - if(CLIPPER_LIBRARIES_RELEASE AND CLIPPER_LIBRARIES_DEBUG) - set_target_properties(Clipper::Clipper PROPERTIES - IMPORTED_LOCATION_DEBUG ${CLIPPER_LIBRARIES_DEBUG} - IMPORTED_LOCATION_RELWITHDEBINFO ${CLIPPER_LIBRARIES_RELEASE} - IMPORTED_LOCATION_RELEASE ${CLIPPER_LIBRARIES_RELEASE} - IMPORTED_LOCATION_MINSIZEREL ${CLIPPER_LIBRARIES_RELEASE} - ) - endif() -endif() diff --git a/cmake/FindNLopt.cmake b/cmake/FindNLopt.cmake deleted file mode 100644 index bf2ed35..0000000 --- a/cmake/FindNLopt.cmake +++ /dev/null @@ -1,83 +0,0 @@ -#Find NLopt library. -#The following variables are set -# -#NLopt_FOUND -#NLopt_INCLUDE_DIRS -#NLopt_LIBRARIES -# -#It searches the environment variable $NLopt_PATH automatically. - -unset(NLopt_FOUND CACHE) -unset(NLopt_INCLUDE_DIRS CACHE) -unset(NLopt_LIBRARIES CACHE) -unset(NLopt_LIBRARIES_RELEASE CACHE) -unset(NLopt_LIBRARIES_DEBUG CACHE) - -if($ EQUAL "debug") - set(NLopt_BUILD_TYPE DEBUG) -else() - set(NLopt_BUILD_TYPE RELEASE) -endif() - -find_path(NLopt_INCLUDE_DIRS nlopt.hpp - $ENV{NLopt_PATH} - $ENV{NLopt_PATH}/cpp/ - $ENV{NLopt_PATH}/include/ - ${CMAKE_PREFIX_PATH}/include/nlopt - ${CMAKE_PREFIX_PATH}/include/ - /opt/local/include/ - /opt/local/include/nlopt/ - /usr/local/include/ - /usr/local/include/nlopt/ - /usr/include - /usr/include/nlopt/ -) - -set(LIB_SEARCHDIRS - $ENV{NLopt_PATH} - $ENV{NLopt_PATH}/cpp/ - $ENV{NLopt_PATH}/cpp/build/ - $ENV{NLopt_PATH}/lib/ - $ENV{NLopt_PATH}/lib/nlopt/ - ${CMAKE_PREFIX_PATH}/lib/ - ${CMAKE_PREFIX_PATH}/lib/nlopt/ - /opt/local/lib/ - /opt/local/lib/nlopt/ - /usr/local/lib/ - /usr/local/lib/nlopt/ - /usr/lib/nlopt -) - -set(_deb_postfix "d") - -find_library(NLopt_LIBRARIES_RELEASE nlopt ${LIB_SEARCHDIRS}) -find_library(NLopt_LIBRARIES_DEBUG nlopt${_deb_postfix} ${LIB_SEARCHDIRS}) - -if(NLopt_LIBRARIES_${NLopt_BUILD_TYPE}) - set(NLopt_LIBRARIES "${NLopt_LIBRARIES_${NLopt_BUILD_TYPE}}") -else() - set(NLopt_LIBRARIES "${NLopt_LIBRARIES_RELEASE}") -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(NLopt - "NLopt library cannot be found. Consider set NLopt_PATH environment variable" - NLopt_INCLUDE_DIRS - NLopt_LIBRARIES -) - -mark_as_advanced(NLopt_INCLUDE_DIRS NLopt_LIBRARIES) - -if(NLopt_FOUND) - add_library(NLopt::nlopt UNKNOWN IMPORTED) - set_target_properties(NLopt::nlopt PROPERTIES IMPORTED_LOCATION ${NLopt_LIBRARIES}) - set_target_properties(NLopt::nlopt PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${NLopt_INCLUDE_DIRS}) - if(NLopt_LIBRARIES_RELEASE AND NLopt_LIBRARIES_DEBUG) - set_target_properties(NLopt::nlopt PROPERTIES - IMPORTED_LOCATION_DEBUG ${NLopt_LIBRARIES_DEBUG} - IMPORTED_LOCATION_RELWITHDEBINFO ${NLopt_LIBRARIES_RELEASE} - IMPORTED_LOCATION_RELEASE ${NLopt_LIBRARIES_RELEASE} - IMPORTED_LOCATION_MINSIZEREL ${NLopt_LIBRARIES_RELEASE} - ) - endif() -endif() diff --git a/cmake/FindSIP.cmake b/cmake/FindSIP.cmake index 6d16530..8e2c1e9 100644 --- a/cmake/FindSIP.cmake +++ b/cmake/FindSIP.cmake @@ -1,75 +1,78 @@ -#Find SIP -#~~~~~~~~ +# Find SIP +# ~~~~~~~~ # -#SIP website: http://www.riverbankcomputing.co.uk/sip/index.php +# SIP website: http://www.riverbankcomputing.co.uk/sip/index.php # -#Find the installed version of SIP. FindSIP should be called after Python has -#been found. +# Find the installed version of SIP. FindSIP should be called after Python +# has been found. # -#This file defines the following variables: +# This file defines the following variables: # -#SIP_VERSION - SIP version. -#SIP_EXECUTABLE - Path to the SIP executable. -#SIP_INCLUDE_DIRS - The SIP include directories. +# SIP_VERSION - SIP version. +# +# SIP_EXECUTABLE - Path to the SIP executable. +# +# SIP_INCLUDE_DIRS - The SIP include directories. # -#Copyright (c) 2007, Simon Edwards -#Redistribution and use is allowed according to the terms of the BSD license. -#For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. if(APPLE) - #Workaround for broken FindPythonLibs. It will always find Python 2.7 libs on OSX. + # Workaround for broken FindPythonLibs. It will always find Python 2.7 libs on OSX set(CMAKE_FIND_FRAMEWORK LAST) endif() -#FIXME: Use the new FindPython3 module rather than these. New in CMake 3.12. -#However currently that breaks on our CI server, since the CI server finds the built-in Python3.6 and then doesn't find the headers. -find_package(PythonInterp 3.5 REQUIRED) -find_package(PythonLibs 3.5 REQUIRED) - -#Define variables that are available in FindPython3, so there's no need to branch off in the later part. -set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE}) -set(Python3_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) -set(Python3_LIBRARIES ${PYTHON_LIBRARIES}) +if(NOT Python_VERSION) + set(Python_VERSION + 3.8 + CACHE STRING "Python Version" FORCE) + message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") +endif() +find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS Interpreter Development) execute_process( - COMMAND ${Python3_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific = False, standard_lib = False))" - RESULT_VARIABLE _process_status - OUTPUT_VARIABLE _process_output - OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${Python3_EXECUTABLE} -c + "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False))" + RESULT_VARIABLE _process_status + OUTPUT_VARIABLE _process_output + OUTPUT_STRIP_TRAILING_WHITESPACE ) if(${_process_status} EQUAL 0) - string(STRIP ${_process_output} Python3_SITELIB) + string(STRIP ${_process_output} Python3_SITELIB) else() - message(FATAL_ERROR "Failed to get Python3_SITELIB. Error: ${_process_output}") + message(FATAL_ERROR "Failed to get Python3_SITELIB. Error: ${_process_output}") endif() execute_process( - COMMAND ${Python3_EXECUTABLE} -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific = True, standard_lib = False))" - RESULT_VARIABLE _process_status - OUTPUT_VARIABLE _process_output - OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${Python3_EXECUTABLE} -c + "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False))" + RESULT_VARIABLE _process_status + OUTPUT_VARIABLE _process_output + OUTPUT_STRIP_TRAILING_WHITESPACE ) if(${_process_status} EQUAL 0) - string(STRIP ${_process_output} Python3_SITEARCH) + string(STRIP ${_process_output} Python3_SITEARCH) else() - message(FATAL_ERROR "Failed to get Python3_SITEARCH. Error: ${_process_output}") + message(FATAL_ERROR "Failed to get Python3_SITEARCH. Error: ${_process_output}") endif() get_filename_component(_python_binary_path ${Python3_EXECUTABLE} DIRECTORY) find_program(SIP_EXECUTABLE sip - HINTS ${CMAKE_PREFIX_PATH}/bin ${CMAKE_INSTALL_PATH}/bin ${_python_binary_path} ${Python3_SITELIB}/PyQt5 -) + HINTS ${CMAKE_PREFIX_PATH}/bin ${CMAKE_INSTALL_PATH}/bin ${_python_binary_path} ${Python3_SITELIB}/PyQt5 + ) find_path(SIP_INCLUDE_DIRS sip.h - HINTS ${CMAKE_PREFIX_PATH}/include ${CMAKE_INSTALL_PATH}/include ${Python3_INCLUDE_DIRS} ${Python3_SITELIB}/PyQt5 -) + HINTS ${CMAKE_PREFIX_PATH}/include ${CMAKE_INSTALL_PATH}/include ${Python3_INCLUDE_DIRS} ${Python3_SITELIB}/PyQt5 + ) execute_process( - COMMAND ${Python3_EXECUTABLE} -c "import sip; print(sip.SIP_VERSION_STR)" - RESULT_VARIABLE _process_status - OUTPUT_VARIABLE _process_output - OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${Python3_EXECUTABLE} -c "import sip; print(sip.SIP_VERSION_STR)" + RESULT_VARIABLE _process_status + OUTPUT_VARIABLE _process_output + OUTPUT_STRIP_TRAILING_WHITESPACE ) if(${_process_status} EQUAL 0) @@ -83,4 +86,9 @@ if(SIP_FOUND) include(${CMAKE_CURRENT_LIST_DIR}/SIPMacros.cmake) endif() -mark_as_advanced(SIP_EXECUTABLE SIP_INCLUDE_DIRS SIP_VERSION) +add_library(SIP::SIP INTERFACE IMPORTED) +set_property(TARGET SIP::SIP + PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${SIP_INCLUDE_DIRS} APPEND) + +mark_as_advanced(SIP_EXECUTABLE SIP_INCLUDE_DIRS SIP_VERSION SIP::SIP) \ No newline at end of file diff --git a/cmake/Findlibnest2d.cmake b/cmake/Findlibnest2d.cmake index 5ba4e45..5c69413 100644 --- a/cmake/Findlibnest2d.cmake +++ b/cmake/Findlibnest2d.cmake @@ -4,16 +4,16 @@ # This script finds libnest2d on your computer. # # The output of this script is the following variables: -# - LIBNEST2D_INCLUDE_DIR: The include directory for libnest2d. +# - libnest2d_INCLUDE_DIR: The include directory for libnest2d. find_package(PkgConfig) # To easily find files on your computer. # First try with packageconfig to get a beginning of an idea where to search. pkg_check_modules(PC_LIBNEST2D QUIET libnest2d) -find_path(LIBNEST2D_INCLUDE_DIRS NAMES libnest2d/libnest2d.hpp HINTS - ${PC_LIBNEST2D_INCLUDE_DIRS} - ${PC_LIBNEST2D_INCLUDE_DIRS}/libnest2d +find_path(libnest2d_INCLUDE_DIRS NAMES libnest2d/libnest2d.hpp HINTS + ${PC_libnest2d_INCLUDE_DIRS} + ${PC_libnest2d_INCLUDE_DIRS}/libnest2d ${CMAKE_PREFIX_PATH}/include/ ${CMAKE_PREFIX_PATH}/include/libnest2d /opt/local/include/ @@ -25,5 +25,12 @@ find_path(LIBNEST2D_INCLUDE_DIRS NAMES libnest2d/libnest2d.hpp HINTS ) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LIBNEST2D DEFAULT_MSG - LIBNEST2D_INCLUDE_DIRS) +find_package_handle_standard_args(libnest2d DEFAULT_MSG libnest2d_INCLUDE_DIRS) + +if(libnest2d_FOUND) + add_library(libnest2d::libnest2d INTERFACE IMPORTED) + set_target_properties(libnest2d::libnest2d PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${libnest2d_INCLUDE_DIRS}") +endif() + +mark_as_advanced(libnest2d_INCLUDE_DIRS) \ No newline at end of file diff --git a/cmake/SIPMacros.cmake b/cmake/SIPMacros.cmake index ce2096c..b04c6cd 100644 --- a/cmake/SIPMacros.cmake +++ b/cmake/SIPMacros.cmake @@ -1,20 +1,20 @@ -#Macros for SIP -#~~~~~~~~~~~~~~ -#Copyright (c) 2007, Simon Edwards -#Redistribution and use is allowed according to the terms of the BSD license. -#For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# Macros for SIP +# ~~~~~~~~~~~~~~ +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. # -#SIP website: http://www.riverbankcomputing.co.uk/sip/index.php +# SIP website: http://www.riverbankcomputing.co.uk/sip/index.php # -#This file defines the following macros: +# This file defines the following macros: # -#ADD_SIP_PYTHON_MODULE (MODULE_NAME MODULE_SIP [library1, libaray2, ...]) -# Specifies a SIP file to be built into a Python module and installed. -# MODULE_NAME is the name of Python module including any path name. (e.g. -# os.sys, Foo.bar etc). MODULE_SIP the path and filename of the .sip file to -# process and compile. libraryN are libraries that the Python module, which -# is typically a shared library, should be linked to. The built module will -# also be installed into Python's site-packages directory. +# ADD_SIP_PYTHON_MODULE (MODULE_NAME MODULE_SIP [library1, libaray2, ...]) +# Specifies a SIP file to be built into a Python module and installed. +# MODULE_NAME is the name of Python module including any path name. (e.g. +# os.sys, Foo.bar etc). MODULE_SIP the path and filename of the .sip file +# to process and compile. libraryN are libraries that the Python module, +# which is typically a shared library, should be linked to. The built +# module will also be install into Python's site-packages directory. # #The behaviour of the ADD_SIP_PYTHON_MODULE macro can be controlled by a number #of variables: @@ -111,10 +111,6 @@ macro(ADD_SIP_PYTHON_MODULE MODULE_NAME MODULE_SIP) else(CYGWIN OR APPLE) add_library(${_logical_name} SHARED ${_sip_output_files} ${SIP_EXTRA_SOURCE_FILES}) endif(CYGWIN OR APPLE) - if(NOT APPLE) - target_link_libraries(${_logical_name} ${Python3_LIBRARIES}) - endif(NOT APPLE) - target_link_libraries(${_logical_name} ${EXTRA_LINK_LIBRARIES}) if(APPLE) set_target_properties(${_logical_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") endif(APPLE) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake new file mode 100644 index 0000000..b63ad7a --- /dev/null +++ b/cmake/StandardProjectSettings.cmake @@ -0,0 +1,166 @@ +include(GNUInstallDirs) # Standard install dirs +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") # TODO: Check if this is still needed + +# Uniform how we define BUILD_STATIC or BUILD_SHARED_LIBS (common practice) +if(DEFINED BUILD_STATIC) + if(DEFINED BUILD_SHARED_LIBS) + if(${BUILD_SHARED_LIBS} AND ${BUILD_STATIC}) + message(FATAL_ERROR "Conflicting arguments for BUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} and BUILD_STATIC=${BUILD_STATIC}") + endif() + else() + set(BUILD_SHARED_LIBS NOT ${BUILD_STATIC}) + endif() +else() + if(NOT DEFINED BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS ON) + endif() +endif() +message(STATUS "Setting BUILD_SHARED_LIBS to ${BUILD_SHARED_LIBS}") + +# Set a default build type if none was specified +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE + Release + CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui, ccmake + set_property( + CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS + "Debug" + "Release" + "MinSizeRel" + "RelWithDebInfo") +endif() + +# Generate compile_commands.json to make it easier to work with clang based tools +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +if (NOT MSVC) + # Compile with the -fPIC options if supported + if(DEFINED POSITION_INDEPENDENT_CODE) # Use the user/Conan set value + message(STATUS "Using POSITION_INDEPENDENT_CODE: ${POSITION_INDEPENDENT_CODE}") + else() + set(POSITION_INDEPENDENT_CODE ON) # Defaults to on + message(STATUS "Setting POSITION_INDEPENDENT_CODE: ${POSITION_INDEPENDENT_CODE}") + + # Set Visual Studio flags MD/MDd or MT/MTd + if(BUILD_STATIC OR NOT BUILD_SHARED_LIBS) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + endif() + endif() +endif() + +# Use C++17 Standard +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Set common project options for the target +function(set_project_standards project_name) + if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + option(ENABLE_BUILD_WITH_TIME_TRACE "Enable -ftime-trace to generate time tracing .json files on clang" OFF) + if(ENABLE_BUILD_WITH_TIME_TRACE) + add_compile_definitions(${project_name} PRIVATE -ftime-trace) + endif() + if (APPLE) # Linux already compiles against libstdc++ + target_compile_options(${project_name} PRIVATE "-stdlib=libc++") + endif() + endif() +endfunction() + +# Ultimaker uniform Python linking method +function(use_python project_name) + SET(COMPONENTS ${ARGN}) + if(NOT DEFINED Python_VERSION) + set(Python_VERSION + 3.8 + CACHE STRING "Python Version" FORCE) + message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") + endif() + find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS ${COMPONENTS}) + target_link_libraries(${project_name} PRIVATE ${Python3_LIBRARIES}) + target_include_directories(${project_name} PUBLIC ${Python3_INCLUDE_DIRS}) + message(STATUS "Linking and building ${project_name} against Python ${Python3_VERSION}") +endfunction() + +# Ultimaker uniform Thread linking method +function(use_threads project_name) + message(STATUS "Enabling threading support for ${project_name}") + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads) + target_link_libraries(${project_name} PRIVATE Threads::Threads) +endfunction() + +# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md +function(set_project_warnings project_name) + + set(MSVC_WARNINGS + /W4 # Baseline reasonable warnings + /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not + # be destructed correctly + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside + # the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /permissive- # standards conformance mode for MSVC compiler. + ) + + set(CLANG_WARNINGS + -Wall + -Wextra # reasonable and standard + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps + # catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + ) + + set(GCC_WARNINGS + ${CLANG_WARNINGS} + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + -Wduplicated-cond # warn if if / else chain has duplicated conditions + -Wduplicated-branches # warn if if / else branches have duplicated code + -Wlogical-op # warn about logical operations being used where bitwise were probably wanted + -Wuseless-cast # warn if you perform a cast to the same type + ) + + if(MSVC) + set(PROJECT_WARNINGS ${MSVC_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + set(PROJECT_WARNINGS ${CLANG_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(PROJECT_WARNINGS ${GCC_WARNINGS}) + else() + message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") + endif() + + target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS}) + +endfunction() \ No newline at end of file diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..49e4803 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,97 @@ +import os +import pathlib + +from conans import ConanFile, tools +from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake + + +class pynest2dConan(ConanFile): + name = "pynest2d" + version = "4.10.0" + license = "LGPL-3.0" + author = "Ultimaker B.V." + url = "https://github.com/Ultimaker/pynest2d" + description = "Python bindings for libnest2d" + topics = ("conan", "cura", "prusaslicer", "nesting", "c++", "bin packaging", "python", "sip") + settings = "os", "compiler", "build_type", "arch" + exports = "LICENSE" + options = { + "shared": [True, False], + "python_version": "ANY" + } + default_options = { + "shared": True, + "python_version": "3.8" + } + scm = { + "type": "git", + "subfolder": ".", + "url": "auto", + "revision": "auto" + } + + def config_options(self): + if self.settings.os == "Windows" and self.settings.compiler == "gcc": + self.options.python = False + + def configure(self): + if self.options.shared or self.settings.compiler == "Visual Studio": + del self.options.fPIC + self.options["SIP"].python_version = self.options.python_version + self.options["SIP"].shared = self.options.shared + self.options["libnest2d"].geometries = "clipper" + self.options["libnest2d"].optimizer = "nlopt" + self.options["libnest2d"].threading = "std" + self.options["libnest2d"].shared = self.options.shared + + def build_requirements(self): + self.build_requires("cmake/[>=3.16.2]") + + def requirements(self): + self.requires("SIP/[>=4.19.24]@riverbankcomputing/testing") + self.requires(f"libnest2d/4.10.0@ultimaker/testing") + + def validate(self): + if self.settings.compiler.get_safe("cppstd"): + tools.check_min_cppstd(self, 17) + + 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["SIP_MODULE_SITE_PATH"] = "site-packages" + tc.variables["Python_VERSION"] = self.options.python_version + tc.generate() + + _cmake = None + + def configure_cmake(self): + if self._cmake: + return self._cmake + self._cmake = CMake(self) + self._cmake.configure() + return self._cmake + + def build(self): + cmake = self.configure_cmake() + cmake.build() + + def package(self): + cmake = self.configure_cmake() + cmake.install() + self.copy("*", src = os.path.join("package", "site-packages"), dst = "site-packages") + self.copy("*.pyi", src = ".", dst = "site-packages") + + def package_info(self): + if self.in_local_cache: + self.runenv_info.prepend_path("PYTHONPATH", os.path.join(self.package_folder, "site-packages")) + else: + self.runenv_info.prepend_path("PYTHONPATH", os.path.join(str(pathlib.Path(__file__).parent.absolute())), + f"cmake-build{self.settings.build_type}".lower()) From e19fbeaacfb466892aa4f120f3e116e996739a08 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 7 Aug 2021 16:46:18 +0200 Subject: [PATCH 2/6] Add Sanitizers and best practices You can now set the following extra options (default is OFF) - ENABLE_CPPCHECK "Enable static analysis with cppcheck" - ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" - ENABLE_INCLUDE_WHAT_YOU_USE "Enable static analysis with include-what-you-use" - ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" - ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" - ENABLE_SANITIZER_LEAK "Enable leak sanitizer" - ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" - ENABLE_SANITIZER_THREAD "Enable thread sanitizer" - ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" --- cmake/StandardProjectSettings.cmake | 171 ++++++++++++++++++++++++++-- 1 file changed, 159 insertions(+), 12 deletions(-) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index b63ad7a..54aaeea 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -34,8 +34,24 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) endif() # Generate compile_commands.json to make it easier to work with clang based tools +message(STATUS "Generating compile commands to ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" ON) +if(ENABLE_IPO) + include(CheckIPOSupported) + check_ipo_supported( + RESULT + result + OUTPUT + output) + if(result) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(SEND_ERROR "IPO is not supported: ${output}") + endif() +endif() + if (NOT MSVC) # Compile with the -fPIC options if supported if(DEFINED POSITION_INDEPENDENT_CODE) # Use the user/Conan set value @@ -43,17 +59,20 @@ if (NOT MSVC) else() set(POSITION_INDEPENDENT_CODE ON) # Defaults to on message(STATUS "Setting POSITION_INDEPENDENT_CODE: ${POSITION_INDEPENDENT_CODE}") - - # Set Visual Studio flags MD/MDd or MT/MTd - if(BUILD_STATIC OR NOT BUILD_SHARED_LIBS) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - else() - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") - endif() + endif() +else() + # Set Visual Studio flags MD/MDd or MT/MTd + if(BUILD_STATIC OR NOT BUILD_SHARED_LIBS) + message(STATUS "Setting MD/MDd flags") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + else() + message(STATUS "Setting MT/MTd flags") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif() endif() # Use C++17 Standard +message(STATUS "Setting C++17 support with extensions off and standard required") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -63,9 +82,11 @@ function(set_project_standards project_name) if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") option(ENABLE_BUILD_WITH_TIME_TRACE "Enable -ftime-trace to generate time tracing .json files on clang" OFF) if(ENABLE_BUILD_WITH_TIME_TRACE) + message(STATUS "Enabling time tracing for ${project_name}") add_compile_definitions(${project_name} PRIVATE -ftime-trace) endif() - if (APPLE) # Linux already compiles against libstdc++ + if (APPLE) + message(STATUS "Compiling ${project_name} against libc++") target_compile_options(${project_name} PRIVATE "-stdlib=libc++") endif() endif() @@ -73,7 +94,7 @@ endfunction() # Ultimaker uniform Python linking method function(use_python project_name) - SET(COMPONENTS ${ARGN}) + set(COMPONENTS ${ARGN}) if(NOT DEFINED Python_VERSION) set(Python_VERSION 3.8 @@ -97,7 +118,7 @@ endfunction() # https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md function(set_project_warnings project_name) - + message(STATUS "Setting warnings for ${project_name}") set(MSVC_WARNINGS /W4 # Baseline reasonable warnings /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data @@ -161,6 +182,132 @@ function(set_project_warnings project_name) message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") endif() - target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS}) + target_compile_options(${project_name} PRIVATE ${PROJECT_WARNINGS}) + +endfunction() + +# This function will prevent in-source builds +function(AssureOutOfSourceBuilds) + # make sure the user doesn't play dirty with symlinks + get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) + get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) + + # disallow in-source builds + if("${srcdir}" STREQUAL "${bindir}") + message("######################################################") + message("Warning: in-source builds are disabled") + message("Please create a separate build directory and run cmake from there") + message("######################################################") + message(FATAL_ERROR "Quitting configuration") + endif() +endfunction() + +assureoutofsourcebuilds() + +function(enable_sanitizers project_name) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) + + if(ENABLE_COVERAGE) + target_compile_options(${project_name} INTERFACE --coverage -O0 -g) + target_link_libraries(${project_name} INTERFACE --coverage) + endif() + + set(SANITIZERS "") + + option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" FALSE) + if(ENABLE_SANITIZER_ADDRESS) + list(APPEND SANITIZERS "address") + endif() + + option(ENABLE_SANITIZER_LEAK "Enable leak sanitizer" FALSE) + if(ENABLE_SANITIZER_LEAK) + list(APPEND SANITIZERS "leak") + endif() -endfunction() \ No newline at end of file + option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" FALSE) + if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR) + list(APPEND SANITIZERS "undefined") + endif() + + option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE) + if(ENABLE_SANITIZER_THREAD) + if("address" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS) + message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled") + else() + list(APPEND SANITIZERS "thread") + endif() + endif() + + option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" FALSE) + if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + if("address" IN_LIST SANITIZERS + OR "thread" IN_LIST SANITIZERS + OR "leak" IN_LIST SANITIZERS) + message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled") + else() + list(APPEND SANITIZERS "memory") + endif() + endif() + + list( + JOIN + SANITIZERS + "," + LIST_OF_SANITIZERS) + + endif() + + if(LIST_OF_SANITIZERS) + if(NOT + "${LIST_OF_SANITIZERS}" + STREQUAL + "") + target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) + target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS}) + endif() + endif() + +endfunction() + +option(ENABLE_CPPCHECK "Enable static analysis with cppcheck" OFF) +option(ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF) +option(ENABLE_INCLUDE_WHAT_YOU_USE "Enable static analysis with include-what-you-use" OFF) + +if(ENABLE_CPPCHECK) + find_program(CPPCHECK cppcheck) + if(CPPCHECK) + message(STATUS "Using cppcheck") + set(CMAKE_CXX_CPPCHECK + ${CPPCHECK} + --suppress=missingInclude + --enable=all + --inline-suppr + --inconclusive + -i + ${CMAKE_SOURCE_DIR}/imgui/lib) + else() + message(WARNING "cppcheck requested but executable not found") + endif() +endif() + +if(ENABLE_CLANG_TIDY) + find_program(CLANGTIDY clang-tidy) + if(CLANGTIDY) + message(STATUS "Using clang-tidy") + set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option) + else() + message(WARNING "clang-tidy requested but executable not found") + endif() +endif() + +if(ENABLE_INCLUDE_WHAT_YOU_USE) + find_program(INCLUDE_WHAT_YOU_USE include-what-you-use) + if(INCLUDE_WHAT_YOU_USE) + message(STATUS "Using include-what-you-use") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE}) + else() + message(WARNING "include-what-you-use requested but executable not found") + endif() +endif() \ No newline at end of file From 4022ebb887ff0cabb1a897a26afcfb32701cc58b Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Sat, 7 Aug 2021 17:14:58 +0200 Subject: [PATCH 3/6] Allow for building in-source Strongly discouraged but some automated systems use this method. This can be enabled by setting ALLOW_IN_SOURCE_BUILD ON --- cmake/StandardProjectSettings.cmake | 5 ++++- conanfile.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index 54aaeea..00c9f58 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -202,7 +202,10 @@ function(AssureOutOfSourceBuilds) endif() endfunction() -assureoutofsourcebuilds() +option(ALLOW_IN_SOURCE_BUILD "Allow building in your source folder. Strongly discouraged" OFF) +if(NOT ALLOW_IN_SOURCE_BUILD) + assureoutofsourcebuilds() +endif() function(enable_sanitizers project_name) diff --git a/conanfile.py b/conanfile.py index 49e4803..ed19638 100644 --- a/conanfile.py +++ b/conanfile.py @@ -66,6 +66,7 @@ def generate(self): tc.blocks["generic_system"].values["generator_platform"] = None tc.blocks["generic_system"].values["toolset"] = None + tc.variables["ALLOW_IN_SOURCE_BUILD"] = True tc.variables["SIP_MODULE_SITE_PATH"] = "site-packages" tc.variables["Python_VERSION"] = self.options.python_version tc.generate() From 6abdacbd5b7cd0ba01b935739a988156e70f7a59 Mon Sep 17 00:00:00 2001 From: "j.spijker@ultimaker.com" Date: Sun, 8 Aug 2021 16:43:42 +0200 Subject: [PATCH 4/6] Fixed mixed messages of MT and MD --- cmake/StandardProjectSettings.cmake | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index 00c9f58..e7a825c 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -62,12 +62,14 @@ if (NOT MSVC) endif() else() # Set Visual Studio flags MD/MDd or MT/MTd - if(BUILD_STATIC OR NOT BUILD_SHARED_LIBS) - message(STATUS "Setting MD/MDd flags") - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - else() - message(STATUS "Setting MT/MTd flags") - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) + if(BUILD_STATIC OR NOT BUILD_SHARED_LIBS) + message(STATUS "Setting MT/MTd flags") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + else() + message(STATUS "Setting MD/MDd flags") + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") + endif() endif() endif() From 64d6a003175e0d4461e0cd0b18aa60ccbc1c6b97 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 10 Aug 2021 23:26:35 +0200 Subject: [PATCH 5/6] Never link against Apple Frameworks --- cmake/StandardProjectSettings.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index e7a825c..cf20b1b 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -103,6 +103,9 @@ function(use_python project_name) CACHE STRING "Python Version" FORCE) message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") endif() + if(APPLE) + set(Python3_FIND_FRAMEWORK NEVER) + endif() find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS ${COMPONENTS}) target_link_libraries(${project_name} PRIVATE ${Python3_LIBRARIES}) target_include_directories(${project_name} PUBLIC ${Python3_INCLUDE_DIRS}) From c52897a01af4f0e05dc6a129f062d83675fa3f76 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Wed, 8 Sep 2021 11:06:19 +0200 Subject: [PATCH 6/6] Use Conan build Python --- cmake/StandardProjectSettings.cmake | 10 +++++----- conanfile.py | 18 ++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index cf20b1b..0d5dede 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -104,12 +104,12 @@ function(use_python project_name) message(STATUS "Setting Python version to ${Python_VERSION}. Set Python_VERSION if you want to compile against an other version.") endif() if(APPLE) - set(Python3_FIND_FRAMEWORK NEVER) + set(Python_FIND_FRAMEWORK NEVER) endif() - find_package(Python3 ${Python_VERSION} EXACT REQUIRED COMPONENTS ${COMPONENTS}) - target_link_libraries(${project_name} PRIVATE ${Python3_LIBRARIES}) - target_include_directories(${project_name} PUBLIC ${Python3_INCLUDE_DIRS}) - message(STATUS "Linking and building ${project_name} against Python ${Python3_VERSION}") + find_package(Python ${Python_VERSION} EXACT REQUIRED COMPONENTS ${COMPONENTS}) + target_link_libraries(${project_name} PRIVATE Python::Python) + target_include_directories(${project_name} PUBLIC ${Python_INCLUDE_DIRS}) + message(STATUS "Linking and building ${project_name} against Python ${Python_VERSION}") endfunction() # Ultimaker uniform Thread linking method diff --git a/conanfile.py b/conanfile.py index ed19638..d5acf1c 100644 --- a/conanfile.py +++ b/conanfile.py @@ -7,21 +7,23 @@ class pynest2dConan(ConanFile): name = "pynest2d" - version = "4.10.0" + version = "4.11.0" license = "LGPL-3.0" author = "Ultimaker B.V." url = "https://github.com/Ultimaker/pynest2d" description = "Python bindings for libnest2d" topics = ("conan", "cura", "prusaslicer", "nesting", "c++", "bin packaging", "python", "sip") settings = "os", "compiler", "build_type", "arch" + revision_mode = "scm" + build_policy = "missing" exports = "LICENSE" options = { "shared": [True, False], - "python_version": "ANY" + "fPIC": [True, False] } default_options = { "shared": True, - "python_version": "3.8" + "fPIC": True } scm = { "type": "git", @@ -30,14 +32,9 @@ class pynest2dConan(ConanFile): "revision": "auto" } - def config_options(self): - if self.settings.os == "Windows" and self.settings.compiler == "gcc": - self.options.python = False - def configure(self): if self.options.shared or self.settings.compiler == "Visual Studio": del self.options.fPIC - self.options["SIP"].python_version = self.options.python_version self.options["SIP"].shared = self.options.shared self.options["libnest2d"].geometries = "clipper" self.options["libnest2d"].optimizer = "nlopt" @@ -49,7 +46,8 @@ def build_requirements(self): def requirements(self): self.requires("SIP/[>=4.19.24]@riverbankcomputing/testing") - self.requires(f"libnest2d/4.10.0@ultimaker/testing") + self.requires("Python/3.8.10@python/testing") + self.requires(f"libnest2d/4.11.0@ultimaker/testing") def validate(self): if self.settings.compiler.get_safe("cppstd"): @@ -68,7 +66,7 @@ def generate(self): tc.variables["ALLOW_IN_SOURCE_BUILD"] = True tc.variables["SIP_MODULE_SITE_PATH"] = "site-packages" - tc.variables["Python_VERSION"] = self.options.python_version + tc.variables["Python_VERSION"] = self.deps_cpp_info["Python"].version tc.generate() _cmake = None