summaryrefslogtreecommitdiff
path: root/Meta/CMake/Superbuild/CMakeLists.txt
blob: 6750b2a7cc590763e854d01ed2b8d12783400537 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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 "Compiler 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>"
    "-DUCD_PATH:STRING=${SERENITY_BUILD_DIR}/UCD"
    "-DCLDR_PATH: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"
    "-DUCD_PATH:STRING=${SERENITY_BUILD_DIR}/UCD"
    "-DCLDR_PATH: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 configure install
    ${console_access}
)

ensure_dependencies(serenity)