Repository: conan-io/conan-center-index

Issue:
[package] boost/1.73: Shared Library Builds broken if you build without fiber
### Package and Environment Details (include every applicable attribute)
  * Package Name/Version: boost/1.73
  * Operating System+version: Windows 10
  * Compiler+version: Visual Studio 2019
  * Conan version: conan 1.35.1
  * Python version: via chocolatey

### Conan profile (output of `conan profile show default` or `conan profile show <profile>` if custom profile is in use)
```
[settings]
os=Windows
os_build=Windows
arch=x86_64
arch_build=x86_64
compiler=Visual Studio
compiler.version=16
build_type=Release
[options]
[build_requires]
[env]
```

### Steps to reproduce (Include if Applicable)
install boost/1.73 with shared=true and boost:without_fiber true
numa is disabled in visual studio, but numa is deleted when without_fiber is true, so you get:


ERROR: boost/1.73.0: Error in validate() method, line 337
if self.options.numa:
ConanException: option 'numa' doesn't exist






Discussion:
Indeed, it should be `self.options.get_safe("numa")`.

i got the same problem with boost/1.76.

Resolving patch:
diff --git a/recipes/boost/all/conanfile.py b/recipes/boost/all/conanfile.py
--- a/recipes/boost/all/conanfile.py
+++ b/recipes/boost/all/conanfile.py
@@ -94,6 +94,8 @@ class BoostConan(ConanFile):
         "extra_b2_flags": "ANY",  # custom b2 flags
         "i18n_backend": ["iconv", "icu", None],
         "visibility": ["global", "protected", "hidden"],
+        "addr2line_location": "ANY",
+        "with_stacktrace_backtrace": [True, False],
     }
     options.update({"without_{}".format(_name): [True, False] for _name in CONFIGURE_OPTIONS})
 
@@ -124,6 +126,8 @@ class BoostConan(ConanFile):
         "extra_b2_flags": "None",
         "i18n_backend": "iconv",
         "visibility": "hidden",
+        "addr2line_location": "/usr/bin/addr2line",
+        "with_stacktrace_backtrace": True,
     }
     default_options.update({"without_{}".format(_name): False for _name in CONFIGURE_OPTIONS})
     default_options.update({"without_{}".format(_name): True for _name in ("graph_parallel", "mpi", "python")})
@@ -234,6 +238,10 @@ def config_options(self):
             if "without_{}".format(opt_name) not in self.options:
                 raise ConanException("{} has the configure options {} which is not available in conanfile.py".format(self._dependency_filename, opt_name))
 
+        # libbacktrace cannot be built on Visual Studio
+        if self.settings.compiler == "Visual Studio":
+            del self.options.with_stacktrace_backtrace
+
         # nowide requires a c++11-able compiler + movable std::fstream: change default to not build on compiler with too old default c++ standard or too low compiler.cppstd
         # json requires a c++11-able compiler: change default to not build on compiler with too old default c++ standard or too low compiler.cppstd
         if self.settings.compiler.cppstd:
@@ -297,6 +305,10 @@ def _fPIC(self):
     def _shared(self):
         return self.options.get_safe("shared", self.default_options["shared"])
 
+    @property
+    def _stacktrace_addr2line_available(self):
+        return not self.options.header_only and not self.options.without_stacktrace and self.settings.compiler != "Visual Studio"
+
     def configure(self):
         if self.options.header_only:
             del self.options.shared
@@ -315,6 +327,15 @@ def configure(self):
                 self.options.python_version = self._detect_python_version()
                 self.options.python_executable = self._python_executable
 
+        if self._stacktrace_addr2line_available:
+            if os.path.abspath(str(self.options.addr2line_location)) != str(self.options.addr2line_location):
+                raise ConanInvalidConfiguration("addr2line_location must be an absolute path to addr2line")
+        else:
+            del self.options.addr2line_location
+
+        if self.options.get_safe("without_stacktrace", True):
+            del self.options.with_stacktrace_backtrace
+
         if self.options.layout == "b2-default":
             self.options.layout = "versioned" if self.settings.os == "Windows" else "system"
 
@@ -334,7 +355,7 @@ def validate(self):
         if self.settings.compiler == "Visual Studio" and self._shared:
             if "MT" in str(self.settings.compiler.runtime):
                 raise ConanInvalidConfiguration("Boost can not be built as shared library with MT runtime.")
-            if self.options.numa:
+            if self.options.get_safe("numa"):
                 raise ConanInvalidConfiguration("Cannot build a shared boost with numa support on Visual Studio")
 
         # Check, when a boost module is enabled, whether the boost modules it depends on are enabled as well.
@@ -424,6 +445,10 @@ def _with_icu(self):
     def _with_iconv(self):
         return not self.options.header_only and self._with_dependency("iconv") and self.options.i18n_backend == "iconv"
 
+    @property
+    def _with_stacktrace_backtrace(self):
+        return not self.options.header_only and self.options.get_safe("with_stacktrace_backtrace", False)
+
     def requirements(self):
         if self._with_zlib:
             self.requires("zlib/1.2.11")
@@ -433,6 +458,9 @@ def requirements(self):
             self.requires("xz_utils/5.2.5")
         if self._with_zstd:
             self.requires("zstd/1.4.9")
+        if self._with_stacktrace_backtrace:
+            self.requires("libbacktrace/cci.20210118")
+            self.requires("libunwind/1.5.0")
 
         if self._with_icu:
             self.requires("icu/68.2")
@@ -672,8 +700,7 @@ def _build_bcp(self):
         with tools.vcvars(self.settings) if self._is_msvc else tools.no_op():
             with tools.chdir(folder):
                 command = "%s -j%s --abbreviate-paths toolset=%s" % (self._b2_exe, tools.cpu_count(), self._toolset)
-                if "debug_level" in self.options:
-                    command += " -d%d" % self.options.debug_level
+                command += " -d%d" % self.options.debug_level
                 self.output.warn(command)
                 self.run(command, run_environment=True)
 
@@ -703,6 +730,22 @@ def _run_bcp(self):
                 self.run(command)
 
     def build(self):
+        if tools.cross_building(self.settings, skip_x64_x86=True):
+            # When cross building, do not attempt to run the test-executable (assume they work)
+            tools.replace_in_file(os.path.join(self.source_folder, self._source_subfolder, "libs", "stacktrace", "build", "Jamfile.v2"),
+                                  "$(>) > $(<)",
+                                  "echo \"\" > $(<)", strict=False)
+        # Older clang releases require a thread_local variable to be initialized by a constant value
+        tools.replace_in_file(os.path.join(self.source_folder, self._source_subfolder, "boost", "stacktrace", "detail", "libbacktrace_impls.hpp"),
+                              "/* thread_local */", "thread_local", strict=False)
+        tools.replace_in_file(os.path.join(self.source_folder, self._source_subfolder, "boost", "stacktrace", "detail", "libbacktrace_impls.hpp"),
+                              "/* static __thread */", "static __thread", strict=False)
+        if self.settings.compiler == "clang" and tools.Version(self.settings.compiler.version) < 6:
+            tools.replace_in_file(os.path.join(self.source_folder, self._source_subfolder, "boost", "stacktrace", "detail", "libbacktrace_impls.hpp"),
+                                  "thread_local", "/* thread_local */")
+            tools.replace_in_file(os.path.join(self.source_folder, self._source_subfolder, "boost", "stacktrace", "detail", "libbacktrace_impls.hpp"),
+                                  "static __thread", "/* static __thread */")
+
         if self.options.header_only:
             self.output.warn("Header only package, skipping build")
             return
@@ -957,18 +1000,22 @@ def add_defines(library):
         link_flags = 'linkflags="%s"' % " ".join(link_flags) if link_flags else ""
         flags.append(link_flags)
 
+        if self.options.get_safe("addr2line_location"):
+            cxx_flags.append("-DBOOST_STACKTRACE_ADDR2LINE_LOCATION={}".format(self.options.addr2line_location))
+
         cxx_flags = 'cxxflags="%s"' % " ".join(cxx_flags) if cxx_flags else ""
         flags.append(cxx_flags)
 
         if self.options.extra_b2_flags:
             flags.extend(shlex.split(str(self.options.extra_b2_flags)))
 
-        flags.extend(["install",
-                      "--prefix=%s" % self.package_folder,
-                      "-j%s" % tools.cpu_count(),
-                      "--abbreviate-paths"])
-        if "debug_level" in self.options:
-            flags.append("-d%d" % self.options.debug_level)
+        flags.extend([
+            "install",
+            "--prefix=%s" % self.package_folder,
+            "-j%s" % tools.cpu_count(),
+            "--abbreviate-paths",
+            "-d%d" % self.options.debug_level,
+        ])
         return flags
 
     @property
@@ -1066,7 +1113,7 @@ def create_library_config(deps_name, name):
 
         # Specify here the toolset with the binary if present if don't empty parameter :
         contents += '\nusing "%s" : %s : ' % (self._toolset, self._toolset_version)
-        
+
         if self._is_msvc:
             contents += ' "%s"' % self._cxx.replace("\\", "/")
         else:
@@ -1083,16 +1130,27 @@ def create_library_config(deps_name, name):
             contents += '<archiver>"%s" ' % tools.which(self._ar).replace("\\", "/")
         if self._ranlib:
             contents += '<ranlib>"%s" ' % tools.which(self._ranlib).replace("\\", "/")
-        if "CXXFLAGS" in os.environ:
-            contents += '<cxxflags>"%s" ' % os.environ["CXXFLAGS"]
-        if "CFLAGS" in os.environ:
-            contents += '<cflags>"%s" ' % os.environ["CFLAGS"]
-        if "CPPFLAGS" in os.environ:
-            contents += '<compileflags>"%s" ' % os.environ["CPPFLAGS"]
-        if "LDFLAGS" in os.environ:
-            contents += '<linkflags>"%s" ' % os.environ["LDFLAGS"]
-        if "ASFLAGS" in os.environ:
-            contents += '<asmflags>"%s" ' % os.environ["ASFLAGS"]
+        cxxflags = tools.get_env("CXXFLAGS", "") + " "
+        cflags = tools.get_env("CFLAGS", "") + " "
+        cppflags = tools.get_env("CPPFLAGS", "") + " "
+        ldflags = tools.get_env("LDFLAGS", "") + " "
+        asflags = tools.get_env("ASFLAGS", "") + " "
+
+        if self._with_stacktrace_backtrace:
+            for l in ("libbacktrace", "libunwind"):
+                cppflags += " ".join("-I{}".format(p) for p in self.deps_cpp_info[l].include_paths) + " "
+                ldflags += " ".join("-L{}".format(p) for p in self.deps_cpp_info[l].lib_paths) + " "
+
+        if cxxflags.strip():
+            contents += '<cxxflags>"%s" ' % cxxflags.strip()
+        if cflags.strip():
+            contents += '<cflags>"%s" ' % cflags.strip()
+        if cppflags.strip():
+            contents += '<compileflags>"%s" ' % cppflags.strip()
+        if ldflags.strip():
+            contents += '<linkflags>"%s" ' % ldflags.strip()
+        if asflags.strip():
+            contents += '<asmflags>"%s" ' % asflags.strip()
 
         contents += " ;"
 
@@ -1349,14 +1407,8 @@ def filter_transform_module_libraries(names):
                 for name in names:
                     if name in ("boost_stacktrace_windbg", "boost_stacktrace_windbg_cached") and self.settings.os != "Windows":
                         continue
-                    if name in ("boost_stacktrace_addr2line", "boost_stacktrace_basic") and self.settings.compiler == "Visual Studio":
+                    if name in ("boost_stacktrace_addr2line", "boost_stacktrace_backtrace", "boost_stacktrace_basic",) and self.settings.compiler == "Visual Studio":
                         continue
-                    if name == "boost_stacktrace_backtrace":
-                        if "boost_stacktrace_backtrace" not in all_detected_libraries:
-                            continue
-                        # FIXME: Boost.Build sometimes picks up a system libbacktrace library.
-                        # How to avoid this and force using a conan packaged libbacktrace package.
-                        self.output.warn("Picked up a system libbacktrace library")
                     if not self.options.get_safe("numa") and "_numa" in name:
                         continue
                     libs.append(add_libprefix(name.format(**libformatdata)) + libsuffix)
@@ -1368,6 +1420,11 @@ def filter_transform_module_libraries(names):
                     continue
 
                 module_libraries = filter_transform_module_libraries(self._dependencies["libs"][module])
+
+                # Don't create components for modules that should have libraries, but don't have (because of filter)
+                if self._dependencies["libs"][module] and not module_libraries:
+                    continue
+
                 all_expected_libraries = all_expected_libraries.union(module_libraries)
                 if set(module_libraries).difference(all_detected_libraries):
                     incomplete_components.append(module)
@@ -1380,9 +1437,6 @@ def filter_transform_module_libraries(names):
                 self.cpp_info.components[module].names["pkg_config"] = "boost_{}".format(module)
 
                 for requirement in self._dependencies.get("requirements", {}).get(module, []):
-                    if requirement == "backtrace":
-                        # FIXME: backtrace not (yet) available in cci
-                        continue
                     if self.options.get_safe(requirement, None) == False:
                         continue
                     conan_requirement = self._option_to_conan_requirement(requirement)
@@ -1392,8 +1446,9 @@ def filter_transform_module_libraries(names):
                         if requirement != self.options.i18n_backend:
                             continue
                     self.cpp_info.components[module].requires.append("{0}::{0}".format(conan_requirement))
+
             for incomplete_component in incomplete_components:
-                self.output.warn("Boost component '{0}' is missing libraries. Try building boost with '-o boost:without_{0}'.".format(incomplete_component))
+                self.output.warn("Boost component '{0}' is missing libraries. Try building boost with '-o boost:without_{0}'. (Option is not guaranteed to exist)".format(incomplete_component))
 
             non_used = all_detected_libraries.difference(all_expected_libraries)
             if non_used:
@@ -1403,6 +1458,33 @@ def filter_transform_module_libraries(names):
             if non_built:
                 raise ConanException("These libraries were expected to be built, but were not built: {}".format(non_built))
 
+            if not self.options.without_stacktrace:
+                if self.settings.os in ("Linux", "FreeBSD"):
+                    self.cpp_info.components["stacktrace_basic"].system_libs.append("dl")
+                    self.cpp_info.components["stacktrace_addr2line"].system_libs.append("dl")
+                    if self._with_stacktrace_backtrace:
+                        self.cpp_info.components["stacktrace_backtrace"].system_libs.append("dl")
+
+                if self._stacktrace_addr2line_available:
+                    self.cpp_info.components["stacktrace_addr2line"].defines.extend([
+                        "BOOST_STACKTRACE_ADDR2LINE_LOCATION=\"{}\"".format(self.options.addr2line_location),
+                        "BOOST_STACKTRACE_USE_ADDR2LINE",
+                    ])
+
+                if self._with_stacktrace_backtrace:
+                    self.cpp_info.components["stacktrace_backtrace"].defines.append("BOOST_STACKTRACE_USE_BACKTRACE")
+                    self.cpp_info.components["stacktrace_backtrace"].system_libs.append("dl")
+                    self.cpp_info.components["stacktrace_backtrace"].requires.extend([
+                        "libunwind::libunwind",
+                        "libbacktrace::libbacktrace",
+                    ])
+
+                self.cpp_info.components["stacktrace_noop"].defines.append("BOOST_STACKTRACE_USE_NOOP")
+
+                if self.settings.os == "Windows":
+                    self.cpp_info.components["stacktrace_windb"].defines.append("BOOST_STACKTRACE_USE_WINDBG")
+                    self.cpp_info.components["stacktrace_windb_cached"].defines.append("BOOST_STACKTRACE_USE_WINDBG_CACHED")
+
             if not self.options.without_python:
                 pyversion = tools.Version(self._python_version)
                 self.cpp_info.components["python{}{}".format(pyversion.major, pyversion.minor)].requires = ["python"]
@@ -1438,3 +1520,4 @@ def filter_transform_module_libraries(names):
                     self.cpp_info.components["headers"].defines.extend(["BOOST_AC_USE_PTHREADS", "BOOST_SP_USE_PTHREADS"])
                 else:
                     self.cpp_info.components["headers"].defines.extend(["BOOST_AC_DISABLE_THREADS", "BOOST_SP_DISABLE_THREADS"])
+        self.user_info.stacktrace_addr2line_available = self._stacktrace_addr2line_available


Test patch:
diff --git a/recipes/boost/all/test_package/CMakeLists.txt b/recipes/boost/all/test_package/CMakeLists.txt
--- a/recipes/boost/all/test_package/CMakeLists.txt
+++ b/recipes/boost/all/test_package/CMakeLists.txt
@@ -62,6 +62,43 @@ if(NOT HEADER_ONLY)
         target_link_libraries(locale_exe PRIVATE Boost::locale)
     endif()
 
+    if(WITH_STACKTRACE_ADDR2LINE)
+        find_package(Boost COMPONENTS stacktrace REQUIRED)
+        add_executable(stacktrace_addr2line_exe stacktrace.cpp)
+        target_compile_definitions(stacktrace_addr2line_exe PRIVATE TEST_STACKTRACE_IMPL=1)
+        target_link_libraries(stacktrace_addr2line_exe PRIVATE Boost::stacktrace_addr2line)
+    endif()
+
+    if(WITH_STACKTRACE_BACKTRACE)
+        add_executable(stacktrace_backtrace_exe stacktrace.cpp)
+        target_compile_definitions(stacktrace_backtrace_exe PRIVATE TEST_STACKTRACE_IMPL=2)
+        target_link_libraries(stacktrace_backtrace_exe PRIVATE Boost::stacktrace_backtrace)
+    endif()
+
+    if(WITH_STACKTRACE)
+        find_package(Boost COMPONENTS stacktrace REQUIRED)
+
+        if(NOT MSVC)
+            add_executable(stacktrace_basic_exe stacktrace.cpp)
+            target_compile_definitions(stacktrace_basic_exe PRIVATE TEST_STACKTRACE_IMPL=3)
+            target_link_libraries(stacktrace_basic_exe PRIVATE Boost::stacktrace_basic)
+        endif()
+
+            add_executable(stacktrace_noop_exe stacktrace.cpp)
+            target_compile_definitions(stacktrace_noop_exe PRIVATE TEST_STACKTRACE_IMPL=4)
+            target_link_libraries(stacktrace_noop_exe PRIVATE Boost::stacktrace_noop)
+
+        if(WIN32)
+            add_executable(stacktrace_windbg_exe stacktrace.cpp)
+            target_compile_definitions(stacktrace_windbg_exe PRIVATE TEST_STACKTRACE_IMPL=5)
+            target_link_libraries(stacktrace_windbg_exe PRIVATE Boost::stacktrace_windbg)
+
+            add_executable(stacktrace_windbg_cached_exe stacktrace.cpp)
+            target_compile_definitions(stacktrace_windbg_cached_exe PRIVATE TEST_STACKTRACE_IMPL=6)
+            target_link_libraries(stacktrace_windbg_cached_exe PRIVATE Boost::stacktrace_windbg_cached)
+        endif()
+    endif()
+
     if(WITH_PYTHON)
         find_package(Boost COMPONENTS python REQUIRED)
         add_library(hello_ext MODULE python.cpp)
diff --git a/recipes/boost/all/test_package/conanfile.py b/recipes/boost/all/test_package/conanfile.py
--- a/recipes/boost/all/test_package/conanfile.py
+++ b/recipes/boost/all/test_package/conanfile.py
@@ -34,7 +34,12 @@ def build(self):
             cmake.definitions["WITH_LOCALE"] = not self.options["boost"].without_locale
             cmake.definitions["WITH_NOWIDE"] = not self._boost_option("without_nowide", True)
             cmake.definitions["WITH_JSON"] = not self._boost_option("without_json", True)
+            cmake.definitions["WITH_STACKTRACE"] = not self.options["boost"].without_stacktrace
+            cmake.definitions["WITH_STACKTRACE_ADDR2LINE"] = self.deps_user_info["boost"].stacktrace_addr2line_available
+            cmake.definitions["WITH_STACKTRACE_BACKTRACE"] = self._boost_option("with_stacktrace_backtrace", False)
             cmake.configure()
+            # Disable parallel builds because c3i (=conan-center's test/build infrastructure) seems to choke here
+            cmake.parallel = False
             cmake.build()
 
     def test(self):
@@ -65,3 +70,14 @@ def test(self):
             with tools.environment_append({"PYTHONPATH": "{}:{}".format("bin", "lib")}):
                 self.run("{} {}".format(self.options["boost"].python_executable, os.path.join(self.source_folder, "python.py")), run_environment=True)
             self.run(os.path.join("bin", "numpy_exe"), run_environment=True)
+        if not self.options["boost"].without_stacktrace:
+            if self.settings.compiler != "Visual Studio":
+                self.run(os.path.join("bin", "stacktrace_basic_exe"), run_environment=True)
+            self.run(os.path.join("bin", "stacktrace_noop_exe"), run_environment=True)
+            if str(self.deps_user_info["boost"].stacktrace_addr2line_available) == "True":
+                self.run(os.path.join("bin", "stacktrace_addr2line_exe"), run_environment=True)
+            if self.settings.os == "Windows":
+                self.run(os.path.join("bin", "stacktrace_windbg_exe"), run_environment=True)
+                self.run(os.path.join("bin", "stacktrace_windbg_cached_exe"), run_environment=True)
+            if self._boost_option("with_stacktrace_backtrace", False):
+                self.run(os.path.join("bin", "stacktrace_backtrace_exe"), run_environment=True)
diff --git a/recipes/boost/all/test_package/stacktrace.cpp b/recipes/boost/all/test_package/stacktrace.cpp
new file mode 100644
--- /dev/null
+++ b/recipes/boost/all/test_package/stacktrace.cpp
@@ -0,0 +1,78 @@
+#include <boost/stacktrace.hpp>
+
+#include <iostream>
+
+void f3() {
+    std::cout << "==start stacktrace==\n" << boost::stacktrace::stacktrace() << "==end stacktrace==\n";
+}
+
+void f2() {
+    f3();
+}
+
+void f1() {
+    f2();
+}
+
+#define TEST_STACKTRACE_ADDR2LINE 1
+#define TEST_STACKTRACE_BACKTRACE 2
+#define TEST_STACKTRACE_BASIC 3
+#define TEST_STACKTRACE_NOOP 4
+#define TEST_STACKTRACE_WINDBG 5
+#define TEST_STACKTRACE_WINDBG_CACHED 6
+
+static const char *stacktrace_impls[] = {
+    "addr2line",
+    "backtrace",
+    "basic",
+    "noop",
+    "windbg",
+    "windbg_cached",
+};
+
+int main() {
+    int res = 0;
+
+#if !defined TEST_STACKTRACE_IMPL
+    std::cerr << "TEST_STACKTRACE_IMPL not defined!\n";
+    res = 1;
+#else
+    std::cerr << "Testing stacktrace_" << stacktrace_impls[TEST_STACKTRACE_IMPL-1] << "...\n";
+#   if defined(BOOST_STACKTRACE_USE_ADDR2LINE)
+#       if TEST_STACKTRACE_IMPL != TEST_STACKTRACE_ADDR2LINE
+            std::cerr << "BOOST_STACKTRACE_USE_ADDR2LINE defined but not testing stacktrace_addr2line\n";
+            res = 1;
+#       endif
+#       if !defined(BOOST_STACKTRACE_ADDR2LINE_LOCATION)
+            std::cerr << "error: BOOST_STACKTRACE_ADDR2LINE_LOCATION not defined\n";
+            res = 1;
+#       endif
+#   endif
+#   if defined(BOOST_STACKTRACE_USE_BACKTRACE)
+#       if TEST_STACKTRACE_IMPL != TEST_STACKTRACE_BACKTRACE
+            std::cerr << "BOOST_STACKTRACE_USE_BACKTRACE defined but not testing stacktrace_backtrace\n";
+            res = 1;
+#       endif
+#   endif
+#   if defined(BOOST_STACKTRACE_USE_NOOP)
+#       if TEST_STACKTRACE_IMPL != TEST_STACKTRACE_NOOP
+            std::cerr << "BOOST_STACKTRACE_USE_NOOP defined but not testing stacktrace_noop\n";
+            res = 1;
+#       endif
+#   endif
+#   if defined(BOOST_STACKTRACE_USE_WINDBG)
+#       if TEST_STACKTRACE_IMPL != TEST_STACKTRACE_WINDBG
+            std::cerr << "BOOST_STACKTRACE_USE_WINDBG defined but not testing stacktrace_windbg\n";
+            res = 1;
+#       endif
+#   endif
+#   if defined(BOOST_STACKTRACE_USE_WINDBG_CACHED)
+#       if TEST_STACKTRACE_IMPL != TEST_STACKTRACE_WINDBG_CACHED
+            std::cerr << "BOOST_STACKTRACE_USE_WINDBG_CACHED defined but not testing stacktrace_windbg_cached\n";
+            res = 1;
+#       endif
+#   endif
+#endif
+    f1();
+    return res;
+}