Repository: conan-io/conan-center-index

Issue:
[package] abseil/*: consider pinning the ABI at install time
### Package and Environment Details (include every applicable attribute)

  * Package Name/Version: **abseil/all versions**
  * Operating System+version: any
  * Compiler+version: any

### Steps to reproduce (Include if Applicable)

Try to use `Abseil/*` with C++17 enabled. A good example can be found in #5766 .

By default, Abseil assumes that the whole application (including Abseil) is compiled with the same compiler and flags.  A good discussion can be found in abseil/abseil-cpp#696.  If Abseil is compiled with C++11 and used from an application compiled in C++17 this does not work, as the ABI (and arguably the API) changes depending on the C++ flags in effect when the Abseil headers are *used*.

However, it is possible to "pin" Abseil's API to whatever was used when it was compiled and installed.

Specifically one would need to set the pre-processor macros in this file to `0` if compiled with C++ < 17, and to `2` if compiled with C++ >= 17:

https://github.com/abseil/abseil-cpp/blob/master/absl/base/options.h

We use this to compile Abseil with C++11 and then use it from both C++11 and C++17:

https://github.com/googleapis/google-cloud-cpp/blob/7ee1d91d4fb6915dc50617c01ebc04777e183ebd/ci/cloudbuild/dockerfiles/fedora-34.Dockerfile#L60



Discussion:
/FYI: @devjgm 
I will be sending a PR for this.
@uilianries I can try to fix this bug, but first I would like to check if this is a bad idea.

My proposal would be to pin the ABI of the Abseil package to the ABI used when it was compiled.  One does this by setting these defines:

https://github.com/abseil/abseil-cpp/blob/1ce4ceca2b2931bc4d7e470228c2dbb2f3dfea0f/absl/base/options.h#L130
https://github.com/abseil/abseil-cpp/blob/1ce4ceca2b2931bc4d7e470228c2dbb2f3dfea0f/absl/base/options.h#L157
https://github.com/abseil/abseil-cpp/blob/1ce4ceca2b2931bc4d7e470228c2dbb2f3dfea0f/absl/base/options.h#L183

The values must be `0` if Abseil was compiled with C++ < 17.  The values must be `1` if Abseil was compiled with C++ >= 17, and then one can only use the installed library with C++ >= 17.

It seems to me one could change the `options.h` header in the `package()` step.  Does that sound feasible?

@coryan Thank you for checking a possible workaround. Indeed you suggestion seems be enough for our case. Instead of copying a new file, is it possible only replacing that value in file before building, like a patch? 
Yes, I believe that is possible. I will try to create a PR based on this discussion, will ping you once I submit it and you can tell me what I did wrong :grinning: 

Thank you so much! I'm present to all PRs (notified by email), but feel free to ping me! 

Resolving patch:
diff --git a/recipes/abseil/all/conanfile.py b/recipes/abseil/all/conanfile.py
--- a/recipes/abseil/all/conanfile.py
+++ b/recipes/abseil/all/conanfile.py
@@ -56,9 +56,39 @@ def _configure_cmake(self):
         self._cmake.configure()
         return self._cmake
 
+    @property
+    def _abseil_abi_macros(self):
+        return [
+            "ABSL_OPTION_USE_STD_ANY",
+            "ABSL_OPTION_USE_STD_OPTIONAL",
+            "ABSL_OPTION_USE_STD_STRING_VIEW",
+            "ABSL_OPTION_USE_STD_VARIANT",
+        ]
+
+    def _abseil_abi_config(self):
+        """Determine the Abseil ABI for polyfills (absl::any, absl::optional, absl::string_view, and absl::variant)"""
+        if self.settings.compiler.get_safe("cppstd"):
+            if self.settings.compiler.get_safe("cppstd") >= "17":
+                return "1"
+            return "0"
+        # As-of 2021-09-27 only GCC-11 defaults to C++17.
+        if (
+            self.settings.compiler == "gcc"
+            and tools.Version(self.settings.compiler.version) >= "11"
+        ):
+            return "1"
+        return "0"
+
     def build(self):
         for patch in self.conan_data.get("patches", {}).get(self.version, []):
             tools.patch(**patch)
+        absl_option = self._abseil_abi_config()
+        for macro in self._abseil_abi_macros:
+            tools.replace_in_file(
+                os.path.join(self._source_subfolder, "absl", "base", "options.h"),
+                "#define {} 2".format(macro),
+                "#define {} {}".format(macro, absl_option),
+            )
         cmake = self._configure_cmake()
         cmake.build()
 


Test patch: