209 lines
6.3 KiB
CMake
209 lines
6.3 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
project(CPP_TEMPLATE VERSION 0.1.0 LANGUAGES C CXX)
|
|
|
|
# Set C++ standard
|
|
set(CMAKE_CXX_STANDARD 23)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
# Set C standard
|
|
set(CMAKE_C_STANDARD 17)
|
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
set(CMAKE_C_EXTENSIONS OFF)
|
|
|
|
# Export compile commands for IDE support (clangd, etc.)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# Create symlink to compile_commands.json in project root for LSP
|
|
if(CMAKE_EXPORT_COMPILE_COMMANDS)
|
|
add_custom_target(symlink_compile_commands ALL
|
|
COMMAND ${CMAKE_COMMAND} -E create_symlink
|
|
${CMAKE_BINARY_DIR}/compile_commands.json
|
|
${CMAKE_SOURCE_DIR}/compile_commands.json
|
|
COMMENT "Creating symlink to compile_commands.json in project root"
|
|
)
|
|
endif()
|
|
|
|
# Set output directories
|
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
|
|
|
# Build type defaults
|
|
if(NOT CMAKE_BUILD_TYPE)
|
|
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type" FORCE)
|
|
endif()
|
|
|
|
# Options
|
|
option(ENABLE_SANITIZERS "Enable address and undefined behavior sanitizers" ON)
|
|
option(ENABLE_STATIC_ANALYSIS "Enable static analysis warnings" ON)
|
|
set(OUTPUT_NAME "" CACHE STRING "Name of the output executable (defaults to project name)")
|
|
|
|
# Gather source files (avoid GLOB_RECURSE - explicitly list files is better practice)
|
|
# But keeping it for template flexibility
|
|
file(GLOB_RECURSE PROJECT_SOURCES
|
|
${CMAKE_SOURCE_DIR}/source/*.cpp
|
|
${CMAKE_SOURCE_DIR}/source/*.c
|
|
)
|
|
|
|
file(GLOB_RECURSE LIBRARY_SOURCES
|
|
${CMAKE_SOURCE_DIR}/libraries/*.cpp
|
|
${CMAKE_SOURCE_DIR}/libraries/*.c
|
|
${CMAKE_SOURCE_DIR}/libraries/imgui/*.cpp
|
|
${CMAKE_SOURCE_DIR}/libraries/imgui/*.c
|
|
)
|
|
|
|
# Don't glob headers from include/ as sources (they should only be included)
|
|
file(GLOB_RECURSE PROJECT_HEADERS
|
|
${CMAKE_SOURCE_DIR}/include/*.hpp
|
|
${CMAKE_SOURCE_DIR}/include/*.h
|
|
${CMAKE_SOURCE_DIR}/libraries/*.hpp
|
|
${CMAKE_SOURCE_DIR}/libraries/*.h
|
|
${CMAKE_SOURCE_DIR}/source/*.hpp
|
|
${CMAKE_SOURCE_DIR}/source/*.h
|
|
)
|
|
|
|
|
|
# Combine all sources
|
|
set(ALL_SOURCES ${PROJECT_SOURCES} ${LIBRARY_SOURCES})
|
|
|
|
# Determine executable name
|
|
if(OUTPUT_NAME)
|
|
set(EXECUTABLE_NAME ${OUTPUT_NAME})
|
|
else()
|
|
set(EXECUTABLE_NAME ${PROJECT_NAME})
|
|
endif()
|
|
|
|
# Create executable
|
|
add_executable(${EXECUTABLE_NAME} ${ALL_SOURCES})
|
|
|
|
# Set target properties
|
|
set_target_properties(${EXECUTABLE_NAME} PROPERTIES
|
|
OUTPUT_NAME ${EXECUTABLE_NAME}
|
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
|
)
|
|
|
|
# Include directories - use target-specific commands
|
|
target_include_directories(${EXECUTABLE_NAME} PRIVATE
|
|
${CMAKE_SOURCE_DIR}/include
|
|
${CMAKE_SOURCE_DIR}/libraries
|
|
)
|
|
|
|
# 1. Find the GLFW library in your lib folder
|
|
find_library(GLFW_LIB NAMES glfw glfw3 PATHS "${CMAKE_SOURCE_DIR}/libraries" NO_DEFAULT_PATH)
|
|
|
|
# 2. Link GLFW and the required Apple Frameworks
|
|
if(APPLE)
|
|
target_link_libraries(${EXECUTABLE_NAME} PRIVATE
|
|
${GLFW_LIB}
|
|
"-framework Cocoa"
|
|
"-framework IOKit"
|
|
"-framework CoreVideo"
|
|
)
|
|
else()
|
|
# For Windows/Linux
|
|
target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${GLFW_LIB})
|
|
endif()
|
|
|
|
|
|
# Compiler-specific flags
|
|
if(MSVC)
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE
|
|
/W4 # Warning level 4
|
|
/permissive- # Standards conformance
|
|
/Zc:__cplusplus # Correct __cplusplus macro
|
|
/Zc:inline # Remove unreferenced COMDAT
|
|
/WX- # Don't treat warnings as errors by default
|
|
)
|
|
|
|
if(ENABLE_STATIC_ANALYSIS)
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE /analyze)
|
|
endif()
|
|
|
|
# MSVC debug flags
|
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE /Zi /Od)
|
|
endif()
|
|
|
|
else() # GCC/Clang
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE
|
|
-Wall
|
|
-Wextra
|
|
-Wpedantic
|
|
-Wshadow
|
|
-Wconversion
|
|
-Wsign-conversion
|
|
-Wuninitialized
|
|
-Wunused
|
|
-Werror=return-type
|
|
-Wcast-align
|
|
-Wformat=2
|
|
-Wnull-dereference
|
|
)
|
|
|
|
# Additional warnings for static analysis
|
|
if(ENABLE_STATIC_ANALYSIS)
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE
|
|
-Wcast-qual
|
|
-Wdouble-promotion
|
|
-Wold-style-cast
|
|
)
|
|
endif()
|
|
|
|
# Sanitizers (Debug builds)
|
|
if(ENABLE_SANITIZERS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
# Check if sanitizers are available
|
|
include(CheckCXXCompilerFlag)
|
|
check_cxx_compiler_flag("-fsanitize=address" HAS_ASAN)
|
|
check_cxx_compiler_flag("-fsanitize=undefined" HAS_UBSAN)
|
|
|
|
if(HAS_ASAN AND HAS_UBSAN)
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE
|
|
-fsanitize=address,undefined,leak
|
|
-fno-omit-frame-pointer
|
|
-g
|
|
)
|
|
target_link_options(${EXECUTABLE_NAME} PRIVATE
|
|
-fsanitize=address,undefined,leak
|
|
)
|
|
message(STATUS "Sanitizers enabled: address, undefined, leak")
|
|
else()
|
|
message(WARNING "Sanitizers requested but not available - skipping")
|
|
endif()
|
|
endif()
|
|
|
|
# Optimization flags for Release
|
|
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE
|
|
-O3
|
|
-march=native
|
|
-DNDEBUG
|
|
)
|
|
endif()
|
|
|
|
# Debug flags
|
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
target_compile_options(${EXECUTABLE_NAME} PRIVATE
|
|
-O0
|
|
-g3
|
|
-ggdb
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
# Print configuration summary
|
|
message(STATUS "=== Configuration Summary ===")
|
|
message(STATUS "Project: ${PROJECT_NAME} v${PROJECT_VERSION}")
|
|
message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
|
|
message(STATUS "C++ Standard: ${CMAKE_CXX_STANDARD}")
|
|
message(STATUS "C Standard: ${CMAKE_C_STANDARD}")
|
|
message(STATUS "Executable Name: ${EXECUTABLE_NAME}")
|
|
message(STATUS "Sanitizers: ${ENABLE_SANITIZERS}")
|
|
message(STATUS "Static Analysis: ${ENABLE_STATIC_ANALYSIS}")
|
|
message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
|
|
message(STATUS "============================")
|
|
|
|
# Optionally, enable testing
|
|
# enable_testing()
|
|
# add_subdirectory(tests)
|