Add a real dependency on Abseil (#10416)

* Proof of concept for Abseil dependency

* Adding most common Abseil libraries

* Fixing shared library breakages

* Switching to quotes over angled brackets

* Disable install target by default

* Fixing abseil to LTS commit

* Upgrade to latest Abseil LTS

* Turning install back on by default, removing unnecessary export statements

* Add note to future self

* Fixing unsafe globals
diff --git a/.gitmodules b/.gitmodules
index 4aec90b..5942031 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,4 +9,4 @@
 [submodule "third_party/abseil-cpp"]
 	path = third_party/abseil-cpp
 	url = https://github.com/abseil/abseil-cpp
-	branch = lts_2021_11_02
+	branch = lts_2022_06_23
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e38e237..6f9b751 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -79,6 +79,11 @@
 # User options
 include(${protobuf_SOURCE_DIR}/cmake/protobuf-options.cmake)
 
+if (protobuf_BUILD_SHARED_LIBS)
+  # This is necessary for linking in Abseil.
+  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+endif ()
+
 # Version metadata
 set(protobuf_VERSION_STRING "3.21.4")
 set(protobuf_DESCRIPTION "Protocol Buffers")
diff --git a/cmake/abseil-cpp.cmake b/cmake/abseil-cpp.cmake
index 24d13f5..7466732 100644
--- a/cmake/abseil-cpp.cmake
+++ b/cmake/abseil-cpp.cmake
@@ -27,6 +27,24 @@
 set(_protobuf_FIND_ABSL "if(NOT TARGET absl::strings)\n  find_package(absl CONFIG)\nendif()")
 
 set(protobuf_ABSL_USED_TARGETS
+  absl::algorithm
+  absl::base
+  absl::bind_front
+  absl::cleanup
+  absl::debugging
+  absl::flags
+  absl::flat_hash_map
+  absl::flat_hash_set
+  absl::function_ref
+  absl::hash
+  absl::memory
+  absl::optional
+  absl::span
+  absl::status
+  absl::statusor
   absl::strings
-  absl::strings_internal
+  absl::synchronization
+  absl::time
+  absl::utility
+  absl::variant
 )
diff --git a/cmake/install.cmake b/cmake/install.cmake
index 9379aa7..533c64f 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -93,18 +93,6 @@
 
 # Allows the build directory to be used as a find directory.
 
-if (protobuf_BUILD_PROTOC_BINARIES)
-  export(TARGETS libprotobuf-lite libprotobuf libprotoc protoc
-    NAMESPACE protobuf::
-    FILE ${CMAKE_BUILD_CMAKEDIR}/protobuf-targets.cmake
-  )
-else (protobuf_BUILD_PROTOC_BINARIES)
-  export(TARGETS libprotobuf-lite libprotobuf
-    NAMESPACE protobuf::
-    FILE ${CMAKE_BUILD_CMAKEDIR}/protobuf-targets.cmake
-  )
-endif (protobuf_BUILD_PROTOC_BINARIES)
-
 install(EXPORT protobuf-targets
   DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
   NAMESPACE protobuf::
diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake
index 36ed3df..8047969 100644
--- a/cmake/libprotobuf-lite.cmake
+++ b/cmake/libprotobuf-lite.cmake
@@ -23,6 +23,7 @@
   target_link_libraries(libprotobuf-lite PRIVATE log)
 endif()
 target_include_directories(libprotobuf-lite PUBLIC ${protobuf_SOURCE_DIR}/src)
+target_link_libraries(libprotobuf-lite PRIVATE ${protobuf_ABSL_USED_TARGETS})
 target_include_directories(libprotobuf-lite PRIVATE ${ABSL_ROOT_DIR})
 if(protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotobuf-lite
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 2607374..7fae976 100644
--- a/cmake/libprotobuf.cmake
+++ b/cmake/libprotobuf.cmake
@@ -26,6 +26,7 @@
   target_link_libraries(libprotobuf PRIVATE log)
 endif()
 target_include_directories(libprotobuf PUBLIC ${protobuf_SOURCE_DIR}/src)
+target_link_libraries(libprotobuf PRIVATE ${protobuf_ABSL_USED_TARGETS})
 target_include_directories(libprotobuf PRIVATE ${ABSL_ROOT_DIR})
 if(protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotobuf
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index 509d87b..b3a907f 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -16,6 +16,7 @@
     LINK_DEPENDS ${protobuf_SOURCE_DIR}/src/libprotoc.map)
 endif()
 target_link_libraries(libprotoc PRIVATE libprotobuf)
+target_link_libraries(libprotoc PRIVATE ${protobuf_ABSL_USED_TARGETS})
 target_include_directories(libprotoc PRIVATE ${ABSL_ROOT_DIR})
 if(protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotoc
diff --git a/src/google/protobuf/compiler/cpp/BUILD.bazel b/src/google/protobuf/compiler/cpp/BUILD.bazel
index 098fd63..44f08fe 100644
--- a/src/google/protobuf/compiler/cpp/BUILD.bazel
+++ b/src/google/protobuf/compiler/cpp/BUILD.bazel
@@ -55,6 +55,7 @@
     deps = [
         "//:protobuf",
         "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/container:flat_hash_set",
     ],
 )
 
diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc
index b3ceafb..9135159 100644
--- a/src/google/protobuf/compiler/cpp/helpers.cc
+++ b/src/google/protobuf/compiler/cpp/helpers.cc
@@ -41,9 +41,9 @@
 #include <map>
 #include <memory>
 #include <queue>
-#include <unordered_set>
 #include <vector>
 
+#include "absl/container/flat_hash_set.h"
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/descriptor.h>
@@ -176,15 +176,17 @@
 #endif  // !PROTOBUF_FUTURE_BREAKING_CHANGES
 };
 
-static std::unordered_set<std::string>* MakeKeywordsMap() {
-  auto* result = new std::unordered_set<std::string>();
-  for (const auto keyword : kKeywordList) {
-    result->emplace(keyword);
-  }
-  return result;
-}
+const absl::flat_hash_set<std::string>& Keywords() {
+  static const auto* keywords = []{
+    auto* keywords = new absl::flat_hash_set<std::string>();
 
-static std::unordered_set<std::string>& kKeywords = *MakeKeywordsMap();
+    for (const auto keyword : kKeywordList) {
+      keywords->emplace(keyword);
+    }
+    return keywords;
+  }();
+  return *keywords;
+}
 
 std::string IntTypeName(const Options& options, const std::string& type) {
   return type + "_t";
@@ -509,7 +511,7 @@
 }
 
 std::string ResolveKeyword(const std::string& name) {
-  if (kKeywords.count(name) > 0) {
+  if (Keywords().count(name) > 0) {
     return name + "_";
   }
   return name;
@@ -518,7 +520,7 @@
 std::string FieldName(const FieldDescriptor* field) {
   std::string result = field->name();
   LowerString(&result);
-  if (kKeywords.count(result) > 0) {
+  if (Keywords().count(result) > 0) {
     result.append("_");
   }
   return result;
@@ -552,7 +554,7 @@
 
 std::string EnumValueName(const EnumValueDescriptor* enum_value) {
   std::string result = enum_value->name();
-  if (kKeywords.count(result) > 0) {
+  if (Keywords().count(result) > 0) {
     result.append("_");
   }
   return result;
@@ -863,7 +865,7 @@
     // Single underscore will also make it conflicting with the private data
     // member. We use double underscore to escape function names.
     function_name.append("__");
-  } else if (kKeywords.count(name) > 0) {
+  } else if (Keywords().count(name) > 0) {
     // If the field name is a keyword, we append the underscore back to keep it
     // consistent with other function names.
     function_name.append("_");
@@ -1116,7 +1118,7 @@
 }
 
 bool IsWellKnownMessage(const FileDescriptor* file) {
-  static const std::unordered_set<std::string> well_known_files{
+  static const auto* well_known_files = new absl::flat_hash_set<std::string>{
       "google/protobuf/any.proto",
       "google/protobuf/api.proto",
       "google/protobuf/compiler/plugin.proto",
@@ -1130,7 +1132,7 @@
       "google/protobuf/type.proto",
       "google/protobuf/wrappers.proto",
   };
-  return well_known_files.find(file->name()) != well_known_files.end();
+  return well_known_files->find(file->name()) != well_known_files->end();
 }
 
 static void GenerateUtf8CheckCode(const FieldDescriptor* field,
diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp
index 8c6e53e..273292d 160000
--- a/third_party/abseil-cpp
+++ b/third_party/abseil-cpp
@@ -1 +1 @@
-Subproject commit 8c6e53ef3adb1227fffa442c50349dab134a54bc
+Subproject commit 273292d1cfc0a94a65082ee350509af1d113344d