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

gtest: Add support for Conan V2 #12326

Merged
merged 11 commits into from
Aug 26, 2022
13 changes: 0 additions & 13 deletions recipes/gtest/all/CMakeLists.txt

This file was deleted.

5 changes: 0 additions & 5 deletions recipes/gtest/all/conandata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,10 @@ sources:
patches:
"1.11.0":
- patch_file: "patches/gtest-1.11.0.patch"
base_path: "source_subfolder"
"cci.20210126":
- patch_file: "patches/gtest-1.10.0.patch"
base_path: "source_subfolder"
"1.10.0":
- patch_file: "patches/gtest-1.10.0.patch"
base_path: "source_subfolder"
- patch_file: "patches/gtest-1.10.0-override.patch"
base_path: "source_subfolder"
"1.8.1":
- patch_file: "patches/gtest-1.8.1.patch"
base_path: "source_subfolder"
111 changes: 56 additions & 55 deletions recipes/gtest/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from conan.tools.microsoft import is_msvc, msvc_runtime_flag
from conans import ConanFile, CMake, tools
from conans.errors import ConanInvalidConfiguration
import os
import functools

required_conan_version = ">=1.45.0"
from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.build import check_min_cppstd
from conan.tools.files import apply_conandata_patches, copy, get, replace_in_file, rm, rmdir
from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain
from conan.tools.microsoft import is_msvc, msvc_runtime_flag, check_min_vs
from conan.tools.scm import Version

required_conan_version = ">=1.50.0"


class GTestConan(ConanFile):
Expand All @@ -14,14 +18,13 @@ class GTestConan(ConanFile):
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/google/googletest"
topics = ("testing", "google-testing", "unit-test")

settings = "os", "arch", "compiler", "build_type"
options = {
"shared": [True, False],
"build_gmock": [True, False],
"fPIC": [True, False],
"no_main": [True, False],
"debug_postfix": "ANY",
"debug_postfix": ["ANY"],
"hide_symbols": [True, False],
}
default_options = {
Expand All @@ -33,16 +36,6 @@ class GTestConan(ConanFile):
"hide_symbols": False,
}

generators = "cmake"

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

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

@property
def _minimum_cpp_standard(self):
if self.version == "1.8.1":
Expand Down Expand Up @@ -76,9 +69,8 @@ def _is_clang_cl(self):
return self.settings.os == "Windows" and self.settings.compiler == "clang"

def export_sources(self):
self.copy("CMakeLists.txt")
for patch in self.conan_data.get("patches", {}).get(self.version, []):
self.copy(patch["patch_file"])
copy(self, patch["patch_file"], self.recipe_folder, self.export_sources_folder)

def config_options(self):
if self.settings.os == "Windows":
Expand All @@ -101,7 +93,7 @@ def validate(self):
)

if self.settings.compiler.get_safe("cppstd"):
tools.check_min_cppstd(self, self._minimum_cpp_standard)
check_min_cppstd(self, self._minimum_cpp_standard)

def loose_lt_semver(v1, v2):
lv1 = [int(v) for v in v1.split(".")]
Expand All @@ -112,57 +104,65 @@ def loose_lt_semver(v1, v2):
min_version = self._minimum_compilers_version.get(str(self.settings.compiler))
if min_version and loose_lt_semver(str(self.settings.compiler.version), min_version):
raise ConanInvalidConfiguration(
"{0} requires {1} {2}. The current compiler is {1} {3}.".format(
self.name, self.settings.compiler,
min_version, self.settings.compiler.version
)
f"{self.name} requires {self.settings.compiler} {min_version}. The current compiler is {self.settings.compiler} {self.settings.compiler.version}."
)

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

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

def _patch_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
tools.patch(**patch)
apply_conandata_patches(self)
# No warnings as errors
internal_utils = os.path.join(self._source_subfolder, "googletest",
internal_utils = os.path.join(self.source_folder, "googletest",
"cmake", "internal_utils.cmake")
tools.replace_in_file(internal_utils, "-WX", "")
if self.version == "cci.20210126" or tools.Version(self.version) < "1.12.0":
tools.replace_in_file(internal_utils, "-Werror", "")
replace_in_file(self, internal_utils, "-WX", "")
if self.version == "cci.20210126" or Version(self.version) < "1.12.0":
replace_in_file(self, internal_utils, "-Werror", "")

@functools.lru_cache(1)
def _configure_cmake(self):
cmake = CMake(self)
def generate(self):
tc = CMakeToolchain(self)

# Honor BUILD_SHARED_LIBS from conan_toolchain (see https://github.com/conan-io/conan/issues/11840)
tc.cache_variables["CMAKE_POLICY_DEFAULT_CMP0077"] = "NEW"

if self.settings.build_type == "Debug":
cmake.definitions["CUSTOM_DEBUG_POSTFIX"] = self.options.debug_postfix
tc.cache_variables["CUSTOM_DEBUG_POSTFIX"] = str(self.options.debug_postfix)
jwillikers marked this conversation as resolved.
Show resolved Hide resolved
if is_msvc(self) or self._is_clang_cl:
cmake.definitions["gtest_force_shared_crt"] = "MD" in msvc_runtime_flag(self)
cmake.definitions["BUILD_GMOCK"] = self.options.build_gmock
tc.cache_variables["gtest_force_shared_crt"] = "MD" in msvc_runtime_flag(self)
jwillikers marked this conversation as resolved.
Show resolved Hide resolved

try:
check_min_vs(self, "191")
except ConanInvalidConfiguration:
tc.preprocessor_definitions["GTEST_LANG_CXX11"] = 1
tc.preprocessor_definitions["GTEST_HAS_TR1_TUPLE"] = 0

tc.cache_variables["BUILD_GMOCK"] = bool(self.options.build_gmock)
jwillikers marked this conversation as resolved.
Show resolved Hide resolved
if self.settings.os == "Windows" and self.settings.compiler == "gcc":
cmake.definitions["gtest_disable_pthreads"] = True
cmake.definitions["gtest_hide_internal_symbols"] = self.options.hide_symbols
cmake.configure(build_folder=self._build_subfolder)
return cmake
tc.cache_variables["gtest_disable_pthreads"] = True
tc.cache_variables["gtest_hide_internal_symbols"] = bool(self.options.hide_symbols)
jwillikers marked this conversation as resolved.
Show resolved Hide resolved
tc.generate()

def build(self):
self._patch_sources()
cmake = self._configure_cmake()
cmake = CMake(self)
cmake.configure()
cmake.build()

def package(self):
self.copy("LICENSE", dst="licenses", src=self._source_subfolder)
cmake = self._configure_cmake()
copy(self, "LICENSE", self.source_folder, os.path.join(self.package_folder, "licenses"))
cmake = CMake(self)
cmake.install()
tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))
tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
tools.remove_files_by_mask(os.path.join(self.package_folder, "lib"), "*.pdb")
rmdir(self, os.path.join(self.package_folder, "lib", "pkgconfig"))
rmdir(self, os.path.join(self.package_folder, "lib", "cmake"))
rm(self, "*.pdb", os.path.join(self.package_folder, "lib"))

@property
def _postfix(self):
# In 1.12.0, gtest remove debug postfix.
if self.version != "cci.20210126" and tools.Version(self.version) >= "1.12.0":
if self.version != "cci.20210126" and Version(self.version) >= "1.12.0":
return ""
return self.options.debug_postfix if self.settings.build_type == "Debug" else ""

Expand All @@ -174,16 +174,17 @@ def package_info(self):
self.cpp_info.components["libgtest"].set_property("cmake_target_name", "GTest::gtest")
self.cpp_info.components["libgtest"].set_property("cmake_target_aliases", ["GTest::GTest"])
self.cpp_info.components["libgtest"].set_property("pkg_config_name", "gtest")
self.cpp_info.components["libgtest"].libs = ["gtest{}".format(self._postfix)]
self.cpp_info.components["libgtest"].libs = [f"gtest{self._postfix}"]
if self.settings.os in ["Linux", "FreeBSD"]:
self.cpp_info.components["libgtest"].system_libs.append("m")
self.cpp_info.components["libgtest"].system_libs.append("pthread")
if self.settings.os == "Neutrino" and self.settings.os.version == "7.1":
self.cpp_info.components["libgtest"].system_libs.append("regex")
if self.options.shared:
self.cpp_info.components["libgtest"].defines.append("GTEST_LINKED_AS_SHARED_LIBRARY=1")
if self.version == "1.8.1":
if (self.settings.compiler == "Visual Studio" and tools.Version(self.settings.compiler.version) >= "15") or \
(str(self.settings.compiler) == "msvc" and tools.Version(self.settings.compiler.version) >= "191"):
if (self.settings.compiler == "Visual Studio" and Version(self.settings.compiler.version) >= "15") or \
(str(self.settings.compiler) == "msvc" and Version(self.settings.compiler.version) >= "191"):
self.cpp_info.components["libgtest"].defines.append("GTEST_LANG_CXX11=1")
self.cpp_info.components["libgtest"].defines.append("GTEST_HAS_TR1_TUPLE=0")

Expand All @@ -192,21 +193,21 @@ def package_info(self):
self.cpp_info.components["gtest_main"].set_property("cmake_target_name", "GTest::gtest_main")
self.cpp_info.components["gtest_main"].set_property("cmake_target_aliases", ["GTest::Main"])
self.cpp_info.components["gtest_main"].set_property("pkg_config_name", "gtest_main")
self.cpp_info.components["gtest_main"].libs = ["gtest_main{}".format(self._postfix)]
self.cpp_info.components["gtest_main"].libs = [f"gtest_main{self._postfix}"]
self.cpp_info.components["gtest_main"].requires = ["libgtest"]

# gmock
if self.options.build_gmock:
self.cpp_info.components["gmock"].set_property("cmake_target_name", "GTest::gmock")
self.cpp_info.components["gmock"].set_property("pkg_config_name", "gmock")
self.cpp_info.components["gmock"].libs = ["gmock{}".format(self._postfix)]
self.cpp_info.components["gmock"].libs = [f"gmock{self._postfix}"]
self.cpp_info.components["gmock"].requires = ["libgtest"]

# gmock_main
if not self.options.no_main:
self.cpp_info.components["gmock_main"].set_property("cmake_target_name", "GTest::gmock_main")
self.cpp_info.components["gmock_main"].set_property("pkg_config_name", "gmock_main")
self.cpp_info.components["gmock_main"].libs = ["gmock_main{}".format(self._postfix)]
self.cpp_info.components["gmock_main"].libs = [f"gmock_main{self._postfix}"]
self.cpp_info.components["gmock_main"].requires = ["gmock"]

# TODO: to remove in conan v2 once cmake_find_package_* generators removed
Expand Down
5 changes: 1 addition & 4 deletions recipes/gtest/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
cmake_minimum_required(VERSION 3.1.2)
cmake_minimum_required(VERSION 3.15)
project(test_package CXX)

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

find_package(GTest REQUIRED)

if(WITH_MAIN)
Expand Down
35 changes: 27 additions & 8 deletions recipes/gtest/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
from conans import ConanFile, CMake, tools
import os

from conan import ConanFile
from conan.tools.build import can_run
from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain


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

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

def layout(self):
cmake_layout(self)

def generate(self):
tc = CMakeToolchain(self)

with_gmock = bool(self.dependencies[self.tested_reference_str].options.build_gmock)
tc.cache_variables['WITH_GMOCK'] = with_gmock
tc.preprocessor_definitions['WITH_GMOCK'] = 1 if with_gmock else 0

with_main = not self.dependencies[self.tested_reference_str].options.no_main
tc.cache_variables['WITH_MAIN'] = with_main
tc.preprocessor_definitions['WITH_MAIN'] = 1 if with_main else 0

tc.generate()

def build(self):
cmake = CMake(self)
cmake.definitions['WITH_GMOCK'] = self.options['gtest'].build_gmock
cmake.definitions['WITH_MAIN'] = not self.options['gtest'].no_main
cmake.configure()
cmake.build()

def test(self):
assert os.path.isfile(os.path.join(self.deps_cpp_info["gtest"].rootpath, "licenses", "LICENSE"))
if not tools.cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)
if can_run(self):
bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package")
self.run(bin_path, env="conanrun")
30 changes: 30 additions & 0 deletions recipes/gtest/all/test_v1_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.1.2)
project(test_package CXX)

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

find_package(GTest REQUIRED)

if(WITH_MAIN)
add_executable(${PROJECT_NAME} ../test_package/test_package.cpp)
else()
add_executable(${PROJECT_NAME} ../test_package/main.cpp ../test_package/test_package.cpp)
endif()

if(WITH_MAIN)
target_link_libraries(${PROJECT_NAME} GTest::gtest GTest::gtest_main)
if(WITH_GMOCK)
target_link_libraries(${PROJECT_NAME} GTest::gmock GTest::gmock_main)
endif()
else()
target_link_libraries(${PROJECT_NAME} GTest::gtest)
if(WITH_GMOCK)
target_link_libraries(${PROJECT_NAME} GTest::gmock)
endif()
endif()

set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)
if(WITH_GMOCK)
target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_GMOCK)
endif()
22 changes: 22 additions & 0 deletions recipes/gtest/all/test_v1_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os

from conan.tools.build import cross_building
from conans import ConanFile, CMake


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

def build(self):
cmake = CMake(self)
cmake.definitions['WITH_GMOCK'] = self.options['gtest'].build_gmock
cmake.definitions['WITH_MAIN'] = not self.options['gtest'].no_main
cmake.configure()
cmake.build()

def test(self):
assert os.path.isfile(os.path.join(self.deps_cpp_info["gtest"].rootpath, "licenses", "LICENSE"))
if not cross_building(self):
bin_path = os.path.join("bin", "test_package")
self.run(bin_path, run_environment=True)