diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e041ff20f..2e0e0e1d81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(SERENITY_ARCH "i686" CACHE STRING "Target architecture for SerenityOS.") +if("${SERENITY_ARCH}" STREQUAL "i686") + set(SERENITY_CLANG_ARCH "i386") +else() + set(SERENITY_CLANG_ARCH ${SERENITY_ARCH}) +endif() + # Central location for all custom options used in the Serenity build. option(ENABLE_ADDRESS_SANITIZER "Enable address sanitizer testing in gcc/clang" OFF) option(ENABLE_KERNEL_ADDRESS_SANITIZER "Enable kernel address sanitizer testing in gcc/clang" OFF) @@ -37,6 +43,7 @@ option(ENABLE_PCI_IDS_DOWNLOAD "Enable download of the pci.ids database at build option(ENABLE_USB_IDS_DOWNLOAD "Enable download of the usb.ids database at build time" ON) option(BUILD_LAGOM "Build parts of the system targeting the host OS for fuzzing/testing" OFF) option(ENABLE_KERNEL_LTO "Build the kernel with link-time optimization" OFF) +option(USE_CLANG_TOOLCHAIN "Build the kernel with the experimental Clang toolchain" OFF) include(Meta/CMake/wasm_spec_tests.cmake) @@ -60,18 +67,22 @@ add_custom_target(setup-and-run add_custom_target(image DEPENDS qemu-image ) + +set(GCC_VERSION 11.2.0) +set(LLVM_VERSION 12.0.1) + add_custom_target(qemu-image - COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${CMAKE_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" ${CMAKE_SOURCE_DIR}/Meta/build-image-qemu.sh + COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${CMAKE_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "USE_CLANG_TOOLCHAIN=$" "LLVM_VERSION=${LLVM_VERSION}" ${CMAKE_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=${CMAKE_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" ${CMAKE_SOURCE_DIR}/Meta/build-image-grub.sh + COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${CMAKE_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "USE_CLANG_TOOLCHAIN=$" "LLVM_VERSION=${LLVM_VERSION}" ${CMAKE_SOURCE_DIR}/Meta/build-image-grub.sh BYPRODUCTS ${CMAKE_BINARY_DIR}/grub_disk_image USES_TERMINAL ) add_custom_target(extlinux-image - COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${CMAKE_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" ${CMAKE_SOURCE_DIR}/Meta/build-image-extlinux.sh + COMMAND ${CMAKE_COMMAND} -E env "SERENITY_SOURCE_DIR=${CMAKE_SOURCE_DIR}" "SERENITY_ARCH=${SERENITY_ARCH}" "USE_CLANG_TOOLCHAIN=$" "LLVM_VERSION=${LLVM_VERSION}" ${CMAKE_SOURCE_DIR}/Meta/build-image-extlinux.sh BYPRODUCTS ${CMAKE_BINARY_DIR}/extlinux_disk_image USES_TERMINAL ) @@ -100,12 +111,13 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -add_compile_options(-Wno-literal-suffix) add_compile_options(-fsized-deallocation) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") add_compile_options(-Wno-literal-suffix) elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$") - add_compile_options(-Wno-overloaded-virtual -Wno-user-defined-literals) + add_compile_options(-Wno-overloaded-virtual) + add_compile_options(-Wno-user-defined-literals) + add_compile_options(-fconstexpr-steps=16777216) endif() if (ENABLE_ALL_DEBUG_FACILITIES) @@ -159,10 +171,23 @@ 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) -set(GCC_VERSION 11.2.0) if (${CMAKE_HOST_SYSTEM_NAME} MATCHES SerenityOS) message("Good job on building cmake!") +elseif(USE_CLANG_TOOLCHAIN) + set(TOOLCHAIN_ROOT ${CMAKE_SOURCE_DIR}/Toolchain/Local/clang/${SERENITY_ARCH}/) + set(TOOLCHAIN_PATH ${TOOLCHAIN_ROOT}/bin) + + set(CMAKE_C_COMPILER ${TOOLCHAIN_PATH}/clang) + set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PATH}/clang++) + set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PATH}/clang) + set(CMAKE_LINKER ${TOOLCHAIN_PATH}/ld.lld) + set(CMAKE_RANLIB ${TOOLCHAIN_PATH}/llvm-ranlib) + set(CMAKE_STRIP ${TOOLCHAIN_PATH}/llvm-strip) + set(CMAKE_AR ${TOOLCHAIN_PATH}/llvm-ar) + set(CMAKE_CXXFILT ${TOOLCHAIN_PATH}/llvm-cxxfilt) + # FIXME: Persuade LLVM maintainers to add `--update-section` to llvm-objcopy, as it's required for the kernel symbol map. + set(CMAKE_OBJCOPY ${TOOLCHAIN_ROOT}/binutils/bin/${SERENITY_ARCH}-pc-serenity-objcopy) else() set(TOOLCHAIN_ROOT ${CMAKE_SOURCE_DIR}/Toolchain/Local/${SERENITY_ARCH}/) set(TOOLCHAIN_PATH ${TOOLCHAIN_ROOT}/bin) @@ -219,11 +244,9 @@ add_compile_options(-Wextra) # The following warnings are sorted by the "base" name (the part excluding the initial Wno or W). add_compile_options(-Wno-address-of-packed-member) -add_compile_options(-Wcast-align) add_compile_options(-Wcast-qual) add_compile_options(-Wno-deprecated-copy) add_compile_options(-Wduplicated-cond) -add_compile_options(-Wdouble-promotion) add_compile_options(-Wno-expansion-to-defined) add_compile_options(-Wformat=2) add_compile_options(-Wimplicit-fallthrough) @@ -235,16 +258,52 @@ add_compile_options(-Wnon-virtual-dtor) add_compile_options(-Wno-unknown-warning-option) add_compile_options(-Wundef) add_compile_options(-Wunused) +add_compile_options(-Wno-unused-private-field) +add_compile_options(-Wno-unused-const-variable) +add_compile_options(-Wno-unused-command-line-argument) add_compile_options(-Wwrite-strings) add_compile_options(-Wno-maybe-uninitialized) add_compile_options(-ffile-prefix-map=${CMAKE_SOURCE_DIR}=.) add_compile_options(-fno-exceptions) +add_compile_options(-ftls-model=initial-exec) +add_compile_options(-fno-semantic-interposition) +add_compile_options(-fstack-clash-protection) add_compile_options(-fstack-protector-strong) add_compile_options(-g1) -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - add_compile_options(-fstack-clash-protection) +if (USE_CLANG_TOOLCHAIN) + add_compile_options(-Wno-atomic-alignment) + add_compile_options(-Wno-c99-designator) + add_compile_options(-Wno-implicit-const-int-float-conversion) + add_compile_options(-Wno-inconsistent-missing-override) + add_compile_options(-Wno-tautological-constant-out-of-range-compare) + add_compile_options(-Wno-unneeded-internal-declaration) + add_compile_options(-Wno-unused-function) + add_compile_options(-Wno-user-defined-literals) + # Without the 'SHELL' prefix, this would get removed through de-duplication with the flags set for the host compiler. + # Then, that would come before '-Wextra', so it would not negate the '-Woverloaded-virtual' set by '-Wextra'. + add_compile_options(SHELL:-Wno-overloaded-virtual) + + add_compile_options(--sysroot=${CMAKE_BINARY_DIR}/Root) + add_compile_options(--target=${SERENITY_CLANG_ARCH}-pc-serenity) + add_compile_options(-fno-aligned-allocation) + add_compile_options(-fconstexpr-steps=16777216) + add_compile_options(-gdwarf-4) + + # FIXME: Why is Clang not picking up this path? + link_directories(${TOOLCHAIN_ROOT}/lib/clang/${LLVM_VERSION}/lib/serenity) + + add_link_options(LINKER:--allow-shlib-undefined) +else() + add_compile_options(-Wcast-align) + add_compile_options(-Wdouble-promotion) +endif() + +if("${SERENITY_ARCH}" STREQUAL "i686") + add_compile_options(-march=i686) +else() + add_compile_options(-march=x86-64) endif() add_compile_definitions(SANITIZE_PTRS) @@ -256,6 +315,7 @@ if (ENABLE_COMPILETIME_FORMAT_CHECK) endif() add_link_options(--sysroot ${CMAKE_BINARY_DIR}/Root) +add_link_options(-Wno-unused-command-line-argument) include_directories(Userland/Libraries/LibC) include_directories(Userland/Libraries/LibCrypt) diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index ea58982611..96c968eca4 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -349,19 +349,32 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-80387 -mno-mmx -mno-sse -mno-sse2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-asynchronous-unwind-tables") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-strong") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nodefaultlibs -nostdlib -nostdinc -nostdinc++") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nodefaultlibs -nostdlib") # Apply any flags that are only available on >= GCC 11.1 -if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) +if (NOT USE_CLANG_TOOLCHAIN AND CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11.1) # Zero any registers used within a function on return (to reduce data lifetime and ROP gadgets). set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fzero-call-used-regs=used-gpr") endif() +if (NOT USE_CLANG_TOOLCHAIN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc -nostdinc++") +endif() + +macro (set_new_alignment alignment) + if (USE_CLANG_TOOLCHAIN) + add_compile_options(-faligned-allocation) + add_compile_options(-fnew-alignment=${alignment}) + else() + add_compile_options(-faligned-new=${alignment}) + endif() +endmacro() + if ("${SERENITY_ARCH}" STREQUAL "x86_64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=large -mno-red-zone") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-new=8") + set_new_alignment(8) else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -faligned-new=4") + set_new_alignment(4) endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-pie") @@ -412,16 +425,26 @@ add_compile_definitions(KERNEL) # It's needed because CLion doesn't understand the way we switch compilers mid-build. add_compile_definitions(__serenity__) +if (USE_CLANG_TOOLCHAIN) + add_link_options(LINKER:-z,notext) + add_link_options(LINKER:--build-id=none) +endif() + add_library(kernel_heap STATIC ${KERNEL_HEAP_SOURCES}) if (${CMAKE_HOST_SYSTEM_NAME} MATCHES SerenityOS) include_directories(/usr/local/include/c++/${GCC_VERSION}/) +elseif (USE_CLANG_TOOLCHAIN) + include_directories("${TOOLCHAIN_ROOT}/include/c++/v1") else() if (NOT EXISTS ${TOOLCHAIN_ROOT}/${SERENITY_ARCH}-pc-serenity/include/c++/${GCC_VERSION}/) message(FATAL_ERROR "Toolchain version ${GCC_VERSION} appears to be missing! Please run: Meta/serenity.sh rebuild-toolchain") endif() include_directories(${TOOLCHAIN_ROOT}/${SERENITY_ARCH}-pc-serenity/include/c++/${GCC_VERSION}/) include_directories(${TOOLCHAIN_ROOT}/${SERENITY_ARCH}-pc-serenity/include/c++/${GCC_VERSION}/${SERENITY_ARCH}-pc-serenity/) +endif() + +if (NOT USE_CLANG_TOOLCHAIN) link_directories(${TOOLCHAIN_ROOT}/${SERENITY_ARCH}-pc-serenity/lib) link_directories(${TOOLCHAIN_ROOT}/lib/gcc/${SERENITY_ARCH}-pc-serenity/${GCC_VERSION}/) endif() @@ -447,7 +470,13 @@ if (ENABLE_KERNEL_LTO) check_ipo_supported() set_property(TARGET Kernel PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) endif() -target_link_libraries(Kernel kernel_heap gcc) + +if (USE_CLANG_TOOLCHAIN) + target_link_libraries(Kernel kernel_heap clang_rt.builtins-${SERENITY_CLANG_ARCH}) +else() + target_link_libraries(Kernel kernel_heap gcc) +endif() + add_dependencies(Kernel kernel_heap) add_custom_command( diff --git a/Kernel/Prekernel/CMakeLists.txt b/Kernel/Prekernel/CMakeLists.txt index 7615dff660..a950245170 100644 --- a/Kernel/Prekernel/CMakeLists.txt +++ b/Kernel/Prekernel/CMakeLists.txt @@ -18,14 +18,18 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static") add_executable(${PREKERNEL_TARGET} ${SOURCES}) target_compile_options(${PREKERNEL_TARGET} PRIVATE -no-pie -fno-pic) -target_link_options(${PREKERNEL_TARGET} PRIVATE LINKER:-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld -nostdlib) +target_link_options(${PREKERNEL_TARGET} PRIVATE LINKER:-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld -nostdlib LINKER:--no-pie) set_target_properties(${PREKERNEL_TARGET} PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) -target_link_libraries(${PREKERNEL_TARGET} gcc supc++) +if (USE_CLANG_TOOLCHAIN) + target_link_libraries(${PREKERNEL_TARGET} clang_rt.builtins-${SERENITY_CLANG_ARCH} c++abi) +else() + target_link_libraries(${PREKERNEL_TARGET} gcc supc++) +endif() add_custom_command( TARGET ${PREKERNEL_TARGET} POST_BUILD - COMMAND ${TOOLCHAIN_PREFIX}objcopy -O elf32-i386 ${CMAKE_CURRENT_BINARY_DIR}/${PREKERNEL_TARGET} ${CMAKE_CURRENT_BINARY_DIR}/Prekernel + COMMAND ${CMAKE_OBJCOPY} -O elf32-i386 ${CMAKE_CURRENT_BINARY_DIR}/${PREKERNEL_TARGET} ${CMAKE_CURRENT_BINARY_DIR}/Prekernel BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/Prekernel ) diff --git a/Meta/CMake/utils.cmake b/Meta/CMake/utils.cmake index 942f327ddc..c5c4510620 100644 --- a/Meta/CMake/utils.cmake +++ b/Meta/CMake/utils.cmake @@ -51,6 +51,9 @@ function(serenity_libc target_name fs_name) add_library(${target_name} SHARED ${SOURCES}) install(TARGETS ${target_name} DESTINATION usr/lib) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME ${fs_name}) + if (USE_CLANG_TOOLCHAIN) + target_link_libraries(${target_name} clang_rt.builtins-${SERENITY_CLANG_ARCH}) + endif() target_link_directories(LibC PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) serenity_generated_sources(${target_name}) endfunction() diff --git a/Meta/build-root-filesystem.sh b/Meta/build-root-filesystem.sh index bdd571f69c..8eb8de7dbf 100755 --- a/Meta/build-root-filesystem.sh +++ b/Meta/build-root-filesystem.sh @@ -44,10 +44,11 @@ else rsync -aH --inplace Root/ mnt/ chown -R 0:0 mnt/ fi + SERENITY_ARCH="${SERENITY_ARCH:-i686}" LLVM_VERSION="${LLVM_VERSION:-12.0.1}" -if [ "$USE_CLANG_TOOLCHAIN" = "ON" ]; then +if [ "$USE_CLANG_TOOLCHAIN" = "1" ]; then TOOLCHAIN_DIR="$SERENITY_SOURCE_DIR"/Toolchain/Local/clang/"$SERENITY_ARCH" mkdir -p mnt/usr/lib/clang/"$LLVM_VERSION"/lib/serenity $CP "$TOOLCHAIN_DIR"/lib/clang/"$LLVM_VERSION"/lib/serenity/* mnt/usr/lib/clang/"$LLVM_VERSION"/lib/serenity diff --git a/Userland/DynamicLoader/CMakeLists.txt b/Userland/DynamicLoader/CMakeLists.txt index af20a733a2..f75ffa1347 100644 --- a/Userland/DynamicLoader/CMakeLists.txt +++ b/Userland/DynamicLoader/CMakeLists.txt @@ -32,6 +32,12 @@ set_source_files_properties (../Libraries/LibC/ssp.cpp PROPERTIES COMPILE_FLAGS "-fno-stack-protector") add_executable(Loader.so ${SOURCES}) -target_link_libraries(Loader.so gcc) + +if (USE_CLANG_TOOLCHAIN) + target_link_libraries(Loader.so clang_rt.builtins-${SERENITY_CLANG_ARCH}) +else() + target_link_libraries(Loader.so gcc) +endif() + target_link_options(Loader.so PRIVATE LINKER:--no-dynamic-linker) install(TARGETS Loader.so RUNTIME DESTINATION usr/lib/) diff --git a/Userland/Libraries/LibC/CMakeLists.txt b/Userland/Libraries/LibC/CMakeLists.txt index 3108399552..6746a93b33 100644 --- a/Userland/Libraries/LibC/CMakeLists.txt +++ b/Userland/Libraries/LibC/CMakeLists.txt @@ -110,7 +110,10 @@ add_custom_command( set(SOURCES ${LIBC_SOURCES} ${AK_SOURCES} ${ELF_SOURCES} ${ASM_SOURCES}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++") +if (NOT USE_CLANG_TOOLCHAIN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++") +endif() + add_library(LibCStaticWithoutDeps STATIC ${SOURCES}) target_link_libraries(LibCStaticWithoutDeps ssp) add_dependencies(LibCStaticWithoutDeps LibM LibSystem LibUBSanitizer) @@ -133,7 +136,7 @@ set_property( PROPERTY ADDITIONAL_CLEAN_FILES ${TEMP_OBJ_FILES} ) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nolibc") serenity_libc(LibC c) add_dependencies(LibC crti crt0 crt0_shared crtn) target_link_libraries(LibC ssp system)