Skip to content

Commit

Permalink
Refactor CMakeLists to improve autodetection and building on various …
Browse files Browse the repository at this point in the history
…platforms
  • Loading branch information
d235j committed Feb 8, 2024
1 parent bfcac79 commit 48103ac
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 906 deletions.
159 changes: 97 additions & 62 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,50 +1,65 @@
cmake_minimum_required(VERSION 3.16)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
cmake_minimum_required(VERSION 3.20)
include_directories(cmake) #WORKAROUND needed for find_package(Vulkan) for Vulkan SDK

# Check for Vulkan SDK env var and prepend it to CMAKE_PREFIX_PATH if set to prefer Vulkan SDK packages if available
if(DEFINED ENV{VULKAN_SDK})
message("Detected and using VULKAN_SDK at $ENV{VULKAN_SDK}")
cmake_path(CONVERT "$ENV{VULKAN_SDK}" TO_CMAKE_PATH_LIST VULKAN_SDK_PATH NORMALIZE)
list(PREPEND CMAKE_PREFIX_PATH ${VULKAN_SDK_PATH})
endif()

project(ngscopeclient)

include(CTest)

# Configuration settings
set(BUILD_DOCS CACHE BOOL "Build the documentation")
set(ANALYZE CACHE BOOL "Run static analysis on the code, requires cppcheck and clang-analyzer to be installed")
set(DISABLE_PCH CACHE BOOL "Disable precompiled headers as this may break certain configurations")

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # error if compiler doesn't support c++17
set(CMAKE_CXX_EXTENSIONS OFF) # use c++17 instead of gnu++17

# PCH needs to be disabled before targets are created/added/PCH is added to them
if(DISABLE_PCH)
set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON)
endif()

# Compiler flags
set(WARNINGS "-Wall -Wextra -Wuninitialized ")
set(WARNINGS "${WARNINGS} -Wshadow -Wpedantic -Wcast-align -Wwrite-strings")
set(WARNINGS "${WARNINGS} -Wmissing-declarations -Wvla")
add_compile_options(-Wall -Wextra -Wuninitialized)
add_compile_options(-Wshadow -Wpedantic -Wcast-align -Wwrite-strings)
add_compile_options(-Wmissing-declarations -Wvla)

# Compiler warnings
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(WARNINGS "${WARNINGS} ")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(WARNINGS "${WARNINGS} -Wno-gnu-zero-variadic-macro-arguments -Wno-unknown-warning-option")
add_compile_options(-Wpointer-sign -Wno-gnu-zero-variadic-macro-arguments -Wno-unknown-warning-option)
endif()
add_compile_options(-g -mtune=native)
add_compile_options("$<$<CONFIG:RELEASE>:-O3>")
add_compile_options("$<$<CONFIG:DEBUG>:-O0;-D_DEBUG>")

set(CMAKE_CXX_FLAGS "-g ${WARNINGS} -mtune=native -fsigned-char")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

# Default build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif(NOT CMAKE_BUILD_TYPE)
endif()

if(SANITIZE)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -fsanitize=address -D_DEBUG")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -D_DEBUG")
add_compile_options(-fsanitize=memory -fsanitize=thread -fsanitize=address -fsanitize=undefined -fsanitize=cfi -flto)
endif()

if(WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_USE_MATH_DEFINES -D_POSIX_THREAD_SAFE_FUNCTIONS")
add_compile_options(-D_USE_MATH_DEFINES -D_POSIX_THREAD_SAFE_FUNCTIONS)
endif()

# Detect Apple Silicon as FFTS is not available for it
if(APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_APPLE_SILICON")
add_compile_options(-D_APPLE_SILICON)
set(APPLE_SILICON TRUE)
endif()


# Git is used for git-describe based version generation if we have it
find_package(Git)

Expand All @@ -71,83 +86,103 @@ if(NOT TARGET yaml-cpp::yaml-cpp)
set_property(TARGET yaml-cpp::yaml-cpp PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${YAML_CPP_INCLUDEFILES_DIR})
endif()

pkg_check_modules(SIGCXX sigc++-3.0) # look for latest version first
pkg_check_modules(SIGCXX QUIET IMPORTED_TARGET sigc++-3.0) # look for latest version first
if(NOT SIGCXX_FOUND)
pkg_check_modules(SIGCXX sigc++-2.0) # look for older version too
pkg_check_modules(SIGCXX QUIET IMPORTED_TARGET sigc++-2.0) # look for older version too
endif()
if(NOT SIGCXX_FOUND)
message(FATAL_ERROR "Unable to find any version of sigc++; this is required to build ngscopeclient.")
endif()

# cairomm is used by EyeMask
pkg_check_modules(CAIROMM cairomm-1.16) # look for latest version first
pkg_check_modules(CAIROMM QUIET IMPORTED_TARGET cairomm-1.16) # look for latest version first
if(NOT CAIROMM_FOUND)
pkg_check_modules(CAIROMM cairomm-1.0) # look for older version too
pkg_check_modules(CAIROMM QUIET IMPORTED_TARGET cairomm-1.0) # look for older version too
endif()
if(NOT CAIROMM_FOUND)
message(FATAL_ERROR "Unable to find any version of cairomm; this is required to build ngscopeclient.")
endif()

# We still use gtk on Linux for the file browser dialog in "native" mode)
if(LINUX)
pkg_check_modules(GTK REQUIRED gtk+-3.0)
pkg_check_modules(GTK QUIET IMPORTED_TARGET REQUIRED gtk+-3.0)
endif()

# find ffts, except on Apple Silicon where it's not supported
if(NOT APPLE_SILICON)
find_package(FFTS)
# ffts ships a broken pkgconfig file on some platforms so we are not going to use it
find_path(LIBFFTS_INCLUDE_DIRS ffts.h PATH_SUFFIXES ffts REQUIRED)
find_library(LIBFFTS_LIBRARIES NAMES ffts libffts REQUIRED)
endif()
include(FindOpenMP)
find_package(glfw3 3.2 REQUIRED)

# Use the local FindVulkan script until we can rely on all users having CMake 3.24 available, at which point we can remove it
set(Vulkan_FIND_COMPONENTS glslang shaderc_combined)
include(FindVulkan)
#WORKAROUND Fedora 38 does not include Threads from the glslang .cmake file, fixed in Fedora 39+
find_package(Threads MODULE REQUIRED)

if(NOT Vulkan_FOUND)
message(FATAL_ERROR "No Vulkan SDK found.")
# Configure and enable OpenMP
find_package(OpenMP MODULE)
if(NOT OpenMP_CXX_FOUND)
message(FATAL_ERROR "ngscopeclient requires OpenMP but your C++ compiler does not appear to support it.")
endif()

if(NOT Vulkan_glslc_FOUND)
message(FATAL_ERROR "No Vulkan glslc found. This is needed to compile shaders.")
# GLFW is required
find_package(glfw3 3.2 REQUIRED)

# Find Vulkan-related packages
#WORKAROUND glslang does not look for SPIRV-Tools-opt but needs it on macOS, harmless elsewhere
find_package(SPIRV-Tools-opt REQUIRED)
if(DEFINED VULKAN_SDK_PATH)
#WORKAROUND The Vulkan SDK ships incomplete cmake config files.
# Work around this, which does require FindVulkan.cmake.
# FindVulkan does not find glslang correctly on macOS
find_package(Vulkan REQUIRED COMPONENTS glslc shaderc_combined SPIRV-Tools)
find_package(glslang REQUIRED)
add_library(Vulkan::Loader ALIAS Vulkan::Vulkan)
else()
find_package(glslang REQUIRED)
find_package(VulkanHeaders REQUIRED)
find_package(VulkanLoader QUIET)
if(NOT VulkanLoader_FOUND) #WORKAROUND Alpine Linux has missing cmake files for VulkanLoader
find_library(VulkanLoader_LIB libvulkan.so REQUIRED)
cmake_path(GET VulkanLoader_LIB FILENAME VulkanLoader_LIB_NAME)
add_library(Vulkan::Loader SHARED IMPORTED)
set_property(TARGET Vulkan::Loader PROPERTY IMPORTED_LOCATION ${VulkanLoader_LIB})
endif()
endif()
# The following should work regardless of Vulkan SDK or individual components
# shaderc does not provide a .cmake file, but does provide a pkgconfig file
# pkgconfig file is not provided by Vulkan SDK, however
pkg_check_modules(SHADERC shaderc QUIET IMPORTED_TARGET)
# This is needed due to shaderc not providing a programmatic way to derive the path of the glslc executable
if(SHADERC_FOUND)
cmake_path(GET SHADERC_INCLUDE_DIRS PARENT_PATH SHADERC_PREFIX)
endif()
# This should find glslc from either shaderc or the Vulkan SDK
find_program(Vulkan_GLSLC_EXECUTABLE glslc HINTS SHADERC_PREFIX)

# Add specific VulkanSDK Lib & Include for glslang (tested on Linux Ubuntu 22.04 LTS)
if(NOT WIN32)
include_directories($ENV{VULKAN_SDK}/include/glslang/Include)
link_directories($ENV{VULKAN_SDK}/lib)
if(NOT Vulkan_GLSLC_EXECUTABLE)
message(FATAL_ERROR "glslc not found. This is needed to compile shaders. Please install shaderc or load the Vulkan SDK.")
else()
message("-- Found glslc: ${Vulkan_GLSLC_EXECUTABLE}")
endif()

# Includes are incomplete in VulkanSDK 1.3.224.1 so we use the include path from MINGW64 mingw-w64-x86_64-glslang
if(WIN32)
find_path(Glslang_BUILD_INCLUDE_DIR
NAMES include/glslang/Include/glslang_c_interface.h
HINTS
$ENV{GLSLANG_BUILD_PATH}
)
mark_as_advanced(Glslang_BUILD_INCLUDE_DIR)

if(Glslang_BUILD_INCLUDE_DIR)
include_directories($ENV{GLSLANG_BUILD_PATH}/include/glslang/Include)
else()
message(FATAL_ERROR "Glslang_BUILD_INCLUDE_DIR Not found")
# This is needed due to VkFFT not using a standard path for glslang_c_interface.h
get_target_property(glslang_INCLUDE_DIR glslang::glslang INTERFACE_INCLUDE_DIRECTORIES)
# Find MoltenVK on macOS, no need to link it later
if(APPLE)
find_library(MOLTENVK_LIBRARIES NAMES MoltenVK libMoltenVK)
if( NOT MOLTENVK_LIBRARIES )
message( FATAL_ERROR "scopehal-apps requires MoltenVK to be installed in order to function on macOS.")
endif()

link_directories($ENV{GLSLANG_BUILD_PATH}/lib)
link_directories($ENV{GLSLANG_BUILD_PATH}/lib/glslang)
endif()

if(NOT WIN32)
include(GNUInstallDirs)
endif()

# Configure and enable OpenMP
if(NOT OpenMP_CXX_FOUND)
message(FATAL_ERROR "ngscopeclient requires OpenMP but your C++ compiler does not appear to support it.")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")

# Documentation
if(BUILD_DOCS)
add_subdirectory("${PROJECT_SOURCE_DIR}/doc")
add_subdirectory("${PROJECT_SOURCE_DIR}/doc")
if(NOT BUILD_DOCS)
set_property(TARGET doc PROPERTY EXCLUDE_FROM_ALL ON)
endif()

# Static analysis
Expand All @@ -163,7 +198,7 @@ if(ANALYZE)
message(STATUS "Found CPPCheck: ${CPPCHECK_PATH} but ignored it as it was ${CPPCHECK_VERSION} < 2")
endif()
else()
message(STATUS "CPPCheck not found")
message(FATAL_ERROR "CPPCheck not found, required for ANALYZE")
endif()
# The actual clang-analyzer compiler wrapper doesn't get installed on $PATH, only scan-build which is useless to us
find_program(CLANGANALYZER_SCANBUILD_PATH scan-build DOC "Path to clang-analyzer's scan-build tool, used as a hint to find the rest of the clang-analyzer")
Expand All @@ -174,7 +209,7 @@ if(ANALYZE)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CLANGANALYZER_CXXANALYZER_PATH}")
message(STATUS "Found clang-analyzer: ${CLANGANALYZER_CXXANALYZER_PATH}")
else()
message(STATUS "clang-analyzer not found")
message(FATAL_ERROR "clang-analyzer not found, required for ANALYZE")
endif()
endif()

Expand All @@ -194,7 +229,7 @@ if(BUILD_TESTING)
# Must include catch2/catch_all.hpp instead of catch2/catch.hpp
# So we set a compile flag to let the code know.
if(NOT Catch2_VERSION MATCHES "^[0-2]\\.")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CATCH2_V3")
add_compile_options(-D_CATCH2_V3)
endif()
add_subdirectory("${PROJECT_SOURCE_DIR}/tests")
endif()
Expand Down
34 changes: 0 additions & 34 deletions cmake/FindFFTS.cmake

This file was deleted.

Loading

0 comments on commit 48103ac

Please sign in to comment.