Skip to content

Commit c7edf85

Browse files
committed
Add ability to compile recipes with clang
The android ndk has been migrated his default compiler from gcc to clang and soon will be removed from the ndk. Here we prepare p4a to compile recipes with clang, which will allow us to successfully compile an updated openssl libs. Without this openssl upgrade we will not be able to grant support to python3's _ssl.so module. Note: The default p4a compiler still is gcc...so...no changes on the compile behaviour unless explicitly requested
1 parent 6f4077d commit c7edf85

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

pythonforandroid/archs.py

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,26 @@ def include_dirs(self):
3030
d.format(arch=self))
3131
for d in self.ctx.include_dirs]
3232

33-
def get_env(self, with_flags_in_cc=True):
33+
def get_env(self, with_flags_in_cc=True, clang=False):
34+
'''.. versionchanged:: 0.6.0
35+
Add ``clang`` to kwargs. If enabled, will allow us to get the
36+
necessary flags to compile with clang instead of gcc (default).'''
3437
env = {}
3538

36-
env['CFLAGS'] = ' '.join([
37-
'-DANDROID', '-mandroid', '-fomit-frame-pointer'
38-
' -D__ANDROID_API__={}'.format(self.ctx.ndk_api),
39-
])
39+
cflags = [
40+
'-DANDROID',
41+
'-fomit-frame-pointer',
42+
'-D__ANDROID_API__={}'.format(self.ctx.ndk_api)]
43+
if clang:
44+
toolchain_root = join(self.ctx.ndk_dir, 'toolchains',
45+
'{}-4.9'.format(self.toolchain_prefix),
46+
'prebuilt', 'linux-x86_64')
47+
cflags += ['-target armv7-none-linux-androideabi']
48+
cflags += ['-gcc-toolchain {}'.format(toolchain_root)]
49+
else:
50+
cflags += ['-mandroid']
51+
52+
env['CFLAGS'] = ' '.join(cflags)
4053
env['LDFLAGS'] = ' '
4154

4255
sysroot = join(self.ctx._ndk_dir, 'sysroot')
@@ -82,8 +95,19 @@ def get_env(self, with_flags_in_cc=True):
8295
env['NDK_CCACHE'] = self.ctx.ccache
8396
env.update({k: v for k, v in environ.items() if k.startswith('CCACHE_')})
8497

85-
cc = find_executable('{command_prefix}-gcc'.format(
86-
command_prefix=command_prefix), path=environ['PATH'])
98+
if clang:
99+
clang_path = join(
100+
self.ctx.ndk_dir, 'toolchains', 'llvm', 'prebuilt',
101+
'linux-x86_64', 'bin')
102+
environ['PATH'] = '{clang_path}:{path}'.format(
103+
clang_path=clang_path, path=environ['PATH'])
104+
cc = join(clang_path, 'clang')
105+
ccxx = join(clang_path, 'clang++')
106+
else:
107+
cc = '{command_prefix}-gcc'.format(command_prefix=command_prefix)
108+
ccxx = '{command_prefix}-g++'.format(command_prefix=command_prefix)
109+
110+
cc = find_executable(cc, path=environ['PATH'])
87111
if cc is None:
88112
print('Searching path are: {!r}'.format(environ['PATH']))
89113
warning('Couldn\'t find executable for CC. This indicates a '
@@ -92,22 +116,11 @@ def get_env(self, with_flags_in_cc=True):
92116
'installed. Exiting.')
93117
exit(1)
94118

119+
env['CC'] = '{ccache}{cc}'.format(ccache=ccache, cc=cc)
120+
env['CXX'] = '{ccache}{ccxx}'.format(ccache=ccache, ccxx=ccxx)
95121
if with_flags_in_cc:
96-
env['CC'] = '{ccache}{command_prefix}-gcc {cflags}'.format(
97-
command_prefix=command_prefix,
98-
ccache=ccache,
99-
cflags=env['CFLAGS'])
100-
env['CXX'] = '{ccache}{command_prefix}-g++ {cxxflags}'.format(
101-
command_prefix=command_prefix,
102-
ccache=ccache,
103-
cxxflags=env['CXXFLAGS'])
104-
else:
105-
env['CC'] = '{ccache}{command_prefix}-gcc'.format(
106-
command_prefix=command_prefix,
107-
ccache=ccache)
108-
env['CXX'] = '{ccache}{command_prefix}-g++'.format(
109-
command_prefix=command_prefix,
110-
ccache=ccache)
122+
env['CC'] += ' {}'.format(env['CFLAGS'])
123+
env['CXX'] += ' {cxxflags}'.format(cxxflags=env['CXXFLAGS'])
111124

112125
env['AR'] = '{}-ar'.format(command_prefix)
113126
env['RANLIB'] = '{}-ranlib'.format(command_prefix)
@@ -151,8 +164,8 @@ class ArchARM(Arch):
151164
class ArchARMv7_a(ArchARM):
152165
arch = 'armeabi-v7a'
153166

154-
def get_env(self, with_flags_in_cc=True):
155-
env = super(ArchARMv7_a, self).get_env(with_flags_in_cc)
167+
def get_env(self, with_flags_in_cc=True, clang=False):
168+
env = super(ArchARMv7_a, self).get_env(with_flags_in_cc, clang=clang)
156169
env['CFLAGS'] = (env['CFLAGS'] +
157170
(' -march=armv7-a -mfloat-abi=softfp '
158171
'-mfpu=vfp -mthumb'))
@@ -166,8 +179,8 @@ class Archx86(Arch):
166179
command_prefix = 'i686-linux-android'
167180
platform_dir = 'arch-x86'
168181

169-
def get_env(self, with_flags_in_cc=True):
170-
env = super(Archx86, self).get_env(with_flags_in_cc)
182+
def get_env(self, with_flags_in_cc=True, clang=False):
183+
env = super(Archx86, self).get_env(with_flags_in_cc, clang=clang)
171184
env['CFLAGS'] = (env['CFLAGS'] +
172185
' -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32')
173186
env['CXXFLAGS'] = env['CFLAGS']
@@ -180,8 +193,8 @@ class Archx86_64(Arch):
180193
command_prefix = 'x86_64-linux-android'
181194
platform_dir = 'arch-x86'
182195

183-
def get_env(self, with_flags_in_cc=True):
184-
env = super(Archx86_64, self).get_env(with_flags_in_cc)
196+
def get_env(self, with_flags_in_cc=True, clang=False):
197+
env = super(Archx86_64, self).get_env(with_flags_in_cc, clang=clang)
185198
env['CFLAGS'] = (env['CFLAGS'] +
186199
' -march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel')
187200
env['CXXFLAGS'] = env['CFLAGS']
@@ -194,8 +207,8 @@ class ArchAarch_64(Arch):
194207
command_prefix = 'aarch64-linux-android'
195208
platform_dir = 'arch-arm64'
196209

197-
def get_env(self, with_flags_in_cc=True):
198-
env = super(ArchAarch_64, self).get_env(with_flags_in_cc)
210+
def get_env(self, with_flags_in_cc=True, clang=False):
211+
env = super(ArchAarch_64, self).get_env(with_flags_in_cc, clang=clang)
199212
incpath = ' -I' + join(dirname(__file__), 'includes', 'arm64-v8a')
200213
env['EXTRA_CFLAGS'] = incpath
201214
env['CFLAGS'] += incpath

pythonforandroid/recipe.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,12 @@ def unpack(self, arch):
406406
else:
407407
info('{} is already unpacked, skipping'.format(self.name))
408408

409-
def get_recipe_env(self, arch=None, with_flags_in_cc=True):
409+
def get_recipe_env(self, arch=None, with_flags_in_cc=True, clang=False):
410410
"""Return the env specialized for the recipe
411411
"""
412412
if arch is None:
413413
arch = self.filtered_archs[0]
414-
return arch.get_env(with_flags_in_cc=with_flags_in_cc)
414+
return arch.get_env(with_flags_in_cc=with_flags_in_cc, clang=clang)
415415

416416
def prebuild_arch(self, arch):
417417
'''Run any pre-build tasks for the Recipe. By default, this checks if

0 commit comments

Comments
 (0)