diff options
author | Andrew Kaster <akaster@serenityos.org> | 2021-09-07 02:21:36 -0600 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-09-15 19:04:52 +0430 |
commit | b5c98ede084e5d29b8586f3bb2bf134184d372be (patch) | |
tree | 7f4ece17df372bbe5dd27c5063b67195e1f578ea /Meta | |
parent | 904a268872416dc9b9f26c83fd0b1bd8b715c511 (diff) | |
download | serenity-b5c98ede084e5d29b8586f3bb2bf134184d372be.zip |
Meta: Switch to a SuperBuild that splits host and target builds
Replace the old logic where we would start with a host build, and swap
all the CMake compiler and target variables underneath it to trick
CMake into building for Serenity after we configured and built the Lagom
code generators.
The SuperBuild creates two ExternalProjects, one for Lagom and one for
Serenity. The Serenity project depends on the install stage for the
Lagom build. The SuperBuild also generates a CMakeToolchain file for the
Serenity build to use that replaces the old toolchain file that was only
used for Ports.
To ensure that code generators are rebuilt when core libraries such as
AK and LibCore are modified, developers will need to direct their manual
`ninja` invocations to the SuperBuild's binary directory instead of the
Serenity binary directory.
This commit includes warning coalescing and option style cleanup for the
affected CMakeLists in the Kernel, top level, and runtime support
libraries. A large part of the cleanup is replacing USE_CLANG_TOOLCHAIN
with the proper CMAKE_CXX_COMPILER_ID variable, which will no longer be
confused by a host clang compiler.
Diffstat (limited to 'Meta')
-rw-r--r-- | Meta/Azure/Serenity.yml | 23 | ||||
-rw-r--r-- | Meta/CMake/Superbuild/CMakeLists.txt | 137 | ||||
-rw-r--r-- | Meta/CMake/utils.cmake | 5 | ||||
-rw-r--r-- | Meta/Lagom/CMakeLists.txt | 146 | ||||
-rwxr-xr-x | Meta/build-root-filesystem.sh | 2 |
5 files changed, 218 insertions, 95 deletions
diff --git a/Meta/Azure/Serenity.yml b/Meta/Azure/Serenity.yml index 42a406fe0f..04f3af3281 100644 --- a/Meta/Azure/Serenity.yml +++ b/Meta/Azure/Serenity.yml @@ -21,7 +21,7 @@ jobs: parameters: arch: '${{ parameters.arch }}' toolchain: 'clang' - build_directory: 'Build' + build_directory: 'Build/${{ parameters.arch }}clang' - script: ./Toolchain/BuildClang.sh displayName: Build Toolchain @@ -30,31 +30,30 @@ jobs: ARCH: '${{ parameters.arch }}' - script: | - mkdir -p Build + mkdir -p Build/superbuild displayName: 'Create Build Directory' - script: | - cmake -GNinja \ + cmake -S Meta/CMake/Superbuild -B Build/superbuild -GNinja \ -DSERENITY_ARCH=${{ parameters.arch }} \ - -DUSE_CLANG_TOOLCHAIN=ON \ + -DSERENITY_TOOLCHAIN=Clang \ -DENABLE_UNDEFINED_SANITIZER=ON \ -DENABLE_PCI_IDS_DOWNLOAD=OFF \ -DENABLE_USB_IDS_DOWNLOAD=OFF \ -DCMAKE_C_COMPILER=gcc-10 \ - -DCMAKE_CXX_COMPILER=g++-10 \ - .. + -DCMAKE_CXX_COMPILER=g++-10 displayName: 'Create Build Environment' - workingDirectory: $(Build.SourcesDirectory)/Build + workingDirectory: $(Build.SourcesDirectory) - script: | - cmake --build . + cmake --build ./Build/superbuild displayName: 'Build' - workingDirectory: $(Build.SourcesDirectory)/Build + workingDirectory: $(Build.SourcesDirectory) - script: | ninja install && ninja image displayName: 'Create RootFS' - workingDirectory: $(Build.SourcesDirectory)/Build + workingDirectory: $(Build.SourcesDirectory)/Build/${{ parameters.arch }}clang - script: | ninja run @@ -73,7 +72,7 @@ jobs: exit 1 fi displayName: 'Test' - workingDirectory: $(Build.SourcesDirectory)/Build + workingDirectory: $(Build.SourcesDirectory)/Build/${{ parameters.arch }}clang timeoutInMinutes: 60 env: SERENITY_QEMU_CPU: 'max,vmx=off' @@ -83,7 +82,7 @@ jobs: - script: | [ ! -e debug.log ] || cat debug.log displayName: 'Print Target Logs' - workingDirectory: $(Build.SourcesDirectory)/Build + workingDirectory: $(Build.SourcesDirectory)/Build/${{ parameters.arch }}clang condition: failed() - script: | diff --git a/Meta/CMake/Superbuild/CMakeLists.txt b/Meta/CMake/Superbuild/CMakeLists.txt new file mode 100644 index 0000000000..b1c7128b8f --- /dev/null +++ b/Meta/CMake/Superbuild/CMakeLists.txt @@ -0,0 +1,137 @@ +cmake_minimum_required(VERSION 3.16) + +project( + SerenitySuperbuild + DESCRIPTION "Orchestrate host and target builds in a single build" + LANGUAGES NONE +) + +# NOTE: Before CMake 3.19, if a custom command is attached to multiple step targets for Makefile and Visual Studio generators, +# it might be run multiple times during the build. Enable new behavior of policy CMP0114 to avoid this, or apply the +# workaround from https://gitlab.kitware.com/cmake/cmake/-/issues/18663#note_489967 +if(NOT CMAKE_VERSION VERSION_LESS "3.19") + cmake_policy(SET CMP0114 NEW) + macro(ensure_dependencies) + endmacro() +else() + macro(ensure_dependencies proj) + foreach(step IN ITEMS configure build install) + if(NOT TARGET "${proj}-${step}") + ExternalProject_Add_StepTargets("${proj}" "${step}") + endif() + if(step STREQUAL "install") + ExternalProject_Add_StepDependencies("${proj}" install "${proj}-build") + elseif(step STREQUAL "build") + ExternalProject_Add_StepDependencies("${proj}" build "${proj}-configure") + endif() + endforeach() + endmacro() +endif() + +get_filename_component( + SERENITY_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../.." + ABSOLUTE CACHE +) +set(SERENITY_ARCH "i686" CACHE STRING "Target architecture for SerenityOS.") +set(SERENITY_TOOLCHAIN "GNU" CACHE STRING "Compliler toolchain to use for Serenity (GNU or Clang)") + +# FIXME: It is preferred to keep all the sub-build artifacts below the binary directory for the superbuild +# However, this has an impact on developer's IDE settings and more significantly, the Ports tree. +# See https://github.com/SerenityOS/serenity/pull/9297#discussion_r697877603 +set(SERENITY_BUILD_DIR_SUFFIX "") +if(NOT SERENITY_TOOLCHAIN STREQUAL "GNU") + string(TOLOWER "${SERENITY_TOOLCHAIN}" SERENITY_BUILD_DIR_SUFFIX) +endif() +set(SERENITY_BUILD_DIR "${PROJECT_BINARY_DIR}/../${SERENITY_ARCH}${SERENITY_BUILD_DIR_SUFFIX}") + +if (CMAKE_HOST_SYSTEM_NAME MATCHES "SerenityOS") + message(STATUS "Good job on building cmake!") +else() + configure_file("${SERENITY_SOURCE_DIR}/Toolchain/CMake/${SERENITY_TOOLCHAIN}Toolchain.txt.in" "${SERENITY_BUILD_DIR}/CMakeToolchain.txt" @ONLY) + set(SERENITY_TOOLCHAIN_FILE "${SERENITY_BUILD_DIR}/CMakeToolchain.txt" CACHE PATH "Toolchain file to use for cross-compilation") + # Support non-cross builds by stuffing this in a variable + set(SERENITY_TOOLCHAIN_FILE_ARG "-DCMAKE_TOOLCHAIN_FILE:STRING=${SERENITY_TOOLCHAIN_FILE}") +endif() + +# Allow the Ninja generators to output messages as they happen by assigning +# these jobs to the 'console' job pool +set(console_access "") +if(CMAKE_GENERATOR MATCHES "^Ninja") + set( + console_access + USES_TERMINAL_CONFIGURE YES + USES_TERMINAL_BUILD YES + USES_TERMINAL_INSTALL YES + ) +endif() + +include(ExternalProject) + +# Collect options for Lagom build +set(lagom_options "") +macro(serenity_option name) + set(${ARGV}) + list(APPEND lagom_options "-D${name}:STRING=${${name}}") +endmacro() +include("${SERENITY_SOURCE_DIR}/Meta/CMake/lagom_options.cmake") + +# Forward user defined host toolchain to lagom build +if (DEFINED CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "${CMAKE_C_COMPILER}" CACHE STRING "C Compiler to use for host builds") + list(APPEND lagom_options "-DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER}") +endif() +if (DEFINED CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER}" CACHE STRING "C++ Compiler to use for host builds") + list(APPEND lagom_options "-DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}") +endif() + +ExternalProject_Add( + lagom + SOURCE_DIR "${SERENITY_SOURCE_DIR}/Meta/Lagom" + BINARY_DIR "${PROJECT_BINARY_DIR}/../lagom" + INSTALL_DIR "${PROJECT_BINARY_DIR}/../lagom-install" + EXCLUDE_FROM_ALL YES + CMAKE_CACHE_ARGS + "-DCMAKE_INSTALL_PREFIX:STRING=<INSTALL_DIR>" + "-DUNICODE_CACHE_LOCATION:STRING=${SERENITY_BUILD_DIR}/UCD" + "-DLOCALE_DATA_CACHE_LOCATION:STRING=${SERENITY_BUILD_DIR}/CLDR" + ${lagom_options} + # Always call the build step of tools, so keeping things up-to-date is easy + BUILD_ALWAYS YES + # Expose install step as a target, so it can be depended on + STEP_TARGETS install + ${console_access} +) + +ensure_dependencies(lagom) + +# Collect options for serenity build +set(serenity_options "") +macro(serenity_option name) + set(${ARGV}) + list(APPEND serenity_options "-D${name}:STRING=${${name}}") +endmacro() +include("${SERENITY_SOURCE_DIR}/Meta/CMake/serenity_options.cmake") + +ExternalProject_Add( + serenity + SOURCE_DIR "${SERENITY_SOURCE_DIR}" + BINARY_DIR "${SERENITY_BUILD_DIR}" + CMAKE_CACHE_ARGS + # Tell the find_package(Lagom REQUIRED) command call where to find + # the CMake package + "-DCMAKE_PREFIX_PATH:STRING=${PROJECT_BINARY_DIR}/../lagom-install" + "-DUNICODE_CACHE_LOCATION:STRING=${SERENITY_BUILD_DIR}/UCD" + "-DLOCALE_DATA_CACHE_LOCATION:STRING=${SERENITY_BUILD_DIR}/CLDR" + "-DSERENITY_ARCH:STRING=${SERENITY_ARCH}" + "${SERENITY_TOOLCHAIN_FILE_ARG}" + ${serenity_options} + # Always call the build step + BUILD_ALWAYS YES + # Host tools must be built and installed before the OS can be built + DEPENDS lagom-install + STEP_TARGETS install + ${console_access} +) + +ensure_dependencies(serenity) diff --git a/Meta/CMake/utils.cmake b/Meta/CMake/utils.cmake index d2e315ffec..f992c7c11a 100644 --- a/Meta/CMake/utils.cmake +++ b/Meta/CMake/utils.cmake @@ -56,8 +56,8 @@ 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}) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang$") + 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}) @@ -101,7 +101,6 @@ function(serenity_test test_src sub_dir) install(TARGETS ${test_name} RUNTIME DESTINATION usr/Tests/${sub_dir} OPTIONAL) endfunction() - function(serenity_testjs_test test_src sub_dir) cmake_parse_arguments(PARSE_ARGV 2 SERENITY_TEST "" "CUSTOM_MAIN" "LIBS") if ("${SERENITY_TEST_CUSTOM_MAIN}" STREQUAL "") diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index 69fcdd6a5c..e9f02ac40c 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -8,9 +8,10 @@ project( LANGUAGES C CXX ) -option(BUILD_SHARED_LIBS "Build shared libraries instead of static libraries" ON) -if (ENABLE_OSS_FUZZ) - set(BUILD_SHARED_LIBS OFF) # Don't use shared libraries on oss-fuzz, for ease of integration with their infrastructure +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.2") + message(FATAL_ERROR + "A GCC version less than 10.2 was detected (${CMAKE_CXX_COMPILER_VERSION}), this is unsupported.\n" + "Please re-read the build instructions documentation, and upgrade your host compiler.\n") endif() # This is required for CMake (when invoked for a Lagom-only build) to @@ -33,12 +34,22 @@ endif() include(lagom_options) +if(ENABLE_ALL_THE_DEBUG_MACROS) + include(all_the_debug_macros) +endif() + +option(BUILD_SHARED_LIBS "Build shared libraries instead of static libraries" ON) +if (ENABLE_OSS_FUZZ) + set(BUILD_SHARED_LIBS OFF) # Don't use shared libraries on oss-fuzz, for ease of integration with their infrastructure +endif() + find_package(Threads REQUIRED) if (ENABLE_LAGOM_CCACHE) find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${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() endif() @@ -58,7 +69,7 @@ set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # See slide 100 of the following ppt :^) # https://crascit.com/wp-content/uploads/2019/09/Deep-CMake-For-Library-Authors-Craig-Scott-CppCon-2019.pdf if (NOT APPLE) - set(CMAKE_INSTALL_RPATH $ORIGIN) + set(CMAKE_INSTALL_RPATH $ORIGIN:$ORIGIN/../lib) endif() set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) @@ -79,7 +90,7 @@ if (ENABLE_UNDEFINED_SANITIZER) set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined -fno-sanitize=vptr") endif() -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$") +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang$") # Clang's default constexpr-steps limit is 1048576(2^20), GCC doesn't have one add_compile_options(-Wno-overloaded-virtual -Wno-user-defined-literals -fconstexpr-steps=16777216) @@ -88,7 +99,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$") set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=fuzzer") endif() -elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_compile_options(-Wno-expansion-to-defined) endif() @@ -101,11 +112,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}") -# FIXME: This is a hack, because the lagom stuff can be built individually or -# in combination with the system, we generate two Debug.h files. One in -# Build/AK/Debug.h and the other in Build/Meta/Lagom/AK/Debug.h. configure_file(../../AK/Debug.h.in AK/Debug.h @ONLY) -configure_file(../../Kernel/Debug.h.in Kernel/Debug.h @ONLY) include_directories(../../) include_directories(../../Userland/) @@ -114,59 +121,36 @@ include_directories(${CMAKE_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) # install rules, think about moving to its own helper cmake file -# Don't install Lagom libs into the target Root/ -# FIXME: Remove this check for 4594 -if (CMAKE_SOURCE_DIR MATCHES ".*/Lagom") - include(CMakePackageConfigHelpers) - include(GNUInstallDirs) - - # find_package(<package>) call for consumers to find this project - set(package Lagom) - - write_basic_package_version_file( - "${package}ConfigVersion.cmake" - COMPATIBILITY SameMajorVersion - ) - - # Allow package maintainers to freely override the path for the configs - set(Lagom_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" - CACHE PATH "CMake package config location relative to the install prefix") - mark_as_advanced(Lagom_INSTALL_CMAKEDIR) - - install( - FILES ${SERENITY_PROJECT_ROOT}/Meta/CMake/lagom-install-config.cmake - DESTINATION "${Lagom_INSTALL_CMAKEDIR}" - RENAME "${package}Config.cmake" - COMPONENT Lagom_Development - ) - - install( - FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake" - DESTINATION "${Lagom_INSTALL_CMAKEDIR}" - COMPONENT Lagom_Development - ) - - install( - EXPORT LagomTargets - NAMESPACE Lagom:: - DESTINATION "${Lagom_INSTALL_CMAKEDIR}" - COMPONENT Lagom_Development - ) +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +# find_package(<package>) call for consumers to find this project +set(package Lagom) + +# Allow package maintainers to freely override the path for the configs +set(Lagom_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" + CACHE PATH "CMake package config location relative to the install prefix") +mark_as_advanced(Lagom_INSTALL_CMAKEDIR) + +install( + FILES "${SERENITY_PROJECT_ROOT}/Meta/CMake/lagom-install-config.cmake" + DESTINATION "${Lagom_INSTALL_CMAKEDIR}" + RENAME "${package}Config.cmake" + COMPONENT Lagom_Development +) - # Manually install AK - install( - DIRECTORY "${SERENITY_PROJECT_ROOT}/AK" - COMPONENT Lagom_Development - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING PATTERN "*.h" - ) -endif() +install( + EXPORT LagomTargets + NAMESPACE Lagom:: + DESTINATION "${Lagom_INSTALL_CMAKEDIR}" + COMPONENT Lagom_Development +) function(lagom_lib library fs_name) cmake_parse_arguments(LAGOM_LIBRARY "" "" "SOURCES;LIBS" ${ARGN}) set(target_name "Lagom${library}") add_library(${target_name} ${LAGOM_LIBRARY_SOURCES}) - # alias for pretty exports + # alias for parity with exports add_library(Lagom::${library} ALIAS ${target_name}) set_target_properties( @@ -180,29 +164,25 @@ function(lagom_lib library fs_name) if (NOT ${target_name} STREQUAL "LagomCore") target_link_libraries(${target_name} LagomCore) endif() - # Don't install Lagom libs into the target Root/ - # FIXME: Remove this check for 4594 - if (CMAKE_SOURCE_DIR MATCHES ".*/Lagom") - install( - TARGETS ${target_name} - EXPORT LagomTargets - RUNTIME # - COMPONENT Lagom_Runtime - LIBRARY # - COMPONENT Lagom_Runtime - NAMELINK_COMPONENT Lagom_Development - ARCHIVE # - COMPONENT Lagom_Development - INCLUDES # - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) - install( - DIRECTORY "${SERENITY_PROJECT_ROOT}/Userland/Libraries/Lib${library}" + install( + TARGETS ${target_name} + EXPORT LagomTargets + RUNTIME # + COMPONENT Lagom_Runtime + LIBRARY # + COMPONENT Lagom_Runtime + NAMELINK_COMPONENT Lagom_Development + ARCHIVE # COMPONENT Lagom_Development + INCLUDES # DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILES_MATCHING PATTERN "*.h" - ) - endif() + ) + install( + DIRECTORY "${SERENITY_PROJECT_ROOT}/Userland/Libraries/Lib${library}" + COMPONENT Lagom_Development + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h" + ) endfunction() function(lagom_test source) @@ -229,6 +209,14 @@ if (NOT APPLE) target_link_libraries(LagomCore crypt) # Core::Account uses crypt() but it's not in libcrypt on macOS endif() +# Manually install AK headers +install( + DIRECTORY "${SERENITY_PROJECT_ROOT}/AK" + COMPONENT Lagom_Development + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h" +) + # Code Generators and other host tools # We need to make sure not to build code generators for Fuzzer builds, as they already have their own main.cpp if (NOT ENABLE_OSS_FUZZ AND NOT ENABLE_FUZZER_SANITIZER) diff --git a/Meta/build-root-filesystem.sh b/Meta/build-root-filesystem.sh index 33cbe10c49..3dd09ceaf0 100755 --- a/Meta/build-root-filesystem.sh +++ b/Meta/build-root-filesystem.sh @@ -48,7 +48,7 @@ fi SERENITY_ARCH="${SERENITY_ARCH:-i686}" LLVM_VERSION="${LLVM_VERSION:-12.0.1}" -if [ "$USE_CLANG_TOOLCHAIN" = "1" ]; then +if [ "$SERENITY_TOOLCHAIN" = "Clang" ]; 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 |