Skip to content

Commit

Permalink
Merge pull request #239 from Exawind/patch-cmake-code
Browse files Browse the repository at this point in the history
Increase readability of the CMake build systems code
  • Loading branch information
faisal-bhuiyan authored Aug 15, 2024
2 parents 7f2bcb7 + dca1af0 commit 71426e5
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 246 deletions.
42 changes: 21 additions & 21 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
cmake_minimum_required (VERSION 3.21 FATAL_ERROR)

if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
endif()
cmake_minimum_required(VERSION 3.21 FATAL_ERROR)

# Set C++ standard, prefer 17, no extensions
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to be used")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Project declaration
project(
OpenTurbine
OpenTurbine
VERSION 0.0.0
DESCRIPTION "Wind turbine structural dynamics simulation code"
LANGUAGES CXX)
DESCRIPTION "A flexible multibody structural dynamics code for wind turbines"
LANGUAGES CXX
)

# Include custom CMake modules
include(cmake/PreventInSourceBuilds.cmake)
include(OpenTurbineOptions.cmake)

# Setup project-specific options
openturbine_setup_options()

openturbine_global_options()

# Include and setup dependencies
include(Dependencies.cmake)
openturbine_setup_dependencies()

# Setup local project options
openturbine_local_options()

set(
GIT_SHA
"Unknown"
CACHE STRING "SHA this build was generated from")
STRING(
SUBSTRING "${GIT_SHA}"
0
8
GIT_SHORT_SHA
)
# Generate a shortened Git SHA for versioning
set(GIT_SHA "Unknown" CACHE STRING "SHA this build was generated from")
string(SUBSTRING "${GIT_SHA}" 0 8 GIT_SHORT_SHA)

# Alias libraries for ease of use in targets
add_library(OpenTurbine::openturbine_options ALIAS openturbine_options)
add_library(OpenTurbine::openturbine_warnings ALIAS openturbine_warnings)

# Add the main source directory
add_subdirectory(src)

# Enable testing if requested
include(CTest)

if(${OpenTurbine_ENABLE_TESTS})
if(OpenTurbine_ENABLE_TESTS)
add_subdirectory(tests)
endif()
13 changes: 8 additions & 5 deletions Dependencies.cmake
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
function(openturbine_setup_dependencies)
# Find and link required packages
find_package(KokkosKernels REQUIRED)

find_package(Amesos2 REQUIRED)

find_package(yaml-cpp REQUIRED)

# Optionally find and link MKL if available
if(TARGET Kokkos::MKL)
find_package(MKL REQUIRED)
endif()

# Conditionally find and link VTK if enabled
if(OpenTurbine_ENABLE_VTK)
find_package(VTK REQUIRED IOXML)
find_package(VTK REQUIRED COMPONENTS IOXML)
endif()

# Conditionally find and link GTest if testing is enabled
if(OpenTurbine_ENABLE_TESTS)
find_package(GTest REQUIRED)
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES GNU)
# Link filesystem library for older GCC versions
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0")
set(FS_LIB stdc++fs)
endif()
endif()
endfunction()
endfunction()
85 changes: 43 additions & 42 deletions cmake/CompilerWarnings.cmake
Original file line number Diff line number Diff line change
@@ -1,73 +1,74 @@
function(
openturbine_set_project_warnings
project_name
WARNINGS_AS_ERRORS
CLANG_WARNINGS
GCC_WARNINGS
CUDA_WARNINGS)
function(openturbine_set_project_warnings project_name WARNINGS_AS_ERRORS CLANG_WARNINGS GCC_WARNINGS CUDA_WARNINGS)

# Set default Clang warnings if not provided
if("${CLANG_WARNINGS}" STREQUAL "")
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)
-Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation
-Wall # Enable all standard warnings
-Wextra # Enable extra warnings
-Wshadow # Warn if a variable declaration shadows one from a parent context
-Wnon-virtual-dtor # Warn if a class with virtual functions has a non-virtual destructor
-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 implicitly promoted to double
-Wformat=2 # Warn on security issues around functions that format output (e.g., printf)
-Wimplicit-fallthrough # Warn on statements that fall through without an explicit annotation
)
endif()

# Set default GCC warnings if not provided
if("${GCC_WARNINGS}" STREQUAL "")
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
-Wsuggest-override # warn if an overridden member function is not marked 'override' or 'final'
${CLANG_WARNINGS} # Include Clang warnings
-Wmisleading-indentation # Warn if indentation implies blocks where blocks do not exist
-Wduplicated-cond # Warn if an 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
-Wsuggest-override # Warn if an overridden member function is not marked 'override' or 'final'
)
endif()

# Set default CUDA warnings if not provided
if("${CUDA_WARNINGS}" STREQUAL "")
set(CUDA_WARNINGS
-Wall
-Wextra
-Wunused
-Wconversion
-Wshadow
-Wall
-Wextra
-Wunused
-Wconversion
-Wshadow
)
endif()

# Treat warnings as errors if specified
if(WARNINGS_AS_ERRORS)
message(TRACE "Warnings are treated as errors")
message(STATUS "Warnings are treated as errors for project '${project_name}'")
list(APPEND CLANG_WARNINGS -Werror)
list(APPEND GCC_WARNINGS -Werror)
list(APPEND CUDA_WARNINGS -Werror)
endif()

if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# Set compiler-specific warning flags
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(PROJECT_WARNINGS_CXX ${CLANG_WARNINGS})
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(PROJECT_WARNINGS_CXX ${GCC_WARNINGS})
else()
message(AUTHOR_WARNING "No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
message(WARNING "No compiler warnings set for CXX compiler: '${CMAKE_CXX_COMPILER_ID}'")
endif()

set(PROJECT_WARNINGS_CUDA "${CUDA_WARNINGS}")

# Apply the warning flags to the target
target_compile_options(
${project_name}
INTERFACE
$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>
$<$<COMPILE_LANGUAGE:CUDA>:${PROJECT_WARNINGS_CUDA}>)
INTERFACE
$<$<COMPILE_LANGUAGE:CXX>:${PROJECT_WARNINGS_CXX}>
$<$<COMPILE_LANGUAGE:CUDA>:${PROJECT_WARNINGS_CUDA}>
)

endfunction()
endfunction()
22 changes: 14 additions & 8 deletions cmake/PreventInSourceBuilds.cmake
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
function(openturbine_assure_out_of_source_builds)
# make sure the user doesn't play dirty with symlinks
# Get the real paths of the source and binary directories
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)

# disallow in-source builds
# 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")
message(FATAL_ERROR
"######################################################\n"
"Error: In-source builds are disabled.\n"
"Please create a separate build directory and run CMake from there.\n"
"Example:\n"
" mkdir -p build\n"
" cd build\n"
" cmake ..\n"
"######################################################"
)
endif()
endfunction()

openturbine_assure_out_of_source_builds()
# Invoke the function to enforce the out-of-source build
openturbine_assure_out_of_source_builds()
87 changes: 40 additions & 47 deletions cmake/Sanitizers.cmake
Original file line number Diff line number Diff line change
@@ -1,87 +1,80 @@
function(
openturbine_enable_sanitizers
# Function to enable various sanitizers for a given target
function(openturbine_enable_sanitizers
project_name
ENABLE_SANITIZER_ADDRESS
ENABLE_SANITIZER_LEAK
ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
ENABLE_SANITIZER_THREAD
ENABLE_SANITIZER_MEMORY)

# Initialize an empty list to hold the enabled sanitizers
set(SANITIZERS "")

# Check if using GCC or Clang and enable the appropriate sanitizers
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
set(SANITIZERS "")

if(${ENABLE_SANITIZER_ADDRESS})
if(ENABLE_SANITIZER_ADDRESS)
list(APPEND SANITIZERS "address")
endif()

if(${ENABLE_SANITIZER_LEAK})
if(ENABLE_SANITIZER_LEAK)
list(APPEND SANITIZERS "leak")
endif()

if(${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR})
if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR)
list(APPEND SANITIZERS "undefined")
endif()

if(${ENABLE_SANITIZER_THREAD})
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")
message(WARNING "Thread sanitizer cannot be used with Address or Leak sanitizers.")
else()
list(APPEND SANITIZERS "thread")
endif()
endif()

if(${ENABLE_SANITIZER_MEMORY} AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
message(
WARNING
"Memory sanitizer requires all the code (including libc++) to be MSan-instrumented otherwise it reports false positives"
)
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 or Leak sanitizer enabled")
if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
message(WARNING "Memory sanitizer requires MSan-instrumented code, otherwise it may report false positives.")
if("address" IN_LIST SANITIZERS OR "thread" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS)
message(WARNING "Memory sanitizer cannot be used with Address, Thread, or Leak sanitizers.")
else()
list(APPEND SANITIZERS "memory")
endif()
endif()

# Check if using MSVC and enable the appropriate sanitizers
elseif(MSVC)
if(${ENABLE_SANITIZER_ADDRESS})
if(ENABLE_SANITIZER_ADDRESS)
list(APPEND SANITIZERS "address")
endif()
if(${ENABLE_SANITIZER_LEAK}
OR ${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR}
OR ${ENABLE_SANITIZER_THREAD}
OR ${ENABLE_SANITIZER_MEMORY})
message(WARNING "MSVC only supports address sanitizer")

if(ENABLE_SANITIZER_LEAK OR ENABLE_SANITIZER_UNDEFINED_BEHAVIOR OR ENABLE_SANITIZER_THREAD OR ENABLE_SANITIZER_MEMORY)
message(WARNING "MSVC only supports the Address sanitizer.")
endif()
endif()

list(
JOIN
SANITIZERS
","
LIST_OF_SANITIZERS)
# Join the sanitizers into a comma-separated string
list(JOIN SANITIZERS "," LIST_OF_SANITIZERS)

# If any sanitizers are enabled, apply them to the target
if(LIST_OF_SANITIZERS)
if(NOT
"${LIST_OF_SANITIZERS}"
STREQUAL
"")
if(NOT MSVC)
target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
else()
string(FIND "$ENV{PATH}" "$ENV{VSINSTALLDIR}" index_of_vs_install_dir)
if("${index_of_vs_install_dir}" STREQUAL "-1")
message(
SEND_ERROR
"Using MSVC sanitizers requires setting the MSVC environment before building the project. Please manually open the MSVC command prompt and rebuild the project."
)
endif()
target_compile_options(${project_name} INTERFACE /fsanitize=${LIST_OF_SANITIZERS} /Zi /INCREMENTAL:NO)
target_compile_definitions(${project_name} INTERFACE _DISABLE_VECTOR_ANNOTATION _DISABLE_STRING_ANNOTATION)
target_link_options(${project_name} INTERFACE /INCREMENTAL:NO)
if(NOT MSVC)
# Apply sanitizers for GCC/Clang.
target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
else()
# Apply sanitizers for MSVC.
string(FIND "$ENV{PATH}" "$ENV{VSINSTALLDIR}" index_of_vs_install_dir)
if("${index_of_vs_install_dir}" STREQUAL "-1")
message(
SEND_ERROR
"Using MSVC sanitizers requires setting the MSVC environment before building the project. Please manually open the MSVC command prompt and rebuild the project."
)
endif()
target_compile_options(${project_name} INTERFACE /fsanitize=${LIST_OF_SANITIZERS} /Zi /INCREMENTAL:NO)
target_compile_definitions(${project_name} INTERFACE _DISABLE_VECTOR_ANNOTATION _DISABLE_STRING_ANNOTATION)
target_link_options(${project_name} INTERFACE /INCREMENTAL:NO)
endif()
endif()

endfunction()
endfunction()
Loading

0 comments on commit 71426e5

Please sign in to comment.