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
Changes from 23 commits
f320810
f13d5b7
d636224
c4037a2
5df0f08
0913f5f
725d9d4
d879ac2
c2c6033
ab34548
0408def
f5a965d
a7d6760
10ac43a
abb921f
dc170c4
610126d
d877dc5
af51bdb
55a8007
72f94bf
427035b
b3d5a0c
3a56544
69d7baa
4de7716
cd6f6a6
a46fe2d
a0f4c76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,25 @@ | ||
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": | ||
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" | ||
base_path: "source_subfolder" | ||
3.13.0: | ||
"3.13.0": | ||
- patch_file: "patches/upstream-pr-7761-cmake-regex-fix.patch" | ||
base_path: "source_subfolder" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,6 @@ | ||
import os | ||
import glob | ||
from conans import ConanFile, CMake, tools | ||
from conans.errors import ConanInvalidConfiguration | ||
from conans.tools import Version | ||
import os | ||
|
||
|
||
class ProtobufConan(ConanFile): | ||
|
@@ -13,13 +11,25 @@ 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 = {"shared": [True, False], "with_zlib": [True, False], "fPIC": [True, False], "lite": [True, False]} | ||
default_options = {"with_zlib": False, "shared": False, "fPIC": True, "lite": False} | ||
options = { | ||
"shared": [True, False], | ||
"fPIC": [True, False], | ||
"with_zlib": [True, False], | ||
"lite": [True, False], | ||
} | ||
default_options = { | ||
"shared": False, | ||
"fPIC": True, | ||
"with_zlib": True, | ||
"lite": False, | ||
} | ||
|
||
short_paths = True | ||
|
||
exports_sources = ["CMakeLists.txt", "patches/*"] | ||
generators = "cmake" | ||
_cmake = None | ||
|
||
@property | ||
|
@@ -34,12 +44,6 @@ def _build_subfolder(self): | |
def _is_clang_x86(self): | ||
return self.settings.compiler == "clang" and self.settings.arch == "x86" | ||
|
||
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 | ||
|
@@ -48,20 +52,27 @@ 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"]: | ||
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.") | ||
|
||
if self.settings.compiler == "clang": | ||
if tools.Version(self.version) >= "3.15.4" and tools.Version(self.settings.compiler.version) < "4": | ||
raise ConanInvalidConfiguration("protobuf {} doesn't support clang < 4".format(self.version)) | ||
|
||
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") | ||
|
@@ -73,67 +84,75 @@ 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 self.settings.compiler == "Visual Studio": | ||
self._cmake.definitions["protobuf_MSVC_STATIC_RUNTIME"] = "MT" in str(self.settings.compiler.runtime) | ||
if tools.Version(self.version) >= "3.14.0": | ||
self._cmake.definitions["protobuf_BUILD_LIBPROTOC"] = True | ||
if tools.Version(self.version) >= "3.15.4": | ||
self._cmake.definitions["protobuf_DISABLE_RTTI"] = False # TODO: create an option for 3.15.4+? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this release/feature might be broken, see the convo above There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @floriansimon1 Is the usage here a problem? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pretty much, yes. @SpaceIm, if we merge this, it means we won't be able to disable RTTI, which is a feature I explicitly need for 3.15.5. Why disable it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Like the TODO says, add an option? 😃 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
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) | ||
if(NOT PROTOC_PROGRAM) | ||
set(PROTOC_PROGRAM "protoc") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not clear to me how this is not conflicting with: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's removed. This PR adds There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. 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:
Result:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok so maybe we could keep this There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you test with a0f4c76 please? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
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 | ||
("get_filename_component(PROTOC_FULL_PATH \"${{CMAKE_CURRENT_LIST_DIR}}/{protoc_rel_path}\" ABSOLUTE)\n" | ||
"set(Protobuf_PROTOC_EXECUTABLE ${{PROTOC_FULL_PATH}} CACHE FILEPATH \"The protoc compiler\")\n" | ||
"if(NOT TARGET protobuf::protoc)\n" | ||
" add_executable(protobuf::protoc IMPORTED)\n" | ||
" set_property(TARGET protobuf::protoc PROPERTY IMPORTED_LOCATION ${{Protobuf_PROTOC_EXECUTABLE}})\n" | ||
"endif()" | ||
).format(protoc_rel_path=protoc_rel_path) | ||
) | ||
|
||
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): | ||
|
@@ -163,6 +182,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 "" | ||
|
@@ -180,25 +200,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) | ||
|
@@ -216,9 +228,9 @@ def package_info(self): | |
if self.options.shared: | ||
self.cpp_info.components["libprotobuf-lite"].defines = ["PROTOBUF_USE_DLLS"] | ||
|
||
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"), | ||
]) | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from conans import ConanFile, CMake, RunEnvironment, tools | ||
from conans import ConanFile, CMake, tools | ||
import os | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +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": | ||
folder: all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did it change?! https://github.com/conan-io/conan/blob/03b3d71890c537df1154b3d04cc35ed2654a5894/conans/client/conf/__init__.py#L91
Nice catch you two!
There was a problem hiding this comment.
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 :)