Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ build

# Generated headers
/src/SavitarExport.h

cmake-build-*/
tmp/*
141 changes: 59 additions & 82 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,51 +1,16 @@
cmake_minimum_required(VERSION 3.13)
project(savitar)
cmake_minimum_required(VERSION 3.8)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(GenerateExportHeader)

option(BUILD_PYTHON "Build " ON)
option(BUILD_STATIC "Build as a static library" OFF)
option(BUILD_TESTS "Building the test-suite" OFF)

if(BUILD_TESTS)
message(STATUS "Building with tests...")
find_package(GTest REQUIRED)
find_package(Threads QUIET)
endif()

add_subdirectory(pugixml)

if(BUILD_PYTHON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)

# 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.4 REQUIRED)
find_package(PythonLibs 3.4 REQUIRED)

else()
# Use FindPython3 for CMake >=3.12
find_package(Python3 3.4 REQUIRED COMPONENTS Interpreter Development)
endif()

find_package(SIP REQUIRED)
if(NOT DEFINED LIB_SUFFIX)
set(LIB_SUFFIX "")
endif()

include_directories(python/ src/ ${SIP_INCLUDE_DIRS} ${Python3_INCLUDE_DIRS})
endif()

set(CMAKE_CXX_STANDARD 17)
include(cmake/StandardProjectSettings.cmake)
include(CMakePackageConfigHelpers)
include(GenerateExportHeader)

if(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
set(SAVITAR_VERSION 0.1.2)
set(SAVITAR_SOVERSION 0)

set(savitar_SRCS
src/Namespace.cpp
Expand All @@ -66,41 +31,59 @@ set(savitar_HDRS
src/MeshData.h
src/Vertex.h
src/Face.h
${CMAKE_CURRENT_BINARY_DIR}/src/SavitarExport.h
src/SavitarExport.h
)

set(SAVITAR_VERSION 0.1.2)
set(SAVITAR_SOVERSION 0)
if(BUILD_SHARED_LIBS)
add_library(Savitar SHARED ${savitar_SRCS})
else()
add_library(Savitar STATIC ${savitar_SRCS})
endif()

set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR})
use_threads(Savitar)

if(BUILD_STATIC)
add_library(Savitar STATIC ${savitar_SRCS})
set_project_standards(Savitar)
set_project_warnings(Savitar)
enable_sanitizers(Savitar)

set(USE_SHIPPED_PUGIXML ON CACHE BOOL "Use the shipped pugixml library")
if(USE_SHIPPED_PUGIXML)
message(STATUS "Using shipped pugixml library")
add_subdirectory(pugixml)
else()
add_library(Savitar SHARED ${savitar_SRCS})
find_package(pugixml 1.8 REQUIRED)
endif()

set(Savitar_LINK_LIBRARIES pugixml)
if(CMAKE_USE_PTHREADS_INIT)
list(APPEND Savitar_LINK_LIBRARIES pthread)
endif()
target_link_libraries(Savitar PUBLIC ${Savitar_LINK_LIBRARIES})
target_link_libraries(Savitar PUBLIC pugixml::pugixml)

if(NOT WIN32 OR CMAKE_COMPILER_IS_GNUCXX)
set_target_properties(Savitar PROPERTIES COMPILE_FLAGS -fPIC)
endif()
generate_export_header(Savitar EXPORT_FILE_NAME ${CMAKE_SOURCE_DIR}/src/SavitarExport.h)
target_include_directories(Savitar
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

if(BUILD_PYTHON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)

find_package(SIP REQUIRED)

set(SIP_EXTRA_FILES_DEPEND python/Types.sip python/MeshData.sip python/SceneNode.sip python/Scene.sip)
#set(SIP_EXTRA_SOURCE_FILES python/Types.cpp)
set(SIP_EXTRA_OPTIONS -g -n PyQt5.sip) # -g means always release the GIL before calling C++ methods. -n PyQt5.sip is required to not get the PyCapsule error
set(SIP_EXTRA_OPTIONS -y Savitar.pyi -o -g -n PyQt5.sip)

add_sip_python_module(Savitar python/ThreeMFParser.sip Savitar)
endif()

target_include_directories(Savitar PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_project_standards(python_module_Savitar)
set_project_warnings(python_module_Savitar)
use_python(python_module_Savitar Interpreter Development)

target_link_libraries(python_module_Savitar PRIVATE SIP::SIP Savitar)
target_include_directories(python_module_Savitar
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/python>
)
endif()

if(${CMAKE_BUILD_TYPE})
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
Expand All @@ -118,13 +101,6 @@ set_target_properties(Savitar PROPERTIES
VISIBILITY_INLINES_HIDDEN 1
)

generate_export_header(Savitar
EXPORT_FILE_NAME src/SavitarExport.h
)
# This is required when building out-of-tree.
# The compiler won't find the generated header otherwise.
include_directories(${CMAKE_BINARY_DIR}/src)

install(TARGETS Savitar
EXPORT Savitar-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
Expand All @@ -133,23 +109,22 @@ install(TARGETS Savitar
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/Savitar
)

install(EXPORT Savitar-targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Savitar
)
install(EXPORT Savitar-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Savitar)

configure_package_config_file(SavitarConfig.cmake.in ${CMAKE_BINARY_DIR}/SavitarConfig.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Savitar)
write_basic_package_version_file(${CMAKE_BINARY_DIR}/SavitarConfigVersion.cmake VERSION ${SAVITAR_VERSION} COMPATIBILITY SameMajorVersion)

# List of tests. For each test there must be a file tests/${NAME}.cpp.
set(savitar_TEST
ThreeMFParserTest
MeshDataTest
NamespaceTest
)

# Compiling the test environment.
if (BUILD_TESTS)
include_directories(${GTEST_INCLUDE_DIR})
message(STATUS "Building with tests...")
find_package(GTest CONFIG REQUIRED)

# List of tests. For each test there must be a file tests/${NAME}.cpp.
set(savitar_TEST
ThreeMFParserTest
MeshDataTest
NamespaceTest
)

enable_testing()

Expand All @@ -159,7 +134,9 @@ if (BUILD_TESTS)

foreach (test ${savitar_TEST})
add_executable(${test} tests/main.cpp tests/${test}.cpp)
target_link_libraries(${test} Savitar ${GTEST_BOTH_LIBRARIES})
set_project_standards(${test})
set_project_warnings(${test})
target_link_libraries(${test} PRIVATE Savitar GTest::gtest GTest::gmock pugixml::pugixml)
add_test(${test} ${test})
add_dependencies(build_all_tests ${test}) #Make sure that this gets built as part of the build_all_tests target.
endforeach()
Expand Down
67 changes: 35 additions & 32 deletions cmake/FindSIP.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -24,57 +24,55 @@ if(APPLE)
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)
Expand All @@ -88,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)
Loading