Skip to content

Commit

Permalink
(conan-io#15105) [boost] Fix issues building with Conan 2 and with py…
Browse files Browse the repository at this point in the history
…thon

* Fix issues with boost in conan 2 (and boost python)

* Fix linker issues with NumPy on Windows

* Use run scope when checking python version
  • Loading branch information
jcar87 authored and AbrilRBS committed Jan 16, 2023
1 parent 74a47ed commit 3908964
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 134 deletions.
47 changes: 26 additions & 21 deletions recipes/boost/all/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def disable_math():
else:
min_compiler_version = self._min_compiler_version_default_cxx11
if min_compiler_version is None:
self.output.warn("Assuming the compiler supports c++11 by default")
self.output.warning("Assuming the compiler supports c++11 by default")
elif Version(self.settings.compiler.version) < min_compiler_version:
disable_math()

Expand All @@ -343,7 +343,7 @@ def disable_wave():
else:
min_compiler_version = self._min_compiler_version_default_cxx11
if min_compiler_version is None:
self.output.warn("Assuming the compiler supports c++11 by default")
self.output.warning("Assuming the compiler supports c++11 by default")
elif Version(self.settings.compiler.version) < min_compiler_version:
disable_wave()

Expand All @@ -365,7 +365,7 @@ def disable_locale():
else:
min_compiler_version = self._min_compiler_version_default_cxx11
if min_compiler_version is None:
self.output.warn("Assuming the compiler supports c++11 by default")
self.output.warning("Assuming the compiler supports c++11 by default")
elif Version(self.settings.compiler.version) < min_compiler_version:
disable_locale()

Expand Down Expand Up @@ -396,7 +396,7 @@ def configure(self):
self.options.rm_safe("fPIC")

if self.options.i18n_backend != "deprecated":
self.output.warn("i18n_backend option is deprecated, do not use anymore.")
self.output.warning("i18n_backend option is deprecated, do not use anymore.")
if self.options.i18n_backend == "iconv":
self.options.i18n_backend_iconv = "libiconv"
self.options.i18n_backend_icu = False
Expand Down Expand Up @@ -539,7 +539,7 @@ def requirements(self):
if self._with_zstd:
self.requires("zstd/1.5.2")
if self._with_stacktrace_backtrace:
self.requires("libbacktrace/cci.20210118")
self.requires("libbacktrace/cci.20210118", transitive_headers=True)

if self._with_icu:
self.requires("icu/72.1")
Expand All @@ -558,8 +558,6 @@ def package_id(self):
del self.info.options.python_executable # PATH to the interpreter is not important, only version matters
if self.info.options.without_python:
del self.info.options.python_version
else:
self.info.options.python_version = self._python_version

def build_requirements(self):
if not self.options.header_only:
Expand Down Expand Up @@ -589,7 +587,7 @@ def _run_python_script(self, script):
command = f'"{self._python_executable}" -c "{script}"'
self.output.info(f"running {command}")
try:
self.run(command=command, output=output)
self.run(command, output, scope="run")
except ConanException:
self.output.info("(failed)")
return None
Expand Down Expand Up @@ -641,7 +639,7 @@ def _get_python_var(self, name):
NOTE: distutils is deprecated and breaks the recipe since Python 3.10
"""
python_version_parts = self.info.options.python_version.split('.')
python_version_parts = str(self.info.options.python_version).split('.')
python_major = int(python_version_parts[0])
python_minor = int(python_version_parts[1])
if(python_major >= 3 and python_minor >= 10):
Expand Down Expand Up @@ -723,9 +721,10 @@ def _python_library_dir(self):
multiarch = self._get_python_var("MULTIARCH")
masd = self._get_python_var("multiarchsubdir")
with_dyld = self._get_python_var("WITH_DYLD")
if libdir and multiarch and masd:
if libdir and multiarch and masd and not libdir.endswith(masd):
if masd.startswith(os.sep):
masd = masd[len(os.sep):]
self.output.warning(f"Python libdir candidate thingy: {libdir}")
libdir = os.path.join(libdir, masd)

if not libdir:
Expand Down Expand Up @@ -770,7 +769,7 @@ def _clean(self):
]
for d in clean_dirs:
if os.path.isdir(d):
self.output.warn(f"removing '{d}'")
self.output.warning(f"removing '{d}'")
shutil.rmtree(d)

@property
Expand All @@ -795,7 +794,7 @@ def _build_bcp(self):
with chdir(self, folder):
command = f"{self._b2_exe} -j{build_jobs(self)} --abbreviate-paths toolset={self._toolset}"
command += f" -d{self.options.debug_level}"
self.output.warn(command)
self.output.warning(command)
self.run(command)

def _run_bcp(self):
Expand All @@ -813,7 +812,7 @@ def _run_bcp(self):
libraries.add(d)
libraries = " ".join(libraries)
command = f"{self._bcp_exe} {namespace} {alias} {boostdir} {libraries} {self._bcp_dir}"
self.output.warn(command)
self.output.warning(command)
self.run(command)

def build(self):
Expand Down Expand Up @@ -846,7 +845,7 @@ def build(self):
strict=False)

if self.options.header_only:
self.output.warn("Header only package, skipping build")
self.output.warning("Header only package, skipping build")
return

self._clean()
Expand All @@ -864,7 +863,7 @@ def build(self):
# -d2 is to print more debug info and avoid travis timing out without output
sources = os.path.join(self.source_folder, self._bcp_dir) if self._use_bcp else self.source_folder
full_command += f' --debug-configuration --build-dir="{self.build_folder}"'
self.output.warn(full_command)
self.output.warning(full_command)

# If sending a user-specified toolset to B2, setting the vcvars
# interferes with the compiler selection.
Expand Down Expand Up @@ -1160,7 +1159,7 @@ def _build_cross_flags(self):
elif arch.startswith("mips"):
pass
else:
self.output.warn(f"Unable to detect the appropriate ABI for {arch} architecture.")
self.output.warning(f"Unable to detect the appropriate ABI for {arch} architecture.")
self.output.info(f"Cross building flags: {flags}")

return flags
Expand Down Expand Up @@ -1201,7 +1200,7 @@ def _cxx(self):

def _create_user_config_jam(self, folder):
"""To help locating the zlib and bzip2 deps"""
self.output.warn("Patching user-config.jam")
self.output.warning("Patching user-config.jam")

contents = ""
if self._zip_bzip2_requires_needed:
Expand Down Expand Up @@ -1284,7 +1283,7 @@ def create_library_config(deps_name, name):

contents += " ;"

self.output.warn(contents)
self.output.warning(contents)
filename = f"{folder}/user-config.jam"
save(self, filename, contents)

Expand Down Expand Up @@ -1394,7 +1393,7 @@ def _create_emscripten_libs(self):
self.package_folder, "lib"
)
if not os.path.exists(staged_libs):
self.output.warn(f"Lib folder doesn't exist, can't collect libraries: {staged_libs}")
self.output.warning(f"Lib folder doesn't exist, can't collect libraries: {staged_libs}")
return
for bc_file in os.listdir(staged_libs):
if bc_file.startswith("lib") and bc_file.endswith(".bc"):
Expand Down Expand Up @@ -1649,11 +1648,15 @@ def filter_transform_module_libraries(names):
self.cpp_info.components[module].names["cmake_find_package_multi"] = module
self.cpp_info.components[module].names["pkg_config"] = f"boost_{module}"

# extract list of names of direct host dependencies to check for dependencies
# of components that exist in other packages
dependencies = [d.ref.name for d, _ in self.dependencies.direct_host.items()]

for requirement in self._dependencies.get("requirements", {}).get(module, []):
if self.options.get_safe(requirement, None) == False:
continue
conan_requirement = self._option_to_conan_requirement(requirement)
if conan_requirement not in self.requires:
if conan_requirement not in dependencies:
continue
if module == "locale" and requirement in ("icu", "iconv"):
if requirement == "icu" and not self._with_icu:
Expand All @@ -1663,7 +1666,7 @@ def filter_transform_module_libraries(names):
self.cpp_info.components[module].requires.append(f"{conan_requirement}::{conan_requirement}")

for incomplete_component in incomplete_components:
self.output.warn(f"Boost component '{incomplete_component}' is missing libraries. Try building boost with '-o boost:without_{incomplete_component}'. (Option is not guaranteed to exist)")
self.output.warning(f"Boost component '{incomplete_component}' is missing libraries. Try building boost with '-o boost:without_{incomplete_component}'. (Option is not guaranteed to exist)")

non_used = all_detected_libraries.difference(all_expected_libraries)
if non_used:
Expand Down Expand Up @@ -1738,4 +1741,6 @@ def filter_transform_module_libraries(names):
self.cpp_info.components["headers"].defines.append("BOOST_SP_USE_SPINLOCK")
else:
self.cpp_info.components["headers"].defines.extend(["BOOST_AC_DISABLE_THREADS", "BOOST_SP_DISABLE_THREADS"])
#TODO: remove in the future, user_info deprecated in conan2, but kept for compatibility while recipe is cross-compatible.
self.user_info.stacktrace_addr2line_available = self._stacktrace_addr2line_available
self.conf_info.define("user.boost:stacktrace_addr2line_available", self._stacktrace_addr2line_available)
33 changes: 26 additions & 7 deletions recipes/boost/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.15)
project(test_package LANGUAGES CXX)

enable_testing()

if(BOOST_NAMESPACE)
add_definitions("-DBOOST_NAMESPACE=${BOOST_NAMESPACE}")
endif()
Expand All @@ -10,70 +12,81 @@ if(NOT HEADER_ONLY)
find_package(Boost COMPONENTS random REQUIRED)
add_executable(random_exe random.cpp)
target_link_libraries(random_exe PRIVATE Boost::random)
add_test(NAME boost_random COMMAND random_exe)
endif()

if(WITH_REGEX)
find_package(Boost COMPONENTS regex REQUIRED)
add_executable(regex_exe regex.cpp)
target_link_libraries(regex_exe PRIVATE Boost::regex)
add_test(NAME boost_regex COMMAND regex_exe)
endif()

if(WITH_TEST)
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
add_executable(test_exe test.cpp)
target_link_libraries(test_exe PRIVATE Boost::unit_test_framework)
add_test(NAME boost_test COMMAND test_exe)
endif()

if(WITH_COROUTINE)
find_package(Boost COMPONENTS coroutine REQUIRED)
add_executable(coroutine_exe coroutine.cpp)
target_link_libraries(coroutine_exe PRIVATE Boost::coroutine)
add_test(NAME coroutine_test COMMAND coroutine_exe)
endif()

if(WITH_CHRONO)
find_package(Boost COMPONENTS chrono REQUIRED)
add_executable(chrono_exe chrono.cpp)
target_link_libraries(chrono_exe PRIVATE Boost::chrono)
add_test(NAME chrono_test COMMAND chrono_exe)
endif()

if(WITH_FIBER)
find_package(Boost COMPONENTS fiber REQUIRED)
add_executable(fiber_exe fiber.cpp)
target_link_libraries(fiber_exe PRIVATE Boost::fiber)
set_property(TARGET fiber_exe PROPERTY CXX_STANDARD 11)
add_test(NAME boost_fiber COMMAND fiber_exe)
endif()

if(WITH_JSON)
find_package(Boost COMPONENTS json REQUIRED)
add_executable(json_exe json.cpp)
target_link_libraries(json_exe PRIVATE Boost::json)
set_property(TARGET json_exe PROPERTY CXX_STANDARD 11)
add_test(NAME boost_json COMMAND json_exe)
endif()

if(WITH_NOWIDE)
find_package(Boost COMPONENTS nowide REQUIRED)
add_executable(nowide_exe nowide.cpp)
target_link_libraries(nowide_exe PRIVATE Boost::nowide)
set_property(TARGET nowide_exe PROPERTY CXX_STANDARD 11)
add_test(NAME boost_nowide COMMAND nowide_exe ${CMAKE_CURRENT_SOURCE_DIR}/conanfile.py)
endif()

if(WITH_LOCALE)
find_package(Boost COMPONENTS locale REQUIRED)
add_executable(locale_exe locale.cpp)
target_link_libraries(locale_exe PRIVATE Boost::locale)
add_test(NAME boost_locale COMMAND locale_exe)
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)
add_test(NAME boost_stacktrace_addr2line COMMAND stacktrace_addr2line_exe)
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)
add_test(NAME boost_stacktrace_backtrace COMMAND stacktrace_backtrace_exe)
endif()

if(WITH_STACKTRACE)
Expand All @@ -82,19 +95,23 @@ if(NOT HEADER_ONLY)
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)
add_test(NAME boost_stacktrace_noop COMMAND stacktrace_noop_exe)

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_test(NAME boost_stacktrace_windbg COMMAND stacktrace_windbg_exe)

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)
add_test(NAME boost_stacktrace_windbg_cached COMMAND stacktrace_windbg_cached_exe)
else()
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)
add_test(NAME boost_stacktrace_basic COMMAND stacktrace_basic_exe)
endif()
endif()

Expand All @@ -103,22 +120,24 @@ if(NOT HEADER_ONLY)
add_library(hello_ext MODULE python.cpp)
set_property(TARGET hello_ext PROPERTY PREFIX "")

find_package(PythonInterp REQUIRED)
find_package(PythonLibs REQUIRED)
find_package(Python ${PYTHON_VERSION_TO_SEARCH} COMPONENTS Interpreter Development NumPy REQUIRED)

target_include_directories(hello_ext PRIVATE ${PYTHON_INCLUDE_DIRS})
target_link_libraries(hello_ext PRIVATE Boost::python${PYTHON_COMPONENT_SUFFIX} ${PYTHON_LIBRARIES})
target_link_libraries(hello_ext PRIVATE Boost::python Python::Python)
if(WIN32)
set_target_properties(hello_ext PROPERTIES SUFFIX ".pyd")
endif()
add_test(NAME boost_python COMMAND Python::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/python.py")
set_property(TEST boost_python PROPERTY ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:hello_ext>")

add_executable(numpy_exe numpy.cpp)
target_include_directories(numpy_exe PRIVATE ${PYTHON_INCLUDE_DIRS})
target_link_libraries(numpy_exe PRIVATE Boost::numpy${PYTHON_COMPONENT_SUFFIX} ${PYTHON_LIBRARIES})
target_link_libraries(numpy_exe PRIVATE Boost::numpy Python::Python Python::NumPy)
add_test(NAME boost_numpy COMMAND numpy_exe)
set_property(TEST boost_numpy PROPERTY ENVIRONMENT "PYTHONPATH=${Python_SITELIB}")
endif()
endif()

# Test header-only target
find_package(Boost REQUIRED)
add_executable(lambda_exe lambda.cpp)
target_link_libraries(lambda_exe PRIVATE Boost::headers)
add_test(NAME boost_boost COMMAND lambda_exe)
Loading

0 comments on commit 3908964

Please sign in to comment.