Add standalone CMake build to generate_build_files.py

This change adds a 'cmake' build type to generate_build_files.py, which
creates a standalone, CMake build without (most) of the complexities of
the full development CMake build.

(This is just a sketch for now. Some deduplication of the CMake is
called for before landing, presuming that this is useful.)

Change-Id: I1f91a8905cabaedf8f9ec588da5784edd67bfed0
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38744
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/util/generate_build_files.py b/util/generate_build_files.py
index 6bd3abc..af02ed0 100644
--- a/util/generate_build_files.py
+++ b/util/generate_build_files.py
@@ -1,3 +1,5 @@
+# coding=utf8
+
 # Copyright (c) 2015, Google Inc.
 #
 # Permission to use, copy, modify, and/or distribute this software for any
@@ -413,6 +415,177 @@
 
       gypi.write('  }\n}\n')
 
+class CMake(object):
+
+  def __init__(self):
+    self.header = \
+R'''# Copyright (c) 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is created by generate_build_files.py. Do not edit manually.
+
+cmake_minimum_required(VERSION 3.0)
+
+project(BoringSSL LANGUAGES C CXX)
+
+if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  set(CLANG 1)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fvisibility=hidden -fno-common -fno-exceptions -fno-rtti")
+  if(APPLE)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+  endif()
+
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fno-common")
+  if((CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR CLANG)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
+  else()
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+  endif()
+endif()
+
+# pthread_rwlock_t requires a feature flag.
+if(NOT WIN32)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700")
+endif()
+
+if(WIN32)
+  add_definitions(-D_HAS_EXCEPTIONS=0)
+  add_definitions(-DWIN32_LEAN_AND_MEAN)
+  add_definitions(-DNOMINMAX)
+  # Allow use of fopen.
+  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+  # VS 2017 and higher supports STL-only warning suppressions.
+  # A bug in CMake < 3.13.0 may cause the space in this value to
+  # cause issues when building with NASM. In that case, update CMake.
+  add_definitions("-D_STL_EXTRA_DISABLED_WARNINGS=4774 4987")
+endif()
+
+add_definitions(-DBORINGSSL_IMPLEMENTATION)
+
+if(OPENSSL_NO_ASM)
+  add_definitions(-DOPENSSL_NO_ASM)
+  set(ARCH "generic")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+  set(ARCH "x86_64")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
+  set(ARCH "x86_64")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
+  # cmake reports AMD64 on Windows, but we might be building for 32-bit.
+  if(CMAKE_CL_64)
+    set(ARCH "x86_64")
+  else()
+    set(ARCH "x86")
+  endif()
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86")
+  set(ARCH "x86")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386")
+  set(ARCH "x86")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
+  set(ARCH "x86")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+  set(ARCH "aarch64")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64")
+  set(ARCH "aarch64")
+# Apple A12 Bionic chipset which is added in iPhone XS/XS Max/XR uses arm64e architecture.
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64e")
+  set(ARCH "aarch64")
+elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm*")
+  set(ARCH "arm")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "mips")
+  # Just to avoid the “unknown processor” error.
+  set(ARCH "generic")
+elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
+  set(ARCH "ppc64le")
+else()
+  message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
+endif()
+
+if(NOT OPENSSL_NO_ASM)
+  if(UNIX)
+    enable_language(ASM)
+
+    # Clang's integerated assembler does not support debug symbols.
+    if(NOT CMAKE_ASM_COMPILER_ID MATCHES "Clang")
+      set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g")
+    endif()
+
+    # CMake does not add -isysroot and -arch flags to assembly.
+    if(APPLE)
+      if(CMAKE_OSX_SYSROOT)
+        set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -isysroot \"${CMAKE_OSX_SYSROOT}\"")
+      endif()
+      foreach(arch ${CMAKE_OSX_ARCHITECTURES})
+        set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch ${arch}")
+      endforeach()
+    endif()
+  else()
+    set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -gcv8")
+    enable_language(ASM_NASM)
+  endif()
+endif()
+
+include_directories(src/include)
+
+'''
+
+  def PrintLibrary(self, out, name, files):
+    out.write('add_library(\n')
+    out.write('  %s\n\n' % name)
+
+    for f in sorted(files):
+      out.write('  %s\n' % PathOf(f))
+
+    out.write(')\n\n')
+
+  def PrintExe(self, out, name, files, libs):
+    out.write('add_executable(\n')
+    out.write('  %s\n\n' % name)
+
+    for f in sorted(files):
+      out.write('  %s\n' % PathOf(f))
+
+    out.write(')\n\n')
+    out.write('target_link_libraries(%s %s)\n\n' % (name, ' '.join(libs)))
+
+  def PrintSection(self, out, name, files):
+    out.write('set(\n')
+    out.write('  %s\n\n' % name)
+    for f in sorted(files):
+      out.write('  %s\n' % PathOf(f))
+    out.write(')\n\n')
+
+  def WriteFiles(self, files, asm_outputs):
+    with open('CMakeLists.txt', 'w+') as cmake:
+      cmake.write(self.header)
+
+      for ((osname, arch), asm_files) in asm_outputs:
+        self.PrintSection(cmake, 'CRYPTO_%s_%s_SOURCES' % (osname, arch),
+            asm_files)
+
+      cmake.write(
+R'''if(APPLE AND ${ARCH} STREQUAL "aarch64")
+  set(CRYPTO_ARCH_SOURCES ${CRYPTO_ios_aarch64_SOURCES})
+elseif(APPLE AND ${ARCH} STREQUAL "arm")
+  set(CRYPTO_ARCH_SOURCES ${CRYPTO_ios_arm_SOURCES})
+elseif(APPLE)
+  set(CRYPTO_ARCH_SOURCES ${CRYPTO_mac_${ARCH}_SOURCES})
+elseif(UNIX)
+  set(CRYPTO_ARCH_SOURCES ${CRYPTO_linux_${ARCH}_SOURCES})
+elseif(WIN32)
+  set(CRYPTO_ARCH_SOURCES ${CRYPTO_win_${ARCH}_SOURCES})
+endif()
+
+''')
+
+      self.PrintLibrary(cmake, 'crypto',
+          files['crypto'] + ['${CRYPTO_ARCH_SOURCES}'])
+      self.PrintLibrary(cmake, 'ssl', files['ssl'])
+      self.PrintExe(cmake, 'bssl', files['tool'],
+          ['ssl', 'crypto', '-lpthread'])
 
 def FindCMakeFiles(directory):
   """Returns list of all CMakeLists.txt files recursively in directory."""
@@ -781,6 +954,8 @@
       platforms.append(GN())
     elif s == 'gyp':
       platforms.append(GYP())
+    elif s == 'cmake':
+      platforms.append(CMake())
     else:
       parser.print_help()
       sys.exit(1)