mirror of
https://github.com/gbdev/rgbds.git
synced 2026-03-25 06:13:03 +00:00
Set the flags in the build itself instead of trying to override the cache (this was an artifact of when I didn't understand the CMake variable model), which avoids them being duplicated on each re-configuration. Also remove `-g`, since it's defined by the build type by default (we leave it up to the user to choose Debug or RelWithDebInfo).
163 lines
6.6 KiB
CMake
163 lines
6.6 KiB
CMake
# SPDX-License-Identifier: MIT
|
|
|
|
# 3.17 required for LTO checks messages
|
|
cmake_minimum_required(VERSION 3.17...4.2 FATAL_ERROR)
|
|
|
|
# Read the project version from the header (the canonical source of truth).
|
|
file(STRINGS "include/version.hpp" version_defines REGEX "^[ \t]*#define[ \t]+PACKAGE_VERSION_")
|
|
foreach(line IN LISTS version_defines)
|
|
# We want the `CMAKE_MATCH_n` variables, so we just need to run *some* regex op.
|
|
string(REGEX MATCH "PACKAGE_(VERSION_[^ \t]+)[ \t]+([0-9]+)" dummy "${line}")
|
|
set("${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}")
|
|
endforeach()
|
|
|
|
project(rgbds
|
|
VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"
|
|
LANGUAGES CXX
|
|
DESCRIPTION "Game Boy assembly toolchain"
|
|
HOMEPAGE_URL "https://rgbds.gbdev.io")
|
|
if(DEFINED VERSION_RC)
|
|
string(APPEND CMAKE_PROJECT_VERSION "-rc${VERSION_RC}")
|
|
endif()
|
|
|
|
# Reject in-source builds, as they may conflict with the Makefile.
|
|
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
|
|
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
|
|
if(srcdir STREQUAL bindir)
|
|
message(FATAL_ERROR "RGBDS should not be built in the source directory.
|
|
Instead, create a separate build directory and specify to CMake the path to the source directory.")
|
|
endif()
|
|
|
|
include(CTest) # Note: CTest only functions properly if included from the top-level CMakeLists.
|
|
include(GNUInstallDirs)
|
|
|
|
include(CMakeDependentOption)
|
|
option(SANITIZERS "Build with sanitizers enabled" OFF)
|
|
cmake_dependent_option(MORE_WARNINGS "Turn on more warnings" OFF !MSVC OFF)
|
|
|
|
if(MSVC)
|
|
add_compile_options(
|
|
/wd5030 # Warning C5030 is about unknown attributes (`[[gnu::ATTR]]`), none of ours being load-bearing.
|
|
/wd4996 # Warning C4996 is about using POSIX names, which we want to do for portability.
|
|
/Zc:preprocessor # Opt into the C++20-conformant preprocessor.
|
|
)
|
|
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
|
|
|
if(SANITIZERS)
|
|
message(STATUS "ASan enabled")
|
|
add_compile_options(/fsanitize=address) # Note that this shouldn't be passed to the linker.
|
|
endif()
|
|
else()
|
|
add_compile_options(-Wall -pedantic -fno-exceptions -fno-rtti -Wno-unknown-warning-option
|
|
# C++20 allows macros to take zero variadic arguments.
|
|
# Some versions of Clang don't recognize this, and treat them as a GNU extension.
|
|
-Wno-gnu-zero-variadic-macro-arguments)
|
|
if(SANITIZERS)
|
|
message(STATUS "ASan and UBSan enabled")
|
|
set(SAN_FLAGS -fsanitize=address -fsanitize=undefined
|
|
-fsanitize=float-divide-by-zero)
|
|
add_compile_options(${SAN_FLAGS})
|
|
add_link_options(${SAN_FLAGS})
|
|
add_definitions(-D_GLIBCXX_ASSERTIONS -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG)
|
|
# A non-zero optimization level is desired even in debug mode (especially for Clang),
|
|
# and the two codegen flags improve the sanitizers' backtraces, but we want the user to
|
|
# be able to override these easily so we put them first.
|
|
string(PREPEND CMAKE_CXX_FLAGS_DEBUG "-Og -fno-omit-frame-pointer -fno-optimize-sibling-calls ")
|
|
endif()
|
|
|
|
if(MORE_WARNINGS)
|
|
add_compile_options(-Werror -Wextra
|
|
-Walloc-zero -Wcast-align -Wcast-qual -Wduplicated-branches -Wduplicated-cond
|
|
-Wfloat-equal -Wlogical-op -Wnull-dereference -Wold-style-cast -Wshift-overflow=2
|
|
-Wstringop-overflow=4 -Wtrampolines -Wundef -Wuninitialized -Wunused -Wshadow
|
|
-Wformat=2 -Wformat-overflow=2 -Wformat-truncation=1
|
|
-Wno-format-nonliteral -Wno-strict-overflow
|
|
-Wno-unused-but-set-variable # bison's `yynerrs_` is incremented but unused
|
|
-Wno-type-limits -Wno-tautological-constant-out-of-range-compare
|
|
-Wvla # MSVC does not support VLAs
|
|
-Wno-unknown-warning-option) # Clang shouldn't diagnose unknown warnings
|
|
endif()
|
|
endif()
|
|
|
|
# Use versioning consistent with Makefile
|
|
# the git revision is used but uses the fallback in an archive
|
|
|
|
message(CHECK_START "Determining RGBDS version from Git history")
|
|
list(APPEND CMAKE_MESSAGE_INDENT " ")
|
|
set(GIT_REV "") # This fallback is important!
|
|
find_package(Git)
|
|
list(POP_BACK CMAKE_MESSAGE_INDENT)
|
|
if(NOT Git_FOUND)
|
|
message(CHECK_FAIL "Git not found")
|
|
else()
|
|
execute_process(COMMAND "${GIT_EXECUTABLE}" --git-dir=.git -c safe.directory='*'
|
|
describe --tags --dirty --always --match "v[0-9]*"
|
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
|
OUTPUT_VARIABLE GIT_REV OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_VARIABLE git_err ERROR_STRIP_TRAILING_WHITESPACE
|
|
RESULT_VARIABLE result)
|
|
if(NOT result EQUAL 0)
|
|
# Note that this happens e.g. when building from a tarball, so it shouldn't fail the build!
|
|
message(CHECK_FAIL "error ${result} from Git:")
|
|
list(APPEND CMAKE_MESSAGE_INDENT " ")
|
|
message("${git_err}")
|
|
list(POP_BACK CMAKE_MESSAGE_INDENT)
|
|
else()
|
|
message(CHECK_PASS "${GIT_REV}")
|
|
if(NOT "${GIT_REV}" MATCHES "^v[0-9]+\\.[0-9]+\\.[0-9]+(-rc[0-9]+)?")
|
|
# Can't find an ancestor tag! (That passes `--match`, anyway.)
|
|
message(WARNING "No `v*` Git tag reachable; falling back")
|
|
elseif(NOT CMAKE_MATCH_0 STREQUAL "v${CMAKE_PROJECT_VERSION}")
|
|
message(SEND_ERROR "\
|
|
Version mismatch! Git says ${CMAKE_MATCH_0},
|
|
version.hpp says v${CMAKE_PROJECT_VERSION}!")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
find_package(PkgConfig)
|
|
if(MSVC OR NOT PKG_CONFIG_FOUND)
|
|
# fallback to find_package
|
|
# cmake's FindPNG is very fragile; it breaks when multiple versions are installed
|
|
# this is most evident on macOS but can occur on Linux too
|
|
find_package(PNG REQUIRED)
|
|
else()
|
|
pkg_check_modules(LIBPNG REQUIRED IMPORTED_TARGET libpng)
|
|
add_library(PNG::PNG ALIAS PkgConfig::LIBPNG)
|
|
endif()
|
|
|
|
include_directories("include")
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
|
|
message(CHECK_START "Checking if LTO is supported")
|
|
include(CheckIPOSupported)
|
|
check_ipo_supported(RESULT enable_lto)
|
|
if(enable_lto)
|
|
message(CHECK_PASS "yes")
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON)
|
|
else()
|
|
message(CHECK_FAIL "no")
|
|
endif()
|
|
|
|
add_subdirectory(src)
|
|
add_subdirectory(test)
|
|
|
|
set(man1 "man/rgbasm.1"
|
|
"man/rgbfix.1"
|
|
"man/rgbgfx.1"
|
|
"man/rgblink.1")
|
|
set(man5 "man/rgbasm.5"
|
|
"man/rgbasm-old.5"
|
|
"man/rgblink.5"
|
|
"man/rgbds.5")
|
|
set(man7 "man/gbz80.7"
|
|
"man/rgbds.7")
|
|
|
|
foreach(SECTION "man1" "man5" "man7")
|
|
install(FILES ${${SECTION}} DESTINATION "${CMAKE_INSTALL_MANDIR}/${SECTION}")
|
|
endforeach()
|