Repository: conan-io/conan-center-index

Issue:
[package] onetbb/2020.3: compiler.cppstd isn't used
### Description

onetbb recipe doesn't forward -std=c++17 flag on Macos during onetbb build. This leads to improper exception handling in runtime.
"TBB Warning: Exact exception propagation is requested by application but the linked library is built without support for it"
Example:

```
#include <tbb/parallel_for.h>
#include <iostream>
#include <stdexcept>

int main()
try {
    tbb::parallel_for(std::size_t{0}, std::size_t{1}, [](const std::size_t i){
        if (i == 0)
            throw std::runtime_error("test exception");
    });
    std::cout << "no exception";
    return 1;
} catch (const std::runtime_error&) {
    std::cout << "Got exception";
    return 0;
} catch (const tbb::captured_exception&) {
    std::cout << "Unexpected tbb::captured_exception";
    return 2;
}
```


### Package and Environment Details

* Package Name/Version: **onetbb/2020.3**
* Operating System+version: **macOS Catalina 10.15.7**
* Compiler+version: **Apple clang version 12.0.0 (clang-1200.0.32.2)**
* Docker image: ****
* Conan version: **conan 1.52.0**
* Python version: **Python 3.10.4**


### Conan profile

[settings]
os=Macos
os_build=Macos
arch=x86_64
arch_build=x86_64
compiler=apple-clang
compiler.cppstd=17
compiler.version=12.0
compiler.libcxx=libc++
build_type=Release
[options]
[conf]
[build_requires]
[env]


### Steps to reproduce

conan install -r conancenter onetbb/2020.3@ -pr:b=default -pr:h=default -s compiler.cppstd=17 --build=onetbb

### Logs

<details><summary>Click to expand log</summary>

```
...
Created the ./build/macos_intel64_clang_cc12.0.0_os10.15.7_release directory
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C "./build/macos_intel64_clang_cc12.0.0_os10.15.7_release"  -r -f ../../build/Makefile.tbb cfg=release
../../build/Makefile.tbb:28: CONFIG: cfg=release arch=intel64 compiler=clang target=macos runtime=cc12.0.0_os10.15.7
clang++ -o concurrent_hash_map.o -c -MMD -g -O2 -DUSE_PTHREAD -DDO_ITT_NOTIFY -stdlib=libc++ -m64 -mrtm -mmacosx-version-min=10.11  -fPIC  -D__TBB_BUILD=1 -Wall -Wno-non-virtual-dtor -Wno-dangling-else  -DTBB_SUPPRESS_DEPRECATED_MESSAGES=1   -I../../src -I../../src/rml/include -I../../include ../../src/tbb/concurrent_hash_map.cpp
...
```

</details>



Discussion:

Resolving patch:
diff --git a/recipes/onetbb/2020.x/conanfile.py b/recipes/onetbb/2020.x/conanfile.py
--- a/recipes/onetbb/2020.x/conanfile.py
+++ b/recipes/onetbb/2020.x/conanfile.py
@@ -1,10 +1,14 @@
-from conan.tools.microsoft import msvc_runtime_flag
-from conans import ConanFile, tools
-from conans.errors import ConanInvalidConfiguration, ConanException
+from conan import ConanFile
+from conan.tools.microsoft import msvc_runtime_flag, is_msvc
+from conan.tools.build import cross_building
+from conan.tools.files import get, replace_in_file, save, chdir, copy
+from conan.tools.scm import Version
+from conan.errors import ConanInvalidConfiguration, ConanException
+from conans import tools
 import os
 import textwrap
 
-required_conan_version = ">=1.43.0"
+required_conan_version = ">=1.47.0"
 
 
 class OneTBBConan(ConanFile):
@@ -41,10 +45,6 @@ def _source_subfolder(self):
     def _settings_build(self):
         return getattr(self, "settings_build", self.settings)
 
-    @property
-    def _is_msvc(self):
-        return str(self.settings.compiler) in ["Visual Studio", "msvc"]
-
     @property
     def _is_clanglc(self):
         return self.settings.os == "Windows" and self.settings.compiler == "clang"
@@ -66,10 +66,10 @@ def configure(self):
 
     def validate(self):
         if self.settings.os == "Macos":
-            if hasattr(self, "settings_build") and tools.cross_building(self):
+            if hasattr(self, "settings_build") and cross_building(self):
                 # See logs from https://github.com/conan-io/conan-center-index/pull/8454
                 raise ConanInvalidConfiguration("Cross building on Macos is not yet supported. Contributions are welcome")
-            if self.settings.compiler == "apple-clang" and tools.Version(self.settings.compiler.version) < "8.0":
+            if self.settings.compiler == "apple-clang" and Version(self.settings.compiler.version) < "8.0":
                 raise ConanInvalidConfiguration("%s %s couldn't be built by apple-clang < 8.0" % (self.name, self.version))
         if not self.options.shared:
             self.output.warn("oneTBB strongly discourages usage of static linkage")
@@ -88,7 +88,7 @@ def build_requirements(self):
                 self.build_requires("make/4.2.1")
 
     def source(self):
-        tools.get(**self.conan_data["sources"][self.version],
+        get(self, **self.conan_data["sources"][self.version],
                   strip_root=True, destination=self._source_subfolder)
 
     def build(self):
@@ -100,14 +100,14 @@ def add_flag(name, value):
 
         # Get the version of the current compiler instead of gcc
         linux_include = os.path.join(self._source_subfolder, "build", "linux.inc")
-        tools.replace_in_file(linux_include, "shell gcc", "shell $(CC)")
-        tools.replace_in_file(linux_include, "= gcc", "= $(CC)")
+        replace_in_file(self, linux_include, "shell gcc", "shell $(CC)")
+        replace_in_file(self, linux_include, "= gcc", "= $(CC)")
 
         if self.version != "2019_u9" and self.settings.build_type == "Debug":
-            tools.replace_in_file(os.path.join(self._source_subfolder, "Makefile"), "release", "debug")
+            replace_in_file(self, os.path.join(self._source_subfolder, "Makefile"), "release", "debug")
 
         if str(self._base_compiler) in ["Visual Studio", "msvc"]:
-            tools.save(
+            save(self,
                 os.path.join(self._source_subfolder, "build", "big_iron_msvc.inc"),
                 # copy of big_iron.inc adapted for MSVC
                 textwrap.dedent("""\
@@ -195,12 +195,23 @@ def add_flag(name, value):
                 extra += " compiler=icl"
             else:
                 extra += " compiler=cl"
+        cxx_std_flag = tools.cppstd_flag(self.settings)
+        if cxx_std_flag:
+            cxx_std_value = (
+                cxx_std_flag.split("=")[1]
+                if "=" in cxx_std_flag
+                else cxx_std_flag.split(":")[1]
+                if ":" in cxx_std_flag
+                else None
+            )
+            if cxx_std_value:
+                extra += f" stdver={cxx_std_value}"
 
         make = tools.get_env("CONAN_MAKE_PROGRAM", tools.which("make") or tools.which("mingw32-make"))
         if not make:
             raise ConanException("This package needs 'make' in the path to build")
 
-        with tools.chdir(self._source_subfolder):
+        with chdir(self, self._source_subfolder):
             # intentionally not using AutoToolsBuildEnvironment for now - it's broken for clang-cl
             if self._is_clanglc:
                 add_flag("CFLAGS", "-mrtm")
@@ -210,36 +221,35 @@ def add_flag(name, value):
             context = tools.no_op()
             if self.settings.compiler == "intel":
                 context = tools.intel_compilervars(self)
-            elif self._is_msvc:
+            elif is_msvc(self):
                 # intentionally not using vcvars for clang-cl yet
                 context = tools.vcvars(self)
             with context:
                 self.run("%s %s %s" % (make, extra, " ".join(targets)))
 
     def package(self):
-        self.copy("LICENSE", dst="licenses", src=self._source_subfolder)
-        self.copy(pattern="*.h", dst="include", src="%s/include" % self._source_subfolder)
-        self.copy(pattern="*", dst="include/tbb/compat", src="%s/include/tbb/compat" % self._source_subfolder)
-        build_folder = "%s/build/" % self._source_subfolder
+        copy(self, "LICENSE", dst=os.path.join(self.package_folder, "licenses"), src=self._source_subfolder)
+        copy(self, pattern="*.h", dst=os.path.join(self.package_folder, "include"), src=os.path.join(self._source_subfolder, "include"))
+        copy(self, pattern="*", dst=os.path.join(self.package_folder, "include", "tbb", "compat"), src=os.path.join(self._source_subfolder, "include", "tbb", "compat"))
+        build_folder = os.path.join(self._source_subfolder, "build")
         build_type = "debug" if self.settings.build_type == "Debug" else "release"
-        self.copy(pattern="*%s*.lib" % build_type, dst="lib", src=build_folder, keep_path=False)
-        self.copy(pattern="*%s*.a" % build_type, dst="lib", src=build_folder, keep_path=False)
-        self.copy(pattern="*%s*.dll" % build_type, dst="bin", src=build_folder, keep_path=False)
-        self.copy(pattern="*%s*.dylib" % build_type, dst="lib", src=build_folder, keep_path=False)
+        copy(self, pattern=f"*{build_type}*.lib", dst=os.path.join(self.package_folder, "lib"), src=build_folder, keep_path=False)
+        copy(self, pattern=f"*{build_type}*.a", dst=os.path.join(self.package_folder, "lib"), src=build_folder, keep_path=False)
+        copy(self, pattern=f"*{build_type}*.dll", dst=os.path.join(self.package_folder, "bin"), src=build_folder, keep_path=False)
+        copy(self, pattern=f"*{build_type}*.dylib", dst=os.path.join(self.package_folder, "lib"), src=build_folder, keep_path=False)
         # Copy also .dlls to lib folder so consumers can link against them directly when using MinGW
         if self.settings.os == "Windows" and self.settings.compiler == "gcc":
-            self.copy("*%s*.dll" % build_type, dst="lib", src=build_folder, keep_path=False)
+            copy(self, f"*{build_type}*.dll", dst=os.path.join(self.package_folder, "lib"), src=build_folder, keep_path=False)
 
         if self.settings.os == "Linux":
             extension = "so"
             if self.options.shared:
-                self.copy("*%s*.%s.*" % (build_type, extension), "lib", build_folder,
-                          keep_path=False)
+                copy(self, f"*{build_type}*.{extension}.*", dst=os.path.join(self.package_folder, "lib"), src=build_folder, keep_path=False)
                 outputlibdir = os.path.join(self.package_folder, "lib")
-                os.chdir(outputlibdir)
-                for fpath in os.listdir(outputlibdir):
-                    self.run("ln -s \"%s\" \"%s\"" %
-                             (fpath, fpath[0:fpath.rfind("." + extension) + len(extension) + 1]))
+                with chdir(self, outputlibdir):
+                    for fpath in os.listdir(outputlibdir):
+                        filepath = fpath[0:fpath.rfind("." + extension) + len(extension) + 1]
+                        self.run(f'ln -s "{fpath}" "{filepath}"', run_environment=True)
 
     def package_info(self):
         self.cpp_info.set_property("cmake_file_name", "TBB")


Test patch: