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

Add support for cpr 1.6.2 #5353

Merged
merged 11 commits into from
May 12, 2021
137 changes: 89 additions & 48 deletions recipes/cpr/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from typing import no_type_check
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
from typing import no_type_check

Because this will break python2 and there is no typing in conanfiles at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bleh, I think my editor added this in and I didn't catch it. Thanks.

from conans import ConanFile, CMake, tools
from conans.errors import ConanInvalidConfiguration
import os


class CprConan(ConanFile):
AUTO_SSL = "auto"
Copy link
Contributor

Choose a reason for hiding this comment

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

Custom attributes should always be prefixed with _

NO_SSL = "off"

name = "cpr"
description = "C++ Requests: Curl for People, a spiritual port of Python Requests"
url = "https://github.com/conan-io/conan-center-index"
Expand All @@ -18,16 +22,14 @@ class CprConan(ConanFile):
"fPIC": [True, False],
"with_openssl": [True, False],
"with_winssl": [True, False],
"with_darwinssl": [True, False],
"no_ssl": [True, False],
"ssl": ["openssl", "darwinssl", "winssl", AUTO_SSL, NO_SSL]
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please stick with our usual, with_ syntax?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do!

}
default_options = {
"shared": False,
"fPIC": True,
"with_openssl": True,
"with_openssl": False,
"with_winssl": False,
"with_darwinssl": False,
"no_ssl": False,
"ssl": AUTO_SSL
}

_cmake = None
Expand Down Expand Up @@ -55,10 +57,10 @@ def _supports_winssl(self):
@property
def _supports_darwinssl(self):
# https://github.com/whoshuu/cpr/releases/tag/1.6.1
return tools.Version(self.version) >= "1.6.1"
return tools.Version(self.version) >= "1.6.1" and tools.is_apple_os(self.settings.os)

@property
def _can_disable_ssl(self):
def _can_auto_ssl(self):
# https://github.com/whoshuu/cpr/releases/tag/1.6.0
return not self._uses_old_cmake_options

Expand All @@ -82,24 +84,24 @@ def config_options(self):
del self.options.fPIC

def configure(self):
SSL_CURL_LIBS = {
"openssl": "openssl",
"darwinssl": "darwinssl",
"winssl": "schannel"
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be easier if we used the name value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, not sure what you're referring to here. Could you clarify?

Copy link
Contributor

Choose a reason for hiding this comment

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

There's a bit of complexity from the CPR values being different from the curl recipe...

But looking at it again, it's just combinatorics hell, since the options and support have changed a lot it's very complicated

}

if self.options.shared:
del self.options.fPIC
if not self._supports_openssl:
del self.options.with_openssl
if not self._supports_winssl:
del self.options.with_winssl
if not self._supports_darwinssl:
del self.options.with_darwinssl

ssl_library = self._get_ssl_library()
# Make sure libcurl uses the same SSL implementation
if self.options.get_safe("with_openssl", False):
# self.options["libcurl"].with_openssl = True # deprecated in https://github.com/conan-io/conan-center-index/pull/2880
self.options["libcurl"].with_ssl = "openssl"
if self.options.get_safe("with_winssl", False):
# self.options["libcurl"].with_winssl = True # deprecated in https://github.com/conan-io/conan-center-index/pull/2880
self.options["libcurl"].with_ssl = "schannel"
if self.options.get_safe("with_darwinssl", False):
self.options["libcurl"].with_ssl = "darwinssl"
# "auto" will be handled by cpr
if self._supports_ssl_library(ssl_library) and ssl_library in SSL_CURL_LIBS:
self.options["libcurl"].with_ssl = SSL_CURL_LIBS[ssl_library]


def source(self):
Expand Down Expand Up @@ -139,52 +141,91 @@ def _configure_cmake(self):
self._cmake.definitions[self._get_cmake_option("CPR_GENERATE_COVERAGE")] = False
self._cmake.definitions[self._get_cmake_option("CPR_USE_SYSTEM_GTEST")] = False

if self._supports_openssl:
self._cmake.definitions["CMAKE_USE_OPENSSL"] = self.options.get_safe("with_openssl", False)

if self._supports_darwinssl:
self._cmake.definitions[self._get_cmake_option("CPR_FORCE_DARWINSSL_BACKEND")] = self.options.get_safe("with_darwinssl", False)
self._cmake.definitions["CMAKE_USE_OPENSSL"] = self._supports_openssl and self.options.get_safe("with_openssl", False)
ssl_value = self.options.get_safe("ssl")
SSL_OPTIONS = {
"CPR_FORCE_DARWINSSL_BACKEND": ssl_value == "darwinssl",
"CPR_FORCE_OPENSSL_BACKEND": ssl_value == "openssl",
"CPR_FORCE_WINSSL_BACKEND": ssl_value == "winssl",
}

if self._supports_winssl: # The CMake options changed
# https://github.com/whoshuu/cpr/commit/18e1fc5c3fc0ffc07695f1d78897fb69e7474ea9#diff-1e7de1ae2d059d21e1dd75d5812d5a34b0222cef273b7c3a2af62eb747f9d20aR39-R40
self._cmake.definitions[self._get_cmake_option("CPR_FORCE_OPENSSL_BACKEND")] = self.options.get_safe("with_openssl", False)
self._cmake.definitions[self._get_cmake_option("CPR_FORCE_WINSSL_BACKEND")] = self.options.get_safe("with_winssl", False)
for cmake_option, value in SSL_OPTIONS.items():
self._cmake.definitions[self._get_cmake_option(cmake_option)] = value

if self._can_disable_ssl and self.options.get_safe("no_ssl", False):
# If we are on a version where disabling SSL requires a cmake option, disable it
if not self._uses_old_cmake_options and self._get_ssl_library() == CprConan.NO_SSL:
self._cmake.definitions["CPR_ENABLE_SSL"] = False

self._cmake.configure(build_folder=self._build_subfolder)
return self._cmake

def validate(self):
if not self._uses_valid_abi_and_compiler:
raise ConanInvalidConfiguration("Cannot compile cpr/1.6.0 with libstdc++ on clang < 9")
# Check if the system supports the given ssl library
def _supports_ssl_library(self, library):
if library == CprConan.NO_SSL:
return True
elif library == CprConan.AUTO_SSL:
return self._can_auto_ssl

validators = {
"openssl": self._supports_openssl,
"darwinssl": self._supports_darwinssl,
"winssl": self._supports_winssl
}

if not self._can_disable_ssl and self.options.get_safe("no_ssl", False):
# https://github.com/whoshuu/cpr/issues/546
raise ConanInvalidConfiguration("cpr < 1.6.0 cannot manually disable SSL.")
if library not in validators:
# This should never happen, as the options are validated by conan.
raise ValueError(f"Unknown SSL library: {library}")

if self.options.get_safe("with_openssl", False) and tools.is_apple_os(self.settings.os):
# https://github.com/whoshuu/cpr/issues/546
raise ConanInvalidConfiguration("cpr cannot be built on macOS with openssl")
return validators[library]

if self.options.get_safe("with_darwinssl", False) and not tools.is_apple_os(self.settings.os):
raise ConanInvalidConfiguration("cpr only supports darwinssl on macOS")
# Get the configured ssl library
def _get_ssl_library(self):
ssl_library = str(self.options.get_safe("ssl"))
if self.options.get_safe("with_openssl", False):
self.output.warn("with_openssl is deprecated. Please use the ssl option.")
return "openssl"
elif self.options.get_safe("with_winssl", False):
self.output.warn("with_winssl is deprecated. Please use the ssl option.")
return "winssl"
elif not self._can_auto_ssl and ssl_library == CprConan.AUTO_SSL:
if self._supports_openssl:
self.output.info("Auto SSL is not available below version 1.6.0. Falling back to openssl")
return "openssl"
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps this should be moved to config_options

such that the default is sensibly configured. We also try to no shock the user by override their explicit input and a minimum this should be a raise ConanInvalidConfiguration

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes total sense. Will fix this up later today.

elif not self._supports_openssl:
self.output.info("Auto SSL is not available below version 1.6.0, and openssl not supported. Disabling SSL")
return CprConan.NO_SSL
elif ssl_library == CprConan.AUTO_SSL and tools.Version(self.version) in ["1.6.0", "1.6.1"] and tools.is_apple_os(self.settings.os):
# https://github.com/whoshuu/cpr/issues/546
self.output.info("Auto SSL is not available on macOS with version 1.6.0/1.6.1, and openssl not supported. Disabling SSL")
return CprConan.NO_SSL

return ssl_library

def validate(self):
SSL_FAILURE_MESSAGES = {
"openssl": "OpenSSL is not supported on macOS or on CPR versions < 1.5.0",
"darwinssl": "DarwinSSL is only supported on macOS and on CPR versions >= 1.6.1",
"winssl": "WinSSL is only on Windows and on CPR versions >= 1.5.1",
CprConan.AUTO_SSL: "Automatic SSL selection is only available on CPR versions >= 1.6.0"
}

if self.options.get_safe("with_winssl", False) and self.settings.os != "Windows":
raise ConanInvalidConfiguration("cpr only supports winssl on Windows")
if not self._uses_valid_abi_and_compiler:
raise ConanInvalidConfiguration("Cannot compile cpr/1.6.0 with libstdc++ on clang < 9")

ssl_library = self._get_ssl_library()
if not self._supports_ssl_library(ssl_library):
raise ConanInvalidConfiguration(
f"Invalid SSL selection for the given configuration: {SSL_FAILURE_MESSAGES[ssl_library]}"
Copy link
Contributor

Choose a reason for hiding this comment

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

We are trying typing to maintain support for older python versions, could you please use "".format() instead please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah shoot - wasn't thinking about that. I've been in the f-string mindset for too long 😅

if ssl_library not in (CprConan.AUTO_SSL, CprConan.NO_SSL)
else f"Invalid value of ssl option, {ssl_library}"
)

if self.options.get_safe("with_openssl", False) and self.options.get_safe("with_winssl", False):
raise ConanInvalidConfiguration("cpr can not be built with both openssl and winssl")
if ssl_library not in (CprConan.AUTO_SSL, CprConan.NO_SSL) and ssl_library != self.options["libcurl"].with_ssl:
raise ConanInvalidConfiguration(f"cpr requires libcurl to be built with the option with_ssl='{self.options.get_safe('ssl')}'.")

if self.settings.compiler == "Visual Studio" and self.options.shared and "MT" in self.settings.compiler.runtime:
raise ConanInvalidConfiguration("Visual Studio build for shared library with MT runtime is not supported")

if self.options.get_safe("with_openssl", False) and self.options["libcurl"].with_ssl != "openssl":
raise ConanInvalidConfiguration("cpr requires libcurl to be built with the option with_ssl='openssl'.")

if self.options.get_safe("with_winssl", False) and self.options["libcurl"].with_ssl != "schannel":
raise ConanInvalidConfiguration("cpr requires libcurl to be built with the option with_ssl='schannel'.")


def build(self):
self._patch_sources()
Expand Down