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

protobuf: allow shared on Macos + add protobuf::protoc imported target #4776

Merged
merged 29 commits into from Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f320810
really provide protobuf::protoc target
SpaceIm Mar 3, 2021
f13d5b7
cosmetic change
SpaceIm Mar 3, 2021
d636224
simplify check of runtime
SpaceIm Mar 3, 2021
c4037a2
properly handle protobuf with zlib
SpaceIm Mar 3, 2021
5df0f08
append to builddirs
SpaceIm Mar 3, 2021
0913f5f
cleanup
SpaceIm Mar 3, 2021
725d9d4
fix semicolon replacement
SpaceIm Mar 3, 2021
d879ac2
more robust DYLD_LIBRARY_PATH injection
SpaceIm Mar 4, 2021
c2c6033
cosmetic change
SpaceIm Mar 4, 2021
ab34548
improve runtime handling
SpaceIm Mar 4, 2021
0408def
no protobuf_BUILD_LIBPROTOC option before 3.14.0
SpaceIm Mar 4, 2021
f5a965d
honor upstream default value for with_zlib
SpaceIm Mar 4, 2021
a7d6760
add protobuf/3.15.4
SpaceIm Mar 4, 2021
10ac43a
provide Protobuf_PROTOC_EXECUTABLE CACHE variable
SpaceIm Mar 4, 2021
abb921f
trick to no break pkg_config generator internal handling in conan
SpaceIm Mar 4, 2021
dc170c4
workaround for invalid-constexpr with clang
SpaceIm Mar 4, 2021
610126d
clang < 4 not supported in recent protobuf
SpaceIm Mar 5, 2021
d877dc5
cleanup
SpaceIm Mar 5, 2021
af51bdb
do not disable rtti by default
SpaceIm Mar 5, 2021
55a8007
Revert "workaround for invalid-constexpr with clang"
SpaceIm Mar 5, 2021
72f94bf
remove useless test of find_program
SpaceIm Mar 5, 2021
427035b
use TARGET_FILE in apple patch
SpaceIm Mar 5, 2021
b3d5a0c
add 3.15.5 instead of 3.15.4
SpaceIm Mar 5, 2021
3a56544
add rtti option if protobuf >= 3.15.4
SpaceIm Mar 7, 2021
69d7baa
Merge branch 'master' into fix/protobu-protoc-target
SpaceIm Mar 11, 2021
4de7716
removed duplicated version
SpaceIm Mar 11, 2021
cd6f6a6
Merge branch 'master' into fix/protobu-protoc-target
SpaceIm Mar 16, 2021
a46fe2d
empty commit
SpaceIm Mar 19, 2021
a0f4c76
keep find_program protoc logic for cross compilation
SpaceIm Mar 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 8 additions & 8 deletions recipes/protobuf/all/conandata.yml
@@ -1,21 +1,21 @@
sources:
3.9.1:
"3.9.1":
sha256: 98e615d592d237f94db8bf033fba78cd404d979b0b70351a9e5aaff725398357
url: https://github.com/protocolbuffers/protobuf/archive/v3.9.1.tar.gz
3.11.4:
"3.11.4":
sha256: a79d19dcdf9139fa4b81206e318e33d245c4c9da1ffed21c87288ed4380426f9
url: https://github.com/protocolbuffers/protobuf/archive/v3.11.4.tar.gz
3.12.4:
"3.12.4":
sha256: 512e5a674bf31f8b7928a64d8adf73ee67b8fe88339ad29adaa3b84dbaa570d8
url: https://github.com/protocolbuffers/protobuf/archive/v3.12.4.tar.gz
3.13.0:
"3.13.0":
sha256: 9b4ee22c250fe31b16f1a24d61467e40780a3fbb9b91c3b65be2a376ed913a1a
url: https://github.com/protocolbuffers/protobuf/archive/v3.13.0.tar.gz
3.15.5:
"3.15.5":
sha256: bc3dbf1f09dba1b2eb3f2f70352ee97b9049066c9040ce0c9b67fb3294e91e4b
url: https://github.com/protocolbuffers/protobuf/archive/v3.15.5.tar.gz
patches:
3.12.4:
"3.12.4":
- patch_file: "patches/upstream-pr-7761-cmake-regex-fix.patch"
base_path: "source_subfolder"
- patch_file: "patches/upstream-issue-7567-no-export-template-define.patch"
Expand All @@ -24,13 +24,13 @@ patches:
base_path: "source_subfolder"
- patch_file: "patches/upstream-pr-8301-bundle-destination.patch"
base_path: "source_subfolder"
3.13.0:
"3.13.0":
- patch_file: "patches/upstream-pr-7761-cmake-regex-fix.patch"
base_path: "source_subfolder"
- patch_file: "patches/upstream-pr-7288-android-log.patch"
base_path: "source_subfolder"
- patch_file: "patches/upstream-pr-8301-bundle-destination.patch"
base_path: "source_subfolder"
3.15.5:
"3.15.5":
- patch_file: "patches/upstream-pr-8301-bundle-destination.patch"
base_path: "source_subfolder"
150 changes: 77 additions & 73 deletions recipes/protobuf/all/conanfile.py
@@ -1,7 +1,7 @@
import os
from conans import ConanFile, CMake, tools
from conans.errors import ConanInvalidConfiguration
from conans.tools import Version
import os
import textwrap


class ProtobufConan(ConanFile):
Expand All @@ -12,25 +12,27 @@ class ProtobufConan(ConanFile):
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/protocolbuffers/protobuf"
license = "BSD-3-Clause"
exports_sources = ["CMakeLists.txt", "patches/*"]
generators = "cmake"
short_paths = True

settings = "os", "arch", "compiler", "build_type"
options = {
"fPIC": [True, False],
"lite": [True, False],
"shared": [True, False],
"fPIC": [True, False],
"with_zlib": [True, False],
"with_rtti": [True, False],
Copy link
Contributor

Choose a reason for hiding this comment

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

Changing option 🙈

Copy link
Member

Choose a reason for hiding this comment

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

@SpaceIm why with_zlib should be True by default?

Copy link
Contributor Author

@SpaceIm SpaceIm Mar 16, 2021

Choose a reason for hiding this comment

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

@prince-chrismc you are reviewing the merge of master branch into this PR. Actually, I don't change the option name introduced in #4682, I resolve a conflict because I also added this option in this PR prior to #4682 merge, but with a different name.

@uilianries with_zlib should be True because it's enabled by default in upstream build files: https://github.com/protocolbuffers/protobuf/blob/146d579738acf7c990611365abf09e1f71d8bfc1/cmake/CMakeLists.txt#L58-L59
You can also look at configure.ac, the logic is less obvious, but it expects zlib by default:
https://github.com/protocolbuffers/protobuf/blob/146d579738acf7c990611365abf09e1f71d8bfc1/configure.ac#L55-L58
https://github.com/protocolbuffers/protobuf/blob/146d579738acf7c990611365abf09e1f71d8bfc1/configure.ac#L139-L171

Copy link
Contributor

Choose a reason for hiding this comment

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

derp, thank you I see it now that I turned off the filter

Copy link
Member

Choose a reason for hiding this comment

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

@SpaceIm Thank you!

"with_zlib": [True, False]
"lite": [True, False],
}
default_options = {
"fPIC": True,
"lite": False,
"shared": False,
"fPIC": True,
"with_zlib": True,
"with_rtti": True,
"with_zlib": False
"lite": False,
}

short_paths = True

exports_sources = ["CMakeLists.txt", "patches/*"]
generators = "cmake"
_cmake = None

@property
Expand All @@ -49,11 +51,6 @@ def _is_clang_x86(self):
def _can_disable_rtti(self):
return tools.Version(self.version) >= "3.15.4"

def source(self):
tools.get(**self.conan_data["sources"][self.version])
extracted_folder = self.name + "-" + self.version
os.rename(extracted_folder, self._source_subfolder)

def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
Expand All @@ -64,14 +61,11 @@ def configure(self):
if self.options.shared:
del self.options.fPIC

if self.settings.os == "Windows" and self.settings.compiler in ["Visual Studio", "clang"] and "MT" in self.settings.compiler.runtime:
if str(self.settings.compiler.get_safe("runtime")) in ["MT", "MTd", "static"]:
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

It is a new compiler setting, so strictly speaking it isn't changed :)

raise ConanInvalidConfiguration("Protobuf can't be built with shared + MT(d) runtimes")

if tools.is_apple_os(self.settings.os):
raise ConanInvalidConfiguration("Protobuf could not be built as shared library for Mac.")

if self.settings.compiler == "Visual Studio":
if Version(self.settings.compiler.version) < "14":
if tools.Version(self.settings.compiler.version) < "14":
raise ConanInvalidConfiguration("On Windows Protobuf can only be built with "
"Visual Studio 2015 or higher.")

Expand All @@ -83,6 +77,11 @@ def requirements(self):
if self.options.with_zlib:
self.requires("zlib/1.2.11")

def source(self):
tools.get(**self.conan_data["sources"][self.version])
extracted_folder = self.name + "-" + self.version
os.rename(extracted_folder, self._source_subfolder)

@property
def _cmake_install_base_path(self):
return os.path.join("lib", "cmake", "protobuf")
Expand All @@ -94,69 +93,81 @@ def _configure_cmake(self):
self._cmake.definitions["protobuf_WITH_ZLIB"] = self.options.with_zlib
self._cmake.definitions["protobuf_BUILD_TESTS"] = False
self._cmake.definitions["protobuf_BUILD_PROTOC_BINARIES"] = True
self._cmake.definitions["protobuf_BUILD_LIBPROTOC"] = True
if tools.Version(self.version) >= "3.14.0":
self._cmake.definitions["protobuf_BUILD_LIBPROTOC"] = True
if self._can_disable_rtti:
self._cmake.definitions["protobuf_DISABLE_RTTI"] = not self.options.with_rtti
if self.settings.compiler == "Visual Studio":
self._cmake.definitions["protobuf_MSVC_STATIC_RUNTIME"] = "MT" in str(self.settings.compiler.runtime)
if self.settings.compiler.get_safe("runtime"):
self._cmake.definitions["protobuf_MSVC_STATIC_RUNTIME"] = str(self.settings.compiler.runtime) in ["MT", "MTd", "static"]
self._cmake.configure(build_folder=self._build_subfolder)
return self._cmake

def _patch_sources(self):
for patch in self.conan_data.get("patches", {}).get(self.version, []):
tools.patch(**patch)

find_protoc = """

# Find the protobuf compiler within the paths added by Conan, for use below.
find_program(PROTOC_PROGRAM protoc PATHS ENV PATH NO_DEFAULT_PATH)
if(NOT PROTOC_PROGRAM)
set(PROTOC_PROGRAM "protoc")
Copy link
Contributor

Choose a reason for hiding this comment

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

It's not clear to me how this is not conflicting with:
369121c#diff-5dfb647bf8fb82769ddb94143d6b47475c5d4d2db2346115ee6b1991a6db6445R112
What will the merge look like?

Copy link
Contributor Author

@SpaceIm SpaceIm Mar 19, 2021

Choose a reason for hiding this comment

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

It's removed. This PR adds protobuf::protoc imported target and Protobuf_PROTOC_EXECUTABLE CACHE variable, but it's not very clear for me if it works with two profiles. I would like some feedbacks.
I should turn this PR to draft for the moment, since it could break cross compilation.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have pasted some commands below with one way you can test it.
The dual profile build doesn't seem to work.
CMake will find the wrong protoc (the one from host context instead of the one from build context).

Command:

conan create . 3.15.5@foo/testing \
    --profile:host android-ndk-r22-api-21-arm64-v8a-clang-c++_static.txt \
    --profile:build default \
    --build=protobuf

android-ndk-r22-api-21-arm64-v8a-clang-c++_static.txt:

[settings]
arch=armv8
build_type=Release
compiler=clang
compiler.libcxx=c++_static
compiler.version=11
os=Android
os.api_level=21
[build_requires]
android-ndk/r22
[options]
[env]

Result:

protobuf/3.15.5@foo/testing (test package): Calling build()
...
[1/4] Running cpp protocol buffer compiler on addressbook.proto
FAILED: addressbook.pb.h addressbook.pb.cc
...
/bin/sh: 1: x/.conan/data/protobuf/3.15.5/dirac/testing/package/475278d37419b9e365c649e594b7c9a419a343bb/bin/protoc: Exec format error

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok so maybe we could keep this find_program, and use this path for protobuf::protoc properties.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, could work. I'm happy to try if you push something later :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you test with a0f4c76 please?

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems to work just fine. I'm happy with it :)

endif()
"""
# Provide relocatable protobuf::protoc target and Protobuf_PROTOC_EXECUTABLE cache variable
# TODO: some of the following logic might be disabled when conan will
# allow to create executable imported targets in package_info()
protobuf_config_cmake = os.path.join(self._source_subfolder, "cmake", "protobuf-config.cmake.in")

tools.replace_in_file(
os.path.join(self._source_subfolder, "cmake", "protobuf-config.cmake.in"),
protobuf_config_cmake,
"@_protobuf_FIND_ZLIB@",
"# CONAN PATCH _protobuf_FIND_ZLIB@"
"# BEGIN CONAN PATCH\n#_protobuf_FIND_ZLIB@\n# END CONAN PATCH"
)

exe_ext = ".exe" if self.settings.os == "Windows" else ""
protoc_filename = "protoc" + exe_ext
module_folder_depth = len(os.path.normpath(self._cmake_install_base_path).split(os.path.sep))
protoc_rel_path = "{}bin/{}".format("".join(["../"] * module_folder_depth), protoc_filename)
protoc_target = textwrap.dedent("""\
if(NOT TARGET protobuf::protoc)
find_program(PROTOC_PROGRAM protoc PATHS ENV PATH NO_DEFAULT_PATH)
if(NOT PROTOC_PROGRAM)
set(PROTOC_PROGRAM \"${{CMAKE_CURRENT_LIST_DIR}}/{protoc_rel_path}\")
endif()
get_filename_component(PROTOC_PROGRAM \"${{PROTOC_PROGRAM}}\" ABSOLUTE)
set(Protobuf_PROTOC_EXECUTABLE ${{PROTOC_PROGRAM}} CACHE FILEPATH \"The protoc compiler\")
add_executable(protobuf::protoc IMPORTED)
set_property(TARGET protobuf::protoc PROPERTY IMPORTED_LOCATION ${{Protobuf_PROTOC_EXECUTABLE}})
endif()
""".format(protoc_rel_path=protoc_rel_path))
tools.replace_in_file(
os.path.join(self._source_subfolder, "cmake", "protobuf-config.cmake.in"),
protobuf_config_cmake,
"include(\"${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake\")",
"# CONAN PATCH include(\"${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake\")" + find_protoc
protoc_target
)

if tools.Version(self.version) < "3.12.0":
# Set DYLD_LIBRARY_PATH in command line to avoid issues with shared protobuf
# (even with virtualrunenv, this fix might be required due to SIP)
# Only works with cmake, cmake_find_package or cmake_find_package_multi generators
if tools.is_apple_os(self.settings.os):
tools.replace_in_file(
os.path.join(self._source_subfolder, "cmake", "protobuf-config.cmake.in"),
"""COMMAND protobuf::protoc
ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_protobuf_include_path} ${_abs_file}
DEPENDS ${_abs_file} protobuf::protoc""",
"""COMMAND "${CMAKE_COMMAND}"
ARGS -E env "DYLD_LIBRARY_PATH=${Protobuf_LIB_DIRS}:${CONAN_LIB_DIRS}:${Protobuf_LIB_DIRS_RELEASE}:${Protobuf_LIB_DIRS_DEBUG}:${Protobuf_LIB_DIRS_RELWITHDEBINFO}:${Protobuf_LIB_DIRS_MINSIZEREL}" ${PROTOC_PROGRAM} --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_protobuf_include_path} ${_abs_file}
DEPENDS ${_abs_file} USES_TERMINAL"""
protobuf_config_cmake,
"add_custom_command(",
("set(CUSTOM_DYLD_LIBRARY_PATH ${CONAN_LIB_DIRS} ${Protobuf_LIB_DIRS} ${Protobuf_LIB_DIRS_RELEASE} ${Protobuf_LIB_DIRS_DEBUG} ${Protobuf_LIB_DIRS_RELWITHDEBINFO} ${Protobuf_LIB_DIRS_MINSIZEREL})\n"
"string(REPLACE \";\" \":\" CUSTOM_DYLD_LIBRARY_PATH \"${CUSTOM_DYLD_LIBRARY_PATH}\")\n"
"add_custom_command(")
)
else:
tools.replace_in_file(
os.path.join(self._source_subfolder, "cmake", "protobuf-config.cmake.in"),
"""COMMAND protobuf::protoc
ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
DEPENDS ${_abs_file} protobuf::protoc""",
"""COMMAND "${CMAKE_COMMAND}"
ARGS -E env "DYLD_LIBRARY_PATH=${Protobuf_LIB_DIRS}:${CONAN_LIB_DIRS}:${Protobuf_LIB_DIRS_RELEASE}:${Protobuf_LIB_DIRS_DEBUG}:${Protobuf_LIB_DIRS_RELWITHDEBINFO}:${Protobuf_LIB_DIRS_MINSIZEREL}" ${PROTOC_PROGRAM} --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
DEPENDS ${_abs_file} USES_TERMINAL"""
protobuf_config_cmake,
"COMMAND protobuf::protoc",
"COMMAND ${CMAKE_COMMAND} -E env \"DYLD_LIBRARY_PATH=${CUSTOM_DYLD_LIBRARY_PATH}\" $<TARGET_FILE:protobuf::protoc>"
)

# Disable a potential warning in protobuf-module.cmake.in
# TODO: remove this patch? Is it really useful?
protobuf_module_cmake = os.path.join(self._source_subfolder, "cmake", "protobuf-module.cmake.in")
tools.replace_in_file(
os.path.join(self._source_subfolder, "cmake", "protobuf-module.cmake.in"),
'if(DEFINED Protobuf_SRC_ROOT_FOLDER)',
"""if(0)
if(DEFINED Protobuf_SRC_ROOT_FOLDER)""",
protobuf_module_cmake,
"if(DEFINED Protobuf_SRC_ROOT_FOLDER)",
"if(0)\nif(DEFINED Protobuf_SRC_ROOT_FOLDER)",
)
tools.replace_in_file(
os.path.join(self._source_subfolder, "cmake", "protobuf-module.cmake.in"),
'# Define upper case versions of output variables',
'endif()',
protobuf_module_cmake,
"# Define upper case versions of output variables",
"endif()",
)

def build(self):
Expand Down Expand Up @@ -186,6 +197,7 @@ def package_info(self):

self.cpp_info.names["cmake_find_package"] = "protobuf"
self.cpp_info.names["cmake_find_package_multi"] = "protobuf"
self.cpp_info.names["pkg_config"] = "protobuf_full_package" # unofficial, but required to avoid side effects (libprotobuf component "steals" the default global pkg_config name)

lib_prefix = "lib" if self.settings.compiler == "Visual Studio" else ""
lib_suffix = "d" if self.settings.build_type == "Debug" else ""
Expand All @@ -205,25 +217,17 @@ def package_info(self):
if self.settings.os == "Windows":
if self.options.shared:
self.cpp_info.components["libprotobuf"].defines = ["PROTOBUF_USE_DLLS"]

self.cpp_info.components["libprotobuf"].builddirs = [
self._cmake_install_base_path,
]

self.cpp_info.components["libprotobuf"].builddirs = [self._cmake_install_base_path]
self.cpp_info.components["libprotobuf"].build_modules.extend([
self.cpp_info.components["libprotobuf"].builddirs.append(self._cmake_install_base_path)
self.cpp_info.components["libprotobuf"].build_modules = [
os.path.join(self._cmake_install_base_path, "protobuf-generate.cmake"),
os.path.join(self._cmake_install_base_path, "protobuf-module.cmake"),
os.path.join(self._cmake_install_base_path, "protobuf-options.cmake"),
])
]

self.cpp_info.components["libprotoc"].name = "libprotoc"
self.cpp_info.components["libprotoc"].libs = [lib_prefix + "protoc" + lib_suffix]
self.cpp_info.components["libprotoc"].requires = ["libprotobuf"]

self.cpp_info.components["protoc"].name = "protoc"
self.cpp_info.components["protoc"].requires.extend(["libprotoc", "libprotobuf"])

bindir = os.path.join(self.package_folder, "bin")
self.output.info("Appending PATH environment variable: {}".format(bindir))
self.env_info.PATH.append(bindir)
Expand All @@ -243,9 +247,9 @@ def package_info(self):
if self.settings.os == "Android":
self.cpp_info.components["libprotobuf-lite"].system_libs.append("log")

self.cpp_info.components["libprotobuf-lite"].builddirs = [self._cmake_install_base_path]
self.cpp_info.components["libprotobuf-lite"].build_modules.extend([
self.cpp_info.components["libprotobuf-lite"].builddirs.append(self._cmake_install_base_path)
self.cpp_info.components["libprotobuf-lite"].build_modules = [
os.path.join(self._cmake_install_base_path, "protobuf-generate.cmake"),
os.path.join(self._cmake_install_base_path, "protobuf-module.cmake"),
os.path.join(self._cmake_install_base_path, "protobuf-options.cmake"),
])
]
2 changes: 1 addition & 1 deletion recipes/protobuf/all/test_package/conanfile.py
@@ -1,4 +1,4 @@
from conans import ConanFile, CMake, RunEnvironment, tools
from conans import ConanFile, CMake, tools
import os


Expand Down
10 changes: 5 additions & 5 deletions recipes/protobuf/config.yml
@@ -1,11 +1,11 @@
versions:
3.9.1:
"3.9.1":
folder: all
3.11.4:
"3.11.4":
folder: all
3.12.4:
"3.12.4":
folder: all
3.13.0:
"3.13.0":
folder: all
3.15.5:
"3.15.5":
folder: all