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

Introduces pkg_config_location in Prerequisite and use OpenSSLPrerequisite().pkg_config_location in hostpython3, so we can support ssl on hostpython3 just out of the box also on macOS #2599

Merged
merged 2 commits into from
May 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions pythonforandroid/prerequisites.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

class Prerequisite(object):
name = "Default"
homebrew_formula_name = ""
mandatory = dict(linux=False, darwin=False)
installer_is_supported = dict(linux=False, darwin=False)

Expand Down Expand Up @@ -108,6 +109,25 @@ def _darwin_get_brew_formula_location_prefix(self, formula, installed=False):
else:
return _stdout_res.decode("utf-8").strip()

def darwin_pkg_config_location(self):
warning(
f"pkg-config location is not supported on macOS for prerequisite: {self.name}"
)
return ""

def linux_pkg_config_location(self):
warning(
f"pkg-config location is not supported on linux for prerequisite: {self.name}"
)
return ""

@property
def pkg_config_location(self):
if sys.platform == "darwin":
return self.darwin_pkg_config_location()
elif sys.platform == "linux":
return self.linux_pkg_config_location()


class HomebrewPrerequisite(Prerequisite):
name = "homebrew"
Expand Down Expand Up @@ -245,19 +265,28 @@ def darwin_installer(self):


class OpenSSLPrerequisite(Prerequisite):
name = "[email protected]"
name = "openssl"
homebrew_formula_name = "[email protected]"
mandatory = dict(linux=False, darwin=True)
installer_is_supported = dict(linux=False, darwin=True)

def darwin_checker(self):
return (
self._darwin_get_brew_formula_location_prefix("[email protected]", installed=True)
self._darwin_get_brew_formula_location_prefix(
self.homebrew_formula_name, installed=True
)
is not None
)

def darwin_pkg_config_location(self):
return os.path.join(
self._darwin_get_brew_formula_location_prefix(self.homebrew_formula_name),
"lib/pkgconfig",
)

def darwin_installer(self):
info("Installing OpenSSL ...")
subprocess.check_output(["brew", "install", "[email protected]"])
subprocess.check_output(["brew", "install", self.homebrew_formula_name])


class AutoconfPrerequisite(Prerequisite):
Expand Down
19 changes: 17 additions & 2 deletions pythonforandroid/recipes/hostpython3/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sh
import os

from multiprocessing import cpu_count
from pathlib import Path
Expand All @@ -11,6 +12,7 @@
current_directory,
ensure_dir,
)
from pythonforandroid.prerequisites import OpenSSLPrerequisite

HOSTPYTHON_VERSION_UNSET_MESSAGE = (
'The hostpython recipe must have set version'
Expand Down Expand Up @@ -60,6 +62,17 @@ def python_exe(self):
'''Returns the full path of the hostpython executable.'''
return join(self.get_path_to_python(), self._exe_name)

def get_recipe_env(self, arch=None):
env = os.environ.copy()
openssl_prereq = OpenSSLPrerequisite()
if env.get("PKG_CONFIG_PATH", ""):
env["PKG_CONFIG_PATH"] = os.pathsep.join(
openssl_prereq.pkg_config_location, env["PKG_CONFIG_PATH"]
)
else:
env["PKG_CONFIG_PATH"] = openssl_prereq.pkg_config_location
return env

def should_build(self, arch):
if Path(self.python_exe).exists():
# no need to build, but we must set hostpython for our Context
Expand All @@ -83,6 +96,8 @@ def get_path_to_python(self):
return join(self.get_build_dir(), self.build_subdir)

def build_arch(self, arch):
env = self.get_recipe_env(arch)

recipe_build_dir = self.get_build_dir(arch.arch)

# Create a subdirectory to actually perform the build
Expand All @@ -92,7 +107,7 @@ def build_arch(self, arch):
# Configure the build
with current_directory(build_dir):
if not Path('config.status').exists():
shprint(sh.Command(join(recipe_build_dir, 'configure')))
shprint(sh.Command(join(recipe_build_dir, 'configure')), _env=env)

with current_directory(recipe_build_dir):
# Create the Setup file. This copying from Setup.dist is
Expand All @@ -110,7 +125,7 @@ def build_arch(self, arch):
SETUP_DIST_NOT_FIND_MESSAGE
)

shprint(sh.make, '-j', str(cpu_count()), '-C', build_dir)
shprint(sh.make, '-j', str(cpu_count()), '-C', build_dir, _env=env)

# make a copy of the python executable giving it the name we want,
# because we got different python's executable names depending on
Expand Down
47 changes: 43 additions & 4 deletions tests/test_prerequisites.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import unittest
from unittest import mock
from unittest import mock, skipIf

import sys

from pythonforandroid.prerequisites import (
JDKPrerequisite,
Expand All @@ -18,6 +20,7 @@ class PrerequisiteSetUpBaseClass:
def setUp(self):
self.mandatory = dict(linux=False, darwin=False)
self.installer_is_supported = dict(linux=False, darwin=False)
self.expected_homebrew_formula_name = ""

def test_is_mandatory_on_darwin(self):
assert self.prerequisite.mandatory["darwin"] == self.mandatory["darwin"]
Expand All @@ -37,6 +40,26 @@ def test_installer_is_supported_on_linux(self):
== self.installer_is_supported["linux"]
)

def test_darwin_pkg_config_location(self):
self.assertEqual(self.prerequisite.darwin_pkg_config_location(), "")

def test_linux_pkg_config_location(self):
self.assertEqual(self.prerequisite.linux_pkg_config_location(), "")

@skipIf(sys.platform != "darwin", "Only run on macOS")
def test_pkg_config_location_property__darwin(self):
self.assertEqual(
self.prerequisite.pkg_config_location,
self.prerequisite.darwin_pkg_config_location(),
)

@skipIf(sys.platform != "linux", "Only run on Linux")
def test_pkg_config_location_property__linux(self):
self.assertEqual(
self.prerequisite.pkg_config_location,
self.prerequisite.linux_pkg_config_location(),
)


class TestJDKPrerequisite(PrerequisiteSetUpBaseClass, unittest.TestCase):
def setUp(self):
Expand Down Expand Up @@ -76,6 +99,8 @@ def setUp(self):
self.mandatory = dict(linux=False, darwin=True)
self.installer_is_supported = dict(linux=False, darwin=True)
self.prerequisite = OpenSSLPrerequisite()
self.expected_homebrew_formula_name = "[email protected]"
self.expected_homebrew_location_prefix = "/opt/homebrew/opt/[email protected]"

@mock.patch(
"pythonforandroid.prerequisites.Prerequisite._darwin_get_brew_formula_location_prefix"
Expand All @@ -84,17 +109,31 @@ def test_darwin_checker(self, _darwin_get_brew_formula_location_prefix):
_darwin_get_brew_formula_location_prefix.return_value = None
self.assertFalse(self.prerequisite.darwin_checker())
_darwin_get_brew_formula_location_prefix.return_value = (
"/opt/homebrew/opt/[email protected]"
self.expected_homebrew_location_prefix
)
self.assertTrue(self.prerequisite.darwin_checker())
_darwin_get_brew_formula_location_prefix.assert_called_with(
"[email protected]", installed=True
self.expected_homebrew_formula_name, installed=True
)

@mock.patch("pythonforandroid.prerequisites.subprocess.check_output")
def test_darwin_installer(self, check_output):
self.prerequisite.darwin_installer()
check_output.assert_called_once_with(["brew", "install", "[email protected]"])
check_output.assert_called_once_with(
["brew", "install", self.expected_homebrew_formula_name]
)

@mock.patch(
"pythonforandroid.prerequisites.Prerequisite._darwin_get_brew_formula_location_prefix"
)
def test_darwin_pkg_config_location(self, _darwin_get_brew_formula_location_prefix):
_darwin_get_brew_formula_location_prefix.return_value = (
self.expected_homebrew_location_prefix
)
self.assertEqual(
self.prerequisite.darwin_pkg_config_location(),
f"{self.expected_homebrew_location_prefix}/lib/pkgconfig",
)


class TestAutoconfPrerequisite(PrerequisiteSetUpBaseClass, unittest.TestCase):
Expand Down