221 lines
7.0 KiB
Python
Executable File
221 lines
7.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# This replicates the logic in Makefile to produce lists of generic
|
|
# and architecture specific sources, then writes them into sources.bp
|
|
# as cc_defaults modules for use by the Android.bp file.
|
|
|
|
import copy
|
|
import glob
|
|
import os.path
|
|
|
|
BP_TO_MUSL_ARCHES = {
|
|
'arm': 'arm',
|
|
'arm64': 'aarch64',
|
|
'x86': 'i386',
|
|
'x86_64': 'x86_64',
|
|
}
|
|
|
|
SRC_DIRS = (
|
|
'src/*',
|
|
'src/malloc/mallocng',
|
|
)
|
|
COMPAT32_SRC_DIRS = (
|
|
'compat/time32',
|
|
)
|
|
OPT_DIRS = (
|
|
'src/internal',
|
|
'src/malloc',
|
|
'src/string',
|
|
)
|
|
NOSSP_SRCS = (
|
|
'src/env/__libc_start_main.c',
|
|
'src/env/__init_tls.c',
|
|
'src/env/__stack_chk_fail.c',
|
|
'src/thread/__set_thread_area.c',
|
|
'src/string/memset.c',
|
|
'src/string/memcpy.c',
|
|
)
|
|
LDSO_SRC_DIRS = (
|
|
'ldso',
|
|
)
|
|
CRT_SRCS = (
|
|
'crt/crt1.c',
|
|
'crt/crti.c',
|
|
'crt/crtn.c',
|
|
'crt/rcrt1.c',
|
|
'crt/Scrt1.c',
|
|
)
|
|
|
|
def overridden_base_src(arch, src):
|
|
src = src.replace('/'+arch+'/','/')
|
|
if src.endswith('.s') or src.endswith('.S'):
|
|
src = src[:-2]+'.c'
|
|
return src
|
|
|
|
def overridden_base_srcs(arch, srcs):
|
|
return [overridden_base_src(arch, src) for src in srcs]
|
|
|
|
def glob_dirs(*args):
|
|
"""glob_dirs takes a list of parts of glob patterns, some of which may be
|
|
lists or tuples, expands the lists and tuples into every combination
|
|
of patterns, and returns the glob expansion of the patterns."""
|
|
ret = []
|
|
for i, arg in enumerate(args):
|
|
if type(arg) is list or type(arg) is tuple:
|
|
for entry in arg:
|
|
new_args = list(args)
|
|
new_args[i] = entry
|
|
ret += glob_dirs(*new_args)
|
|
return ret
|
|
return sorted(glob.glob('/'.join(args)))
|
|
|
|
def force_exists(files):
|
|
"""force_exists raises an exception if any of the input files are missing
|
|
and returns the sorted list of inputs files"""
|
|
files = sorted(files)
|
|
glob_files = glob_dirs(files)
|
|
if glob_files != files:
|
|
raise(Exception('failed to find sources: %s' % ', '.join(['"'+x+'"' for x in list(set(files) - set(glob_files))])))
|
|
return files
|
|
|
|
def files_to_arch_files(base_files, arch):
|
|
files=[]
|
|
for f in base_files:
|
|
base, ext = os.path.splitext(os.path.basename(f))
|
|
pattern = os.path.join(os.path.dirname(f), arch, base+'.[csS]')
|
|
glob_files = glob.glob(pattern)
|
|
if len(glob_files) > 1:
|
|
raise(Exception('expected at most one file for %s, found %s' % (pattern, glob_files)))
|
|
elif glob_files:
|
|
files.append(glob_files[0])
|
|
|
|
return files
|
|
|
|
class SourceSet(object):
|
|
def __init__(self, *, dirs=[], files=[]):
|
|
self.srcs = self._srcs(dirs, files)
|
|
self.arch_srcs, self.arch_exclude_srcs = self._arch_srcs(dirs, files)
|
|
|
|
def _srcs(self, dirs, files):
|
|
return glob_dirs(dirs, '*.c') + force_exists(files)
|
|
|
|
def _arch_srcs(self, dirs, files):
|
|
srcs = {}
|
|
exclude_srcs = {}
|
|
for bp_arch, musl_arch in BP_TO_MUSL_ARCHES.items():
|
|
arch_srcs = glob_dirs(dirs, musl_arch, '*.[csS]')
|
|
arch_srcs += files_to_arch_files(files, musl_arch)
|
|
arch_exclude_srcs = overridden_base_srcs(musl_arch, arch_srcs)
|
|
if arch_srcs:
|
|
srcs[bp_arch] = arch_srcs
|
|
if arch_exclude_srcs:
|
|
exclude_srcs[bp_arch] = arch_exclude_srcs
|
|
return srcs, exclude_srcs
|
|
|
|
def intersect(self, other):
|
|
diff = self.subtract(other)
|
|
return self.subtract(diff)
|
|
|
|
def subtract(self, other):
|
|
ret = copy.deepcopy(self)
|
|
ret.srcs = sorted(list(set(ret.srcs) - set(other.srcs)))
|
|
for bp_arch in BP_TO_MUSL_ARCHES:
|
|
ret.arch_srcs[bp_arch] = sorted(list(set(ret.arch_srcs[bp_arch]) - set(other.arch_srcs[bp_arch])))
|
|
ret.arch_exclude_srcs[bp_arch] = sorted(list(set(ret.arch_exclude_srcs[bp_arch]) - set(other.arch_exclude_srcs[bp_arch])))
|
|
return ret
|
|
|
|
def union(self, other):
|
|
ret = copy.deepcopy(self)
|
|
ret.srcs = sorted(ret.srcs + other.srcs)
|
|
for bp_arch in BP_TO_MUSL_ARCHES:
|
|
ret.arch_srcs[bp_arch] = sorted(ret.arch_srcs[bp_arch] + other.arch_srcs[bp_arch])
|
|
ret.arch_exclude_srcs[bp_arch] = sorted(ret.arch_exclude_srcs[bp_arch] + other.arch_exclude_srcs[bp_arch])
|
|
return self
|
|
|
|
class Blueprint(object):
|
|
def __init__(self, out):
|
|
self.out = out
|
|
|
|
def PrintHeader(self):
|
|
self.out.write(
|
|
"""// Copyright (C) 2021 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// This file is created by generate_bp.py. Do not edit manually.
|
|
""")
|
|
|
|
def PrintDefaults(self, name, srcs):
|
|
"""Print a cc_defaults section from a list of source files, architecture
|
|
specific source files, and source files replaced by architecture specific
|
|
source files"""
|
|
self.out.write('\n')
|
|
self.out.write('cc_defaults {\n')
|
|
self.out.write(' name: "%s",\n' % name)
|
|
self.out.write(' srcs: [\n')
|
|
for f in srcs.srcs:
|
|
self.out.write(' "%s",\n' % f)
|
|
self.out.write(' ],\n')
|
|
|
|
if srcs.arch_srcs or srcs.arch_exclude_srcs:
|
|
self.out.write(' arch: {\n')
|
|
for arch in BP_TO_MUSL_ARCHES.keys():
|
|
if srcs.arch_srcs[arch] or srcs.arch_exclude_srcs[arch]:
|
|
self.out.write(' %s: {\n' % arch)
|
|
if srcs.arch_srcs[arch]:
|
|
self.out.write(' srcs: [\n')
|
|
for f in srcs.arch_srcs[arch]:
|
|
self.out.write(' "%s",\n' % f)
|
|
self.out.write(' ],\n')
|
|
if srcs.arch_exclude_srcs[arch]:
|
|
self.out.write(' exclude_srcs: [\n')
|
|
for f in srcs.arch_exclude_srcs[arch]:
|
|
self.out.write(' "%s",\n' % f)
|
|
self.out.write(' ],\n')
|
|
self.out.write(' },\n')
|
|
self.out.write(' },\n')
|
|
|
|
self.out.write('}\n')
|
|
|
|
|
|
libc = SourceSet(dirs=SRC_DIRS)
|
|
compat32 = SourceSet(dirs=COMPAT32_SRC_DIRS)
|
|
opt = SourceSet(dirs=OPT_DIRS)
|
|
nossp = SourceSet(files=NOSSP_SRCS)
|
|
ldso = SourceSet(dirs=LDSO_SRC_DIRS)
|
|
|
|
crts = {}
|
|
for crt in CRT_SRCS:
|
|
srcs = SourceSet(files=[crt])
|
|
name = os.path.splitext(os.path.basename(crt))[0]
|
|
crts[name] = srcs
|
|
|
|
libc = libc.subtract(opt).subtract(nossp)
|
|
opt_nossp = opt.intersect(nossp)
|
|
opt = opt.subtract(opt_nossp)
|
|
nossp = nossp.subtract(opt_nossp)
|
|
|
|
dir_name = os.path.dirname(os.path.realpath(__file__))
|
|
|
|
with open(os.path.join(dir_name, '..', 'sources.bp'), 'w+') as out:
|
|
bp = Blueprint(out)
|
|
bp.PrintHeader()
|
|
bp.PrintDefaults('libc_musl_sources', libc)
|
|
bp.PrintDefaults('libc_musl_compat32_sources', compat32)
|
|
bp.PrintDefaults('libc_musl_opt_sources', opt)
|
|
bp.PrintDefaults('libc_musl_opt_nossp_sources', opt_nossp)
|
|
bp.PrintDefaults('libc_musl_nossp_sources', nossp)
|
|
bp.PrintDefaults('libc_musl_ldso_sources', ldso)
|
|
for crt in sorted(crts.keys()):
|
|
bp.PrintDefaults('libc_musl_%s_sources' % crt, crts[crt])
|