blob: 9c14f54f13b48ed9f43597cde2babd4492b3ea10 [file] [log] [blame]
# Generates the makefile "sysd-rules" given a list of sysdeps
# subdirectories (the sysdirs search path). For every basename that
# appears in the search path, e.g. "vfork", it picks the source file
# that appears first, e.g. "sysdeps/unix/sysv/linux/i386/vfork.S".
# TODO(mseaborn): Handle check-inhibit-asm
# TODO(mseaborn): Handle rule for installing .h files
import os
import sys
source_suffixes = (".c", ".S", ".s")
def parse_syscalls_list(path):
for line in open(path, "r"):
if not line.startswith("#") and line.strip() != "":
yield line.split()
# This is a list of sources files that take priority over files found
# via the sysdeps search path. This allows us, for example, to ignore
# sysdeps/i386/memcmp.S without overriding
# sysdeps/i386/dl-trampoline.S.
# TODO(mseaborn): Make this mechanism less NaCl-specific by moving
# this list to a file that is found via the search path.
override_list = [
"debug/memcpy_chk.c",
"debug/strcpy_chk.c",
"debug/stpcpy_chk.c",
"dirent/alphasort.c",
"dirent/scandir.c",
"dirent/versionsort.c",
"inet/htonl.c",
"inet/htons.c",
"io/ftw.c",
"io/lockf.c",
"io/posix_fadvise.c",
"libio/fseeko.c",
"libio/ftello.c",
"libio/iofgetpos.c",
"libio/iofopen.c",
"libio/iofsetpos.c",
"math/e_acosl.c",
"math/e_atan2l.c",
"math/e_expl.c",
"math/e_sqrtl.c",
"math/s_atanl.c",
"math/s_cexp.c",
"math/s_cexpl.c",
"math/s_fmax.c",
"math/s_fmaxf.c",
"math/s_fmin.c",
"math/s_fminf.c",
"math/s_significandl.c",
"misc/mkostemp.c",
"misc/mkstemp.c",
"misc/syscall.c",
"nptl/pthread_barrier_wait.c",
"nptl/pthread_cond_broadcast.c",
"nptl/pthread_cond_signal.c",
"nptl/pthread_cond_timedwait.c",
"nptl/pthread_cond_wait.c",
"nptl/pthread_rwlock_rdlock.c",
"nptl/pthread_rwlock_timedrdlock.c",
"nptl/pthread_rwlock_timedwrlock.c",
"nptl/pthread_rwlock_unlock.c",
"nptl/pthread_rwlock_wrlock.c",
"nptl/pthread_spin_init.c",
"nptl/pthread_spin_lock.c",
"nptl/pthread_spin_trylock.c",
"nptl/pthread_spin_unlock.c",
"nptl/sysdeps/unix/sysv/linux/ia64/pthread_once.c",
"nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c",
"nptl/sysdeps/unix/sysv/linux/lowlevellock.c",
"nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c",
"nptl/sysdeps/unix/sysv/linux/sem_post.c",
"nptl/sysdeps/unix/sysv/linux/sem_timedwait.c",
"nptl/sysdeps/unix/sysv/linux/sem_trywait.c",
"nptl/sysdeps/unix/sysv/linux/sem_wait.c",
"posix/alarm.c",
"posix/getegid.c",
"posix/geteuid.c",
"posix/getgid.c",
"posix/getpid.c",
"posix/getuid.c",
"posix/glob.c",
"posix/pread.c",
"posix/pwrite.c",
"posix/vfork.c",
"posix/wait.c",
"posix/waitid.c",
"posix/waitpid.c",
"signal/sigaction.c",
"stdio-common/tmpfile.c",
"stdlib/add_n.c",
"stdlib/addmul_1.c",
"stdlib/getcontext.c",
"stdlib/lshift.c",
"stdlib/makecontext.c",
"stdlib/mul_1.c",
"stdlib/rshift.c",
"stdlib/setcontext.c",
"stdlib/sub_n.c",
"stdlib/submul_1.c",
"stdlib/swapcontext.c",
"string/bzero.c",
"string/memchr.c",
"string/memcmp.c",
"string/memcpy.c",
"string/mempcpy.c",
"string/memset.c",
"string/rawmemchr.c",
"string/stpcpy.c",
"string/stpncpy.c",
"string/strcat.c",
"string/strchr.c",
"string/strchrnul.c",
"string/strcmp.c",
"string/strcpy.c",
"string/strcspn.c",
"string/strlen.c",
"string/strpbrk.c",
"string/strrchr.c",
"string/strspn.c",
"string/strtok.c",
"string/strtok_r.c",
"sysdeps/generic/initfini.c",
"sysdeps/posix/writev.c",
"sysvipc/semtimedop.c",
"sysdeps/ieee754/dbl-64/e_atanh.c",
"sysdeps/ieee754/dbl-64/s_asinh.c",
"sysdeps/ieee754/dbl-64/s_copysign.c",
"sysdeps/ieee754/dbl-64/s_llrint.c",
"sysdeps/ieee754/dbl-64/s_lrint.c",
"sysdeps/ieee754/dbl-64/s_sincos.c",
"sysdeps/ieee754/flt-32/e_atanhf.c",
"sysdeps/ieee754/flt-32/s_asinhf.c",
"sysdeps/ieee754/flt-32/s_copysignf.c",
"sysdeps/ieee754/flt-32/s_llrintf.c",
"sysdeps/ieee754/flt-32/s_lrintf.c",
"sysdeps/ieee754/ldbl-96/e_atanhl.c",
"sysdeps/ieee754/ldbl-96/s_asinhl.c",
"sysdeps/ieee754/ldbl-96/s_logbl.c",
"sysdeps/ieee754/ldbl-96/s_rintl.c",
"sysdeps/nacl/umount.c",
"sysdeps/nacl/getpid.c",
"sysdeps/nacl/start.c",
"sysdeps/nacl/truncate.c",
"sysdeps/posix/libc_fatal.c",
"sysdeps/posix/posix_fallocate.c",
"sysdeps/posix/writev.c",
"sysdeps/unix/readdir_r.c",
"sysdeps/unix/sysv/linux/epoll_pwait.c",
"sysdeps/unix/sysv/linux/fstatvfs.c",
"sysdeps/unix/sysv/linux/getdirentries.c",
"sysdeps/unix/sysv/linux/openat.c",
"sysdeps/unix/sysv/linux/sched_getcpu.c",
"sysdeps/unix/sysv/linux/statvfs.c",
"sysdeps/unix/sysv/linux/sync_file_range.c",
"sysdeps/unix/time.c",
"sysvipc/semtimedop.c",
]
def get_override_map():
override_map = {}
for filename in override_list:
assert filename[-2:] in source_suffixes, filename
assert os.path.exists(filename), filename
override_map[os.path.basename(filename[:-2])] = filename
return override_map
class RuleGenerator(object):
def __init__(self, sysdirs):
self.sysdirs = sysdirs
self.all_leafnames = set()
# Checking all_files is a little faster than os.path.exists().
self.all_files = set()
self.autogen_syscalls = set()
self.override_map = get_override_map()
def scan_sysdirs(self):
for subdir in self.sysdirs:
for leafname in os.listdir(subdir):
pathname = os.path.join(subdir, leafname)
self.all_files.add(pathname)
if leafname[-2:] in source_suffixes:
self.all_leafnames.add(leafname[:-2])
elif leafname == "syscalls.list":
for fields in parse_syscalls_list(pathname):
# We don't need to look at the 2nd field. It
# does not override other files - it can only
# cause this entry to be overridden by others.
name = fields[0]
self.autogen_syscalls.add((subdir, name))
def find_matches(self, leafname):
if leafname in self.override_map:
yield False, self.override_map[leafname]
for subdir in self.sysdirs:
# A syscalls.list entry for "mkdir" (for example) overrides
# "mkdir.c" in the same directory.
if (subdir, leafname) in self.autogen_syscalls:
yield True, "SYSCALL:%s:%s" % (subdir, leafname)
for suffix in source_suffixes:
pathname = os.path.join(subdir, leafname + suffix)
if pathname in self.all_files:
yield False, pathname
def put_leafname_rules(self, stream, leafname):
matches = list(self.find_matches(leafname))
if len(matches) == 0:
raise Exception("No match for %s" % leafname)
matches_string = " ".join(desc for is_autogen, desc in matches)
stream.write("\n### %s: %s\n" % (leafname, matches_string))
is_autogen, pathname = matches[0]
if is_autogen:
# We don't need to generate rules for this leafname:
# its rules are generated by sysdeps/unix/make-syscalls.sh.
return
def put_lib_rules(leafname, flags):
for dest_suffix in (".o", ".os"):
args = {"pathname": pathname,
"src_suffix": pathname[-2:],
"dest_suffix": dest_suffix,
"leafname": leafname,
"flags": flags}
stream.write(
"$(objpfx)%(leafname)s%(dest_suffix)s: "
"$(..)%(pathname)s $(before-compile)\n"
#"\t@echo building %(leafname)s%(dest_suffix)s\n"
"\t$(compile-command%(src_suffix)s)%(flags)s\n" % args)
# Object files for libpthread.so
put_lib_rules("ptw-" + leafname, " $(ptw-CPPFLAGS)")
# Object files for ld.so (dynamic linker)
put_lib_rules("rtld-" + leafname, " $(rtld-CPPFLAGS)")
if leafname.startswith("s_"):
# Object files for libm.so (maths)
put_lib_rules("m_" + leafname[2:], " $(m_CPPFLAGS)")
# Object files for libc.so/libc.a and other libraries
put_lib_rules(leafname, "")
def put_override_warnings(self, stream):
for leafname in sorted(self.override_map.iterkeys()):
if leafname not in self.all_leafnames:
stream.write(
"\n### Warning: nothing to override for %s." % leafname)
def put_rules(self, stream):
for leafname in sorted(self.all_leafnames):
self.put_leafname_rules(stream, leafname)
def main(args):
generator = RuleGenerator(args)
generator.scan_sysdirs()
generator.put_override_warnings(sys.stdout)
generator.put_rules(sys.stdout)
if __name__ == "__main__":
main(sys.argv[1:])