Skip to content

Commit 3dc41cb

Browse files
committed
Move directories back to cross-build, and make the testbed handle both the source layout and the packaged layout
1 parent 5064b8f commit 3dc41cb

File tree

8 files changed

+152
-94
lines changed

8 files changed

+152
-94
lines changed

Android/.gitignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

Android/README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ To do all steps in a single command, run:
6464
./android.py build HOST
6565
```
6666

67-
In the end you should have an Android build of Python and its supporting
68-
libraries in `prefix/HOST`.
67+
In the end you should have a build Python in `cross-build/build`, and a host
68+
Python in `cross-build/HOST`.
6969

7070
You can use `--` as a separator for any of the `configure`-related commands –
7171
including `build` itself – to pass arguments to the underlying `configure`
@@ -88,8 +88,8 @@ package it for release with this command:
8888

8989
`HOST` is defined in the section above.
9090

91-
This will generate a tarball in the `dist` directory, whose structure is similar
92-
to the `Android` directory of the CPython source tree.
91+
This will generate a tarball in `cross-build/HOST/dist`, whose structure is
92+
similar to the `Android` directory of the CPython source tree.
9393

9494

9595
## Testing
@@ -98,8 +98,6 @@ The Python test suite can be run on Linux, macOS, or Windows:
9898

9999
* On Linux, the emulator needs access to the KVM virtualization interface, and
100100
a DISPLAY environment variable pointing at an X server.
101-
* On Windows, you won't be able to do the build on the same machine, so you'll
102-
have to copy the `prefix/HOST` directory from somewhere else.
103101

104102
The test suite can usually be run on a device with 2 GB of RAM, but this is
105103
borderline, so you may need to increase it to 4 GB. As of Android
@@ -109,9 +107,16 @@ and find `hw.ramSize` in both config.ini and hardware-qemu.ini. Either set these
109107
manually to the same value, or use the Android Studio Device Manager, which will
110108
update both files.
111109

112-
Before running the test suite, follow the instructions in the section above
113-
to build the architecture you want to test. Then run the test script in one of
114-
the following modes:
110+
You can run the test suite either:
111+
112+
* Within the CPython repository, after doing a build as described above. On
113+
Windows, you won't be able to do the build on the same machine, so you'll have
114+
to copy the `cross-build/HOST/prefix` directory from somewhere else.
115+
116+
* Or by taking a release package built using the `package` command, extracting
117+
it wherever you want, and using its own copy of `android.py`.
118+
119+
The test script supports the following modes:
115120

116121
* In `--connected` mode, it runs on a device or emulator you have already
117122
connected to the build machine. List the available devices with

Android/android.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@
2323
SCRIPT_NAME = Path(__file__).name
2424
ANDROID_DIR = Path(__file__).resolve().parent
2525
CHECKOUT = ANDROID_DIR.parent
26-
BUILD_DIR = ANDROID_DIR / "build"
27-
DIST_DIR = ANDROID_DIR / "dist"
28-
PREFIX_DIR = ANDROID_DIR / "prefix"
2926
TESTBED_DIR = ANDROID_DIR / "testbed"
27+
CROSS_BUILD_DIR = CHECKOUT / "cross-build"
3028

3129
HOSTS = ["aarch64-linux-android", "x86_64-linux-android"]
3230
APP_ID = "org.python.testbed"
@@ -62,8 +60,8 @@ def delete_glob(pattern):
6260
path.unlink()
6361

6462

65-
def subdir(parent, host, *, create=False):
66-
path = parent / host
63+
def subdir(*parts, create=False):
64+
path = CROSS_BUILD_DIR.joinpath(*parts)
6765
if not path.exists():
6866
if not create:
6967
sys.exit(
@@ -85,7 +83,7 @@ def run(command, *, host=None, env=None, log=True, **kwargs):
8583
env_output = subprocess.run(
8684
f"set -eu; "
8785
f"HOST={host}; "
88-
f"PREFIX={subdir(PREFIX_DIR, host)}; "
86+
f"PREFIX={subdir(host)}/prefix; "
8987
f". {env_script}; "
9088
f"export",
9189
check=True, shell=True, text=True, stdout=subprocess.PIPE
@@ -113,21 +111,21 @@ def run(command, *, host=None, env=None, log=True, **kwargs):
113111

114112
def build_python_path():
115113
"""The path to the build Python binary."""
116-
build_subdir = subdir(BUILD_DIR, "build")
117-
binary = build_subdir / "python"
114+
build_dir = subdir("build", "build")
115+
binary = build_dir / "python"
118116
if not binary.is_file():
119117
binary = binary.with_suffix(".exe")
120118
if not binary.is_file():
121119
raise FileNotFoundError("Unable to find `python(.exe)` in "
122-
f"{build_subdir}")
120+
f"{build_dir}")
123121

124122
return binary
125123

126124

127125
def configure_build_python(context):
128126
if context.clean:
129127
clean("build")
130-
os.chdir(subdir(BUILD_DIR, "build", create=True))
128+
os.chdir(subdir("build", "build", create=True))
131129

132130
command = [relpath(CHECKOUT / "configure")]
133131
if context.args:
@@ -136,7 +134,7 @@ def configure_build_python(context):
136134

137135

138136
def make_build_python(context):
139-
os.chdir(subdir(BUILD_DIR, "build"))
137+
os.chdir(subdir("build", "build"))
140138
run(["make", "-j", str(os.cpu_count())])
141139

142140

@@ -160,13 +158,13 @@ def configure_host_python(context):
160158
if context.clean:
161159
clean(context.host)
162160

163-
prefix_subdir = subdir(PREFIX_DIR, context.host, create=True)
164-
if not (prefix_subdir / "include").exists():
165-
os.chdir(prefix_subdir)
161+
prefix_dir = subdir(context.host, "prefix", create=True)
162+
if not (prefix_dir / "include").exists():
163+
os.chdir(prefix_dir)
166164
unpack_deps(context.host)
167165

168-
build_subdir = subdir(BUILD_DIR, context.host, create=True)
169-
os.chdir(build_subdir)
166+
build_dir = subdir(context.host, "build", create=True)
167+
os.chdir(build_dir)
170168

171169
command = [
172170
# Basic cross-compiling configuration
@@ -182,7 +180,7 @@ def configure_host_python(context):
182180

183181
# Dependent libraries. The others are found using pkg-config: see
184182
# android-env.sh.
185-
f"--with-openssl={prefix_subdir}",
183+
f"--with-openssl={prefix_dir}",
186184
]
187185

188186
if context.args:
@@ -194,13 +192,13 @@ def make_host_python(context):
194192
# The CFLAGS and LDFLAGS set in android-env include the prefix dir, so
195193
# delete any previous Python installation to prevent it being used during
196194
# the build.
197-
prefix_subdir = subdir(PREFIX_DIR, context.host)
195+
prefix_dir = subdir(context.host, "prefix")
198196
for pattern in ("include/python*", "lib/libpython*", "lib/python*"):
199-
delete_glob(f"{prefix_subdir}/{pattern}")
197+
delete_glob(f"{prefix_dir}/{pattern}")
200198

201-
os.chdir(subdir(BUILD_DIR, context.host))
199+
os.chdir(subdir(context.host, "build"))
202200
run(["make", "-j", str(os.cpu_count())], host=context.host)
203-
run(["make", "install", f"prefix={prefix_subdir}"], host=context.host)
201+
run(["make", "install", f"prefix={prefix_dir}"], host=context.host)
204202

205203

206204
def build_all(context):
@@ -211,13 +209,15 @@ def build_all(context):
211209

212210

213211
def clean(host):
214-
for parent in (BUILD_DIR, PREFIX_DIR):
215-
delete_glob(f"{parent}/{host}")
212+
# Don't delete "dist", as that could be difficult to regenerate, and won't
213+
# affect future builds anyway.
214+
for name in ["build", "prefix"]:
215+
delete_glob(CROSS_BUILD_DIR / host / name)
216216

217217

218218
def clean_all(context):
219-
for parent in (BUILD_DIR, PREFIX_DIR):
220-
delete_glob(parent)
219+
for host in HOSTS + ["build"]:
220+
clean(host)
221221

222222

223223
def setup_sdk():
@@ -541,8 +541,8 @@ async def run_testbed(context):
541541
raise e.exceptions[0]
542542

543543

544-
def package_version(prefix_subdir):
545-
patchlevel_glob = f"{prefix_subdir}/include/python*/patchlevel.h"
544+
def package_version(prefix_dir):
545+
patchlevel_glob = f"{prefix_dir}/include/python*/patchlevel.h"
546546
patchlevel_paths = glob(patchlevel_glob)
547547
if len(patchlevel_paths) != 1:
548548
sys.exit(f"{patchlevel_glob} matched {len(patchlevel_paths)} paths.")
@@ -564,8 +564,8 @@ def package_version(prefix_subdir):
564564

565565

566566
def package(context):
567-
prefix_subdir = subdir(PREFIX_DIR, context.host)
568-
version = package_version(prefix_subdir)
567+
prefix_dir = subdir(context.host, "prefix")
568+
version = package_version(prefix_dir)
569569

570570
with TemporaryDirectory(prefix=SCRIPT_NAME) as temp_dir:
571571
temp_dir = Path(temp_dir)
@@ -590,8 +590,8 @@ def package(context):
590590
("lib/pkgconfig", ["*crypto*", "*ssl*", "*python*", "*sqlite*"]),
591591
]:
592592
for pattern in patterns:
593-
for src in glob(f"{prefix_subdir}/{rel_dir}/{pattern}"):
594-
dst = temp_dir / relpath(src, ANDROID_DIR)
593+
for src in glob(f"{prefix_dir}/{rel_dir}/{pattern}"):
594+
dst = temp_dir / relpath(src, prefix_dir.parent)
595595
dst.parent.mkdir(parents=True, exist_ok=True)
596596
if Path(src).is_dir():
597597
shutil.copytree(
@@ -601,9 +601,9 @@ def package(context):
601601
else:
602602
shutil.copy2(src, dst, follow_symlinks=False)
603603

604-
DIST_DIR.mkdir(exist_ok=True)
604+
dist_dir = subdir(context.host, "dist", create=True)
605605
package_path = shutil.make_archive(
606-
f"{DIST_DIR}/python-{version}-{context.host}", "gztar", temp_dir
606+
f"{dist_dir}/python-{version}-{context.host}", "gztar", temp_dir
607607
)
608608
print(f"Wrote {package_path}")
609609

Android/testbed/.gitignore

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
# The Gradle wrapper should be downloaded by running `../android.py setup-testbed`.
1+
# The Gradle wrapper can be downloaded by running the `test` or `build-testbed`
2+
# commands of android.py.
23
/gradlew
34
/gradlew.bat
45
/gradle/wrapper/gradle-wrapper.jar
56

7+
# The repository's top-level .gitignore file ignores all .idea directories, but
8+
# we want to keep any files which can't be regenerated from the Gradle
9+
# configuration.
10+
!.idea/
11+
/.idea/*
12+
!/.idea/inspectionProfiles
13+
614
*.iml
715
.gradle
816
/local.properties
9-
/.idea/caches
10-
/.idea/deploymentTargetDropdown.xml
11-
/.idea/libraries
12-
/.idea/modules.xml
13-
/.idea/workspace.xml
14-
/.idea/navEditor.xml
15-
/.idea/assetWizardSettings.xml
1617
.DS_Store
1718
/build
1819
/captures

Android/testbed/.idea/inspectionProfiles/Project_Default.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)