Skip to content

Commit 71cccb3

Browse files
committed
Add android.py env command
1 parent 2283010 commit 71cccb3

File tree

1 file changed

+64
-33
lines changed

1 file changed

+64
-33
lines changed

Android/android.py

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222

2323
SCRIPT_NAME = Path(__file__).name
2424
ANDROID_DIR = Path(__file__).resolve().parent
25-
CHECKOUT = ANDROID_DIR.parent
25+
PYTHON_DIR = ANDROID_DIR.parent
26+
in_source_tree = (
27+
ANDROID_DIR.name == "Android" and (PYTHON_DIR / "pyconfig.h.in").exists()
28+
)
29+
2630
TESTBED_DIR = ANDROID_DIR / "testbed"
27-
CROSS_BUILD_DIR = CHECKOUT / "cross-build"
31+
CROSS_BUILD_DIR = PYTHON_DIR / "cross-build"
2832

2933
HOSTS = ["aarch64-linux-android", "x86_64-linux-android"]
3034
APP_ID = "org.python.testbed"
@@ -74,41 +78,62 @@ def subdir(*parts, create=False):
7478

7579
def run(command, *, host=None, env=None, log=True, **kwargs):
7680
kwargs.setdefault("check", True)
81+
7782
if env is None:
7883
env = os.environ.copy()
79-
original_env = env.copy()
80-
8184
if host:
82-
env_script = ANDROID_DIR / "android-env.sh"
83-
env_output = subprocess.run(
84-
f"set -eu; "
85-
f"HOST={host}; "
86-
f"PREFIX={subdir(host)}/prefix; "
87-
f". {env_script}; "
88-
f"export",
89-
check=True, shell=True, text=True, stdout=subprocess.PIPE
90-
).stdout
91-
92-
for line in env_output.splitlines():
93-
# We don't require every line to match, as there may be some other
94-
# output from installing the NDK.
95-
if match := re.search(
96-
"^(declare -x |export )?(\\w+)=['\"]?(.*?)['\"]?$", line
97-
):
98-
key, value = match[2], match[3]
99-
if env.get(key) != value:
100-
print(line)
101-
env[key] = value
102-
103-
if env == original_env:
104-
raise ValueError(f"Found no variables in {env_script.name} output:\n"
105-
+ env_output)
85+
env.update(android_env(host))
10686

10787
if log:
10888
print(">", " ".join(map(str, command)))
10989
return subprocess.run(command, env=env, **kwargs)
11090

11191

92+
def print_env(context):
93+
android_env(getattr(context, "host", None))
94+
95+
96+
def android_env(host):
97+
if host:
98+
prefix = subdir(host) / "prefix"
99+
else:
100+
prefix = ANDROID_DIR / "prefix"
101+
sysconfigdata_files = prefix.glob("lib/python*/_sysconfigdata__android_*.py")
102+
host = re.fullmatch(
103+
r"_sysconfigdata__android_(.+).py", next(sysconfigdata_files).name
104+
)[1]
105+
106+
env_script = ANDROID_DIR / "android-env.sh"
107+
env_output = subprocess.run(
108+
f"set -eu; "
109+
f"export HOST={host}; "
110+
f"PREFIX={prefix}; "
111+
f". {env_script}; "
112+
f"export",
113+
check=True, shell=True, capture_output=True, text=True,
114+
).stdout
115+
116+
env = {}
117+
for line in env_output.splitlines():
118+
# We don't require every line to match, as there may be some other
119+
# output from installing the NDK.
120+
if match := re.search(
121+
"^(declare -x |export )?(\\w+)=['\"]?(.*?)['\"]?$", line
122+
):
123+
key, value = match[2], match[3]
124+
if os.environ.get(key) != value:
125+
env[key] = value
126+
127+
if not env:
128+
raise ValueError(f"Found no variables in {env_script.name} output:\n"
129+
+ env_output)
130+
131+
# Format the environment so it can be pasted into a shell.
132+
for key, value in sorted(env.items()):
133+
print(f"export {key}={shlex.quote(value)}")
134+
return env
135+
136+
112137
def build_python_path():
113138
"""The path to the build Python binary."""
114139
build_dir = subdir("build")
@@ -127,7 +152,7 @@ def configure_build_python(context):
127152
clean("build")
128153
os.chdir(subdir("build", create=True))
129154

130-
command = [relpath(CHECKOUT / "configure")]
155+
command = [relpath(PYTHON_DIR / "configure")]
131156
if context.args:
132157
command.extend(context.args)
133158
run(command)
@@ -168,7 +193,7 @@ def configure_host_python(context):
168193
os.chdir(host_dir)
169194
command = [
170195
# Basic cross-compiling configuration
171-
relpath(CHECKOUT / "configure"),
196+
relpath(PYTHON_DIR / "configure"),
172197
f"--host={context.host}",
173198
f"--build={sysconfig.get_config_var('BUILD_GNU_TYPE')}",
174199
f"--with-build-python={build_python_path()}",
@@ -624,8 +649,7 @@ def parse_args():
624649
configure_build = subcommands.add_parser("configure-build",
625650
help="Run `configure` for the "
626651
"build Python")
627-
make_build = subcommands.add_parser("make-build",
628-
help="Run `make` for the build Python")
652+
subcommands.add_parser("make-build", help="Run `make` for the build Python")
629653
configure_host = subcommands.add_parser("configure-host",
630654
help="Run `configure` for Android")
631655
make_host = subcommands.add_parser("make-host",
@@ -637,16 +661,22 @@ def parse_args():
637661
test = subcommands.add_parser(
638662
"test", help="Run the test suite")
639663
package = subcommands.add_parser("package", help="Make a release package")
664+
env = subcommands.add_parser("env", help="Print environment variables")
640665

641666
# Common arguments
642667
for subcommand in build, configure_build, configure_host:
643668
subcommand.add_argument(
644669
"--clean", action="store_true", default=False, dest="clean",
645670
help="Delete the relevant build and prefix directories first")
646-
for subcommand in [build, configure_host, make_host, package]:
671+
672+
host_commands = [build, configure_host, make_host, package]
673+
if in_source_tree:
674+
host_commands.append(env)
675+
for subcommand in host_commands:
647676
subcommand.add_argument(
648677
"host", metavar="HOST", choices=HOSTS,
649678
help="Host triplet: choices=[%(choices)s]")
679+
650680
for subcommand in build, configure_build, configure_host:
651681
subcommand.add_argument("args", nargs="*",
652682
help="Extra arguments to pass to `configure`")
@@ -690,6 +720,7 @@ def main():
690720
"build-testbed": build_testbed,
691721
"test": run_testbed,
692722
"package": package,
723+
"env": print_env,
693724
}
694725

695726
try:

0 commit comments

Comments
 (0)