@@ -24,7 +24,7 @@ class Distribution(object):
2424 ndk_api = None
2525
2626 archs = []
27- '''The arch targets that the dist is built for.'''
27+ '''The names of the arch targets that the dist is built for.'''
2828
2929 recipes = []
3030
@@ -42,12 +42,19 @@ def __repr__(self):
4242 return str(self)
4343
4444 @classmethod
45- def get_distribution(cls, ctx, name=None, recipes=[],
46- ndk_api=None,
47- force_build=False,
48- extra_dist_dirs=[],
49- require_perfect_match=False,
50- allow_replace_dist=True):
45+ def get_distribution(
46+ cls,
47+ ctx,
48+ *,
49+ arch_name, # required keyword argument: there is no sensible default
50+ name=None,
51+ recipes=[],
52+ ndk_api=None,
53+ force_build=False,
54+ extra_dist_dirs=[],
55+ require_perfect_match=False,
56+ allow_replace_dist=True
57+ ):
5158 '''Takes information about the distribution, and decides what kind of
5259 distribution it will be.
5360
@@ -60,6 +67,12 @@ def get_distribution(cls, ctx, name=None, recipes=[],
6067 name : str
6168 The name of the distribution. If a dist with this name already '
6269 exists, it will be used.
70+ ndk_api : int
71+ The NDK API to compile against, included in the dist because it cannot
72+ be changed later during APK packaging.
73+ arch_name : str
74+ The target architecture name to compile against, included in the dist because
75+ it cannot be changed later during APK packaging.
6376 recipes : list
6477 The recipes that the distribution must contain.
6578 force_download: bool
@@ -77,17 +90,24 @@ def get_distribution(cls, ctx, name=None, recipes=[],
7790 a new one with the current requirements.
7891 '''
7992
80- existing_dists = Distribution.get_distributions(ctx)
93+ possible_dists = Distribution.get_distributions(ctx)
8194
82- possible_dists = existing_dists
95+ # Will hold dists that would be built in the same folder as an existing dist
96+ folder_match_dist = None
8397
84- name_match_dist = None
85-
86- # 0) Check if a dist with that name already exists
98+ # 0) Check if a dist with that name and architecture already exists
8799 if name is not None and name:
88- possible_dists = [d for d in possible_dists if d.name == name]
100+ possible_dists = [
101+ d for d in possible_dists if
102+ (d.name == name) and (arch_name in d.archs)]
103+
89104 if possible_dists:
90- name_match_dist = possible_dists[0]
105+ # There should only be one folder with a given dist name *and* arch.
106+ # We could check that here, but for compatibility let's let it slide
107+ # and just record the details of one of them. We only use this data to
108+ # possibly fail the build later, so it doesn't really matter if there
109+ # was more than one clash.
110+ folder_match_dist = possible_dists[0]
91111
92112 # 1) Check if any existing dists meet the requirements
93113 _possible_dists = []
@@ -110,35 +130,37 @@ def get_distribution(cls, ctx, name=None, recipes=[],
110130 else:
111131 info('No existing dists meet the given requirements!')
112132
113- # If any dist has perfect recipes and ndk API, return it
133+ # If any dist has perfect recipes, arch and NDK API, return it
114134 for dist in possible_dists:
115135 if force_build:
116136 continue
117137 if ndk_api is not None and dist.ndk_api != ndk_api:
118138 continue
139+ if arch_name is not None and arch_name not in dist.archs:
140+ continue
119141 if (set(dist.recipes) == set(recipes) or
120142 (set(recipes).issubset(set(dist.recipes)) and
121143 not require_perfect_match)):
122144 info_notify('{} has compatible recipes, using this one'
123145 .format(dist.name))
124146 return dist
125147
126- assert len(possible_dists) < 2
127-
128148 # If there was a name match but we didn't already choose it,
129149 # then the existing dist is incompatible with the requested
130150 # configuration and the build cannot continue
131- if name_match_dist is not None and not allow_replace_dist:
151+ if folder_match_dist is not None and not allow_replace_dist:
132152 raise BuildInterruptingException(
133153 'Asked for dist with name {name} with recipes ({req_recipes}) and '
134154 'NDK API {req_ndk_api}, but a dist '
135155 'with this name already exists and has either incompatible recipes '
136156 '({dist_recipes}) or NDK API {dist_ndk_api}'.format(
137157 name=name,
138158 req_ndk_api=ndk_api,
139- dist_ndk_api=name_match_dist .ndk_api,
159+ dist_ndk_api=folder_match_dist .ndk_api,
140160 req_recipes=', '.join(recipes),
141- dist_recipes=', '.join(name_match_dist.recipes)))
161+ dist_recipes=', '.join(folder_match_dist.recipes)))
162+
163+ assert len(possible_dists) < 2
142164
143165 # If we got this far, we need to build a new dist
144166 dist = Distribution(ctx)
@@ -152,9 +174,16 @@ def get_distribution(cls, ctx, name=None, recipes=[],
152174 name = filen.format(i)
153175
154176 dist.name = name
155- dist.dist_dir = join(ctx.dist_dir, dist.name)
177+ dist.dist_dir = join(
178+ ctx.dist_dir,
179+ generate_dist_folder_name(
180+ name,
181+ [arch_name] if arch_name is not None else None,
182+ )
183+ )
156184 dist.recipes = recipes
157185 dist.ndk_api = ctx.ndk_api
186+ dist.archs = [arch_name]
158187
159188 return dist
160189
@@ -182,7 +211,7 @@ def get_distributions(cls, ctx, extra_dist_dirs=[]):
182211 with open(join(folder, 'dist_info.json')) as fileh:
183212 dist_info = json.load(fileh)
184213 dist = cls(ctx)
185- dist.name = folder.split('/')[-1 ]
214+ dist.name = dist_info['dist_name' ]
186215 dist.dist_dir = folder
187216 dist.needs_build = False
188217 dist.recipes = dist_info['recipes']
@@ -210,7 +239,7 @@ def save_info(self, dirn):
210239 with current_directory(dirn):
211240 info('Saving distribution info')
212241 with open('dist_info.json', 'w') as fileh:
213- json.dump({'dist_name': self.ctx.dist_name ,
242+ json.dump({'dist_name': self.name ,
214243 'bootstrap': self.ctx.bootstrap.name,
215244 'archs': [arch.arch for arch in self.ctx.archs],
216245 'ndk_api': self.ctx.ndk_api,
@@ -236,3 +265,23 @@ def pretty_log_dists(dists, log_func=info):
236265
237266 for line in infos:
238267 log_func('\t' + line)
268+
269+
270+ def generate_dist_folder_name(base_dist_name, arch_names=None):
271+ """Generate the distribution folder name to use, based on a
272+ combination of the input arguments.
273+
274+ Parameters
275+ ----------
276+ base_dist_name : str
277+ The core distribution identifier string
278+ arch_names : list of str
279+ The architecture compile targets
280+ """
281+ if arch_names is None:
282+ arch_names = ["no_arch_specified"]
283+
284+ return '{}__{}'.format(
285+ base_dist_name,
286+ '_'.join(arch_names)
287+ )
0 commit comments