Skip to content

Commit

Permalink
Introduces pkg_config_location in Prerequisite and use OpenSSLPrerequ…
Browse files Browse the repository at this point in the history
…isite().pkg_config_location in hostpython3, so we can support ssl on hostpython3 just out of the box also on macOS (#2599)

* 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
  • Loading branch information
misl6 authored May 21, 2022
1 parent fff7013 commit 71c237f
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 9 deletions.
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 = "openssl@1.1"
name = "openssl"
homebrew_formula_name = "openssl@1.1"
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("openssl@1.1", 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", "openssl@1.1"])
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 = "openssl@1.1"
self.expected_homebrew_location_prefix = "/opt/homebrew/opt/openssl@1.1"

@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/openssl@1.1"
self.expected_homebrew_location_prefix
)
self.assertTrue(self.prerequisite.darwin_checker())
_darwin_get_brew_formula_location_prefix.assert_called_with(
"openssl@1.1", 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", "openssl@1.1"])
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

0 comments on commit 71c237f

Please sign in to comment.