cmake_minimum_required(VERSION 3.16) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Meta/CMake") project(SerenityOS C CXX ASM) if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "") message(FATAL_ERROR ": Don't use CMAKE_BUILD_TYPE when building serenity.\n" "The default build type is optimized with debug info and asserts enabled,\n" "and that's all there is.") endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL "SerenityOS") message(FATAL_ERROR "System name is not SerenityOS, this is unsupported.\n" "Please re-read the BuildInstructions documentation, and use the superbuild configuration\n") endif() # Check for toolchain mismatch, user might need to rebuild toolchain set(GCC_VERSION "12.1.0") set(LLVM_VERSION "14.0.1") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(EXPECTED_COMPILER_VERSION "${GCC_VERSION}") else() set(EXPECTED_COMPILER_VERSION "${LLVM_VERSION}") endif() if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "${EXPECTED_COMPILER_VERSION}") message(FATAL_ERROR "${CMAKE_CXX_COMPILER_ID} version (${CMAKE_CXX_COMPILER_VERSION}) does not match " "expected compiler version (${EXPECTED_COMPILER_VERSION}).\n" "Please rebuild the ${CMAKE_CXX_COMPILER_ID} Toolchain\n") endif() set(CMAKE_INSTALL_MESSAGE NEVER) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(NOT COMMAND serenity_option) macro(serenity_option) set(${ARGV}) endmacro() endif() include(serenity_options) find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE FILEPATH "Path to a compiler launcher program, e.g. ccache") set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" CACHE FILEPATH "Path to a compiler launcher program, e.g. ccache") endif() if (NOT HACKSTUDIO_BUILD) include(check_for_dependencies) # Host tools, required to generate files for the build find_package(Lagom CONFIG REQUIRED) endif() # Meta target to run all code-gen steps in the build. add_custom_target(all_generated) add_custom_target(run COMMAND "${CMAKE_COMMAND}" -E env "SERENITY_ARCH=${SERENITY_ARCH}" "${SerenityOS_SOURCE_DIR}/Meta/run.sh" USES_TERMINAL ) # This can currently only be implemented by ordered commands # as cmake doesn't support inter dependency ordering, and we # would like to avoid inject dependencies on the existing # custom commands to allow people to run commands adhoc with # out forcing re-builds when they might not want them. add_custom_target(setup-and-run COMMAND ${CMAKE_MAKE_PROGRAM} install COMMAND ${CMAKE_MAKE_PROGRAM} image COMMAND ${CMAKE_MAKE_PROGRAM} run USES_TERMINAL ) add_custom_target(image DEPENDS qemu-image ) add_custom_target(qemu-image COMMAND "${CMAKE_COMMAND}" -E env "SERENITY_SOURCE_DIR=${SerenityOS_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "SERENITY_TOOLCHAIN=${CMAKE_CXX_COMPILER_ID}" "LLVM_VERSION=${CMAKE_CXX_COMPILER_VERSION}" "${SerenityOS_SOURCE_DIR}/Meta/build-image-qemu.sh" BYPRODUCTS "${CMAKE_BINARY_DIR}/_disk_image" USES_TERMINAL ) add_custom_target(grub-image COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${SerenityOS_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "SERENITY_TOOLCHAIN=${CMAKE_CXX_COMPILER_ID}" "LLVM_VERSION=${CMAKE_CXX_COMPILER_VERSION}" "${SerenityOS_SOURCE_DIR}/Meta/build-image-grub.sh" BYPRODUCTS ${CMAKE_BINARY_DIR}/grub_disk_image USES_TERMINAL ) add_custom_target(limine-image COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${SerenityOS_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "SERENITY_TOOLCHAIN=${CMAKE_CXX_COMPILER_ID}" "LLVM_VERSION=${CMAKE_CXX_COMPILER_VERSION}" "${SerenityOS_SOURCE_DIR}/Meta/build-image-limine.sh" BYPRODUCTS ${CMAKE_BINARY_DIR}/limine_disk_image USES_TERMINAL ) add_custom_target(extlinux-image COMMAND "${CMAKE_COMMAND}" -E env "SERENITY_SOURCE_DIR=${SerenityOS_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "SERENITY_TOOLCHAIN=${CMAKE_CXX_COMPILER_ID}" "LLVM_VERSION=${CMAKE_CXX_COMPILER_VERSION}" "${SerenityOS_SOURCE_DIR}/Meta/build-image-extlinux.sh" BYPRODUCTS "${CMAKE_BINARY_DIR}/extlinux_disk_image" USES_TERMINAL ) add_custom_target(install-native-partition COMMAND "${CMAKE_COMMAND}" -E env "SERENITY_SOURCE_DIR=${SerenityOS_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "SERENITY_TOOLCHAIN=${CMAKE_CXX_COMPILER_ID}" "LLVM_VERSION=${CMAKE_CXX_COMPILER_VERSION}" "${SerenityOS_SOURCE_DIR}/Meta/build-native-partition.sh" USES_TERMINAL ) add_custom_target(lint-shell-scripts COMMAND "${SerenityOS_SOURCE_DIR}/Meta/lint-shell-scripts.sh" USES_TERMINAL ) add_custom_target(check-style COMMAND "${SerenityOS_SOURCE_DIR}/Meta/check-style.sh" USES_TERMINAL ) add_custom_target(install-ports COMMAND "${CMAKE_COMMAND}" -E env "SERENITY_SOURCE_DIR=${SerenityOS_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "SERENITY_TOOLCHAIN=${CMAKE_CXX_COMPILER_ID}" "${SerenityOS_SOURCE_DIR}/Meta/install-ports-tree.sh" USES_TERMINAL ) if (NOT HACKSTUDIO_BUILD) add_custom_target(configure-components COMMAND "$" USES_TERMINAL ) add_dependencies(configure-components Lagom::ConfigureComponents) endif() if (ENABLE_ALL_DEBUG_FACILITIES) set(ENABLE_ALL_THE_DEBUG_MACROS ON) set(ENABLE_EXTRA_KERNEL_DEBUG_SYMBOLS ON) # Immediately finds violations during boot, shouldn't be discoverable # by people who aren't working on fixing issues. Use this check to make # sure this code continues to build instead of all_debug_macros to avoid # people filing bugs. set(KMALLOC_VERIFY_NO_SPINLOCK_HELD ON) # Enables KCOV API and injects kernel coverage instrumentation via # -fsanitize-coverage=trace-pc. Mostly here to ensure that the CI catches # commits breaking this flag. set(ENABLE_KERNEL_COVERAGE_COLLECTION ON) endif() if (ENABLE_ALL_THE_DEBUG_MACROS) include(all_the_debug_macros) endif(ENABLE_ALL_THE_DEBUG_MACROS) configure_file(AK/Debug.h.in AK/Debug.h @ONLY) configure_file(Kernel/Debug.h.in Kernel/Debug.h @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/AK/Debug.h DESTINATION usr/include/AK) set(CMAKE_STAGING_PREFIX ${CMAKE_BINARY_DIR}/Root) set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/Root) set(CMAKE_INSTALL_DATAROOTDIR ${CMAKE_BINARY_DIR}/Root/res) # We disable it completely because it makes cmake very spammy. # This will need to be revisited when the Loader supports RPATH/RUN_PATH. set(CMAKE_SKIP_RPATH TRUE) include(serenity_compile_options) add_link_options(LINKER:-z,text) add_link_options(LINKER:--no-allow-shlib-undefined) add_compile_definitions(SANITIZE_PTRS) set(CMAKE_CXX_FLAGS_STATIC "${CMAKE_CXX_FLAGS} -static") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pie -fpic") if (ENABLE_COMPILETIME_FORMAT_CHECK) add_compile_definitions(ENABLE_COMPILETIME_FORMAT_CHECK) endif() add_link_options(-Wno-unused-command-line-argument) include_directories(.) include_directories(Userland/Libraries) include_directories(Userland/Libraries/LibC) include_directories(Userland/Libraries/LibCrypt) include_directories(Userland/Libraries/LibM) include_directories(Userland/Libraries/LibPthread) include_directories(Userland/Libraries/LibSystem) include_directories(Userland/Services) include_directories(Userland) include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/Userland/Services) include_directories(${CMAKE_CURRENT_BINARY_DIR}/Userland/Libraries) include_directories(${CMAKE_CURRENT_BINARY_DIR}/Userland) # FIXME: vptr sanitizing requires.. intense ABI wrangling of std::type_info # And would be better served by porting ubsan_type_hash_itanium.cpp from compiler-rt if (ENABLE_UNDEFINED_SANITIZER) add_compile_options(-fsanitize=undefined -fno-sanitize=vptr) add_link_options(-fsanitize=undefined -fno-sanitize=vptr) endif() add_custom_target(components ALL) option(BUILD_EVERYTHING "Build all optional components" ON) include(utils) include(wasm_spec_tests) serenity_component( Tests RECOMMENDED ) if (HACKSTUDIO_BUILD) include_directories(/usr/include/Userland/Services) include(${HACKSTUDIO_BUILD_CMAKE_FILE}) return() endif() add_subdirectory(AK) add_subdirectory(Kernel) if(NOT "${SERENITY_ARCH}" STREQUAL "aarch64") if (ENABLE_MOLD_LINKER) add_link_options(-fuse-ld=mold) endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang$" OR ENABLE_MOLD_LINKER) add_link_options(LINKER:--pack-dyn-relocs=relr) else() add_link_options(LINKER:-z,pack-relative-relocs) endif() add_subdirectory(Userland) add_subdirectory(Tests) endif() if (ENABLE_COMPILETIME_HEADER_CHECK) add_subdirectory(Meta/HeaderCheck) endif() export_components("${CMAKE_BINARY_DIR}/components.ini") set(PCI_IDS_FILE pci.ids) set(PCI_IDS_GZ_URL https://pci-ids.ucw.cz/v2.2/${PCI_IDS_FILE}.gz) set(PCI_IDS_GZ_PATH ${CMAKE_BINARY_DIR}/${PCI_IDS_FILE}.gz) set(PCI_IDS_PATH ${CMAKE_BINARY_DIR}/${PCI_IDS_FILE}) set(PCI_IDS_INSTALL_PATH ${CMAKE_INSTALL_DATAROOTDIR}/${PCI_IDS_FILE}) if(ENABLE_PCI_IDS_DOWNLOAD AND NOT EXISTS ${PCI_IDS_GZ_PATH}) download_file("${PCI_IDS_GZ_URL}" "${PCI_IDS_GZ_PATH}") endif() if(EXISTS ${PCI_IDS_GZ_PATH} AND NOT EXISTS ${PCI_IDS_INSTALL_PATH}) message(STATUS "Extracting PCI ID database from ${PCI_IDS_GZ_PATH}...") file(MAKE_DIRECTORY ${CMAKE_INSTALL_DATAROOTDIR}) execute_process(COMMAND "${GZIP_TOOL}" -d -c "${PCI_IDS_GZ_PATH}" OUTPUT_FILE "${PCI_IDS_INSTALL_PATH}") endif() set(USB_IDS_FILE usb.ids) set(USB_IDS_GZ_URL http://www.linux-usb.org/${USB_IDS_FILE}.gz) set(USB_IDS_GZ_PATH ${CMAKE_BINARY_DIR}/${USB_IDS_FILE}.gz) set(USB_IDS_PATH ${CMAKE_BINARY_DIR}/${USB_IDS_FILE}) set(USB_IDS_INSTALL_PATH ${CMAKE_INSTALL_DATAROOTDIR}/${USB_IDS_FILE}) if(ENABLE_USB_IDS_DOWNLOAD AND NOT EXISTS ${USB_IDS_GZ_PATH}) download_file("${USB_IDS_GZ_URL}" "${USB_IDS_GZ_PATH}") endif() if(EXISTS ${USB_IDS_GZ_PATH} AND NOT EXISTS ${USB_IDS_INSTALL_PATH}) message(STATUS "Extracting USB ID database from ${USB_IDS_GZ_PATH}...") file(MAKE_DIRECTORY ${CMAKE_INSTALL_DATAROOTDIR}) execute_process(COMMAND "${GZIP_TOOL}" -d -c "${USB_IDS_GZ_PATH}" OUTPUT_FILE "${USB_IDS_INSTALL_PATH}") endif()