Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

catch2 (2.x.x): support conan v2 #13794

Merged
merged 19 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions recipes/catch2/2.x.x/CMakeLists.txt

This file was deleted.

127 changes: 62 additions & 65 deletions recipes/catch2/2.x.x/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from conans import ConanFile, CMake, tools
from conans.errors import ConanInvalidConfiguration
import functools
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout
from conan.tools.files import copy, get, rmdir
from conan.tools.scm import Version
import os

required_conan_version = ">=1.43.0"
required_conan_version = ">=1.53.0"


class Catch2Conan(ConanFile):
Expand All @@ -20,7 +22,7 @@ class Catch2Conan(ConanFile):
"with_main": [True, False],
"with_benchmark": [True, False],
"with_prefix": [True, False],
"default_reporter": "ANY",
"default_reporter": [None, "ANY"],
}
default_options = {
"fPIC": True,
Expand All @@ -30,109 +32,104 @@ class Catch2Conan(ConanFile):
"default_reporter": None,
}

exports_sources = "CMakeLists.txt"
generators = "cmake"

@property
def _source_subfolder(self):
return "source_subfolder"

@property
def _build_subfolder(self):
return "build_subfolder"

@property
def _default_reporter_str(self):
return '"{}"'.format(str(self.options.default_reporter).strip('"'))
return str(self.options.default_reporter).strip('"')
prince-chrismc marked this conversation as resolved.
Show resolved Hide resolved

def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC

def configure(self):
if not self.options.with_main:
del self.options.fPIC
del self.options.with_benchmark
self.options.rm_safe("fPIC")
self.options.rm_safe("with_benchmark")

def package_id(self):
if not self.options.with_main:
self.info.header_only()
self.info.clear()

def layout(self):
cmake_layout(self, src_folder="src")

def validate(self):
if tools.Version(self.version) < "2.13.1" and self.settings.arch == "armv8":
raise ConanInvalidConfiguration("ARMv8 is supported by 2.13.1+ only! give up!")
if self.options.with_main and tools.Version(self.version) < "2.13.4":
raise ConanInvalidConfiguration("Option with_main not supported with versions < 2.13.4")
if Version(self.version) < "2.13.1" and self.settings.arch == "armv8":
raise ConanInvalidConfiguration("ARMv8 is not supported by versions < 2.13.1+")
if self.options.with_main and Version(self.version) < "2.13.4":
raise ConanInvalidConfiguration("Option with_main not supported by versions < 2.13.4")

def source(self):
tools.get(**self.conan_data["sources"][self.version], strip_root=True, destination=self._source_subfolder)

@functools.lru_cache(1)
def _configure_cmake(self):
cmake = CMake(self)
cmake.definitions["BUILD_TESTING"] = "OFF"
cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
cmake.definitions["CATCH_INSTALL_HELPERS"] = "ON"
cmake.definitions["CATCH_BUILD_STATIC_LIBRARY"] = self.options.with_main
cmake.definitions["enable_benchmark"] = self.options.get_safe("with_benchmark", False)
prince-chrismc marked this conversation as resolved.
Show resolved Hide resolved
cmake.definitions["CATCH_CONFIG_PREFIX_ALL"] = self.options.with_prefix
get(self, **self.conan_data["sources"][self.version], destination=self.source_folder, strip_root=True)

def generate(self):
tc = CMakeToolchain(self)
tc.variables["BUILD_TESTING"] = False
tc.cache_variables["CATCH_INSTALL_DOCS"] = False # these are cmake options, so use cache_variables
tc.cache_variables["CATCH_INSTALL_HELPERS"] = "ON" # these are cmake options, so use cache_variables
tc.cache_variables["CATCH_BUILD_STATIC_LIBRARY"] = str(self.options.with_main) # these are cmake options, so use cache_variables (str() is required for conan 1.52)
if self.options.with_prefix:
tc.preprocessor_definitions["CATCH_CONFIG_PREFIX_ALL"] = 1
if self.options.get_safe("with_benchmark", False):
tc.preprocessor_definitions["CATCH_CONFIG_ENABLE_BENCHMARKING"] = 1
if self.options.default_reporter:
cmake.definitions["CATCH_CONFIG_DEFAULT_REPORTER"] = self._default_reporter_str

cmake.configure(build_folder=self._build_subfolder)
return cmake
tc.variables["CATCH_CONFIG_DEFAULT_REPORTER"] = self._default_reporter_str
tc.generate()

def build(self):
# Catch2 does skip install if included as subproject:
# https://github.com/catchorg/Catch2/blob/79a5cd795c387e2da58c13e9dcbfd9ea7a2cfb30/CMakeLists.txt#L100-L102
paulharris marked this conversation as resolved.
Show resolved Hide resolved
main_cml = os.path.join(self._source_subfolder, "CMakeLists.txt")
tools.replace_in_file(main_cml, "if (NOT_SUBPROJECT)", "if (TRUE)")
cmake = CMake(self)
cmake.configure()
if self.options.with_main:
cmake = self._configure_cmake()
cmake.build()

def package(self):
self.copy(pattern="LICENSE.txt", dst="licenses", src=self._source_subfolder)
cmake = self._configure_cmake()
copy(self, pattern="LICENSE.txt", dst=os.path.join(self.package_folder, "licenses"), src=self.source_folder)
cmake = CMake(self)
cmake.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
tools.rmdir(os.path.join(self.package_folder, "share"))
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
rmdir(self, os.path.join(self.package_folder, "share"))
for cmake_file in ["ParseAndAddCatchTests.cmake", "Catch.cmake", "CatchAddTests.cmake"]:
self.copy(
copy(self,
cmake_file,
src=os.path.join(self._source_subfolder, "contrib"),
dst=os.path.join("lib", "cmake", "Catch2"),
src=os.path.join(self.source_folder, "contrib"),
dst=os.path.join(self.package_folder, "lib", "cmake", "Catch2"),
)

def package_info(self):
self.cpp_info.set_property("cmake_file_name", "Catch2")
self.cpp_info.set_property("cmake_target_name", "Catch2::Catch2{}".format("WithMain" if self.options.with_main else ""))
self.cpp_info.set_property("pkg_config_name", "catch2".format("-with-main" if self.options.with_main else ""))
self.cpp_info.names["cmake_find_package"] = "Catch2"
self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
self.cpp_info.set_property("pkg_config_name", "catch2{}".format("-with-main" if self.options.with_main else ""))

defines = []
if self.options.get_safe("with_benchmark", False):
defines.append("CATCH_CONFIG_ENABLE_BENCHMARKING")
if self.options.with_prefix:
defines.append("CATCH_CONFIG_PREFIX_ALL")
if self.options.default_reporter:
defines.append(f"CATCH_CONFIG_DEFAULT_REPORTER={self._default_reporter_str}")

if self.options.with_main:
self.cpp_info.components["_catch2"].set_property("cmake_target_name", "Catch2::Catch2")
self.cpp_info.components["_catch2"].set_property("pkg_config_name", "catch2")
self.cpp_info.components["_catch2"].names["cmake_find_package"] = "Catch2"
self.cpp_info.components["_catch2"].names["cmake_find_package_multi"] = "Catch2"
self.cpp_info.components["_catch2"].defines = defines

self.cpp_info.components["catch2_with_main"].builddirs = [os.path.join("lib", "cmake", "Catch2")]
self.cpp_info.components["catch2_with_main"].builddirs.append(os.path.join("lib", "cmake", "Catch2"))
self.cpp_info.components["catch2_with_main"].libs = ["Catch2WithMain"]
self.cpp_info.components["catch2_with_main"].system_libs = ["log"] if self.settings.os == "Android" else []
self.cpp_info.components["catch2_with_main"].set_property("cmake_target_name", "Catch2::Catch2WithMain")
self.cpp_info.components["catch2_with_main"].set_property("pkg_config_name", "catch2-with-main")
self.cpp_info.components["catch2_with_main"].names["cmake_find_package"] = "Catch2WithMain"
self.cpp_info.components["catch2_with_main"].names["cmake_find_package_multi"] = "Catch2WithMain"
defines = self.cpp_info.components["catch2_with_main"].defines
self.cpp_info.components["catch2_with_main"].defines = defines
else:
self.cpp_info.builddirs = [os.path.join("lib", "cmake", "Catch2")]
self.cpp_info.system_libs = ["log"] if self.settings.os == "Android" else []
defines = self.cpp_info.defines
self.cpp_info.defines = defines

if self.options.get_safe("with_benchmark", False):
defines.append("CATCH_CONFIG_ENABLE_BENCHMARKING")
if self.options.with_prefix:
defines.append("CATCH_CONFIG_PREFIX_ALL")
if self.options.default_reporter:
defines.append("CATCH_CONFIG_DEFAULT_REPORTER={}".format(self._default_reporter_str))
# TODO: to remove in conan v2 once legacy generators removed
self.cpp_info.names["cmake_find_package"] = "Catch2"
self.cpp_info.names["cmake_find_package_multi"] = "Catch2"
if self.options.with_main:
self.cpp_info.components["_catch2"].names["cmake_find_package"] = "Catch2"
self.cpp_info.components["_catch2"].names["cmake_find_package_multi"] = "Catch2"
self.cpp_info.components["catch2_with_main"].names["cmake_find_package"] = "Catch2WithMain"
self.cpp_info.components["catch2_with_main"].names["cmake_find_package_multi"] = "Catch2WithMain"
17 changes: 8 additions & 9 deletions recipes/catch2/2.x.x/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
cmake_minimum_required(VERSION 3.5)
project(test_package)
cmake_minimum_required(VERSION 3.8)
project(test_package LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

find_package(Catch2 REQUIRED)
find_package(Catch2 REQUIRED CONFIG)

if(NOT WITH_PREFIX)
add_executable(test_package 000-CatchMain.cpp 100-Fix-Section.cpp)
target_link_libraries(test_package PRIVATE Catch2::Catch2)
target_compile_features(test_package PRIVATE cxx_std_11)

if(WITH_MAIN)
add_executable(standalone 200-standalone.cpp)
target_link_libraries(standalone PRIVATE Catch2::Catch2WithMain)
target_compile_features(standalone PRIVATE cxx_std_11)
if(WITH_BENCHMARK)
add_executable(benchmark 300-benchmark.cpp)
target_link_libraries(benchmark PRIVATE Catch2::Catch2WithMain)
target_compile_features(benchmark PRIVATE cxx_std_11)
endif()
endif()
else()
add_executable(test_package 000-CatchMain.cpp 400-with-prefix.cpp)
target_link_libraries(test_package PRIVATE Catch2::Catch2)
target_compile_features(test_package PRIVATE cxx_std_11)

if(WITH_MAIN)
add_executable(standalone 400-with-prefix.cpp)
target_link_libraries(standalone PRIVATE Catch2::Catch2WithMain)
target_compile_features(standalone PRIVATE cxx_std_11)
endif()
endif()
45 changes: 32 additions & 13 deletions recipes/catch2/2.x.x/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,43 @@
from conans import ConanFile, CMake, tools
from conans.tools import Version
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain
from conan.tools.build import can_run
from conan.tools.cmake import cmake_layout
import os


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake", "cmake_find_package"
generators = "CMakeDeps", "VirtualRunEnv"
test_type = "explicit"

_tests_todo = []

def requirements(self):
self.requires(self.tested_reference_str)

def generate(self):
tc = CMakeToolchain(self)
catch_opts = self.dependencies[self.tested_reference_str].options
tc.variables["WITH_PREFIX"] = catch_opts.with_prefix
tc.variables["WITH_MAIN"] = catch_opts.with_main
tc.variables["WITH_BENCHMARK"] = not catch_opts.with_prefix and catch_opts.with_main and catch_opts.with_benchmark
tc.generate()

# note: this is required as self.dependencies is not available in test()
self._tests_todo.append("test_package")
if catch_opts.with_main:
self._tests_todo.append("standalone")
if not catch_opts.with_prefix and catch_opts.with_main and catch_opts.with_benchmark:
self._tests_todo.append("benchmark")
Comment on lines +30 to +35
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# note: this is required as self.dependencies is not available in test()
self._tests_todo.append("test_package")
if catch_opts.with_main:
self._tests_todo.append("standalone")
if not catch_opts.with_prefix and catch_opts.with_main and catch_opts.with_benchmark:
self._tests_todo.append("benchmark")
# note: this is required as self.dependencies is not available in test()
self._tests_todo.append("test_package")
if catch_opts.with_main:
self._tests_todo.append("standalone")
if not catch_opts.with_prefix and catch_opts.with_main and catch_opts.with_benchmark:
self._tests_todo.append("benchmark")

It does not work. Conan parse twice the recipe folder and _tests_todo will be empty as soon as test() is called.

You can create a temporary file and and those values. More information: conan-io/conan#12411

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this in 332eb40

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cherry-picked your commit and fixed it up slightly


def layout(self):
cmake_layout(self)

def build(self):
cmake = CMake(self)
cmake.definitions["WITH_MAIN"] = self.options["catch2"].with_main
cmake.definitions["WITH_BENCHMARK"] = self.options["catch2"].with_main and self.options["catch2"].with_benchmark
cmake.definitions["WITH_PREFIX"] = self.options["catch2"].with_prefix
cmake.configure()
cmake.build()

def test(self):
if not tools.cross_building(self.settings):
self.run(os.path.join("bin", "test_package"), run_environment=True)
if self.options["catch2"].with_main:
self.run(os.path.join("bin", "standalone"), run_environment=True)
if self.options["catch2"].with_benchmark:
self.run(os.path.join("bin", "benchmark"), run_environment=True)
if can_run(self):
for test_name in self._tests_todo:
self.run(os.path.join(self.cpp.build.bindirs[0], test_name), env="conanrun")
14 changes: 7 additions & 7 deletions recipes/catch2/3.x.x/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from conan.tools.scm import Version
import os

required_conan_version = ">=1.52.0"
required_conan_version = ">=1.53.0"


class Catch2Conan(ConanFile):
Expand Down Expand Up @@ -46,7 +46,7 @@ def _compilers_minimum_version(self):

@property
def _default_reporter_str(self):
return '"{}"'.format(str(self.options.default_reporter).strip('"'))
return str(self.options.default_reporter).strip('"')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SpaceIm as noted in main comment - please check this too


def export_sources(self):
export_conandata_patches(self)
Expand All @@ -57,10 +57,7 @@ def config_options(self):

def configure(self):
if self.options.shared:
try:
del self.options.fPIC
except Exception:
pass
self.options.rm_safe("fPIC")

def layout(self):
cmake_layout(self, src_folder="src")
Expand Down Expand Up @@ -124,11 +121,14 @@ def package_info(self):
self.cpp_info.components["catch2_with_main"].system_libs = ["log"] if self.settings.os == "Android" else []
self.cpp_info.components["catch2_with_main"].set_property("cmake_target_name", "Catch2::Catch2WithMain")
self.cpp_info.components["catch2_with_main"].set_property("pkg_config_name", "catch2-with-main")
defines = self.cpp_info.components["catch2_with_main"].defines
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["catch2_with_main"].system_libs.append("m")
defines = []
if self.options.with_prefix:
defines.append("CATCH_CONFIG_PREFIX_ALL")
if self.options.default_reporter:
defines.append(f"CATCH_CONFIG_DEFAULT_REPORTER={self._default_reporter_str}")
self.cpp_info.components["catch2_with_main"].defines = defines

# TODO: to remove in conan v2 once legacy generators removed
self.cpp_info.names["cmake_find_package"] = "Catch2"
Expand Down