summaryrefslogtreecommitdiff
path: root/libc/CMakeLists.txt
blob: e0e5b69b47cf8e94b12f768fef5333a11b8ce78a (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
cmake_minimum_required(VERSION 3.13.4)

# Include LLVM's cmake policies.
if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS)
  set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
endif()
include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake
  NO_POLICY_SCOPE)

# Default to C++17
set(CMAKE_CXX_STANDARD 17)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")

# The top-level sourse and binary directories.
set(LIBC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBC_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# The top-level directory in which libc is being built.
set(LIBC_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})

if(LLVM_LIBC_FULL_BUILD OR LIBC_GPU_BUILD OR LIBC_GPU_ARCHITECTURES)
  if(NOT LIBC_HDRGEN_EXE)
    # We need to set up hdrgen first since other targets depend on it.
    add_subdirectory(utils/LibcTableGenUtil)
    add_subdirectory(utils/HdrGen)
  else()
    message(STATUS "Will use ${LIBC_HDRGEN_EXE} for libc header generation.")
  endif()
endif()

if(LLVM_ENABLE_RUNTIMES AND NOT LLVM_RUNTIMES_BUILD)
  # When libc is build as part of the runtimes/bootstrap build's CMake run, we
  # only need to build the host tools to build the libc. So, we just do enough
  # to build libc-hdrgen and return.
  return()
endif()

option(LIBC_CMAKE_VERBOSE_LOGGING
       "Log details warnings and notifications during CMake configuration." OFF)
# Path libc/scripts directory.
set(LIBC_BUILD_SCRIPTS_DIR "${LIBC_SOURCE_DIR}/utils/build_scripts")

# Flags to pass down to the compiler while building the libc functions.
set(LIBC_COMPILE_OPTIONS_DEFAULT "" CACHE STRING "Architecture to tell clang to optimize for (e.g. -march=... or -mcpu=...)")

include(common_libc_tuners.cmake)

list(APPEND LIBC_COMPILE_OPTIONS_DEFAULT ${LIBC_COMMON_TUNE_OPTIONS})

# Check --print-resource-dir to find the compiler resource dir if this flag
# is supported by the compiler.
execute_process(
  OUTPUT_STRIP_TRAILING_WHITESPACE
  COMMAND ${CMAKE_CXX_COMPILER} --print-resource-dir
  RESULT_VARIABLE COMMAND_RETURN_CODE
  OUTPUT_VARIABLE COMPILER_RESOURCE_DIR
)
# Retrieve the host compiler's resource dir.
if(COMMAND_RETURN_CODE EQUAL 0)
  set(COMPILER_RESOURCE_DIR
    "${COMPILER_RESOURCE_DIR}" CACHE PATH "path to compiler resource dir"
  )
  message(STATUS "Set COMPILER_RESOURCE_DIR to "
                 "${COMPILER_RESOURCE_DIR} using --print-resource-dir")
else()
  set(COMPILER_RESOURCE_DIR OFF)
  message(STATUS "COMPILER_RESOURCE_DIR not set
                  --print-resource-dir not supported by host compiler")
endif()

option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc" OFF)
option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON)
option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF)

option(LIBC_GPU_BUILD "Build libc for the GPU. All CPU build options will be ignored." OFF)
set(LIBC_TARGET_TRIPLE "" CACHE STRING "The target triple for the libc build.")

set(LIBC_ENABLE_UNITTESTS ON)
set(LIBC_ENABLE_HERMETIC_TESTS ${LLVM_LIBC_FULL_BUILD})

# Defines LIBC_TARGET_ARCHITECTURE and associated macros.
include(LLVMLibCArchitectures)

if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
  include(prepare_libc_gpu_build)
  set(LIBC_ENABLE_UNITTESTS OFF)
endif()

include(LLVMLibCCheckMPFR)

if(LLVM_LIBC_CLANG_TIDY)
  set(LLVM_LIBC_ENABLE_LINTING ON)
endif()

if(LLVM_LIBC_ENABLE_LINTING)
  if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(LLVM_LIBC_ENABLE_LINTING OFF)
    message(WARNING "C++ compiler is not clang++, linting with be disabled.")
  else()
    if (NOT LLVM_LIBC_CLANG_TIDY)
      find_program(LLVM_LIBC_CLANG_TIDY NAMES clang-tidy)
    endif()

    if(LLVM_LIBC_CLANG_TIDY)
      # Check clang-tidy major version.
      execute_process(COMMAND ${LLVM_LIBC_CLANG_TIDY} "--version"
                      OUTPUT_VARIABLE CLANG_TIDY_OUTPUT)
      string(REGEX MATCH "[0-9]+" CLANG_TIDY_VERSION "${CLANG_TIDY_OUTPUT}")
      string(REGEX MATCH "[0-9]+" CLANG_MAJOR_VERSION
             "${CMAKE_CXX_COMPILER_VERSION}")
      if(NOT CLANG_TIDY_VERSION EQUAL CLANG_MAJOR_VERSION)
        set(LLVM_LIBC_ENABLE_LINTING OFF)
        message(WARNING "
          'clang-tidy' (version ${CLANG_TIDY_VERSION}) is not the same as
          'clang' (version ${CLANG_MAJOR_VERSION}).  Linting will
          be disabled.

          The path to the clang-tidy binary can be set manually by passing
          -DLLVM_LIBC_CLANG_TIDY=<path/to/clang-tidy> to CMake.")
      endif()
      add_custom_target(libc-lint)
    else()
      message(FATAL_ERROR "
        Linting is enabled but 'clang-tidy' is not found!

        The path to the clang-tidy binary can be set manually by passing
        -DLLVM_LIBC_CLANG_TIDY=<path/to/clang-tidy> to CMake.

        To disable linting set LLVM_LIBC_ENABLE_LINTING to OFF
        (pass -DLLVM_LIBC_ENABLE_LINTING=OFF to cmake).")
    endif()
  endif()
endif()

option(LLVM_LIBC_INCLUDE_SCUDO "Include the SCUDO standalone as the allocator for LLVM libc" OFF)
if(LLVM_LIBC_INCLUDE_SCUDO)
  if (NOT "compiler-rt" IN_LIST LLVM_ENABLE_PROJECTS)
    message(FATAL_ERROR "SCUDO cannot be included without adding compiler-rt to LLVM_ENABLE_PROJECTS")
  endif()
endif()

option(LIBC_INCLUDE_DOCS "Build the libc documentation." ${LLVM_INCLUDE_DOCS})

include(CMakeParseArguments)
include(LLVMLibCCheckCpuFeatures)
include(LLVMLibCRules)

if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")
  set(entrypoint_file "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/entrypoints.txt")
elseif(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/entrypoints.txt")
  set(entrypoint_file "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/entrypoints.txt")
else()
  message(FATAL_ERROR "entrypoints.txt file for the target platform '${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}' not found.")
endif()
include(${entrypoint_file})

if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/headers.txt")
  include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}/headers.txt")
elseif(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/headers.txt")
  include("${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/headers.txt")
endif()

set(TARGET_ENTRYPOINT_NAME_LIST "")
foreach(entrypoint IN LISTS TARGET_LLVMLIBC_ENTRYPOINTS)
  string(FIND ${entrypoint} "." last_dot_loc REVERSE)
  if(${last_dot_loc} EQUAL -1)
    message(FATAL "Invalid entrypoint target name ${entrypoint}; Expected a '.' "
                  "(dot) in the name.")
  endif()
  math(EXPR name_loc "${last_dot_loc} + 1")
  string(SUBSTRING ${entrypoint} ${name_loc} -1 entrypoint_name)
  list(APPEND TARGET_ENTRYPOINT_NAME_LIST ${entrypoint_name})
endforeach()

set(LIBC_INSTALL_DEPENDS)
if(LLVM_LIBC_FULL_BUILD)
  set(LIBC_INSTALL_DEPENDS "install-libc-static-archives;install-libc-headers")
  if(NOT LIBC_TARGET_OS_IS_BAREMETAL)
    # For now we will disable libc-startup installation for baremetal. The
    # correct way to do it would be to make a hookable startup for baremetal
    # and install it as part of the libc installation.
    list(APPEND LIBC_INSTALL_DEPENDS "libc-startup")
  endif()
else()
  set(LIBC_INSTALL_DEPENDS install-libc-static-archives)
endif()

add_subdirectory(include)
add_subdirectory(config)
add_subdirectory(src)
add_subdirectory(utils)

if(LLVM_LIBC_FULL_BUILD)
  # The startup system can potentially depend on the library components so add
  # it after the library implementation directories.
  add_subdirectory(startup)
endif()

# The lib and test directories are added at the very end as tests
# and libraries potentially draw from the components present in all
# of the other directories.
# TODO: Add testing support for the libc GPU target.
add_subdirectory(lib)
if(LLVM_INCLUDE_TESTS)
  add_subdirectory(test)
  add_subdirectory(fuzzing)
endif()

if(LIBC_INCLUDE_BENCHMARKS)
  add_subdirectory(benchmarks)
endif()

if (LIBC_INCLUDE_DOCS)
  add_subdirectory(docs)
endif()


if(LLVM_LIBC_FULL_BUILD)
  add_llvm_install_targets(
    install-libc-headers
    DEPENDS libc-headers
    COMPONENT libc-headers
  )
endif()

add_llvm_install_targets(
  install-libc
  DEPENDS ${LIBC_INSTALL_DEPENDS}
  COMPONENT libc
)