#!/usr/bin/cmake cmake_minimum_required (VERSION 3.15) # ------------------------------------------------------------------------------------------------- project( NuclexGeometryNative VERSION 1.0.0 DESCRIPTION "Math and geometry library for graphics and game development" ) # Contains compiler options, compiler tag for output directory, etc. include("../BuildSystem/cmake/cplusplus.cmake") set(BUILD_DOCS OFF CACHE BOOL "Whether to generate documentation via Doxygen") # ------------------------------------------------------------------------------------------------- # Include threading library (on Linux/Posix pthreads must be linked) find_package(Threads REQUIRED) # Use CMake's own package for locating Doxygen on the system if(BUILD_DOCS) find_package(Doxygen) endif() # Add Nuclex.Support.Native as a sub-project, we link it for utility methods. if(NOT (TARGET NuclexSupportNative)) add_subdirectory( ${PROJECT_SOURCE_DIR}/../Nuclex.Support.Native ${CMAKE_BINARY_DIR}/NuclexSupportNative ) endif() # Already included by Nuclex.Support.Native, CMake doesn't like a second inclusion... if(NOT (TARGET GoogleTest)) add_subdirectory(${PROJECT_SOURCE_DIR}/../ThirdParty/gtest ${CMAKE_BINARY_DIR}/gtest) endif() # ------------------------------------------------------------------------------------------------- # All source files are in the Source/ directory. # All (public) headers are in the Include/ directory. # All unit test source file are in the Tests/ directory. # # CMake documentation: # | Note: We do not recommend using GLOB to collect a list of # | source files from your source tree. If no CMakeLists.txt file # | changes when a source is added or removed then the generated # | build system cannot know when to ask CMake to regenerate. # # As so very often, CMake becomes a hurdle rather than helping. # I'm not going to manually maintain a list of source files. Rebuilds # where files are added, removed or renamed need to be from scratch. # file( GLOB_RECURSE sourceFiles CONFIGURE_DEPENDS "Source/*.cpp" "Source/*.c" ) file( GLOB_RECURSE headerFiles CONFIGURE_DEPENDS "Include/Nuclex/Geometry/*.h" ) file( GLOB_RECURSE unittestFiles CONFIGURE_DEPENDS "Tests/*.cpp" ) # ------------------------------------------------------------------------------------------------- # Shared library that can be linked to other projects add_library(NuclexGeometryNative SHARED) # Enable compiler warnings only if this library is compiles on its own. # If it's used as a sub-project, the including project's developers aren't # interested in seeing warnings from a project they're not maintaining. if(${CMAKE_PROJECT_NAME} STREQUAL "NuclexGeometryNative") enable_target_compiler_warnings(NuclexGeometryNative) else() disable_target_compiler_warnings(NuclexGeometryNative) endif() # Add directory with public headers to include path target_include_directories( NuclexGeometryNative PUBLIC "Include" ) # Add public headers and sources to compilation list # (headers, too, in case CMake is used to generate an IDE project) target_sources( NuclexGeometryNative PUBLIC ${headerFiles} PRIVATE ${sourceFiles} ) # Link against PThreads and Nuclex.Support.Native target_link_libraries( NuclexGeometryNative PRIVATE Threads::Threads PUBLIC NuclexSupportNative ) # On Unix systems, the library and unit test executable should look for # dependencies in its own directory first. set_target_properties( NuclexGeometryNative PROPERTIES BUILD_RPATH_USE_ORIGIN ON BUILD_WITH_INSTALL_RPATH ON INSTALL_RPATH_USE_LINK_PATH OFF INSTALL_RPATH "\${ORIGIN}" ) # On Windows, we want the shared library to be named Nuclex.Geometry.Native.dll if(WIN32) set_target_properties( NuclexGeometryNative PROPERTIES OUTPUT_NAME "Nuclex.Geometry.Native" ) endif() # ------------------------------------------------------------------------------------------------- # Executable that runs the unit tests (main() supplied by Googletest) add_executable(NuclexGeometryNativeTests) # Enable compiler warnings only if this library is compiles on its own. # If it's used as a sub-project, the including project's developers aren't # interested in seeing warnings from a project they're not maintaining. if(${CMAKE_PROJECT_NAME} STREQUAL "NuclexGeometryNative") enable_target_compiler_warnings(NuclexGeometryNativeTests) else() disable_target_compiler_warnings(NuclexGeometryNativeTests) endif() # Let the code know it's not being compiled into a shared library # (this disables visibility/exports, thus allowing the compiler detect # additional unused code and warn about it) target_compile_definitions( NuclexGeometryNativeTests PRIVATE NUCLEX_GEOMETRY_EXECUTABLE ) # Add directory with public headers to include path target_include_directories( NuclexGeometryNativeTests PUBLIC "Include" ) # Add public headers and sources (normal + unit tests) to compilation list # (headers, too, in case CMake is used to generate an IDE project) target_sources( NuclexGeometryNativeTests PRIVATE ${headerFiles} PRIVATE ${sourceFiles} PRIVATE ${unittestFiles} ) # Link GoogleTest and the main() function supplied by GoogleTest # Also link against PThreads target_link_libraries( NuclexGeometryNativeTests PRIVATE GoogleTest::Static PRIVATE GoogleTest::Main PRIVATE Threads::Threads PUBLIC NuclexSupportNative ) # On Unix systems, the library and unit test executable should look for # dependencies in its own directory first. set_target_properties( NuclexGeometryNativeTests PROPERTIES BUILD_RPATH_USE_ORIGIN ON BUILD_WITH_INSTALL_RPATH ON INSTALL_RPATH_USE_LINK_PATH OFF INSTALL_RPATH "\${ORIGIN}" ) # On Windows, we want the executable to be named Nuclex.Geometry.Native.Tests.exe if(WIN32) set_target_properties( NuclexGeometryNativeTests PROPERTIES OUTPUT_NAME "Nuclex.Geometry.Native.Tests" ) endif() # ------------------------------------------------------------------------------------------------- # Install the shared library into a subdirectory of this CMakeLists.txt file # under ./bin/linux-gcc9.3-amd64-debug/ (the second-level directory is called # "compiler tag" and dynamically formed -- it ensures that when linking # a pre-compiled shared library, the correct library is used). install( TARGETS NuclexGeometryNative ARCHIVE DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} ) # Do the same for Nuclex.Support.Native. Since we depend on this library # and have set the rpath accordingly, it needs to be in the same directory install( TARGETS NuclexSupportNative ARCHIVE DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} ) # Install unit tests in same location as shared library. install( TARGETS NuclexGeometryNativeTests RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin/${NUCLEX_COMPILER_TAG} ) # Install .pdb files on Windows platforms for the unit tests, too. install_debug_symbols(NuclexGeometryNativeTests) # ------------------------------------------------------------------------------------------------- if(BUILD_DOCS) if(NOT DOXYGEN_FOUND) message(FATAL_ERROR "Can't build documentation because Doxygen was not found") endif() add_custom_target( NuclexGeometryNativeDocs ALL COMMAND ${DOXYGEN_EXECUTABLE} "Nuclex.Geometry.Native.doxygen.cfg" WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} ) endif() # ------------------------------------------------------------------------------------------------- file( WRITE "${PROJECT_SOURCE_DIR}/NuclexGeometryNativeConfig.cmake" "#!/usr/bin/cmake # Configuration to include Nuclex.Geometry.Native in a CMake-based project. If you want to # reference Nuclex.Geometry.Native as an externally compiled static library, do this: # # set(NuclexGeometryNative_DIR \"../Nuclex.Geometry.Native\") # find_package(NuclexGeometryNative REQUIRED CONFIG) # # target_link_libraries( # MyAwesomeProject # PRIVATE NuclexGeometryNative::Dynamic # ) # # Alternatively, if you want to build Nuclex.Geometry.Native together with your project, # use the normal CMakeLists.txt with CMake's add_subdirectory() command: # # add_subdirectory( # \"\${PROJECT_SOURCE_DIR}/../Nuclex.Geometry.Native\" # \"\${CMAKE_BINARY_DIR}/nuclex.geometry.native\" # ) # # target_link_libraries( # MyAwesomeProject # PRIVATE NuclexGeometryNative # ) # # ------------------------------------------------------------------------------------------------- if(NOT DEFINED NUCLEX_COMPILER_TAG) message( FATAL_ERROR \"NUCLEX_COMPILER_TAG not defined! Include cplusplus.cmake before importing this package \\ in order to generate a tag identifying the platform/compiler/architecture/variant!\" ) endif() # ------------------------------------------------------------------------------------------------- if(NOT EXISTS \"\${CMAKE_CURRENT_LIST_DIR}/bin/\${NUCLEX_COMPILER_TAG}\") # TODO: Warn and link release build when compiling in debug mode # TODO: Warn and link build for older compiler version if found message( FATAL_ERROR \"Directory '\${CMAKE_CURRENT_LIST_DIR}/bin/\${NUCLEX_COMPILER_TAG}' not found. \\ Please either build and install this project before importing it via \\ find_package() or use this project's main CMakeFiles.txt via add_subdirectory()!\" ) endif() # ------------------------------------------------------------------------------------------------- add_library(NuclexGeometryNative::Dynamic SHARED IMPORTED) # This may cause warnings on recent GCC versions (10.0.0+?) with LTO because GCC detects # that the headers used during build (residing in build/) are not the same used when # linking the library (copies resising in Include/). # # CMake doesn't run the install step during build, so the only way to get the headers # in place before building would be by copying them rather than installing them. set_target_properties( NuclexGeometryNative::Dynamic PROPERTIES INTERFACE_INCLUDE_DIRECTORIES \"\${CMAKE_CURRENT_LIST_DIR}/Include\" IMPORTED_LINK_INTERFACE_LANGUAGES \"C\" ) if(WIN32) set_target_properties( NuclexGeometryNative::Dynamic PROPERTIES IMPORTED_LOCATION \"\${CMAKE_CURRENT_LIST_DIR}/bin/\${NUCLEX_COMPILER_TAG}/Nuclex.Geometry.Native.lib\" ) else() set_target_properties( NuclexGeometryNative::Dynamic PROPERTIES IMPORTED_LOCATION \"\${CMAKE_CURRENT_LIST_DIR}/bin/\${NUCLEX_COMPILER_TAG}/libNuclexGeometryNative.so\" ) endif() message(STATUS \"Imported Nuclex.Geometry.Native targets with binaries in '\${CMAKE_CURRENT_LIST_DIR}'\")" ) # -------------------------------------------------------------------------------------------------