Skip to content

Commit 50358c9

Browse files
authored
Merge pull request kivy#1867 from etc0de/make_debug_release_debuggable
Fix debug build not resulting in gdb-debuggable build
2 parents 24fefcf + acbf02a commit 50358c9

File tree

11 files changed

+95
-23
lines changed

11 files changed

+95
-23
lines changed

pythonforandroid/bootstraps/common/build/build.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,8 @@ def make_package(args):
453453
"args": args,
454454
"service": service,
455455
"service_names": service_names,
456-
"android_api": android_api
456+
"android_api": android_api,
457+
"debug": "debug" in args.build_mode,
457458
}
458459
if get_bootstrap_name() == "sdl2":
459460
render_args["url_scheme"] = url_scheme
@@ -476,7 +477,8 @@ def make_package(args):
476477
aars=aars,
477478
jars=jars,
478479
android_api=android_api,
479-
build_tools_version=build_tools_version
480+
build_tools_version=build_tools_version,
481+
debug_build="debug" in args.build_mode,
480482
)
481483

482484
# ant build templates
@@ -541,7 +543,7 @@ def make_package(args):
541543
raise e
542544

543545

544-
def parse_args(args=None):
546+
def parse_args_and_make_package(args=None):
545547
global BLACKLIST_PATTERNS, WHITELIST_PATTERNS, PYTHON
546548

547549
# Get the default minsdk, equal to the NDK API that this dist is built against
@@ -659,6 +661,10 @@ def parse_args(args=None):
659661
default=join(curdir, 'whitelist.txt'),
660662
help=('Use a whitelist file to prevent blacklisting of '
661663
'file in the final APK'))
664+
ap.add_argument('--release', dest='build_mode', action='store_const',
665+
const='release', default='debug',
666+
help='Build your app as a non-debug release build. '
667+
'(Disables gdb debugging among other things)')
662668
ap.add_argument('--add-jar', dest='add_jar', action='append',
663669
help=('Add a Java .jar to the libs, so you can access its '
664670
'classes with pyjnius. You can specify this '
@@ -805,4 +811,4 @@ def _read_configuration():
805811

806812

807813
if __name__ == "__main__":
808-
parse_args()
814+
parse_args_and_make_package()

pythonforandroid/bootstraps/common/build/templates/build.tmpl.gradle

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,22 @@ android {
3434
versionName '{{ args.version }}'
3535
}
3636

37-
{% if args.sign -%}
38-
signingConfigs {
39-
release {
40-
storeFile file(System.getenv("P4A_RELEASE_KEYSTORE"))
41-
keyAlias System.getenv("P4A_RELEASE_KEYALIAS")
42-
storePassword System.getenv("P4A_RELEASE_KEYSTORE_PASSWD")
43-
keyPassword System.getenv("P4A_RELEASE_KEYALIAS_PASSWD")
44-
}
45-
}
37+
{% if debug_build -%}
38+
packagingOptions {
39+
doNotStrip '**/*.so'
40+
}
41+
{%- endif %}
42+
43+
{% if args.sign -%}
44+
signingConfigs {
45+
release {
46+
storeFile file(System.getenv("P4A_RELEASE_KEYSTORE"))
47+
keyAlias System.getenv("P4A_RELEASE_KEYALIAS")
48+
storePassword System.getenv("P4A_RELEASE_KEYSTORE_PASSWD")
49+
keyPassword System.getenv("P4A_RELEASE_KEYALIAS_PASSWD")
50+
}
51+
}
52+
4653
{%- endif %}
4754

4855
{% if args.packaging_options -%}

pythonforandroid/bootstraps/sdl2/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ def run_distribute(self):
4747
with open('blacklist.txt', 'a') as fileh:
4848
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')
4949

50-
self.strip_libraries(arch)
50+
if not self.ctx.build_as_debuggable:
51+
self.strip_libraries(arch)
5152
self.fry_eggs(site_packages_dir)
5253
super().run_distribute()
5354

pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
An example Java class can be found in README-android.txt
5656
-->
5757
<application android:label="@string/app_name"
58+
{% if debug %}android:debuggable="true"{% endif %}
5859
android:icon="@drawable/icon"
5960
android:allowBackup="{{ args.allow_backup }}"
6061
android:theme="{{args.android_apptheme}}{% if not args.window %}.Fullscreen{% endif %}"

pythonforandroid/bootstraps/service_only/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def run_distribute(self):
4545
with open('blacklist.txt', 'a') as fileh:
4646
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')
4747

48-
self.strip_libraries(arch)
48+
if not self.ctx.build_as_debuggable:
49+
self.strip_libraries(arch)
4950
self.fry_eggs(site_packages_dir)
5051
super().run_distribute()
5152

pythonforandroid/bootstraps/webview/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ def run_distribute(self):
4242
with open('blacklist.txt', 'a') as fileh:
4343
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')
4444

45-
self.strip_libraries(arch)
45+
if not self.ctx.build_as_debuggable:
46+
self.strip_libraries(arch)
4647
self.fry_eggs(site_packages_dir)
4748
super().run_distribute()
4849

pythonforandroid/build.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ class Context:
8181
'''A build context. If anything will be built, an instance this class
8282
will be instantiated and used to hold all the build state.'''
8383

84+
# Whether to build with debugging symbols
85+
build_as_debuggable = False
86+
8487
env = environ.copy()
8588
# the filepath of toolchain.py
8689
root_dir = None
@@ -839,8 +842,10 @@ def run_pymodules_install(ctx, modules, project_dir=None,
839842
)
840843

841844
# Strip object files after potential Cython or native code builds:
842-
standard_recipe.strip_object_files(ctx.archs[0], env,
843-
build_dir=ctx.build_dir)
845+
if not ctx.build_as_debuggable:
846+
standard_recipe.strip_object_files(
847+
ctx.archs[0], env, build_dir=ctx.build_dir
848+
)
844849

845850

846851
def biglink(ctx, arch):

pythonforandroid/recipe.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ def build_arch(self, arch, *extra_args):
801801
shprint(
802802
sh.ndk_build,
803803
'V=1',
804+
'NDK_DEBUG=' + ("1" if self.ctx.build_as_debuggable else "0"),
804805
'APP_PLATFORM=android-' + str(self.ctx.ndk_api),
805806
'APP_ABI=' + arch.arch,
806807
*extra_args, _env=env
@@ -1071,7 +1072,8 @@ def build_cython_components(self, arch):
10711072
info('First build appeared to complete correctly, skipping manual'
10721073
'cythonising.')
10731074

1074-
self.strip_object_files(arch, env)
1075+
if not self.ctx.build_as_debuggable:
1076+
self.strip_object_files(arch, env)
10751077

10761078
def strip_object_files(self, arch, env, build_dir=None):
10771079
if build_dir is None:

pythonforandroid/recipes/sdl2/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ def build_arch(self, arch):
2222
env = self.get_recipe_env(arch)
2323

2424
with current_directory(self.get_jni_dir()):
25-
shprint(sh.ndk_build, "V=1", _env=env)
25+
shprint(
26+
sh.ndk_build,
27+
"V=1",
28+
"NDK_DEBUG=" + ("1" if self.ctx.build_as_debuggable else "0"),
29+
_env=env
30+
)
2631

2732

2833
recipe = LibSDL2Recipe()

pythonforandroid/toolchain.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ def build_dist_from_args(ctx, dist, args):
196196
ctx.recipe_build_order))
197197
info('Dist will also contain modules ({}) installed from pip'.format(
198198
', '.join(ctx.python_modules)))
199+
if hasattr(args, "build_mode") and args.build_mode == "debug":
200+
info('Building WITH debugging symbols (no --release option used)')
201+
else:
202+
info('Building WITHOUT debugging symbols (--release option used)')
199203

200204
ctx.distribution = dist
201205
ctx.prepare_bootstrap(bs)
@@ -498,7 +502,8 @@ def add_parser(subparsers, *args, **kwargs):
498502
parser_apk.add_argument(
499503
'--release', dest='build_mode', action='store_const',
500504
const='release', default='debug',
501-
help='Build the PARSER_APK. in Release mode')
505+
help='Build your app as a non-debug release build. '
506+
'(Disables gdb debugging among other things)')
502507
parser_apk.add_argument(
503508
'--use-setup-py', dest="use_setup_py",
504509
action='store_true', default=False,
@@ -575,6 +580,8 @@ def add_parser(subparsers, *args, **kwargs):
575580
if hasattr(args, "private") and args.private is not None:
576581
# Pass this value on to the internal bootstrap build.py:
577582
args.unknown_args += ["--private", args.private]
583+
if hasattr(args, "build_mode") and args.build_mode == "release":
584+
args.unknown_args += ["--release"]
578585
if hasattr(args, "ignore_setup_py") and args.ignore_setup_py:
579586
args.use_setup_py = False
580587

@@ -591,6 +598,9 @@ def add_parser(subparsers, *args, **kwargs):
591598

592599
self.ctx = Context()
593600
self.ctx.use_setup_py = getattr(args, "use_setup_py", True)
601+
self.ctx.build_as_debuggable = getattr(
602+
args, "build_mode", "debug"
603+
) == "debug"
594604

595605
have_setup_py_or_similar = False
596606
if getattr(args, "private", None) is not None:
@@ -957,7 +967,9 @@ def apk(self, args):
957967
with current_directory(dist.dist_dir):
958968
self.hook("before_apk_build")
959969
os.environ["ANDROID_API"] = str(self.ctx.android_api)
960-
build_args = build.parse_args(args.unknown_args)
970+
build_args = build.parse_args_and_make_package(
971+
args.unknown_args
972+
)
961973
self.hook("after_apk_build")
962974
self.hook("before_apk_assemble")
963975

@@ -1007,7 +1019,9 @@ def apk(self, args):
10071019
gradle_task = "assembleRelease"
10081020
else:
10091021
raise BuildInterruptingException(
1010-
"Unknown build mode {} for apk()".format(args.build_mode))
1022+
"Unknown build mode {} for apk()".
1023+
format(args.build_mode)
1024+
)
10111025
output = shprint(gradlew, gradle_task, _tail=20,
10121026
_critical=True, _env=env)
10131027

tests/test_build.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,32 @@ def test_run_pymodules_install_optional_project_dir(self):
1818
assert run_pymodules_install(ctx, modules, project_dir) is None
1919
assert m_info.call_args_list[-1] == mock.call(
2020
'No Python modules and no setup.py to process, skipping')
21+
22+
def test_strip_if_debuggable(self):
23+
ctx = mock.Mock()
24+
ctx.python_recipe.major_minor_version_string = "python3.6"
25+
ctx.get_site_packages_dir.return_value = "test-doesntexist"
26+
ctx.build_dir = "nonexistant_directory"
27+
ctx.archs = ["arm64"]
28+
29+
modules = ["mymodule"]
30+
project_dir = None
31+
with mock.patch('pythonforandroid.build.info'), \
32+
mock.patch('sh.Command'),\
33+
mock.patch('pythonforandroid.build.open'),\
34+
mock.patch('pythonforandroid.build.shprint'),\
35+
mock.patch('pythonforandroid.build.current_directory'),\
36+
mock.patch('pythonforandroid.build.CythonRecipe') as m_CythonRecipe, \
37+
mock.patch('pythonforandroid.build.project_has_setup_py') as m_project_has_setup_py, \
38+
mock.patch('pythonforandroid.build.run_setuppy_install'):
39+
m_project_has_setup_py.return_value = False
40+
41+
# Make sure it is NOT called when debug build:
42+
ctx.build_as_debuggable = True
43+
assert run_pymodules_install(ctx, modules, project_dir) is None
44+
assert m_CythonRecipe().strip_object_files.called is False
45+
46+
# Make sure strip object files IS called when release build:
47+
ctx.build_as_debuggable = False
48+
assert run_pymodules_install(ctx, modules, project_dir) is None
49+
assert m_CythonRecipe().strip_object_files.called is True

0 commit comments

Comments
 (0)