Add CMake install rules.

This creates an install directory under the top level source directory.
The install contains a CMake config file that produces variables and
targets compatible with FindOpenSSL, or the directory can be scanned by
FindOpenSSL via -DOPEN_SSL_ROOT. This allows using BoringSSL with
third-party dependencies that find an SSL implementation via CMake.

Change-Id: Iffeac64b9cced027d549486c98a6cd9721415454
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52205
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 35ff4c1..df2d630 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,12 @@
 # Defer enabling C and CXX languages.
 project(BoringSSL NONE)
 
+# Don't install BoringSSL to system directories by default; it has no stable
+# ABI. Instead, default to an "install" directory under the source.
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+  set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install CACHE PATH "" FORCE)
+endif()
+
 if(WIN32)
   # On Windows, prefer cl over gcc if both are available. By default most of
   # the CMake generators prefer gcc, even on Windows.
@@ -541,6 +547,7 @@
   set_target_properties(libcxxabi PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes -Wno-implicit-fallthrough")
   # libc++abi depends on libc++ internal headers.
   set_property(TARGET libcxxabi APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/util/bot/libcxx/src")
+  install(TARGETS libcxxabi EXPORT OpenSSLTargets)
 
   add_library(libcxx ${LIBCXX_SOURCES})
   if(ASAN OR MSAN OR TSAN)
@@ -556,6 +563,7 @@
     -DLIBCXX_BUILDING_LIBCXXABI
   )
   target_link_libraries(libcxx libcxxabi)
+  install(TARGETS libcxx EXPORT OpenSSLTargets)
 endif()
 
 # Add minimal googletest targets. The provided one has many side-effects, and
@@ -656,3 +664,12 @@
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     DEPENDS all_tests bssl_shim handshaker fips_specific_tests_if_any
     USES_TERMINAL)
+
+install(DIRECTORY include/ TYPE INCLUDE)
+
+install(EXPORT OpenSSLTargets
+  FILE OpenSSLTargets.cmake
+  NAMESPACE OpenSSL::
+  DESTINATION lib/cmake/OpenSSL
+)
+install(FILES OpenSSLConfig.cmake DESTINATION lib/cmake/OpenSSL)
diff --git a/OpenSSLConfig.cmake b/OpenSSLConfig.cmake
new file mode 100644
index 0000000..3ebaf19
--- /dev/null
+++ b/OpenSSLConfig.cmake
@@ -0,0 +1,32 @@
+include(${CMAKE_CURRENT_LIST_DIR}/OpenSSLTargets.cmake)
+
+# Recursively collect dependency locations for the imported targets.
+macro(_openssl_config_libraries libraries target)
+  get_property(_DEPS TARGET ${target} PROPERTY INTERFACE_LINK_LIBRARIES)
+  foreach(_DEP ${_DEPS})
+    if(TARGET ${_DEP})
+      _openssl_config_libraries(${libraries} ${_DEP})
+    else()
+      list(APPEND ${libraries} ${_DEP})
+    endif()
+  endforeach()
+  get_property(_LOC TARGET ${target} PROPERTY LOCATION)
+  list(APPEND ${libraries} ${_LOC})
+endmacro()
+
+set(OPENSSL_FOUND YES)
+get_property(OPENSSL_INCLUDE_DIR TARGET OpenSSL::SSL PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+get_property(OPENSSL_CRYPTO_LIBRARY TARGET OpenSSL::Crypto PROPERTY LOCATION)
+_openssl_config_libraries(OPENSSL_CRYPTO_LIBRARIES OpenSSL::Crypto)
+list(REMOVE_DUPLICATES OPENSSL_CRYPTO_LIBRARIES)
+
+get_property(OPENSSL_SSL_LIBRARY TARGET OpenSSL::Crypto PROPERTY LOCATION)
+_openssl_config_libraries(OPENSSL_SSL_LIBRARIES OpenSSL::SSL)
+list(REMOVE_DUPLICATES OPENSSL_SSL_LIBRARIES)
+
+set(OPENSSL_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES} ${OPENSSL_SSL_LIBRARIES})
+list(REMOVE_DUPLICATES OPENSSL_LIBRARIES)
+
+set(_DEP)
+set(_DEPS)
+set(_LOC)
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 1cb68ca..39c9921 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -435,6 +435,12 @@
   ${CRYPTO_ARCH_SOURCES}
   ${CRYPTO_FIPS_OBJECTS}
 )
+target_include_directories(crypto INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:include>
+)
+install(TARGETS crypto EXPORT OpenSSLTargets)
+set_property(TARGET crypto PROPERTY EXPORT_NAME Crypto)
 
 if(FIPS_SHARED)
   # Rewrite libcrypto.so to inject the correct module hash value. This assumes
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 4f4abf8..ed02bb5 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -41,6 +41,12 @@
   tls13_enc.cc
   tls13_server.cc
 )
+target_include_directories(ssl INTERFACE
+  $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+  $<INSTALL_INTERFACE:include>
+)
+install(TARGETS ssl EXPORT OpenSSLTargets)
+set_property(TARGET ssl PROPERTY EXPORT_NAME SSL)
 
 add_dependencies(ssl global_target)
 
diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt
index a591b7d..e695f56 100644
--- a/tool/CMakeLists.txt
+++ b/tool/CMakeLists.txt
@@ -21,6 +21,7 @@
   tool.cc
   transport_common.cc
 )
+install(TARGETS bssl)
 
 add_dependencies(bssl global_target)
 
diff --git a/util/fipstools/acvp/modulewrapper/CMakeLists.txt b/util/fipstools/acvp/modulewrapper/CMakeLists.txt
index 267f82c..f13f6df 100644
--- a/util/fipstools/acvp/modulewrapper/CMakeLists.txt
+++ b/util/fipstools/acvp/modulewrapper/CMakeLists.txt
@@ -7,6 +7,7 @@
     main.cc
     modulewrapper.cc
   )
+  install(TARGETS modulewrapper)
 
   add_dependencies(modulewrapper global_target)