blob: 45cbbcc98f9bd9911d24482896895601a3b098f2 [file] [log] [blame]
#!/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])