Skip to content

Commit

Permalink
(conan-io#15450) googleapis: use modern CMake integrations
Browse files Browse the repository at this point in the history
* googleapis: use modern CMake integrations

* Add package_type attribute

* Fix applying patches

* google-apis: modernise test package

* googleapis: use resdirs in components and use shorten cmake target names when building

* Apply conandata patches
  • Loading branch information
jcar87 authored and StellaSmith committed Feb 2, 2023
1 parent d91f1fd commit 26ac6c1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 45 deletions.
3 changes: 0 additions & 3 deletions recipes/googleapis/all/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ cmake_minimum_required(VERSION 3.20)

project(googleapis)

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

find_package(Protobuf REQUIRED CONFIG)

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
Expand Down
49 changes: 21 additions & 28 deletions recipes/googleapis/all/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,29 @@
import glob
from io import StringIO

from conans import CMake, tools

from conan import ConanFile
from conan.tools.files import get, copy
from conan.errors import ConanInvalidConfiguration
from conan.tools.build import check_min_cppstd
from conan.tools.cmake import cmake_layout, CMake
from conan.tools.files import apply_conandata_patches, copy, get, export_conandata_patches, copy
from conan.tools.microsoft import is_msvc
from conan.tools.scm import Version

from conan.errors import ConanInvalidConfiguration

from helpers import parse_proto_libraries

required_conan_version = ">=1.45.0"

required_conan_version = ">=1.50.0"

class GoogleAPIS(ConanFile):
name = "googleapis"
package_type = "library"
description = "Public interface definitions of Google APIs"
license = "Apache-2.0"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/googleapis/googleapis"
topics = "google", "protos", "api"
settings = "os", "arch", "compiler", "build_type"
generators = "cmake", "cmake_find_package_multi"
generators = "CMakeDeps", "CMakeToolchain"
options = {
"shared": [True, False],
"fPIC": [True, False]
Expand All @@ -38,26 +38,27 @@ class GoogleAPIS(ConanFile):
short_paths = True

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, "CMakeLists.txt", src=self.recipe_folder, dst=os.path.join(self.export_sources_folder, "src"))
export_conandata_patches(self)

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

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

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

def configure(self):
if self.options.shared:
del self.options.fPIC
self.options["protobuf"].shared = True

def validate(self):
if self.settings.compiler.cppstd:
tools.check_min_cppstd(self, 11)
check_min_cppstd(self, 11)
if self.settings.compiler == "gcc" and Version(self.settings.compiler.version) <= "5":
raise ConanInvalidConfiguration("Build with GCC 5 fails")

Expand All @@ -81,19 +82,13 @@ def _cmake_new_enough(self):
return True

def requirements(self):
self.requires('protobuf/3.21.4')
self.requires('protobuf/3.21.4', transitive_headers=True)

def build_requirements(self):
self.build_requires('protobuf/3.21.4')
# CMake >= 3.20 is required. There is a proto with dots in the name 'k8s.min.proto' and CMake fails to generate project files
if not self._cmake_new_enough:
self.build_requires('cmake/3.23.2')

@functools.lru_cache(1)
def _configure_cmake(self):
cmake = CMake(self)
cmake.configure()
return cmake
self.build_requires('cmake/3.23.5')

@functools.lru_cache(1)
def _parse_proto_libraries(self):
Expand Down Expand Up @@ -131,13 +126,13 @@ def deactivate_library(key):
# - Inconvenient macro names from usr/include/sys/syslimits.h in some macOS SDKs: GID_MAX
# Patched here: https://github.com/protocolbuffers/protobuf/commit/f138d5de2535eb7dd7c8d0ad5eb16d128ab221fd
# as of 3.21.4 issue still exist
if Version(self.deps_cpp_info["protobuf"].version) <= "3.21.5" and self.settings.os == "Macos" or \
if Version(self.dependencies["protobuf"].ref.version) <= "3.21.5" and self.settings.os == "Macos" or \
self.settings.os == "Android":
deactivate_library("//google/storagetransfer/v1:storagetransfer_proto")
deactivate_library("//google/storagetransfer/v1:storagetransfer_cc_proto")
# - Inconvenient macro names from /usr/include/math.h : DOMAIN
if (self.settings.os == "Linux" and self.settings.compiler == "clang" and self.settings.compiler.libcxx == "libc++") or \
self.settings.compiler in ["Visual Studio", "msvc"]:
is_msvc(self):
deactivate_library("//google/cloud/channel/v1:channel_proto")
deactivate_library("//google/cloud/channel/v1:channel_cc_proto")
# - Inconvenient names for android
Expand All @@ -160,6 +155,7 @@ def deactivate_library(key):
return proto_libraries

def build(self):
apply_conandata_patches(self)
proto_libraries = self._parse_proto_libraries()
# Use a separate file to host the generated code, which is generated in full each time.
# This is safe to call multiple times, for example, if you need to invoke `conan build` more than
Expand All @@ -169,14 +165,10 @@ def build(self):
f.write("# DO NOT EDIT - change the generation code in conanfile.py instead\n")
for it in filter(lambda u: u.is_used, proto_libraries):
f.write(it.cmake_content)
cmake = self._configure_cmake()
cmake = CMake(self)
cmake.configure()
cmake.build()

def _patch_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
# Using **patch here results in an error with the required `patch_description` field.
tools.patch(patch_file=patch['patch_file'])

_DEPS_FILE = "res/generated_targets.deps"

def package(self):
Expand All @@ -203,6 +195,7 @@ def package_info(self):
for line in f.read().splitlines():
(name, libtype, deps) = line.rstrip('\n').split(' ')
self.cpp_info.components[name].requires = deps.split(',')
self.cpp_info.components[name].resdirs = ["res"]
if libtype == 'LIB':
self.cpp_info.components[name].libs = [name]
self.cpp_info.components[name].names["pkg_config"] = name
Expand Down
35 changes: 26 additions & 9 deletions recipes/googleapis/all/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,56 @@ def cmake_target(self):
qname = qname[2:]
return f'{qname.replace("/", "_")}_{self.name}'

def shorten_cmake_target(self, cmake_target):
short_name = cmake_target
prefix = "google_"
suffix = "_proto"
if cmake_target.startswith(prefix):
short_name = short_name[len(prefix):]
if short_name.endswith(suffix):
short_name = short_name[:-len(suffix)]
return short_name

@property
def cmake_deps(self):
def to_cmake_target(item):
if item.startswith("//"):
return item[2:].replace("/", "_").replace(":", "_")
return item
return [to_cmake_target(it) for it in self.deps]

@property
def cmake_deps_short(self):
return [self.shorten_cmake_target(dep) for dep in self.cmake_deps]

@property
def cmake_content(self):
content = f"\n\n# {self.cmake_target}\n"
cmake_target_short = self.shorten_cmake_target(self.cmake_target)
content = f"\n\n# {self.cmake_target} ({cmake_target_short})\n"
content += "\n".join([f"#{it}" for it in self.dumps().split('\n')])
content += "\n"
if not self.srcs:
content += textwrap.dedent(f"""\
add_library({self.cmake_target} INTERFACE)
add_library({cmake_target_short} INTERFACE)
""")
else:
content += textwrap.dedent(f"""\
set({self.cmake_target}_PROTOS {" ".join(["${CMAKE_SOURCE_DIR}/"+it for it in self.srcs])})
add_library({self.cmake_target} ${{{self.cmake_target}_PROTOS}})
target_include_directories({self.cmake_target} PUBLIC ${{CMAKE_BINARY_DIR}})
target_compile_features({self.cmake_target} PUBLIC cxx_std_11)
set({cmake_target_short}_PROTOS {" ".join(["${CMAKE_SOURCE_DIR}/"+it for it in self.srcs])})
add_library({cmake_target_short} ${{{cmake_target_short}_PROTOS}})
target_include_directories({cmake_target_short} PUBLIC ${{CMAKE_BINARY_DIR}})
target_compile_features({cmake_target_short} PUBLIC cxx_std_11)
# set project_label to shorten the name of the vcxproj file and cause shorter paths
set_property(TARGET {cmake_target_short} PROPERTY OUTPUT_NAME "{self.cmake_target}")
protobuf_generate(LANGUAGE cpp
TARGET {self.cmake_target}
PROTOS ${{{self.cmake_target}_PROTOS}}
TARGET {cmake_target_short}
PROTOS ${{{cmake_target_short}_PROTOS}}
IMPORT_DIRS ${{CMAKE_SOURCE_DIR}}
)
""")

if self.deps:
content += textwrap.dedent(f"""\
target_link_libraries({self.cmake_target} {"PUBLIC" if self.srcs else "INTERFACE"} {" ".join(self.cmake_deps)})
target_link_libraries({cmake_target_short} {"PUBLIC" if self.srcs else "INTERFACE"} {" ".join(self.cmake_deps_short)})
""")

return content
Expand Down
9 changes: 4 additions & 5 deletions recipes/googleapis/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import os
from conan import ConanFile
from conan.tools.cmake import CMake, CMakeToolchain
from conan.tools.build import cross_building as tools_cross_building
from conan.tools.layout import cmake_layout
from conan.tools.cmake import cmake_layout, CMake, CMakeToolchain
from conan.tools.build import can_run


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

def requirements(self):
self.requires(self.tested_reference_str)
Expand All @@ -25,5 +24,5 @@ def build(self):
cmake.build()

def test(self):
if not tools_cross_building(self):
if can_run(self):
self.run(os.path.join(self.cpp.build.bindirs[0], "test_package"), env="conanrun")

0 comments on commit 26ac6c1

Please sign in to comment.