• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1cmake_minimum_required(VERSION 2.8.11)
2
3# Report AppleClang separately from Clang. Their version numbers are different.
4# https://cmake.org/cmake/help/v3.0/policy/CMP0025.html
5if(POLICY CMP0025)
6  cmake_policy(SET CMP0025 NEW)
7endif()
8
9# Defer enabling C and CXX languages.
10project(BoringSSL NONE)
11
12if(WIN32)
13  # On Windows, prefer cl over gcc if both are available. By default most of
14  # the CMake generators prefer gcc, even on Windows.
15  set(CMAKE_GENERATOR_CC cl)
16endif()
17
18include(sources.cmake)
19
20enable_language(C)
21enable_language(CXX)
22
23# This is a dummy target which all other targets depend on (manually - see other
24# CMakeLists.txt files). This gives us a hook to add any targets which need to
25# run before all other targets.
26add_custom_target(global_target)
27
28if(ANDROID)
29  # Android-NDK CMake files reconfigure the path and so Go and Perl won't be
30  # found. However, ninja will still find them in $PATH if we just name them.
31  if(NOT PERL_EXECUTABLE)
32    set(PERL_EXECUTABLE "perl")
33  endif()
34  if(NOT GO_EXECUTABLE)
35    set(GO_EXECUTABLE "go")
36  endif()
37else()
38  find_package(Perl REQUIRED)
39  find_program(GO_EXECUTABLE go)
40endif()
41
42if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT CMAKE_CROSSCOMPILING)
43  find_package(PkgConfig QUIET)
44  if (PkgConfig_FOUND)
45    pkg_check_modules(LIBUNWIND libunwind-generic)
46    if(LIBUNWIND_FOUND)
47      add_definitions(-DBORINGSSL_HAVE_LIBUNWIND)
48    else()
49      message("libunwind not found. Disabling unwind tests.")
50    endif()
51  else()
52    message("pkgconfig not found. Disabling unwind tests.")
53  endif()
54endif()
55
56if(NOT GO_EXECUTABLE)
57  message(FATAL_ERROR "Could not find Go")
58endif()
59
60if(USE_CUSTOM_LIBCXX)
61  set(BORINGSSL_ALLOW_CXX_RUNTIME 1)
62endif()
63
64if(BORINGSSL_ALLOW_CXX_RUNTIME)
65  add_definitions(-DBORINGSSL_ALLOW_CXX_RUNTIME)
66endif()
67
68if(CMAKE_BUILD_TYPE STREQUAL "Release")
69  # Windows release builds don't set NDEBUG in NASM flags automatically.
70  set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DNDEBUG")
71endif()
72
73# Add a RelWithAsserts build configuration. It is the same as Release, except it
74# does not define NDEBUG, so asserts run.
75foreach(VAR CMAKE_C_FLAGS CMAKE_CXX_FLAGS CMAKE_ASM_FLAGS)
76  string(REGEX REPLACE "(^| )[/-]DNDEBUG( |$)" " " "${VAR}_RELWITHASSERTS"
77         "${${VAR}_RELEASE}")
78endforeach()
79
80if(BORINGSSL_PREFIX AND BORINGSSL_PREFIX_SYMBOLS)
81  add_definitions(-DBORINGSSL_PREFIX=${BORINGSSL_PREFIX})
82  # CMake automatically connects include_directories to the NASM command-line,
83  # but not add_definitions.
84  set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DBORINGSSL_PREFIX=${BORINGSSL_PREFIX}")
85
86  # Use "symbol_prefix_include" to store generated header files
87  include_directories(${CMAKE_CURRENT_BINARY_DIR}/symbol_prefix_include)
88  add_custom_command(
89    OUTPUT symbol_prefix_include/boringssl_prefix_symbols.h
90           symbol_prefix_include/boringssl_prefix_symbols_asm.h
91           symbol_prefix_include/boringssl_prefix_symbols_nasm.inc
92    COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/symbol_prefix_include
93    COMMAND ${GO_EXECUTABLE} run ${CMAKE_CURRENT_SOURCE_DIR}/util/make_prefix_headers.go -out ${CMAKE_CURRENT_BINARY_DIR}/symbol_prefix_include ${BORINGSSL_PREFIX_SYMBOLS}
94    DEPENDS util/make_prefix_headers.go
95            ${CMAKE_BINARY_DIR}/${BORINGSSL_PREFIX_SYMBOLS})
96
97  # add_dependencies needs a target, not a file, so we add an intermediate
98  # target.
99  add_custom_target(
100    boringssl_prefix_symbols
101    DEPENDS symbol_prefix_include/boringssl_prefix_symbols.h
102            symbol_prefix_include/boringssl_prefix_symbols_asm.h
103            symbol_prefix_include/boringssl_prefix_symbols_nasm.inc)
104  add_dependencies(global_target boringssl_prefix_symbols)
105elseif(BORINGSSL_PREFIX OR BORINGSSL_PREFIX_SYMBOLS)
106  message(FATAL_ERROR "Must specify both or neither of BORINGSSL_PREFIX and BORINGSSL_PREFIX_SYMBOLS")
107endif()
108
109if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
110  set(CLANG 1)
111endif()
112
113if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
114  # Note clang-cl is odd and sets both CLANG and MSVC. We base our configuration
115  # primarily on our normal Clang one.
116  set(C_CXX_FLAGS "-Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings")
117  if(MSVC)
118    # clang-cl sets different default warnings than clang. It also treats -Wall
119    # as -Weverything, to match MSVC. Instead -W3 is the alias for -Wall.
120    # See http://llvm.org/viewvc/llvm-project?view=revision&revision=319116
121    set(C_CXX_FLAGS "${C_CXX_FLAGS} -W3 -Wno-unused-parameter -fmsc-version=1900")
122    # googletest suppresses warning C4996 via a pragma, but clang-cl does not
123    # honor it. Suppress it here to compensate. See https://crbug.com/772117.
124    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-deprecated-declarations")
125  else()
126    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wall -ggdb -fvisibility=hidden -fno-common")
127  endif()
128
129  if(CLANG)
130    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof -fcolor-diagnostics")
131  else()
132    # GCC (at least 4.8.4) has a bug where it'll find unreachable free() calls
133    # and declare that the code is trying to free a stack pointer.
134    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-free-nonheap-object")
135  endif()
136
137  if(CLANG OR NOT "7.0.0" VERSION_GREATER CMAKE_C_COMPILER_VERSION)
138    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wimplicit-fallthrough")
139  endif()
140
141  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
142  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CXX_FLAGS} -Wmissing-declarations")
143
144  if(NOT MSVC)
145    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
146    if(APPLE)
147      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
148    endif()
149    if(NOT BORINGSSL_ALLOW_CXX_RUNTIME)
150      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
151    endif()
152  endif()
153
154  # In GCC, -Wmissing-declarations is the C++ spelling of -Wmissing-prototypes
155  # and using the wrong one is an error. In Clang, -Wmissing-prototypes is the
156  # spelling for both and -Wmissing-declarations is some other warning.
157  #
158  # https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Warning-Options.html#Warning-Options
159  # https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-prototypes
160  # https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-declarations
161  if(CLANG)
162    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes")
163  endif()
164
165  if(CMAKE_COMPILER_IS_GNUCXX AND "4.8" VERSION_GREATER CMAKE_C_COMPILER_VERSION)
166    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-array-bounds")
167  endif()
168
169elseif(MSVC)
170  set(MSVC_DISABLED_WARNINGS_LIST
171      "C4061" # enumerator 'identifier' in switch of enum 'enumeration' is not
172              # explicitly handled by a case label
173              # Disable this because it flags even when there is a default.
174      "C4100" # 'exarg' : unreferenced formal parameter
175      "C4127" # conditional expression is constant
176      "C4200" # nonstandard extension used : zero-sized array in
177              # struct/union.
178      "C4204" # nonstandard extension used: non-constant aggregate initializer
179      "C4221" # nonstandard extension used : 'identifier' : cannot be
180              # initialized using address of automatic variable
181      "C4242" # 'function' : conversion from 'int' to 'uint8_t',
182              # possible loss of data
183      "C4244" # 'function' : conversion from 'int' to 'uint8_t',
184              # possible loss of data
185      "C4267" # conversion from 'size_t' to 'int', possible loss of data
186      "C4371" # layout of class may have changed from a previous version of the
187              # compiler due to better packing of member '...'
188      "C4388" # signed/unsigned mismatch
189      "C4296" # '>=' : expression is always true
190      "C4350" # behavior change: 'std::_Wrap_alloc...'
191      "C4365" # '=' : conversion from 'size_t' to 'int',
192              # signed/unsigned mismatch
193      "C4389" # '!=' : signed/unsigned mismatch
194      "C4464" # relative include path contains '..'
195      "C4510" # 'argument' : default constructor could not be generated
196      "C4512" # 'argument' : assignment operator could not be generated
197      "C4514" # 'function': unreferenced inline function has been removed
198      "C4548" # expression before comma has no effect; expected expression with
199              # side-effect" caused by FD_* macros.
200      "C4610" # struct 'argument' can never be instantiated - user defined
201              # constructor required.
202      "C4623" # default constructor was implicitly defined as deleted
203      "C4625" # copy constructor could not be generated because a base class
204              # copy constructor is inaccessible or deleted
205      "C4626" # assignment operator could not be generated because a base class
206              # assignment operator is inaccessible or deleted
207      "C4668" # 'symbol' is not defined as a preprocessor macro, replacing with
208              # '0' for 'directives'
209              # Disable this because GTest uses it everywhere.
210      "C4706" # assignment within conditional expression
211      "C4710" # 'function': function not inlined
212      "C4711" # function 'function' selected for inline expansion
213      "C4800" # 'int' : forcing value to bool 'true' or 'false'
214              # (performance warning)
215      "C4820" # 'bytes' bytes padding added after construct 'member_name'
216      "C5026" # move constructor was implicitly defined as deleted
217      "C5027" # move assignment operator was implicitly defined as deleted
218      "C5045" # Compiler will insert Spectre mitigation for memory load if
219              # /Qspectre switch specified
220      )
221  set(MSVC_LEVEL4_WARNINGS_LIST
222      # See https://connect.microsoft.com/VisualStudio/feedback/details/1217660/warning-c4265-when-using-functional-header
223      "C4265" # class has virtual functions, but destructor is not virtual
224      )
225  string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
226                            ${MSVC_DISABLED_WARNINGS_LIST})
227  string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR
228                            ${MSVC_LEVEL4_WARNINGS_LIST})
229  set(CMAKE_C_FLAGS   "-utf-8 -Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
230  set(CMAKE_CXX_FLAGS "-utf-8 -Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
231endif()
232
233if(WIN32)
234  add_definitions(-D_HAS_EXCEPTIONS=0)
235  add_definitions(-DWIN32_LEAN_AND_MEAN)
236  add_definitions(-DNOMINMAX)
237  # Allow use of fopen.
238  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
239  # VS 2017 and higher supports STL-only warning suppressions. Manually add to
240  # C++ only to work around a CMake quoting bug when using NASM with the Visual
241  # Studio generator. This will be fixed in CMake 3.13.0. See
242  # https://gitlab.kitware.com/cmake/cmake/merge_requests/2179
243  add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-D_STL_EXTRA_DISABLED_WARNINGS=4774\ 4987>)
244endif()
245
246if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR
247   CLANG)
248  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
249  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
250endif()
251
252if(CMAKE_COMPILER_IS_GNUCXX)
253  if((CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR CLANG)
254    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
255  else()
256    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
257  endif()
258endif()
259
260# pthread_rwlock_t requires a feature flag.
261if(NOT WIN32)
262  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700")
263endif()
264
265if(FUZZ)
266  if(NOT CLANG)
267    message(FATAL_ERROR "You need to build with Clang for fuzzing to work")
268  endif()
269
270  if(CMAKE_C_COMPILER_VERSION VERSION_LESS "6.0.0")
271    message(FATAL_ERROR "You need Clang ≥ 6.0.0")
272  endif()
273
274  add_definitions(-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE)
275  set(RUNNER_ARGS "-deterministic")
276
277  if(NOT NO_FUZZER_MODE)
278    add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
279    set(RUNNER_ARGS ${RUNNER_ARGS} "-fuzzer" "-shim-config" "fuzzer_mode.json")
280  endif()
281
282  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,fuzzer-no-link -fsanitize-coverage=edge,indirect-calls")
283  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,fuzzer-no-link -fsanitize-coverage=edge,indirect-calls")
284endif()
285
286add_definitions(-DBORINGSSL_IMPLEMENTATION)
287
288if(BUILD_SHARED_LIBS)
289  add_definitions(-DBORINGSSL_SHARED_LIBRARY)
290  # Enable position-independent code globally. This is needed because
291  # some library targets are OBJECT libraries.
292  set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
293endif()
294
295if(MSAN)
296  if(NOT CLANG)
297    message(FATAL_ERROR "Cannot enable MSAN unless using Clang")
298  endif()
299
300  if(ASAN)
301    message(FATAL_ERROR "ASAN and MSAN are mutually exclusive")
302  endif()
303
304  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
305  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
306  set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
307endif()
308
309if(ASAN)
310  if(NOT CLANG)
311    message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
312  endif()
313
314  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
315  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
316endif()
317
318if(CFI)
319  if(NOT CLANG)
320    message(FATAL_ERROR "Cannot enable CFI unless using Clang")
321  endif()
322
323  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=cfi -fno-sanitize-trap=cfi -flto=thin")
324  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=cfi -fno-sanitize-trap=cfi -flto=thin")
325  # We use Chromium's copy of clang, which requires -fuse-ld=lld if building
326  # with -flto. That, in turn, can't handle -ggdb.
327  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
328  string(REPLACE "-ggdb" "-g" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
329  string(REPLACE "-ggdb" "-g" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
330  # -flto causes object files to contain LLVM bitcode. Mixing those with
331  # assembly output in the same static library breaks the linker.
332  set(OPENSSL_NO_ASM "1")
333endif()
334
335if(TSAN)
336  if(NOT CLANG)
337    message(FATAL_ERROR "Cannot enable TSAN unless using Clang")
338  endif()
339
340  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
341  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
342  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
343endif()
344
345if(UBSAN)
346  if(NOT CLANG)
347    message(FATAL_ERROR "Cannot enable UBSAN unless using Clang")
348  endif()
349
350  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
351  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
352  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
353
354  if(NOT UBSAN_RECOVER)
355    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize-recover=undefined")
356    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-sanitize-recover=undefined")
357    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fno-sanitize-recover=undefined")
358  endif()
359endif()
360
361if(GCOV)
362  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
363  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
364endif()
365
366if(FIPS)
367  add_definitions(-DBORINGSSL_FIPS)
368  if(FIPS_BREAK_TEST)
369    add_definitions("-DBORINGSSL_FIPS_BREAK_${FIPS_BREAK_TEST}=1")
370  endif()
371  # Delocate does not work for ASan and MSan builds.
372  if(NOT ASAN AND NOT MSAN)
373    set(FIPS_DELOCATE "1")
374  endif()
375endif()
376
377if(OPENSSL_SMALL)
378  add_definitions(-DOPENSSL_SMALL)
379endif()
380
381if(CONSTANT_TIME_VALIDATION)
382  add_definitions(-DBORINGSSL_CONSTANT_TIME_VALIDATION)
383  # Asserts will often test secret data.
384  add_definitions(-DNDEBUG)
385endif()
386
387function(go_executable dest package)
388  set(godeps "${CMAKE_SOURCE_DIR}/util/godeps.go")
389  if(${CMAKE_VERSION} VERSION_LESS "3.7" OR
390     NOT ${CMAKE_GENERATOR} STREQUAL "Ninja")
391    # The DEPFILE parameter to add_custom_command is new as of CMake 3.7 and
392    # only works with Ninja. Query the sources at configure time. Additionally,
393    # everything depends on go.mod. That affects what external packages to use.
394    execute_process(COMMAND ${GO_EXECUTABLE} run ${godeps} -format cmake
395                            -pkg ${package}
396                    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
397                    OUTPUT_VARIABLE sources
398                    RESULT_VARIABLE godeps_result)
399    add_custom_command(OUTPUT ${dest}
400                       COMMAND ${GO_EXECUTABLE} build
401                               -o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package}
402                       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
403                       DEPENDS ${sources} ${CMAKE_SOURCE_DIR}/go.mod)
404  else()
405    # Ninja expects the target in the depfile to match the output. This is a
406    # relative path from the build directory.
407    string(LENGTH "${CMAKE_BINARY_DIR}" root_dir_length)
408    math(EXPR root_dir_length "${root_dir_length} + 1")
409    string(SUBSTRING "${CMAKE_CURRENT_BINARY_DIR}" ${root_dir_length} -1 target)
410    set(target "${target}/${dest}")
411
412    set(depfile "${CMAKE_CURRENT_BINARY_DIR}/${dest}.d")
413    add_custom_command(OUTPUT ${dest}
414                       COMMAND ${GO_EXECUTABLE} build
415                               -o ${CMAKE_CURRENT_BINARY_DIR}/${dest} ${package}
416                       COMMAND ${GO_EXECUTABLE} run ${godeps} -format depfile
417                               -target ${target} -pkg ${package} -out ${depfile}
418                       WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
419                       DEPENDS ${godeps} ${CMAKE_SOURCE_DIR}/go.mod
420                       DEPFILE ${depfile})
421  endif()
422endfunction()
423
424# CMake's iOS support uses Apple's multiple-architecture toolchain. It takes an
425# architecture list from CMAKE_OSX_ARCHITECTURES, leaves CMAKE_SYSTEM_PROCESSOR
426# alone, and expects all architecture-specific logic to be conditioned within
427# the source files rather than the build. This does not work for our assembly
428# files, so we fix CMAKE_SYSTEM_PROCESSOR and only support single-architecture
429# builds.
430if(NOT OPENSSL_NO_ASM AND CMAKE_OSX_ARCHITECTURES)
431  list(LENGTH CMAKE_OSX_ARCHITECTURES NUM_ARCHES)
432  if(NOT ${NUM_ARCHES} EQUAL 1)
433    message(FATAL_ERROR "Universal binaries not supported.")
434  endif()
435  list(GET CMAKE_OSX_ARCHITECTURES 0 CMAKE_SYSTEM_PROCESSOR)
436endif()
437
438if(OPENSSL_NO_ASM)
439  add_definitions(-DOPENSSL_NO_ASM)
440  set(ARCH "generic")
441elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
442  set(ARCH "x86_64")
443elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
444  set(ARCH "x86_64")
445elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
446  # cmake reports AMD64 on Windows, but we might be building for 32-bit.
447  if(CMAKE_CL_64)
448    set(ARCH "x86_64")
449  else()
450    set(ARCH "x86")
451  endif()
452elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86")
453  set(ARCH "x86")
454elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386")
455  set(ARCH "x86")
456elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
457  set(ARCH "x86")
458elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
459  set(ARCH "aarch64")
460elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64")
461  set(ARCH "aarch64")
462# Apple A12 Bionic chipset which is added in iPhone XS/XS Max/XR uses arm64e architecture.
463elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64e")
464  set(ARCH "aarch64")
465elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm*")
466  set(ARCH "arm")
467elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "mips")
468  # Just to avoid the “unknown processor” error.
469  set(ARCH "generic")
470elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
471  set(ARCH "ppc64le")
472else()
473  message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
474endif()
475
476if(ANDROID AND NOT ANDROID_NDK_REVISION AND ${ARCH} STREQUAL "arm")
477  # The third-party Android-NDK CMake files somehow fail to set the -march flag
478  # for assembly files. Without this flag, the compiler believes that it's
479  # building for ARMv5.
480  set(CMAKE_ASM_FLAGS "-march=${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_ASM_FLAGS}")
481endif()
482
483if(${ARCH} STREQUAL "x86" AND APPLE AND ${CMAKE_VERSION} VERSION_LESS "3.0")
484  # With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X,
485  # but clang defaults to 64-bit builds on OS X unless otherwise told.
486  # Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3.
487  set(ARCH "x86_64")
488endif()
489
490if(USE_CUSTOM_LIBCXX)
491  if(NOT CLANG)
492    message(FATAL_ERROR "USE_CUSTOM_LIBCXX only supported with Clang")
493  endif()
494
495  # CMAKE_CXX_FLAGS ends up in the linker flags as well, so use
496  # add_compile_options. There does not appear to be a way to set
497  # language-specific compile-only flags.
498  add_compile_options("-nostdinc++")
499  set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -nostdlib++")
500  include_directories(
501    SYSTEM
502    util/bot/libcxx/include
503    util/bot/libcxxabi/include
504  )
505
506  # This is patterned after buildtools/third_party/libc++/BUILD.gn and
507  # buildtools/third_party/libc++abi/BUILD.gn in Chromium.
508
509  file(GLOB LIBCXX_SOURCES "util/bot/libcxx/src/*.cpp")
510  file(GLOB LIBCXXABI_SOURCES "util/bot/libcxxabi/src/*.cpp")
511
512  # This file is meant for exception-less builds.
513  list(REMOVE_ITEM LIBCXXABI_SOURCES "trunk/src/cxa_noexception.cpp")
514  # libc++ also defines new and delete.
515  list(REMOVE_ITEM LIBCXXABI_SOURCES "trunk/src/stdlib_new_delete.cpp")
516  if(TSAN)
517    # ThreadSanitizer tries to intercept these symbols. Skip them to avoid
518    # symbol conflicts.
519    list(REMOVE_ITEM LIBCXXABI_SOURCES "trunk/src/cxa_guard.cpp")
520  endif()
521
522  add_library(libcxxabi ${LIBCXXABI_SOURCES})
523  target_compile_definitions(
524    libcxxabi PRIVATE
525    -D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS
526  )
527  set_target_properties(libcxxabi PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-implicit-fallthrough")
528
529  add_library(libcxx ${LIBCXX_SOURCES})
530  if(ASAN OR MSAN OR TSAN)
531    # Sanitizers try to intercept new and delete.
532    target_compile_definitions(
533      libcxx PRIVATE
534      -D_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS
535    )
536  endif()
537  target_compile_definitions(
538    libcxx PRIVATE
539    -D_LIBCPP_BUILDING_LIBRARY
540    -DLIBCXX_BUILDING_LIBCXXABI
541  )
542  target_link_libraries(libcxx libcxxabi)
543endif()
544
545# Add minimal googletest targets. The provided one has many side-effects, and
546# googletest has a very straightforward build.
547add_library(boringssl_gtest third_party/googletest/src/gtest-all.cc)
548target_include_directories(boringssl_gtest PRIVATE third_party/googletest)
549
550include_directories(third_party/googletest/include)
551
552# Declare a dummy target to build all unit tests. Test targets should inject
553# themselves as dependencies next to the target definition.
554add_custom_target(all_tests)
555
556add_custom_command(
557  OUTPUT crypto_test_data.cc
558  COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go ${CRYPTO_TEST_DATA} >
559  ${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc
560  DEPENDS util/embed_test_data.go ${CRYPTO_TEST_DATA}
561  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
562
563add_library(crypto_test_data OBJECT crypto_test_data.cc)
564
565add_subdirectory(crypto)
566add_subdirectory(ssl)
567add_subdirectory(ssl/test)
568add_subdirectory(fipstools)
569add_subdirectory(tool)
570add_subdirectory(decrepit)
571
572if(FUZZ)
573  if(LIBFUZZER_FROM_DEPS)
574    file(GLOB LIBFUZZER_SOURCES "util/bot/libFuzzer/*.cpp")
575    add_library(Fuzzer STATIC ${LIBFUZZER_SOURCES})
576    # libFuzzer does not pass our aggressive warnings. It also must be built
577    # without -fsanitize-coverage options or clang crashes.
578    set_target_properties(Fuzzer PROPERTIES COMPILE_FLAGS "-Wno-shadow -Wno-format-nonliteral -Wno-missing-prototypes -fsanitize-coverage=0")
579  endif()
580
581  add_subdirectory(fuzz)
582endif()
583
584if(NOT ${CMAKE_VERSION} VERSION_LESS "3.2")
585  # USES_TERMINAL is only available in CMake 3.2 or later.
586  set(MAYBE_USES_TERMINAL USES_TERMINAL)
587endif()
588
589if(UNIX AND NOT APPLE AND NOT ANDROID)
590  set(HANDSHAKER_ARGS "-handshaker-path" $<TARGET_FILE:handshaker>)
591endif()
592
593add_custom_target(
594    run_tests
595    COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir
596            ${CMAKE_BINARY_DIR}
597    COMMAND cd ssl/test/runner &&
598            ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
599              ${HANDSHAKER_ARGS} ${RUNNER_ARGS}
600    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
601    DEPENDS all_tests bssl_shim handshaker
602    ${MAYBE_USES_TERMINAL})
603