diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-12-27 15:26:46 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-12-27 15:26:46 +0000 |
commit | df6d86d8822458cf787b5f5620490d6a962da3b8 (patch) | |
tree | 8d499fa24a32a195bd6e384dfb70639c45c4a9bb /scripts | |
parent | 2c7242b971fd7b63fa842df15ec6fa3d0ff8aeb0 (diff) | |
parent | 1949a12d5da678a8532359a95717d8e63910d93b (diff) |
Merge commit 'refs/top-bases/t/____longjmp_chk' into t/____longjmp_chkt/____longjmp_chk
Diffstat (limited to 'scripts')
31 files changed, 3125 insertions, 256 deletions
diff --git a/scripts/abilist.awk b/scripts/abilist.awk index bd740d4693..bad7c3807e 100644 --- a/scripts/abilist.awk +++ b/scripts/abilist.awk @@ -72,8 +72,7 @@ $2 == "g" || $2 == "w" && (NF == 7 || NF == 8) { seen_opd = -1; } else if ($4 == "*ABS*") { - type = "A"; - size = ""; + next; } else if (type == "DO") { type = "D"; diff --git a/scripts/backport-support.sh b/scripts/backport-support.sh new file mode 100644 index 0000000000..4057e42d3c --- /dev/null +++ b/scripts/backport-support.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# Create a patch which backports the support/ subdirectory. +# Copyright (C) 2017-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# This script does not backport the Makefile tweaks outside the +# support/ directory (which need to be backported separately), or the +# changes to test-skeleton.c (which should not be backported). + +set -e + +export LC_ALL=C +export GIT_CONFIG=/dev/null +export GTT_CONFIG_NOSYSTEM=0 +export GIT_PAGER= + +usage () { + cat >&2 <<EOF +usage: $0 {patch|commit} +EOF + exit 1 +} + +if test $# -ne 1 ; then + usage +fi + +command="$1" + +case "$command" in + patch|commit) + ;; + *) + usage + ;; +esac + +# The upstream branch to work on. +branch=origin/master + +# The commit which added the support/ directory. +initial_commit=c23de0aacbeaa7a091609b35764bed931475a16d + +# We backport the support directory and this script. Directories need +# to end in a /. +patch_targets="support/ scripts/backport-support.sh" + +latest_commit="$(git log --max-count=1 --pretty=format:%H "$branch" -- \ + $patch_targets)" + +# Simplify the branch name somewhat for reporting. +branch_name="$(echo "$branch" | sed s,^origin/,,)" + +command_patch () { + cat <<EOF +This patch creates the contents of the support/ directory up to this +upstream commit on the $branch_name branch: + +EOF + git log --max-count=1 "$latest_commit" + echo + git diff "$initial_commit"^.."$latest_commit" $patch_targets + echo "# Before applying the patch, run this command:" >&2 + echo "# rm -rf $patch_targets" >&2 +} + +command_commit () { + git status --porcelain | while read line ; do + echo "error: working copy is not clean, cannot commit" >&2 + exit 1 + done + for path in $patch_targets; do + echo "# Processing $path" >&2 + case "$path" in + [a-zA-Z0-9]*/) + # Directory. + git rm --cached --ignore-unmatch -r "$path" + rm -rf "$path" + git read-tree --prefix="$path" "$latest_commit":"$path" + git checkout "$path" + ;; + *) + # File. + git show "$latest_commit":"$path" > "$path" + git add "$path" + esac + done + git commit -m "Synchronize support/ infrastructure with $branch_name + +This commit updates the support/ subdirectory to +commit $latest_commit +on the $branch_name branch. +" +} + +command_$command diff --git a/scripts/begin-end-check.pl b/scripts/begin-end-check.pl deleted file mode 100644 index 1616931bb0..0000000000 --- a/scripts/begin-end-check.pl +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -# Check __BEGIN_NAMESPACE ... __END_NAMESPACE pairing in an include file. - -my $code = 0; -for my $path (@ARGV) { - my $localcode = 0; - my @stack; - - open my $in, '<', $path - or die "open $path failed: $!"; - - while (<$in>) { - if ( /^\s*__BEGIN_(.*)\b/ ) { - push @stack, $1; - } - elsif ( /^\s*__END_(.*)\b/ ) { - if (@stack) { - my $tag = pop @stack; - if ($1 ne $tag) { - print "$path:$.: BEGIN $tag paired with END $1\n"; - $localcode = 1; - } - } - else { - print "$path:$.: END $1 does not match a begin\n"; - $localcode = 1; - } - } - } - - if (@stack) { - print "$path: Unmatched begin tags " . join (' ', @stack) ."\n"; - $localcode = 1; - } - - if ($localcode == 0) { - print "$path: OK\n"; - } else { - $code = $localcode; - } -} - -exit $code; diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py new file mode 100755 index 0000000000..8ef463f57a --- /dev/null +++ b/scripts/build-many-glibcs.py @@ -0,0 +1,1676 @@ +#!/usr/bin/python3 +# Build many configurations of glibc. +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +"""Build many configurations of glibc. + +This script takes as arguments a directory name (containing a src +subdirectory with sources of the relevant toolchain components) and a +description of what to do: 'checkout', to check out sources into that +directory, 'bot-cycle', to run a series of checkout and build steps, +'bot', to run 'bot-cycle' repeatedly, 'host-libraries', to build +libraries required by the toolchain, 'compilers', to build +cross-compilers for various configurations, or 'glibcs', to build +glibc for various configurations and run the compilation parts of the +testsuite. Subsequent arguments name the versions of components to +check out (<component>-<version), for 'checkout', or, for actions +other than 'checkout' and 'bot-cycle', name configurations for which +compilers or glibc are to be built. + +""" + +import argparse +import datetime +import email.mime.text +import email.utils +import json +import os +import re +import shutil +import smtplib +import stat +import subprocess +import sys +import time +import urllib.request + +try: + os.cpu_count +except: + import multiprocessing + os.cpu_count = lambda: multiprocessing.cpu_count() + +try: + re.fullmatch +except: + re.fullmatch = lambda p,s,f=0: re.match(p+"\\Z",s,f) + +try: + subprocess.run +except: + class _CompletedProcess: + def __init__(self, args, returncode, stdout=None, stderr=None): + self.args = args + self.returncode = returncode + self.stdout = stdout + self.stderr = stderr + + def _run(*popenargs, input=None, timeout=None, check=False, **kwargs): + assert(timeout is None) + with subprocess.Popen(*popenargs, **kwargs) as process: + try: + stdout, stderr = process.communicate(input) + except: + process.kill() + process.wait() + raise + returncode = process.poll() + if check and returncode: + raise subprocess.CalledProcessError(returncode, popenargs) + return _CompletedProcess(popenargs, returncode, stdout, stderr) + + subprocess.run = _run + + +class Context(object): + """The global state associated with builds in a given directory.""" + + def __init__(self, topdir, parallelism, keep, replace_sources, strip, + action): + """Initialize the context.""" + self.topdir = topdir + self.parallelism = parallelism + self.keep = keep + self.replace_sources = replace_sources + self.strip = strip + self.srcdir = os.path.join(topdir, 'src') + self.versions_json = os.path.join(self.srcdir, 'versions.json') + self.build_state_json = os.path.join(topdir, 'build-state.json') + self.bot_config_json = os.path.join(topdir, 'bot-config.json') + self.installdir = os.path.join(topdir, 'install') + self.host_libraries_installdir = os.path.join(self.installdir, + 'host-libraries') + self.builddir = os.path.join(topdir, 'build') + self.logsdir = os.path.join(topdir, 'logs') + self.logsdir_old = os.path.join(topdir, 'logs-old') + self.makefile = os.path.join(self.builddir, 'Makefile') + self.wrapper = os.path.join(self.builddir, 'wrapper') + self.save_logs = os.path.join(self.builddir, 'save-logs') + self.script_text = self.get_script_text() + if action != 'checkout': + self.build_triplet = self.get_build_triplet() + self.glibc_version = self.get_glibc_version() + self.configs = {} + self.glibc_configs = {} + self.makefile_pieces = ['.PHONY: all\n'] + self.add_all_configs() + self.load_versions_json() + self.load_build_state_json() + self.status_log_list = [] + self.email_warning = False + + def get_script_text(self): + """Return the text of this script.""" + with open(sys.argv[0], 'r') as f: + return f.read() + + def exec_self(self): + """Re-execute this script with the same arguments.""" + sys.stdout.flush() + os.execv(sys.executable, [sys.executable] + sys.argv) + + def get_build_triplet(self): + """Determine the build triplet with config.guess.""" + config_guess = os.path.join(self.component_srcdir('gcc'), + 'config.guess') + cg_out = subprocess.run([config_guess], stdout=subprocess.PIPE, + check=True, universal_newlines=True).stdout + return cg_out.rstrip() + + def get_glibc_version(self): + """Determine the glibc version number (major.minor).""" + version_h = os.path.join(self.component_srcdir('glibc'), 'version.h') + with open(version_h, 'r') as f: + lines = f.readlines() + starttext = '#define VERSION "' + for l in lines: + if l.startswith(starttext): + l = l[len(starttext):] + l = l.rstrip('"\n') + m = re.fullmatch('([0-9]+)\.([0-9]+)[.0-9]*', l) + return '%s.%s' % m.group(1, 2) + print('error: could not determine glibc version') + exit(1) + + def add_all_configs(self): + """Add all known glibc build configurations.""" + self.add_config(arch='aarch64', + os_name='linux-gnu', + extra_glibcs=[{'variant': 'disable-multi-arch', + 'cfg': ['--disable-multi-arch']}]) + self.add_config(arch='aarch64_be', + os_name='linux-gnu') + self.add_config(arch='alpha', + os_name='linux-gnu') + self.add_config(arch='arm', + os_name='linux-gnueabi') + self.add_config(arch='armeb', + os_name='linux-gnueabi') + self.add_config(arch='armeb', + os_name='linux-gnueabi', + variant='be8', + gcc_cfg=['--with-arch=armv7-a']) + self.add_config(arch='arm', + os_name='linux-gnueabihf', + gcc_cfg=['--with-float=hard', '--with-cpu=arm926ej-s'], + extra_glibcs=[{'variant': 'v7a', + 'ccopts': '-march=armv7-a -mfpu=vfpv3'}, + {'variant': 'v7a-disable-multi-arch', + 'ccopts': '-march=armv7-a -mfpu=vfpv3', + 'cfg': ['--disable-multi-arch']}]) + self.add_config(arch='armeb', + os_name='linux-gnueabihf', + gcc_cfg=['--with-float=hard', '--with-cpu=arm926ej-s']) + self.add_config(arch='armeb', + os_name='linux-gnueabihf', + variant='be8', + gcc_cfg=['--with-float=hard', '--with-arch=armv7-a', + '--with-fpu=vfpv3']) + self.add_config(arch='hppa', + os_name='linux-gnu') + self.add_config(arch='i686', + os_name='gnu') + self.add_config(arch='ia64', + os_name='linux-gnu', + first_gcc_cfg=['--with-system-libunwind']) + self.add_config(arch='m68k', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib']) + self.add_config(arch='m68k', + os_name='linux-gnu', + variant='coldfire', + gcc_cfg=['--with-arch=cf', '--disable-multilib']) + self.add_config(arch='m68k', + os_name='linux-gnu', + variant='coldfire-soft', + gcc_cfg=['--with-arch=cf', '--with-cpu=54455', + '--disable-multilib']) + self.add_config(arch='microblaze', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib']) + self.add_config(arch='microblazeel', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib']) + self.add_config(arch='mips64', + os_name='linux-gnu', + gcc_cfg=['--with-mips-plt'], + glibcs=[{'variant': 'n32'}, + {'arch': 'mips', + 'ccopts': '-mabi=32'}, + {'variant': 'n64', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64', + os_name='linux-gnu', + variant='soft', + gcc_cfg=['--with-mips-plt', '--with-float=soft'], + glibcs=[{'variant': 'n32-soft'}, + {'variant': 'soft', + 'arch': 'mips', + 'ccopts': '-mabi=32'}, + {'variant': 'n64-soft', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64', + os_name='linux-gnu', + variant='nan2008', + gcc_cfg=['--with-mips-plt', '--with-nan=2008', + '--with-arch-64=mips64r2', + '--with-arch-32=mips32r2'], + glibcs=[{'variant': 'n32-nan2008'}, + {'variant': 'nan2008', + 'arch': 'mips', + 'ccopts': '-mabi=32'}, + {'variant': 'n64-nan2008', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64', + os_name='linux-gnu', + variant='nan2008-soft', + gcc_cfg=['--with-mips-plt', '--with-nan=2008', + '--with-arch-64=mips64r2', + '--with-arch-32=mips32r2', + '--with-float=soft'], + glibcs=[{'variant': 'n32-nan2008-soft'}, + {'variant': 'nan2008-soft', + 'arch': 'mips', + 'ccopts': '-mabi=32'}, + {'variant': 'n64-nan2008-soft', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64el', + os_name='linux-gnu', + gcc_cfg=['--with-mips-plt'], + glibcs=[{'variant': 'n32'}, + {'arch': 'mipsel', + 'ccopts': '-mabi=32'}, + {'variant': 'n64', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64el', + os_name='linux-gnu', + variant='soft', + gcc_cfg=['--with-mips-plt', '--with-float=soft'], + glibcs=[{'variant': 'n32-soft'}, + {'variant': 'soft', + 'arch': 'mipsel', + 'ccopts': '-mabi=32'}, + {'variant': 'n64-soft', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64el', + os_name='linux-gnu', + variant='nan2008', + gcc_cfg=['--with-mips-plt', '--with-nan=2008', + '--with-arch-64=mips64r2', + '--with-arch-32=mips32r2'], + glibcs=[{'variant': 'n32-nan2008'}, + {'variant': 'nan2008', + 'arch': 'mipsel', + 'ccopts': '-mabi=32'}, + {'variant': 'n64-nan2008', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='mips64el', + os_name='linux-gnu', + variant='nan2008-soft', + gcc_cfg=['--with-mips-plt', '--with-nan=2008', + '--with-arch-64=mips64r2', + '--with-arch-32=mips32r2', + '--with-float=soft'], + glibcs=[{'variant': 'n32-nan2008-soft'}, + {'variant': 'nan2008-soft', + 'arch': 'mipsel', + 'ccopts': '-mabi=32'}, + {'variant': 'n64-nan2008-soft', + 'ccopts': '-mabi=64'}]) + self.add_config(arch='nios2', + os_name='linux-gnu') + self.add_config(arch='powerpc', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib', '--enable-secureplt'], + extra_glibcs=[{'variant': 'power4', + 'ccopts': '-mcpu=power4', + 'cfg': ['--with-cpu=power4']}]) + self.add_config(arch='powerpc', + os_name='linux-gnu', + variant='soft', + gcc_cfg=['--disable-multilib', '--with-float=soft', + '--enable-secureplt']) + self.add_config(arch='powerpc64', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib', '--enable-secureplt']) + self.add_config(arch='powerpc64le', + os_name='linux-gnu', + gcc_cfg=['--disable-multilib', '--enable-secureplt']) + self.add_config(arch='powerpc', + os_name='linux-gnuspe', + gcc_cfg=['--disable-multilib', '--enable-secureplt', + '--enable-e500-double', '--enable-obsolete']) + self.add_config(arch='powerpc', + os_name='linux-gnuspe', + variant='e500v1', + gcc_cfg=['--disable-multilib', '--enable-secureplt', + '--enable-obsolete']) + self.add_config(arch='riscv64', + os_name='linux-gnu', + variant='rv64imac-lp64', + gcc_cfg=['--with-arch=rv64imac', '--with-abi=lp64', + '--disable-multilib']) + self.add_config(arch='riscv64', + os_name='linux-gnu', + variant='rv64imafdc-lp64', + gcc_cfg=['--with-arch=rv64imafdc', '--with-abi=lp64', + '--disable-multilib']) + self.add_config(arch='riscv64', + os_name='linux-gnu', + variant='rv64imafdc-lp64d', + gcc_cfg=['--with-arch=rv64imafdc', '--with-abi=lp64d', + '--disable-multilib']) + self.add_config(arch='s390x', + os_name='linux-gnu', + glibcs=[{}, + {'arch': 's390', 'ccopts': '-m31'}]) + self.add_config(arch='sh3', + os_name='linux-gnu') + self.add_config(arch='sh3eb', + os_name='linux-gnu') + self.add_config(arch='sh4', + os_name='linux-gnu') + self.add_config(arch='sh4eb', + os_name='linux-gnu') + self.add_config(arch='sh4', + os_name='linux-gnu', + variant='soft', + gcc_cfg=['--without-fp']) + self.add_config(arch='sh4eb', + os_name='linux-gnu', + variant='soft', + gcc_cfg=['--without-fp']) + self.add_config(arch='sparc64', + os_name='linux-gnu', + glibcs=[{}, + {'arch': 'sparcv9', + 'ccopts': '-m32 -mlong-double-128'}], + extra_glibcs=[{'variant': 'disable-multi-arch', + 'cfg': ['--disable-multi-arch']}, + {'variant': 'disable-multi-arch', + 'arch': 'sparcv9', + 'ccopts': '-m32 -mlong-double-128', + 'cfg': ['--disable-multi-arch']}]) + self.add_config(arch='x86_64', + os_name='linux-gnu', + gcc_cfg=['--with-multilib-list=m64,m32,mx32'], + glibcs=[{}, + {'variant': 'x32', 'ccopts': '-mx32'}, + {'arch': 'i686', 'ccopts': '-m32 -march=i686'}], + extra_glibcs=[{'variant': 'disable-multi-arch', + 'cfg': ['--disable-multi-arch']}, + {'variant': 'static-pie', + 'cfg': ['--enable-static-pie']}, + {'variant': 'x32-static-pie', + 'ccopts': '-mx32', + 'cfg': ['--enable-static-pie']}, + {'variant': 'static-pie', + 'arch': 'i686', + 'ccopts': '-m32 -march=i686', + 'cfg': ['--enable-static-pie']}, + {'variant': 'disable-multi-arch', + 'arch': 'i686', + 'ccopts': '-m32 -march=i686', + 'cfg': ['--disable-multi-arch']}, + {'arch': 'i486', + 'ccopts': '-m32 -march=i486'}, + {'arch': 'i586', + 'ccopts': '-m32 -march=i586'}]) + + def add_config(self, **args): + """Add an individual build configuration.""" + cfg = Config(self, **args) + if cfg.name in self.configs: + print('error: duplicate config %s' % cfg.name) + exit(1) + self.configs[cfg.name] = cfg + for c in cfg.all_glibcs: + if c.name in self.glibc_configs: + print('error: duplicate glibc config %s' % c.name) + exit(1) + self.glibc_configs[c.name] = c + + def component_srcdir(self, component): + """Return the source directory for a given component, e.g. gcc.""" + return os.path.join(self.srcdir, component) + + def component_builddir(self, action, config, component, subconfig=None): + """Return the directory to use for a build.""" + if config is None: + # Host libraries. + assert subconfig is None + return os.path.join(self.builddir, action, component) + if subconfig is None: + return os.path.join(self.builddir, action, config, component) + else: + # glibc build as part of compiler build. + return os.path.join(self.builddir, action, config, component, + subconfig) + + def compiler_installdir(self, config): + """Return the directory in which to install a compiler.""" + return os.path.join(self.installdir, 'compilers', config) + + def compiler_bindir(self, config): + """Return the directory in which to find compiler binaries.""" + return os.path.join(self.compiler_installdir(config), 'bin') + + def compiler_sysroot(self, config): + """Return the sysroot directory for a compiler.""" + return os.path.join(self.compiler_installdir(config), 'sysroot') + + def glibc_installdir(self, config): + """Return the directory in which to install glibc.""" + return os.path.join(self.installdir, 'glibcs', config) + + def run_builds(self, action, configs): + """Run the requested builds.""" + if action == 'checkout': + self.checkout(configs) + return + if action == 'bot-cycle': + if configs: + print('error: configurations specified for bot-cycle') + exit(1) + self.bot_cycle() + return + if action == 'bot': + if configs: + print('error: configurations specified for bot') + exit(1) + self.bot() + return + if action == 'host-libraries' and configs: + print('error: configurations specified for host-libraries') + exit(1) + self.clear_last_build_state(action) + build_time = datetime.datetime.utcnow() + if action == 'host-libraries': + build_components = ('gmp', 'mpfr', 'mpc') + old_components = () + old_versions = {} + self.build_host_libraries() + elif action == 'compilers': + build_components = ('binutils', 'gcc', 'glibc', 'linux', 'mig', + 'gnumach', 'hurd') + old_components = ('gmp', 'mpfr', 'mpc') + old_versions = self.build_state['host-libraries']['build-versions'] + self.build_compilers(configs) + else: + build_components = ('glibc',) + old_components = ('gmp', 'mpfr', 'mpc', 'binutils', 'gcc', 'linux', + 'mig', 'gnumach', 'hurd') + old_versions = self.build_state['compilers']['build-versions'] + self.build_glibcs(configs) + self.write_files() + self.do_build() + if configs: + # Partial build, do not update stored state. + return + build_versions = {} + for k in build_components: + if k in self.versions: + build_versions[k] = {'version': self.versions[k]['version'], + 'revision': self.versions[k]['revision']} + for k in old_components: + if k in old_versions: + build_versions[k] = {'version': old_versions[k]['version'], + 'revision': old_versions[k]['revision']} + self.update_build_state(action, build_time, build_versions) + + @staticmethod + def remove_dirs(*args): + """Remove directories and their contents if they exist.""" + for dir in args: + shutil.rmtree(dir, ignore_errors=True) + + @staticmethod + def remove_recreate_dirs(*args): + """Remove directories if they exist, and create them as empty.""" + Context.remove_dirs(*args) + for dir in args: + os.makedirs(dir, exist_ok=True) + + def add_makefile_cmdlist(self, target, cmdlist, logsdir): + """Add makefile text for a list of commands.""" + commands = cmdlist.makefile_commands(self.wrapper, logsdir) + self.makefile_pieces.append('all: %s\n.PHONY: %s\n%s:\n%s\n' % + (target, target, target, commands)) + self.status_log_list.extend(cmdlist.status_logs(logsdir)) + + def write_files(self): + """Write out the Makefile and wrapper script.""" + mftext = ''.join(self.makefile_pieces) + with open(self.makefile, 'w') as f: + f.write(mftext) + wrapper_text = ( + '#!/bin/sh\n' + 'prev_base=$1\n' + 'this_base=$2\n' + 'desc=$3\n' + 'dir=$4\n' + 'path=$5\n' + 'shift 5\n' + 'prev_status=$prev_base-status.txt\n' + 'this_status=$this_base-status.txt\n' + 'this_log=$this_base-log.txt\n' + 'date > "$this_log"\n' + 'echo >> "$this_log"\n' + 'echo "Description: $desc" >> "$this_log"\n' + 'printf "%s" "Command:" >> "$this_log"\n' + 'for word in "$@"; do\n' + ' if expr "$word" : "[]+,./0-9@A-Z_a-z-]\\\\{1,\\\\}\\$" > /dev/null; then\n' + ' printf " %s" "$word"\n' + ' else\n' + ' printf " \'"\n' + ' printf "%s" "$word" | sed -e "s/\'/\'\\\\\\\\\'\'/"\n' + ' printf "\'"\n' + ' fi\n' + 'done >> "$this_log"\n' + 'echo >> "$this_log"\n' + 'echo "Directory: $dir" >> "$this_log"\n' + 'echo "Path addition: $path" >> "$this_log"\n' + 'echo >> "$this_log"\n' + 'record_status ()\n' + '{\n' + ' echo >> "$this_log"\n' + ' echo "$1: $desc" > "$this_status"\n' + ' echo "$1: $desc" >> "$this_log"\n' + ' echo >> "$this_log"\n' + ' date >> "$this_log"\n' + ' echo "$1: $desc"\n' + ' exit 0\n' + '}\n' + 'check_error ()\n' + '{\n' + ' if [ "$1" != "0" ]; then\n' + ' record_status FAIL\n' + ' fi\n' + '}\n' + 'if [ "$prev_base" ] && ! grep -q "^PASS" "$prev_status"; then\n' + ' record_status UNRESOLVED\n' + 'fi\n' + 'if [ "$dir" ]; then\n' + ' cd "$dir"\n' + ' check_error "$?"\n' + 'fi\n' + 'if [ "$path" ]; then\n' + ' PATH=$path:$PATH\n' + 'fi\n' + '"$@" < /dev/null >> "$this_log" 2>&1\n' + 'check_error "$?"\n' + 'record_status PASS\n') + with open(self.wrapper, 'w') as f: + f.write(wrapper_text) + # Mode 0o755. + mode_exec = (stat.S_IRWXU|stat.S_IRGRP|stat.S_IXGRP| + stat.S_IROTH|stat.S_IXOTH) + os.chmod(self.wrapper, mode_exec) + save_logs_text = ( + '#!/bin/sh\n' + 'if ! [ -f tests.sum ]; then\n' + ' echo "No test summary available."\n' + ' exit 0\n' + 'fi\n' + 'save_file ()\n' + '{\n' + ' echo "Contents of $1:"\n' + ' echo\n' + ' cat "$1"\n' + ' echo\n' + ' echo "End of contents of $1."\n' + ' echo\n' + '}\n' + 'save_file tests.sum\n' + 'non_pass_tests=$(grep -v "^PASS: " tests.sum | sed -e "s/^PASS: //")\n' + 'for t in $non_pass_tests; do\n' + ' if [ -f "$t.out" ]; then\n' + ' save_file "$t.out"\n' + ' fi\n' + 'done\n') + with open(self.save_logs, 'w') as f: + f.write(save_logs_text) + os.chmod(self.save_logs, mode_exec) + + def do_build(self): + """Do the actual build.""" + cmd = ['make', '-j%d' % self.parallelism] + subprocess.run(cmd, cwd=self.builddir, check=True) + + def build_host_libraries(self): + """Build the host libraries.""" + installdir = self.host_libraries_installdir + builddir = os.path.join(self.builddir, 'host-libraries') + logsdir = os.path.join(self.logsdir, 'host-libraries') + self.remove_recreate_dirs(installdir, builddir, logsdir) + cmdlist = CommandList('host-libraries', self.keep) + self.build_host_library(cmdlist, 'gmp') + self.build_host_library(cmdlist, 'mpfr', + ['--with-gmp=%s' % installdir]) + self.build_host_library(cmdlist, 'mpc', + ['--with-gmp=%s' % installdir, + '--with-mpfr=%s' % installdir]) + cmdlist.add_command('done', ['touch', os.path.join(installdir, 'ok')]) + self.add_makefile_cmdlist('host-libraries', cmdlist, logsdir) + + def build_host_library(self, cmdlist, lib, extra_opts=None): + """Build one host library.""" + srcdir = self.component_srcdir(lib) + builddir = self.component_builddir('host-libraries', None, lib) + installdir = self.host_libraries_installdir + cmdlist.push_subdesc(lib) + cmdlist.create_use_dir(builddir) + cfg_cmd = [os.path.join(srcdir, 'configure'), + '--prefix=%s' % installdir, + '--disable-shared'] + if extra_opts: + cfg_cmd.extend (extra_opts) + cmdlist.add_command('configure', cfg_cmd) + cmdlist.add_command('build', ['make']) + cmdlist.add_command('check', ['make', 'check']) + cmdlist.add_command('install', ['make', 'install']) + cmdlist.cleanup_dir() + cmdlist.pop_subdesc() + + def build_compilers(self, configs): + """Build the compilers.""" + if not configs: + self.remove_dirs(os.path.join(self.builddir, 'compilers')) + self.remove_dirs(os.path.join(self.installdir, 'compilers')) + self.remove_dirs(os.path.join(self.logsdir, 'compilers')) + configs = sorted(self.configs.keys()) + for c in configs: + self.configs[c].build() + + def build_glibcs(self, configs): + """Build the glibcs.""" + if not configs: + self.remove_dirs(os.path.join(self.builddir, 'glibcs')) + self.remove_dirs(os.path.join(self.installdir, 'glibcs')) + self.remove_dirs(os.path.join(self.logsdir, 'glibcs')) + configs = sorted(self.glibc_configs.keys()) + for c in configs: + self.glibc_configs[c].build() + + def load_versions_json(self): + """Load information about source directory versions.""" + if not os.access(self.versions_json, os.F_OK): + self.versions = {} + return + with open(self.versions_json, 'r') as f: + self.versions = json.load(f) + + def store_json(self, data, filename): + """Store information in a JSON file.""" + filename_tmp = filename + '.tmp' + with open(filename_tmp, 'w') as f: + json.dump(data, f, indent=2, sort_keys=True) + os.rename(filename_tmp, filename) + + def store_versions_json(self): + """Store information about source directory versions.""" + self.store_json(self.versions, self.versions_json) + + def set_component_version(self, component, version, explicit, revision): + """Set the version information for a component.""" + self.versions[component] = {'version': version, + 'explicit': explicit, + 'revision': revision} + self.store_versions_json() + + def checkout(self, versions): + """Check out the desired component versions.""" + default_versions = {'binutils': 'vcs-2.31', + 'gcc': 'vcs-8', + 'glibc': 'vcs-mainline', + 'gmp': '6.1.2', + 'linux': '4.17', + 'mpc': '1.1.0', + 'mpfr': '4.0.1', + 'mig': 'vcs-mainline', + 'gnumach': 'vcs-mainline', + 'hurd': 'vcs-mainline'} + use_versions = {} + explicit_versions = {} + for v in versions: + found_v = False + for k in default_versions.keys(): + kx = k + '-' + if v.startswith(kx): + vx = v[len(kx):] + if k in use_versions: + print('error: multiple versions for %s' % k) + exit(1) + use_versions[k] = vx + explicit_versions[k] = True + found_v = True + break + if not found_v: + print('error: unknown component in %s' % v) + exit(1) + for k in default_versions.keys(): + if k not in use_versions: + if k in self.versions and self.versions[k]['explicit']: + use_versions[k] = self.versions[k]['version'] + explicit_versions[k] = True + else: + use_versions[k] = default_versions[k] + explicit_versions[k] = False + os.makedirs(self.srcdir, exist_ok=True) + for k in sorted(default_versions.keys()): + update = os.access(self.component_srcdir(k), os.F_OK) + v = use_versions[k] + if (update and + k in self.versions and + v != self.versions[k]['version']): + if not self.replace_sources: + print('error: version of %s has changed from %s to %s, ' + 'use --replace-sources to check out again' % + (k, self.versions[k]['version'], v)) + exit(1) + shutil.rmtree(self.component_srcdir(k)) + update = False + if v.startswith('vcs-'): + revision = self.checkout_vcs(k, v[4:], update) + else: + self.checkout_tar(k, v, update) + revision = v + self.set_component_version(k, v, explicit_versions[k], revision) + if self.get_script_text() != self.script_text: + # Rerun the checkout process in case the updated script + # uses different default versions or new components. + self.exec_self() + + def checkout_vcs(self, component, version, update): + """Check out the given version of the given component from version + control. Return a revision identifier.""" + if component == 'binutils': + git_url = 'git://sourceware.org/git/binutils-gdb.git' + if version == 'mainline': + git_branch = 'master' + else: + trans = str.maketrans({'.': '_'}) + git_branch = 'binutils-%s-branch' % version.translate(trans) + return self.git_checkout(component, git_url, git_branch, update) + elif component == 'gcc': + if version == 'mainline': + branch = 'trunk' + else: + trans = str.maketrans({'.': '_'}) + branch = 'branches/gcc-%s-branch' % version.translate(trans) + svn_url = 'svn://gcc.gnu.org/svn/gcc/%s' % branch + return self.gcc_checkout(svn_url, update) + elif component == 'glibc': + git_url = 'git://sourceware.org/git/glibc.git' + if version == 'mainline': + git_branch = 'master' + else: + git_branch = 'release/%s/master' % version + r = self.git_checkout(component, git_url, git_branch, update) + self.fix_glibc_timestamps() + return r + elif component == 'gnumach': + git_url = 'git://git.savannah.gnu.org/hurd/gnumach.git' + git_branch = 'master' + r = self.git_checkout(component, git_url, git_branch, update) + subprocess.run(['autoreconf', '-i'], + cwd=self.component_srcdir(component), check=True) + return r + elif component == 'mig': + git_url = 'git://git.savannah.gnu.org/hurd/mig.git' + git_branch = 'master' + r = self.git_checkout(component, git_url, git_branch, update) + subprocess.run(['autoreconf', '-i'], + cwd=self.component_srcdir(component), check=True) + return r + elif component == 'hurd': + git_url = 'git://git.savannah.gnu.org/hurd/hurd.git' + git_branch = 'master' + r = self.git_checkout(component, git_url, git_branch, update) + subprocess.run(['autoconf'], + cwd=self.component_srcdir(component), check=True) + return r + else: + print('error: component %s coming from VCS' % component) + exit(1) + + def git_checkout(self, component, git_url, git_branch, update): + """Check out a component from git. Return a commit identifier.""" + if update: + subprocess.run(['git', 'remote', 'prune', 'origin'], + cwd=self.component_srcdir(component), check=True) + if self.replace_sources: + subprocess.run(['git', 'clean', '-dxfq'], + cwd=self.component_srcdir(component), check=True) + subprocess.run(['git', 'pull', '-q'], + cwd=self.component_srcdir(component), check=True) + else: + subprocess.run(['git', 'clone', '-q', '-b', git_branch, git_url, + self.component_srcdir(component)], check=True) + r = subprocess.run(['git', 'rev-parse', 'HEAD'], + cwd=self.component_srcdir(component), + stdout=subprocess.PIPE, + check=True, universal_newlines=True).stdout + return r.rstrip() + + def fix_glibc_timestamps(self): + """Fix timestamps in a glibc checkout.""" + # Ensure that builds do not try to regenerate generated files + # in the source tree. + srcdir = self.component_srcdir('glibc') + for dirpath, dirnames, filenames in os.walk(srcdir): + for f in filenames: + if (f == 'configure' or + f == 'preconfigure' or + f.endswith('-kw.h')): + to_touch = os.path.join(dirpath, f) + subprocess.run(['touch', to_touch], check=True) + + def gcc_checkout(self, svn_url, update): + """Check out GCC from SVN. Return the revision number.""" + if not update: + subprocess.run(['svn', 'co', '-q', svn_url, + self.component_srcdir('gcc')], check=True) + subprocess.run(['contrib/gcc_update', '--silent'], + cwd=self.component_srcdir('gcc'), check=True) + r = subprocess.run(['svnversion', self.component_srcdir('gcc')], + stdout=subprocess.PIPE, + check=True, universal_newlines=True).stdout + return r.rstrip() + + def checkout_tar(self, component, version, update): + """Check out the given version of the given component from a + tarball.""" + if update: + return + url_map = {'binutils': 'https://ftp.gnu.org/gnu/binutils/binutils-%(version)s.tar.bz2', + 'gcc': 'https://ftp.gnu.org/gnu/gcc/gcc-%(version)s/gcc-%(version)s.tar.gz', + 'gmp': 'https://ftp.gnu.org/gnu/gmp/gmp-%(version)s.tar.xz', + 'linux': 'https://www.kernel.org/pub/linux/kernel/v4.x/linux-%(version)s.tar.xz', + 'mpc': 'https://ftp.gnu.org/gnu/mpc/mpc-%(version)s.tar.gz', + 'mpfr': 'https://ftp.gnu.org/gnu/mpfr/mpfr-%(version)s.tar.xz', + 'mig': 'https://ftp.gnu.org/gnu/mig/mig-%(version)s.tar.bz2', + 'gnumach': 'https://ftp.gnu.org/gnu/gnumach/gnumach-%(version)s.tar.bz2', + 'hurd': 'https://ftp.gnu.org/gnu/hurd/hurd-%(version)s.tar.bz2'} + if component not in url_map: + print('error: component %s coming from tarball' % component) + exit(1) + url = url_map[component] % {'version': version} + filename = os.path.join(self.srcdir, url.split('/')[-1]) + response = urllib.request.urlopen(url) + data = response.read() + with open(filename, 'wb') as f: + f.write(data) + subprocess.run(['tar', '-C', self.srcdir, '-x', '-f', filename], + check=True) + os.rename(os.path.join(self.srcdir, '%s-%s' % (component, version)), + self.component_srcdir(component)) + os.remove(filename) + + def load_build_state_json(self): + """Load information about the state of previous builds.""" + if os.access(self.build_state_json, os.F_OK): + with open(self.build_state_json, 'r') as f: + self.build_state = json.load(f) + else: + self.build_state = {} + for k in ('host-libraries', 'compilers', 'glibcs'): + if k not in self.build_state: + self.build_state[k] = {} + if 'build-time' not in self.build_state[k]: + self.build_state[k]['build-time'] = '' + if 'build-versions' not in self.build_state[k]: + self.build_state[k]['build-versions'] = {} + if 'build-results' not in self.build_state[k]: + self.build_state[k]['build-results'] = {} + if 'result-changes' not in self.build_state[k]: + self.build_state[k]['result-changes'] = {} + if 'ever-passed' not in self.build_state[k]: + self.build_state[k]['ever-passed'] = [] + + def store_build_state_json(self): + """Store information about the state of previous builds.""" + self.store_json(self.build_state, self.build_state_json) + + def clear_last_build_state(self, action): + """Clear information about the state of part of the build.""" + # We clear the last build time and versions when starting a + # new build. The results of the last build are kept around, + # as comparison is still meaningful if this build is aborted + # and a new one started. + self.build_state[action]['build-time'] = '' + self.build_state[action]['build-versions'] = {} + self.store_build_state_json() + + def update_build_state(self, action, build_time, build_versions): + """Update the build state after a build.""" + build_time = build_time.replace(microsecond=0) + self.build_state[action]['build-time'] = str(build_time) + self.build_state[action]['build-versions'] = build_versions + build_results = {} + for log in self.status_log_list: + with open(log, 'r') as f: + log_text = f.read() + log_text = log_text.rstrip() + m = re.fullmatch('([A-Z]+): (.*)', log_text) + result = m.group(1) + test_name = m.group(2) + assert test_name not in build_results + build_results[test_name] = result + old_build_results = self.build_state[action]['build-results'] + self.build_state[action]['build-results'] = build_results + result_changes = {} + all_tests = set(old_build_results.keys()) | set(build_results.keys()) + for t in all_tests: + if t in old_build_results: + old_res = old_build_results[t] + else: + old_res = '(New test)' + if t in build_results: + new_res = build_results[t] + else: + new_res = '(Test removed)' + if old_res != new_res: + result_changes[t] = '%s -> %s' % (old_res, new_res) + self.build_state[action]['result-changes'] = result_changes + old_ever_passed = {t for t in self.build_state[action]['ever-passed'] + if t in build_results} + new_passes = {t for t in build_results if build_results[t] == 'PASS'} + self.build_state[action]['ever-passed'] = sorted(old_ever_passed | + new_passes) + self.store_build_state_json() + + def load_bot_config_json(self): + """Load bot configuration.""" + with open(self.bot_config_json, 'r') as f: + self.bot_config = json.load(f) + + def part_build_old(self, action, delay): + """Return whether the last build for a given action was at least a + given number of seconds ago, or does not have a time recorded.""" + old_time_str = self.build_state[action]['build-time'] + if not old_time_str: + return True + old_time = datetime.datetime.strptime(old_time_str, + '%Y-%m-%d %H:%M:%S') + new_time = datetime.datetime.utcnow() + delta = new_time - old_time + return delta.total_seconds() >= delay + + def bot_cycle(self): + """Run a single round of checkout and builds.""" + print('Bot cycle starting %s.' % str(datetime.datetime.utcnow())) + self.load_bot_config_json() + actions = ('host-libraries', 'compilers', 'glibcs') + self.bot_run_self(['--replace-sources'], 'checkout') + self.load_versions_json() + if self.get_script_text() != self.script_text: + print('Script changed, re-execing.') + # On script change, all parts of the build should be rerun. + for a in actions: + self.clear_last_build_state(a) + self.exec_self() + check_components = {'host-libraries': ('gmp', 'mpfr', 'mpc'), + 'compilers': ('binutils', 'gcc', 'glibc', 'linux', + 'mig', 'gnumach', 'hurd'), + 'glibcs': ('glibc',)} + must_build = {} + for a in actions: + build_vers = self.build_state[a]['build-versions'] + must_build[a] = False + if not self.build_state[a]['build-time']: + must_build[a] = True + old_vers = {} + new_vers = {} + for c in check_components[a]: + if c in build_vers: + old_vers[c] = build_vers[c] + new_vers[c] = {'version': self.versions[c]['version'], + 'revision': self.versions[c]['revision']} + if new_vers == old_vers: + print('Versions for %s unchanged.' % a) + else: + print('Versions changed or rebuild forced for %s.' % a) + if a == 'compilers' and not self.part_build_old( + a, self.bot_config['compilers-rebuild-delay']): + print('Not requiring rebuild of compilers this soon.') + else: + must_build[a] = True + if must_build['host-libraries']: + must_build['compilers'] = True + if must_build['compilers']: + must_build['glibcs'] = True + for a in actions: + if must_build[a]: + print('Must rebuild %s.' % a) + self.clear_last_build_state(a) + else: + print('No need to rebuild %s.' % a) + if os.access(self.logsdir, os.F_OK): + shutil.rmtree(self.logsdir_old, ignore_errors=True) + shutil.copytree(self.logsdir, self.logsdir_old) + for a in actions: + if must_build[a]: + build_time = datetime.datetime.utcnow() + print('Rebuilding %s at %s.' % (a, str(build_time))) + self.bot_run_self([], a) + self.load_build_state_json() + self.bot_build_mail(a, build_time) + print('Bot cycle done at %s.' % str(datetime.datetime.utcnow())) + + def bot_build_mail(self, action, build_time): + """Send email with the results of a build.""" + if not ('email-from' in self.bot_config and + 'email-server' in self.bot_config and + 'email-subject' in self.bot_config and + 'email-to' in self.bot_config): + if not self.email_warning: + print("Email not configured, not sending.") + self.email_warning = True + return + + build_time = build_time.replace(microsecond=0) + subject = (self.bot_config['email-subject'] % + {'action': action, + 'build-time': str(build_time)}) + results = self.build_state[action]['build-results'] + changes = self.build_state[action]['result-changes'] + ever_passed = set(self.build_state[action]['ever-passed']) + versions = self.build_state[action]['build-versions'] + new_regressions = {k for k in changes if changes[k] == 'PASS -> FAIL'} + all_regressions = {k for k in ever_passed if results[k] == 'FAIL'} + all_fails = {k for k in results if results[k] == 'FAIL'} + if new_regressions: + new_reg_list = sorted(['FAIL: %s' % k for k in new_regressions]) + new_reg_text = ('New regressions:\n\n%s\n\n' % + '\n'.join(new_reg_list)) + else: + new_reg_text = '' + if all_regressions: + all_reg_list = sorted(['FAIL: %s' % k for k in all_regressions]) + all_reg_text = ('All regressions:\n\n%s\n\n' % + '\n'.join(all_reg_list)) + else: + all_reg_text = '' + if all_fails: + all_fail_list = sorted(['FAIL: %s' % k for k in all_fails]) + all_fail_text = ('All failures:\n\n%s\n\n' % + '\n'.join(all_fail_list)) + else: + all_fail_text = '' + if changes: + changes_list = sorted(changes.keys()) + changes_list = ['%s: %s' % (changes[k], k) for k in changes_list] + changes_text = ('All changed results:\n\n%s\n\n' % + '\n'.join(changes_list)) + else: + changes_text = '' + results_text = (new_reg_text + all_reg_text + all_fail_text + + changes_text) + if not results_text: + results_text = 'Clean build with unchanged results.\n\n' + versions_list = sorted(versions.keys()) + versions_list = ['%s: %s (%s)' % (k, versions[k]['version'], + versions[k]['revision']) + for k in versions_list] + versions_text = ('Component versions for this build:\n\n%s\n' % + '\n'.join(versions_list)) + body_text = results_text + versions_text + msg = email.mime.text.MIMEText(body_text) + msg['Subject'] = subject + msg['From'] = self.bot_config['email-from'] + msg['To'] = self.bot_config['email-to'] + msg['Message-ID'] = email.utils.make_msgid() + msg['Date'] = email.utils.format_datetime(datetime.datetime.utcnow()) + with smtplib.SMTP(self.bot_config['email-server']) as s: + s.send_message(msg) + + def bot_run_self(self, opts, action, check=True): + """Run a copy of this script with given options.""" + cmd = [sys.executable, sys.argv[0], '--keep=none', + '-j%d' % self.parallelism] + cmd.extend(opts) + cmd.extend([self.topdir, action]) + sys.stdout.flush() + subprocess.run(cmd, check=check) + + def bot(self): + """Run repeated rounds of checkout and builds.""" + while True: + self.load_bot_config_json() + if not self.bot_config['run']: + print('Bot exiting by request.') + exit(0) + self.bot_run_self([], 'bot-cycle', check=False) + self.load_bot_config_json() + if not self.bot_config['run']: + print('Bot exiting by request.') + exit(0) + time.sleep(self.bot_config['delay']) + if self.get_script_text() != self.script_text: + print('Script changed, bot re-execing.') + self.exec_self() + + +class Config(object): + """A configuration for building a compiler and associated libraries.""" + + def __init__(self, ctx, arch, os_name, variant=None, gcc_cfg=None, + first_gcc_cfg=None, glibcs=None, extra_glibcs=None): + """Initialize a Config object.""" + self.ctx = ctx + self.arch = arch + self.os = os_name + self.variant = variant + if variant is None: + self.name = '%s-%s' % (arch, os_name) + else: + self.name = '%s-%s-%s' % (arch, os_name, variant) + self.triplet = '%s-glibc-%s' % (arch, os_name) + if gcc_cfg is None: + self.gcc_cfg = [] + else: + self.gcc_cfg = gcc_cfg + if first_gcc_cfg is None: + self.first_gcc_cfg = [] + else: + self.first_gcc_cfg = first_gcc_cfg + if glibcs is None: + glibcs = [{'variant': variant}] + if extra_glibcs is None: + extra_glibcs = [] + glibcs = [Glibc(self, **g) for g in glibcs] + extra_glibcs = [Glibc(self, **g) for g in extra_glibcs] + self.all_glibcs = glibcs + extra_glibcs + self.compiler_glibcs = glibcs + self.installdir = ctx.compiler_installdir(self.name) + self.bindir = ctx.compiler_bindir(self.name) + self.sysroot = ctx.compiler_sysroot(self.name) + self.builddir = os.path.join(ctx.builddir, 'compilers', self.name) + self.logsdir = os.path.join(ctx.logsdir, 'compilers', self.name) + + def component_builddir(self, component): + """Return the directory to use for a (non-glibc) build.""" + return self.ctx.component_builddir('compilers', self.name, component) + + def build(self): + """Generate commands to build this compiler.""" + self.ctx.remove_recreate_dirs(self.installdir, self.builddir, + self.logsdir) + cmdlist = CommandList('compilers-%s' % self.name, self.ctx.keep) + cmdlist.add_command('check-host-libraries', + ['test', '-f', + os.path.join(self.ctx.host_libraries_installdir, + 'ok')]) + cmdlist.use_path(self.bindir) + self.build_cross_tool(cmdlist, 'binutils', 'binutils', + ['--disable-gdb', + '--disable-libdecnumber', + '--disable-readline', + '--disable-sim']) + if self.os.startswith('linux'): + self.install_linux_headers(cmdlist) + self.build_gcc(cmdlist, True) + if self.os == 'gnu': + self.install_gnumach_headers(cmdlist) + self.build_cross_tool(cmdlist, 'mig', 'mig') + self.install_hurd_headers(cmdlist) + for g in self.compiler_glibcs: + cmdlist.push_subdesc('glibc') + cmdlist.push_subdesc(g.name) + g.build_glibc(cmdlist, True) + cmdlist.pop_subdesc() + cmdlist.pop_subdesc() + self.build_gcc(cmdlist, False) + cmdlist.add_command('done', ['touch', + os.path.join(self.installdir, 'ok')]) + self.ctx.add_makefile_cmdlist('compilers-%s' % self.name, cmdlist, + self.logsdir) + + def build_cross_tool(self, cmdlist, tool_src, tool_build, extra_opts=None): + """Build one cross tool.""" + srcdir = self.ctx.component_srcdir(tool_src) + builddir = self.component_builddir(tool_build) + cmdlist.push_subdesc(tool_build) + cmdlist.create_use_dir(builddir) + cfg_cmd = [os.path.join(srcdir, 'configure'), + '--prefix=%s' % self.installdir, + '--build=%s' % self.ctx.build_triplet, + '--host=%s' % self.ctx.build_triplet, + '--target=%s' % self.triplet, + '--with-sysroot=%s' % self.sysroot] + if extra_opts: + cfg_cmd.extend(extra_opts) + cmdlist.add_command('configure', cfg_cmd) + cmdlist.add_command('build', ['make']) + # Parallel "make install" for GCC has race conditions that can + # cause it to fail; see + # <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42980>. Such + # problems are not known for binutils, but doing the + # installation in parallel within a particular toolchain build + # (as opposed to installation of one toolchain from + # build-many-glibcs.py running in parallel to the installation + # of other toolchains being built) is not known to be + # significantly beneficial, so it is simplest just to disable + # parallel install for cross tools here. + cmdlist.add_command('install', ['make', '-j1', 'install']) + cmdlist.cleanup_dir() + cmdlist.pop_subdesc() + + def install_linux_headers(self, cmdlist): + """Install Linux kernel headers.""" + arch_map = {'aarch64': 'arm64', + 'alpha': 'alpha', + 'arm': 'arm', + 'hppa': 'parisc', + 'i486': 'x86', + 'i586': 'x86', + 'i686': 'x86', + 'i786': 'x86', + 'ia64': 'ia64', + 'm68k': 'm68k', + 'microblaze': 'microblaze', + 'mips': 'mips', + 'nios2': 'nios2', + 'powerpc': 'powerpc', + 's390': 's390', + 'riscv32': 'riscv', + 'riscv64': 'riscv', + 'sh': 'sh', + 'sparc': 'sparc', + 'x86_64': 'x86'} + linux_arch = None + for k in arch_map: + if self.arch.startswith(k): + linux_arch = arch_map[k] + break + assert linux_arch is not None + srcdir = self.ctx.component_srcdir('linux') + builddir = self.component_builddir('linux') + headers_dir = os.path.join(self.sysroot, 'usr') + cmdlist.push_subdesc('linux') + cmdlist.create_use_dir(builddir) + cmdlist.add_command('install-headers', + ['make', '-C', srcdir, 'O=%s' % builddir, + 'ARCH=%s' % linux_arch, + 'INSTALL_HDR_PATH=%s' % headers_dir, + 'headers_install']) + cmdlist.cleanup_dir() + cmdlist.pop_subdesc() + + def install_gnumach_headers(self, cmdlist): + """Install GNU Mach headers.""" + srcdir = self.ctx.component_srcdir('gnumach') + builddir = self.component_builddir('gnumach') + cmdlist.push_subdesc('gnumach') + cmdlist.create_use_dir(builddir) + cmdlist.add_command('configure', + [os.path.join(srcdir, 'configure'), + '--build=%s' % self.ctx.build_triplet, + '--host=%s' % self.triplet, + '--prefix=', + 'CC=%s-gcc -nostdlib' % self.triplet]) + cmdlist.add_command('install', ['make', 'DESTDIR=%s' % self.sysroot, + 'install-data']) + cmdlist.cleanup_dir() + cmdlist.pop_subdesc() + + def install_hurd_headers(self, cmdlist): + """Install Hurd headers.""" + srcdir = self.ctx.component_srcdir('hurd') + builddir = self.component_builddir('hurd') + cmdlist.push_subdesc('hurd') + cmdlist.create_use_dir(builddir) + cmdlist.add_command('configure', + [os.path.join(srcdir, 'configure'), + '--build=%s' % self.ctx.build_triplet, + '--host=%s' % self.triplet, + '--prefix=', + '--disable-profile', '--without-parted', + 'CC=%s-gcc -nostdlib' % self.triplet]) + cmdlist.add_command('install', ['make', 'prefix=%s' % self.sysroot, + 'no_deps=t', 'install-headers']) + cmdlist.cleanup_dir() + cmdlist.pop_subdesc() + + def build_gcc(self, cmdlist, bootstrap): + """Build GCC.""" + # libsanitizer commonly breaks because of glibc header + # changes, or on unusual targets. libssp is of little + # relevance with glibc's own stack checking support. + # libcilkrts does not support GNU/Hurd (and has been removed + # in GCC 8, so --disable-libcilkrts can be removed once glibc + # no longer supports building with older GCC versions). + cfg_opts = list(self.gcc_cfg) + cfg_opts += ['--disable-libsanitizer', '--disable-libssp', + '--disable-libcilkrts'] + host_libs = self.ctx.host_libraries_installdir + cfg_opts += ['--with-gmp=%s' % host_libs, + '--with-mpfr=%s' % host_libs, + '--with-mpc=%s' % host_libs] + if bootstrap: + tool_build = 'gcc-first' + # Building a static-only, C-only compiler that is + # sufficient to build glibc. Various libraries and + # features that may require libc headers must be disabled. + # When configuring with a sysroot, --with-newlib is + # required to define inhibit_libc (to stop some parts of + # libgcc including libc headers); --without-headers is not + # sufficient. + cfg_opts += ['--enable-languages=c', '--disable-shared', + '--disable-threads', + '--disable-libatomic', + '--disable-decimal-float', + '--disable-libffi', + '--disable-libgomp', + '--disable-libitm', + '--disable-libmpx', + '--disable-libquadmath', + '--without-headers', '--with-newlib', + '--with-glibc-version=%s' % self.ctx.glibc_version + ] + cfg_opts += self.first_gcc_cfg + else: + tool_build = 'gcc' + cfg_opts += ['--enable-languages=c,c++', '--enable-shared', + '--enable-threads'] + self.build_cross_tool(cmdlist, 'gcc', tool_build, cfg_opts) + + +class Glibc(object): + """A configuration for building glibc.""" + + def __init__(self, compiler, arch=None, os_name=None, variant=None, + cfg=None, ccopts=None): + """Initialize a Glibc object.""" + self.ctx = compiler.ctx + self.compiler = compiler + if arch is None: + self.arch = compiler.arch + else: + self.arch = arch + if os_name is None: + self.os = compiler.os + else: + self.os = os_name + self.variant = variant + if variant is None: + self.name = '%s-%s' % (self.arch, self.os) + else: + self.name = '%s-%s-%s' % (self.arch, self.os, variant) + self.triplet = '%s-glibc-%s' % (self.arch, self.os) + if cfg is None: + self.cfg = [] + else: + self.cfg = cfg + self.ccopts = ccopts + + def tool_name(self, tool): + """Return the name of a cross-compilation tool.""" + ctool = '%s-%s' % (self.compiler.triplet, tool) + if self.ccopts and (tool == 'gcc' or tool == 'g++'): + ctool = '%s %s' % (ctool, self.ccopts) + return ctool + + def build(self): + """Generate commands to build this glibc.""" + builddir = self.ctx.component_builddir('glibcs', self.name, 'glibc') + installdir = self.ctx.glibc_installdir(self.name) + logsdir = os.path.join(self.ctx.logsdir, 'glibcs', self.name) + self.ctx.remove_recreate_dirs(installdir, builddir, logsdir) + cmdlist = CommandList('glibcs-%s' % self.name, self.ctx.keep) + cmdlist.add_command('check-compilers', + ['test', '-f', + os.path.join(self.compiler.installdir, 'ok')]) + cmdlist.use_path(self.compiler.bindir) + self.build_glibc(cmdlist, False) + self.ctx.add_makefile_cmdlist('glibcs-%s' % self.name, cmdlist, + logsdir) + + def build_glibc(self, cmdlist, for_compiler): + """Generate commands to build this glibc, either as part of a compiler + build or with the bootstrapped compiler (and in the latter case, run + tests as well).""" + srcdir = self.ctx.component_srcdir('glibc') + if for_compiler: + builddir = self.ctx.component_builddir('compilers', + self.compiler.name, 'glibc', + self.name) + installdir = self.compiler.sysroot + srcdir_copy = self.ctx.component_builddir('compilers', + self.compiler.name, + 'glibc-src', + self.name) + else: + builddir = self.ctx.component_builddir('glibcs', self.name, + 'glibc') + installdir = self.ctx.glibc_installdir(self.name) + srcdir_copy = self.ctx.component_builddir('glibcs', self.name, + 'glibc-src') + cmdlist.create_use_dir(builddir) + # glibc builds write into the source directory, and even if + # not intentionally there is a risk of bugs that involve + # writing into the working directory. To avoid possible + # concurrency issues, copy the source directory. + cmdlist.create_copy_dir(srcdir, srcdir_copy) + use_usr = self.os != 'gnu' + prefix = '/usr' if use_usr else '' + cfg_cmd = [os.path.join(srcdir_copy, 'configure'), + '--prefix=%s' % prefix, + '--enable-profile', + '--build=%s' % self.ctx.build_triplet, + '--host=%s' % self.triplet, + 'CC=%s' % self.tool_name('gcc'), + 'CXX=%s' % self.tool_name('g++'), + 'AR=%s' % self.tool_name('ar'), + 'AS=%s' % self.tool_name('as'), + 'LD=%s' % self.tool_name('ld'), + 'NM=%s' % self.tool_name('nm'), + 'OBJCOPY=%s' % self.tool_name('objcopy'), + 'OBJDUMP=%s' % self.tool_name('objdump'), + 'RANLIB=%s' % self.tool_name('ranlib'), + 'READELF=%s' % self.tool_name('readelf'), + 'STRIP=%s' % self.tool_name('strip')] + if self.os == 'gnu': + cfg_cmd += ['MIG=%s' % self.tool_name('mig')] + cfg_cmd += self.cfg + cmdlist.add_command('configure', cfg_cmd) + cmdlist.add_command('build', ['make']) + cmdlist.add_command('install', ['make', 'install', + 'install_root=%s' % installdir]) + # GCC uses paths such as lib/../lib64, so make sure lib + # directories always exist. + mkdir_cmd = ['mkdir', '-p', + os.path.join(installdir, 'lib')] + if use_usr: + mkdir_cmd += [os.path.join(installdir, 'usr', 'lib')] + cmdlist.add_command('mkdir-lib', mkdir_cmd) + if not for_compiler: + if self.ctx.strip: + cmdlist.add_command('strip', + ['sh', '-c', + ('%s $(find %s/lib* -name "*.so")' % + (self.tool_name('strip'), installdir))]) + cmdlist.add_command('check', ['make', 'check']) + cmdlist.add_command('save-logs', [self.ctx.save_logs], + always_run=True) + cmdlist.cleanup_dir('cleanup-src', srcdir_copy) + cmdlist.cleanup_dir() + + +class Command(object): + """A command run in the build process.""" + + def __init__(self, desc, num, dir, path, command, always_run=False): + """Initialize a Command object.""" + self.dir = dir + self.path = path + self.desc = desc + trans = str.maketrans({' ': '-'}) + self.logbase = '%03d-%s' % (num, desc.translate(trans)) + self.command = command + self.always_run = always_run + + @staticmethod + def shell_make_quote_string(s): + """Given a string not containing a newline, quote it for use by the + shell and make.""" + assert '\n' not in s + if re.fullmatch('[]+,./0-9@A-Z_a-z-]+', s): + return s + strans = str.maketrans({"'": "'\\''"}) + s = "'%s'" % s.translate(strans) + mtrans = str.maketrans({'$': '$$'}) + return s.translate(mtrans) + + @staticmethod + def shell_make_quote_list(l, translate_make): + """Given a list of strings not containing newlines, quote them for use + by the shell and make, returning a single string. If translate_make + is true and the first string is 'make', change it to $(MAKE).""" + l = [Command.shell_make_quote_string(s) for s in l] + if translate_make and l[0] == 'make': + l[0] = '$(MAKE)' + return ' '.join(l) + + def shell_make_quote(self): + """Return this command quoted for the shell and make.""" + return self.shell_make_quote_list(self.command, True) + + +class CommandList(object): + """A list of commands run in the build process.""" + + def __init__(self, desc, keep): + """Initialize a CommandList object.""" + self.cmdlist = [] + self.dir = None + self.path = None + self.desc = [desc] + self.keep = keep + + def desc_txt(self, desc): + """Return the description to use for a command.""" + return '%s %s' % (' '.join(self.desc), desc) + + def use_dir(self, dir): + """Set the default directory for subsequent commands.""" + self.dir = dir + + def use_path(self, path): + """Set a directory to be prepended to the PATH for subsequent + commands.""" + self.path = path + + def push_subdesc(self, subdesc): + """Set the default subdescription for subsequent commands (e.g., the + name of a component being built, within the series of commands + building it).""" + self.desc.append(subdesc) + + def pop_subdesc(self): + """Pop a subdescription from the list of descriptions.""" + self.desc.pop() + + def create_use_dir(self, dir): + """Remove and recreate a directory and use it for subsequent + commands.""" + self.add_command_dir('rm', None, ['rm', '-rf', dir]) + self.add_command_dir('mkdir', None, ['mkdir', '-p', dir]) + self.use_dir(dir) + + def create_copy_dir(self, src, dest): + """Remove a directory and recreate it as a copy from the given + source.""" + self.add_command_dir('copy-rm', None, ['rm', '-rf', dest]) + parent = os.path.dirname(dest) + self.add_command_dir('copy-mkdir', None, ['mkdir', '-p', parent]) + self.add_command_dir('copy', None, ['cp', '-a', src, dest]) + + def add_command_dir(self, desc, dir, command, always_run=False): + """Add a command to run in a given directory.""" + cmd = Command(self.desc_txt(desc), len(self.cmdlist), dir, self.path, + command, always_run) + self.cmdlist.append(cmd) + + def add_command(self, desc, command, always_run=False): + """Add a command to run in the default directory.""" + cmd = Command(self.desc_txt(desc), len(self.cmdlist), self.dir, + self.path, command, always_run) + self.cmdlist.append(cmd) + + def cleanup_dir(self, desc='cleanup', dir=None): + """Clean up a build directory. If no directory is specified, the + default directory is cleaned up and ceases to be the default + directory.""" + if dir is None: + dir = self.dir + self.use_dir(None) + if self.keep != 'all': + self.add_command_dir(desc, None, ['rm', '-rf', dir], + always_run=(self.keep == 'none')) + + def makefile_commands(self, wrapper, logsdir): + """Return the sequence of commands in the form of text for a Makefile. + The given wrapper script takes arguments: base of logs for + previous command, or empty; base of logs for this command; + description; directory; PATH addition; the command itself.""" + # prev_base is the base of the name for logs of the previous + # command that is not always-run (that is, a build command, + # whose failure should stop subsequent build commands from + # being run, as opposed to a cleanup command, which is run + # even if previous commands failed). + prev_base = '' + cmds = [] + for c in self.cmdlist: + ctxt = c.shell_make_quote() + if prev_base and not c.always_run: + prev_log = os.path.join(logsdir, prev_base) + else: + prev_log = '' + this_log = os.path.join(logsdir, c.logbase) + if not c.always_run: + prev_base = c.logbase + if c.dir is None: + dir = '' + else: + dir = c.dir + if c.path is None: + path = '' + else: + path = c.path + prelims = [wrapper, prev_log, this_log, c.desc, dir, path] + prelim_txt = Command.shell_make_quote_list(prelims, False) + cmds.append('\t@%s %s' % (prelim_txt, ctxt)) + return '\n'.join(cmds) + + def status_logs(self, logsdir): + """Return the list of log files with command status.""" + return [os.path.join(logsdir, '%s-status.txt' % c.logbase) + for c in self.cmdlist] + + +def get_parser(): + """Return an argument parser for this module.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('-j', dest='parallelism', + help='Run this number of jobs in parallel', + type=int, default=os.cpu_count()) + parser.add_argument('--keep', dest='keep', + help='Whether to keep all build directories, ' + 'none or only those from failed builds', + default='none', choices=('none', 'all', 'failed')) + parser.add_argument('--replace-sources', action='store_true', + help='Remove and replace source directories ' + 'with the wrong version of a component') + parser.add_argument('--strip', action='store_true', + help='Strip installed glibc libraries') + parser.add_argument('topdir', + help='Toplevel working directory') + parser.add_argument('action', + help='What to do', + choices=('checkout', 'bot-cycle', 'bot', + 'host-libraries', 'compilers', 'glibcs')) + parser.add_argument('configs', + help='Versions to check out or configurations to build', + nargs='*') + return parser + + +def main(argv): + """The main entry point.""" + parser = get_parser() + opts = parser.parse_args(argv) + topdir = os.path.abspath(opts.topdir) + ctx = Context(topdir, opts.parallelism, opts.keep, opts.replace_sources, + opts.strip, opts.action) + ctx.run_builds(opts.action, opts.configs) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/scripts/check-c++-types.sh b/scripts/check-c++-types.sh index 489c4f066f..d02e77d23b 100755 --- a/scripts/check-c++-types.sh +++ b/scripts/check-c++-types.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (C) 2003-2016 Free Software Foundation, Inc. +# Copyright (C) 2003-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -15,6 +15,14 @@ # You should have received a copy of the GNU Lesser General Public # License along with the GNU C Library; if not, see # <http://www.gnu.org/licenses/>. + +# This script creates a list of data types where each type is followed +# by the C++ mangled name for that type. That list is then compared +# against the list in the c++-types.data file for the platform being +# checked. Any difference between the two would mean that the C++ ABI +# had changed and that should not happen even if the change is compatible +# at the C language level. + # # The list of data types has been created with # cat <<EOF | diff --git a/scripts/check-execstack.awk b/scripts/check-execstack.awk index 21d37e9f47..cd6b30ed3c 100644 --- a/scripts/check-execstack.awk +++ b/scripts/check-execstack.awk @@ -6,7 +6,12 @@ # It fails (1) if any did indicate executable stack. # It fails (2) if the input did not take the expected form. -BEGIN { result = sanity = 0; default_exec = -1 } +BEGIN { + result = sanity = 0; default_exec = -1; + split(xfail, xfails, " "); + for (x in xfails) + expected_fails[xfails[x] ".phdr"] = 1; +} /^execstack-no$/ { default_exec = 0; next } /^execstack-yes$/ { default_exec = 1; next } @@ -17,6 +22,10 @@ function check_one(name) { result = 2; } + n = split(name, parts, "/"); + basename = parts[n]; + expected_fail = basename in expected_fails; + if (!sanity) { print name ": *** input did not look like readelf -l output"; result = 2; @@ -24,12 +33,20 @@ function check_one(name) { if (stack_line ~ /^.*RW .*$/) { print name ": OK"; } else if (stack_line ~ /^.*E.*$/) { - print name ": *** executable stack signaled"; - result = result ? result : 1; + if (expected_fail) { + print name ": *** executable stack signaled, expected"; + } else { + print name ": *** executable stack signaled"; + result = result ? result : 1; + } } } else if (default_exec) { - print name ": *** no PT_GNU_STACK entry"; - result = result ? result : 1; + if (expected_fail) { + print name ": *** no PT_GNU_STACK entry, expected"; + } else { + print name ": *** no PT_GNU_STACK entry"; + result = result ? result : 1; + } } else { print name ": no PT_GNU_STACK but default is OK"; } diff --git a/scripts/check-initfini.awk b/scripts/check-initfini.awk new file mode 100644 index 0000000000..19514a98ad --- /dev/null +++ b/scripts/check-initfini.awk @@ -0,0 +1,63 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# This awk script expects to get command-line files that are each +# the output of 'readelf -W --dyn-syms' on a single shared object. +# It exits successfully (0) if none contained _init nor _fini in dynamic +# symbol table. +# It fails (1) if any did contain _init or _fini in dynamic symbol table. +# It fails (2) if the input did not take the expected form. + +BEGIN { result = _init = _fini = sanity = 0 } + +function check_one(name) { + if (!sanity) { + print name ": *** input did not look like readelf -d output"; + result = 2; + } else { + ok = 1; + if (_init) { + print name ": *** _init is in dynamic symbol table"; + result = result ? result : 1; + ok = 0; + } + if (_fini) { + print name ": *** _fini is in dynamic symbol table"; + result = result ? result : 1; + ok = 0; + } + if (ok) + print name ": OK"; + } + + _init = _fini = sanity = 0 +} + +FILENAME != lastfile { + if (lastfile) + check_one(lastfile); + lastfile = FILENAME; +} + +$1 == "Symbol" && $2 == "table" && $3 == "'.dynsym'" { sanity = 1 } +$8 == "_init" { _init = 1 } +$8 == "_fini" { _fini = 1 } + +END { + check_one(lastfile); + exit(result); +} diff --git a/scripts/check-installed-headers.sh b/scripts/check-installed-headers.sh new file mode 100644 index 0000000000..4a062e9cda --- /dev/null +++ b/scripts/check-installed-headers.sh @@ -0,0 +1,174 @@ +#! /bin/sh +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# Check installed headers for cleanliness. For each header, confirm +# that it's possible to compile a file that includes that header and +# does nothing else, in several different compilation modes. Also, +# scan the header for a set of obsolete typedefs that should no longer +# appear. + +# These compilation switches assume GCC or compatible, which is probably +# fine since we also assume that when _building_ glibc. +c_modes="-std=c89 -std=gnu89 -std=c11 -std=gnu11" +cxx_modes="-std=c++98 -std=gnu++98 -std=c++11 -std=gnu++11" + +# An exhaustive test of feature selection macros would take far too long. +# These are probably the most commonly used three. +lib_modes="-D_DEFAULT_SOURCE=1 -D_GNU_SOURCE=1 -D_XOPEN_SOURCE=700" + +# sys/types.h+bits/types.h have to define the obsolete types. +# rpc(svc)/* have the obsolete types too deeply embedded in their API +# to remove. +skip_obsolete_type_check='*/sys/types.h|*/bits/types.h|*/rpc/*|*/rpcsvc/*' +obsolete_type_re=\ +'\<((__)?(quad_t|u(short|int|long|_(char|short|int([0-9]+_t)?|long|quad_t))))\>' + +if [ $# -lt 3 ]; then + echo "usage: $0 c|c++ \"compile command\" header header header..." >&2 + exit 2 +fi +case "$1" in + (c) + lang_modes="$c_modes" + cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.c) + already="$skip_obsolete_type_check" + ;; + (c++) + lang_modes="$cxx_modes" + cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.cc) + # The obsolete-type check can be skipped for C++; it is + # sufficient to do it for C. + already="*" + ;; + (*) + echo "usage: $0 c|c++ \"compile command\" header header header..." >&2 + exit 2;; +esac +shift +cc_cmd="$1" +shift +trap "rm -f '$cih_test_c'" 0 + +failed=0 +is_x86_64=unknown +is_x32=unknown +for header in "$@"; do + # Skip various headers for which this test gets a false failure. + case "$header" in + # bits/* are not meant to be included directly and usually #error + # out if you try it. + # regexp.h is a stub containing only an #error. + # Sun RPC's .x files are traditionally installed in + # $prefix/include/rpcsvc, but they are not C header files. + (bits/* | regexp.h | rpcsvc/*.x) + continue;; + + # All extant versions of sys/elf.h contain nothing more than an + # exhortation (either a #warning or an #error) to use sys/procfs.h + # instead, plus an inclusion of that header. + (sys/elf.h) + continue;; + + # sys/sysctl.h is unsupported for x32. + (sys/sysctl.h) + case "$is_x32" in + (yes) continue;; + (no) ;; + (unknown) + cat >"$cih_test_c" <<EOF +#if defined __x86_64__ && defined __ILP32__ +# error "is x32" +#endif +EOF + if $cc_cmd -fsyntax-only "$cih_test_c" > /dev/null 2>&1 + then + is_x32=no + else + is_x32=yes + continue + fi + ;; + esac + ;; + + # sys/vm86.h is "unsupported on x86-64" and errors out on that target. + (sys/vm86.h) + case "$is_x86_64" in + (yes) continue;; + (no) ;; + (unknown) + cat >"$cih_test_c" <<EOF +#if defined __x86_64__ && __x86_64__ +#error "is x86-64" +#endif +EOF + if $cc_cmd -fsyntax-only "$cih_test_c" > /dev/null 2>&1 + then + is_x86_64=no + else + is_x86_64=yes + continue + fi + ;; + esac + ;; + esac + + echo :: "$header" + for lang_mode in "" $lang_modes; do + for lib_mode in "" $lib_modes; do + echo :::: $lang_mode $lib_mode + if [ -z "$lib_mode" ]; then + expanded_lib_mode='/* default library mode */' + else + expanded_lib_mode=$(echo : $lib_mode | \ + sed 's/^: -D/#define /; s/=/ /') + fi + cat >"$cih_test_c" <<EOF +/* These macros may have been defined on the command line. They are + inappropriate for this test. */ +#undef _LIBC +#undef _GNU_SOURCE +/* The library mode is selected here rather than on the command line to + ensure that this selection wins. */ +$expanded_lib_mode +#include <$header> +int avoid_empty_translation_unit; +EOF + if $cc_cmd -fsyntax-only $lang_mode "$cih_test_c" 2>&1 + then + includes=$($cc_cmd -fsyntax-only -H $lang_mode \ + "$cih_test_c" 2>&1 | sed -ne 's/^[.][.]* //p') + for h in $includes; do + # Don't repeat work. + eval 'case "$h" in ('"$already"') continue;; esac' + + if grep -qE "$obsolete_type_re" "$h"; then + echo "*** Obsolete types detected:" + grep -HE "$obsolete_type_re" "$h" + failed=1 + fi + already="$already|$h" + done + else + failed=1 + fi + done + done +done +exit $failed diff --git a/scripts/check-local-headers.sh b/scripts/check-local-headers.sh index 0670da16bc..0c45cc4079 100755 --- a/scripts/check-local-headers.sh +++ b/scripts/check-local-headers.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (C) 2005-2016 Free Software Foundation, Inc. +# Copyright (C) 2005-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -33,7 +33,7 @@ exec ${AWK} -v includedir="$includedir" ' BEGIN { status = 0 exclude = "^" includedir \ - "/(.*-.*-.*/|)(asm[-/]|arch|linux/|selinux/|mach/|device/|hurd/(((hurd|ioctl)_types|paths)\\.h|ioctls\\.defs)|cthreads\\.h|gd|nss3/|c\\+\\+/|sys/(capability|sdt(|-config))\\.h|libaudit\\.h)" + "/(.*-.*-.*/|.*-.*/|)(asm[-/]|arch|linux/|selinux/|mach/|mach_debug/|device/|hurd/(((hurd|ioctl)_types|paths)\\.h|ioctls\\.defs|ihash\\.h)|cthreads\\.h|gd|nss3/|nspr4?/|c\\+\\+/|sys/(capability|sdt(|-config))\\.h|libaudit\\.h)" } /^[^ ]/ && $1 ~ /.*:/ { obj = $1 } { diff --git a/scripts/config.guess b/scripts/config.guess index dcd5149681..588fe82a42 100755 --- a/scripts/config.guess +++ b/scripts/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2016-01-01' +timestamp='2018-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2016-01-01' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. +# along with this program; if not, see <https://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,7 +27,7 @@ timestamp='2016-01-01' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to <config-patches@gnu.org>. @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -186,9 +186,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. + # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in - arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -237,6 +240,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; + *:MidnightBSD:*:*) + echo ${UNAME_MACHINE}-unknown-midnightbsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -252,6 +262,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; + *:Redox:*:*) + echo ${UNAME_MACHINE}-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -268,55 +284,46 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; @@ -376,16 +383,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build - SUN_ARCH="i386" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` @@ -410,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} @@ -478,13 +485,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); @@ -607,7 +614,7 @@ EOF *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and @@ -628,20 +635,20 @@ EOF 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi @@ -680,11 +687,11 @@ EOF exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build @@ -697,12 +704,12 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -742,7 +749,7 @@ EOF { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -751,7 +758,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -807,14 +814,14 @@ EOF echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) @@ -830,10 +837,11 @@ EOF UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin @@ -847,10 +855,6 @@ EOF *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 - exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; @@ -866,27 +870,12 @@ EOF echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; @@ -896,7 +885,7 @@ EOF exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix @@ -919,7 +908,7 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) @@ -993,6 +982,9 @@ EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; + mips64el:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; @@ -1025,6 +1017,9 @@ EOF ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; @@ -1083,7 +1078,7 @@ EOF i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + i*86:*:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} @@ -1272,6 +1267,9 @@ EOF SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1285,16 +1283,23 @@ EOF UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub @@ -1309,7 +1314,7 @@ EOF exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi @@ -1318,15 +1323,18 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) + NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; - NSR-?:NONSTOP_KERNEL:*:*) + NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; @@ -1340,7 +1348,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" @@ -1382,7 +1390,7 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos @@ -1398,21 +1406,32 @@ EOF exit ;; esac +echo "$0: unable to guess system type" >&2 + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <<EOF + +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. +EOF + ;; +esac + cat >&2 <<EOF -$0: unable to guess system type -This script, last modified $timestamp, has failed to recognize -the operating system you are using. It is advised that you -download the most up to date version of the config scripts from +This script (version $timestamp), has failed to recognize the +operating system you are using. If your script is old, overwrite *all* +copies of config.guess and config.sub with the latest versions from: - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess + https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess and - http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub -If the version you run ($0) is already up to date, please -send the following data and any information you think might be -pertinent to <config-patches@gnu.org> in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1440,7 +1459,7 @@ EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/scripts/config.sub b/scripts/config.sub index da6d1b6826..f2632cd8a2 100755 --- a/scripts/config.sub +++ b/scripts/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2016-01-01' +timestamp='2018-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2016-01-01' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. +# along with this program; if not, see <https://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,7 +33,7 @@ timestamp='2016-01-01' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,7 +117,7 @@ case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -229,9 +229,6 @@ case $os in -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; -psos*) os=-psos ;; @@ -263,7 +260,7 @@ case $basic_machine in | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -301,6 +298,7 @@ case $basic_machine in | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ @@ -314,7 +312,7 @@ case $basic_machine in | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ - | we32k \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -387,7 +385,7 @@ case $basic_machine in | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -428,6 +426,7 @@ case $basic_machine in | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ @@ -444,6 +443,7 @@ case $basic_machine in | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -639,10 +639,18 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -893,7 +901,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -938,6 +946,9 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -1022,7 +1033,7 @@ case $basic_machine in ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) @@ -1032,7 +1043,7 @@ case $basic_machine in ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) @@ -1233,6 +1244,9 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; + wasm32) + basic_machine=wasm32-unknown + ;; w65*) basic_machine=w65-wdc os=-none @@ -1241,6 +1255,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1348,8 +1365,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1369,9 +1386,9 @@ case $os in -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ @@ -1382,14 +1399,14 @@ case $os in | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ @@ -1399,7 +1416,7 @@ case $os in | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos*) + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1474,7 +1491,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1529,8 +1546,23 @@ case $os in -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; + -ios) + ;; -none) ;; *) @@ -1626,6 +1658,9 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; @@ -1671,7 +1706,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1806,7 +1841,7 @@ echo $basic_machine$os exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/scripts/cross-test-ssh.sh b/scripts/cross-test-ssh.sh index 73c4e3ea0f..400ef7d595 100755 --- a/scripts/cross-test-ssh.sh +++ b/scripts/cross-test-ssh.sh @@ -1,6 +1,6 @@ #!/bin/bash # Run a testcase on a remote system, via ssh. -# Copyright (C) 2012-2016 Free Software Foundation, Inc. +# Copyright (C) 2012-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or diff --git a/scripts/evaluate-test.sh b/scripts/evaluate-test.sh index f2c85ed192..b6420ea9fc 100755 --- a/scripts/evaluate-test.sh +++ b/scripts/evaluate-test.sh @@ -1,6 +1,6 @@ #!/bin/sh # Output a test status line. -# Copyright (C) 2012-2016 Free Software Foundation, Inc. +# Copyright (C) 2012-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or diff --git a/scripts/gen-py-const.awk b/scripts/gen-py-const.awk new file mode 100644 index 0000000000..91220281c5 --- /dev/null +++ b/scripts/gen-py-const.awk @@ -0,0 +1,118 @@ +# Script to generate constants for Python pretty printers. +# +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# This script is a smaller version of the clever gen-asm-const.awk hack used to +# generate ASM constants from .sym files. We'll use this to generate constants +# for Python pretty printers. +# +# The input to this script are .pysym files that look like: +# #C_Preprocessor_Directive... +# NAME1 +# NAME2 expression... +# +# A line giving just a name implies an expression consisting of just that name. +# Comments start with '--'. +# +# The output of this script is a 'dummy' function containing 'asm' declarations +# for each non-preprocessor line in the .pysym file. The expression values +# will appear as input operands to the 'asm' declaration. For example, if we +# have: +# +# /* header.h */ +# #define MACRO 42 +# +# struct S { +# char c1; +# char c2; +# char c3; +# }; +# +# enum E { +# ZERO, +# ONE +# }; +# +# /* symbols.pysym */ +# #include <stddef.h> +# #include "header.h" +# -- This is a comment +# MACRO +# C3_OFFSET offsetof(struct S, c3) +# E_ONE ONE +# +# the output will be: +# +# #include <stddef.h> +# #include "header.h" +# void dummy(void) +# { +# asm ("@name@MACRO@value@%0@" : : "i" (MACRO)); +# asm ("@name@C3_OFFSET@value@%0@" : : "i" (offsetof(struct S, c3))); +# asm ("@name@E_ONE@value@%0@" : : "i" (ONE)); +# } +# +# We'll later feed this output to gcc -S. Since '-S' tells gcc to compile but +# not assemble, gcc will output something like: +# +# dummy: +# ... +# @name@MACRO@value@$42@ +# @name@C3_OFFSET@value@$2@ +# @name@E_ONE@value@$1@ +# +# Finally, we can process that output to extract the constant values. +# Notice gcc may prepend a special character such as '$' to each value. + +# found_symbol indicates whether we found a non-comment, non-preprocessor line. +BEGIN { found_symbol = 0 } + +# C preprocessor directives go straight through. +/^#/ { print; next; } + +# Skip comments. +/--/ { next; } + +# Trim leading whitespace. +{ sub(/^[[:blank:]]*/, ""); } + +# If we found a non-comment, non-preprocessor line, print the 'dummy' function +# header. +NF > 0 && !found_symbol { + print "void dummy(void)\n{"; + found_symbol = 1; +} + +# If the line contains just a name, duplicate it so we can use that name +# as the value of the expression. +NF == 1 { sub(/^.*$/, "& &"); } + +# If a line contains a name and an expression... +NF > 1 { + name = $1; + + # Remove any characters before the second field. + sub(/^[^[:blank:]]+[[:blank:]]+/, ""); + + # '$0' ends up being everything that appeared after the first field + # separator. + printf " asm (\"@name@%s@value@%0@\" : : \"i\" (%s));\n", name, $0; +} + +# Close the 'dummy' function. +END { if (found_symbol) print "}"; } diff --git a/scripts/gen-rrtypes.py b/scripts/gen-rrtypes.py new file mode 100644 index 0000000000..a71e1e108b --- /dev/null +++ b/scripts/gen-rrtypes.py @@ -0,0 +1,68 @@ +#!/usr/bin/python3 +# Generate DNS RR type constants for resolv header files. +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +"""Generate DNS RR type constants for resolv header files. + +resolv/arpa/nameser.h and resolv/arpa/nameser_compat.h contain lists +of RR type constants. This script downloads the current definitions +from the IANA DNS Parameters protocol registry and translates it into +the two different lists. + +Two lists are written to standard output. The first one contains enum +constants for resolv/arpa/nameser.h. The second one lists the +preprocessor macros for resolv/arpa/nameser_compat.h. + +""" + +# URL of the IANA registry. +source = "http://www.iana.org/assignments/dns-parameters/dns-parameters-4.csv" + +import collections +import csv +import io +import urllib.request + +Type = collections.namedtuple("Type", "name number comment") + +def get_types(source): + for row in csv.reader(io.TextIOWrapper(urllib.request.urlopen(source))): + if row[0] in ('TYPE', 'Unassigned', 'Private use', 'Reserved'): + continue + name, number, comment = row[:3] + if name == '*': + name = 'ANY' + comment = 'request for all cached records' + number = int(number) + yield Type(name, number, comment) + +types = list(get_types(source)) + +print("// enum constants for resolv/arpa/nameser.h") +print() +for typ in types: + name = typ.name.replace("-", "_").lower() + print(" ns_t_{0} = {1.number},".format(name, typ)) +print() + +print("// macro aliases resolv/arpa/nameser_compat.h") +print() +for typ in types: + name = typ.name.replace("-", "_") + print("#define T_{0} ns_t_{1}".format(name.upper(), name.lower())) +print() diff --git a/scripts/gen-sorted.awk b/scripts/gen-sorted.awk index 9669277b31..f338807e8e 100755 --- a/scripts/gen-sorted.awk +++ b/scripts/gen-sorted.awk @@ -1,7 +1,7 @@ #!/usr/bin/awk -f # Generate sorted list of directories. The sorting is stable but with # dependencies between directories resolved by moving dependees in front. -# Copyright (C) 1998-2016 Free Software Foundation, Inc. +# Copyright (C) 1998-2018 Free Software Foundation, Inc. # Written by Ulrich Drepper <drepper@cygnus.com>, 1998. BEGIN { @@ -46,36 +46,10 @@ type == "Subdirs" && NF == 2 && $1 == "inhibit" { type == "Subdirs" && thisdir { all[cnt++] = thisdir; - if (FILENAME ~ (srcpfx ? /^\.\.\/sysdeps\// : /^sysdeps\//) \ - || system("test -d " srcpfx thisdir) == 0) { - # This Subdirs file is in the main source tree, - # or this subdirectory exists in the main source tree. - this_srcdir = srcpfx thisdir - } - else { - # The Subdirs file comes from an add-on that should have the subdirectory. - dir = FILENAME; - do - sub(/\/[^/]+$/, "", dir); - while (dir !~ /\/sysdeps$/); - sub(/\/sysdeps$/, "", dir); - if (system("test -d " dir "/" thisdir) == 0) - dir = dir "/" thisdir; - else { - sub(/\/[^/]+$/, "", dir); - if (system("test -d " dir "/" thisdir) == 0) - dir = dir "/" thisdir; - else { - print FILENAME ":" FNR ":", "cannot find", thisdir > "/dev/stderr"; - exit 2 - } - } - file = dir "/Depend"; - if (srcpfx) - sub(/^\.\.\//, "", dir); - if (dir !~ /^\/.*$/) - dir = "$(..)" dir; - print thisdir "-srcdir", ":=", dir; + this_srcdir = srcpfx thisdir + if (system("test -d " this_srcdir) != 0) { + print FILENAME ":" FNR ":", "cannot find", this_srcdir > "/dev/stderr"; + exit 2 } file = this_srcdir "/Depend"; if (system("test -f " file) == 0) { diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk new file mode 100644 index 0000000000..622199061a --- /dev/null +++ b/scripts/gen-tunables.awk @@ -0,0 +1,174 @@ +# Generate dl-tunable-list.h from dl-tunables.list + +BEGIN { + min_of["STRING"]="0" + max_of["STRING"]="0" + min_of["INT_32"]="INT32_MIN" + max_of["INT_32"]="INT32_MAX" + min_of["UINT_64"]="0" + max_of["UINT_64"]="UINT64_MAX" + min_of["SIZE_T"]="0" + max_of["SIZE_T"]="SIZE_MAX" + tunable="" + ns="" + top_ns="" +} + +# Skip over blank lines and comments. +/^#/ { + next +} + +/^[ \t]*$/ { + next +} + +# Beginning of either a top namespace, tunable namespace or a tunable, decided +# on the current value of TUNABLE, NS or TOP_NS. +$2 == "{" { + if (top_ns == "") { + top_ns = $1 + } + else if (ns == "") { + ns = $1 + } + else if (tunable == "") { + tunable = $1 + } + else { + printf ("Unexpected occurrence of '{': %s:%d\n", FILENAME, FNR) + exit 1 + } + + next +} + +# End of either a top namespace, tunable namespace or a tunable. +$1 == "}" { + if (tunable != "") { + # Tunables definition ended, now fill in default attributes. + if (!types[top_ns,ns,tunable]) { + types[top_ns,ns,tunable] = "STRING" + } + if (!minvals[top_ns,ns,tunable]) { + minvals[top_ns,ns,tunable] = min_of[types[top_ns,ns,tunable]] + } + if (!maxvals[top_ns,ns,tunable]) { + maxvals[top_ns,ns,tunable] = max_of[types[top_ns,ns,tunable]] + } + if (!env_alias[top_ns,ns,tunable]) { + env_alias[top_ns,ns,tunable] = "NULL" + } + if (!security_level[top_ns,ns,tunable]) { + security_level[top_ns,ns,tunable] = "SXID_ERASE" + } + + tunable = "" + } + else if (ns != "") { + ns = "" + } + else if (top_ns != "") { + top_ns = "" + } + else { + printf ("syntax error: extra }: %s:%d\n", FILENAME, FNR) + exit 1 + } + next +} + +# Everything else, which could either be a tunable without any attributes or a +# tunable attribute. +{ + if (ns == "") { + printf("Line %d: Invalid tunable outside a namespace: %s\n", NR, $0) + exit 1 + } + + if (tunable == "") { + # We encountered a tunable without any attributes, so note it with a + # default. + types[top_ns,ns,$1] = "STRING" + next + } + + # Otherwise, we have encountered a tunable attribute. + split($0, arr, ":") + attr = gensub(/^[ \t]+|[ \t]+$/, "", "g", arr[1]) + val = gensub(/^[ \t]+|[ \t]+$/, "", "g", arr[2]) + + if (attr == "type") { + types[top_ns,ns,tunable] = val + } + else if (attr == "minval") { + minvals[top_ns,ns,tunable] = val + } + else if (attr == "maxval") { + maxvals[top_ns,ns,tunable] = val + } + else if (attr == "env_alias") { + env_alias[top_ns,ns,tunable] = sprintf("\"%s\"", val) + } + else if (attr == "security_level") { + if (val == "SXID_ERASE" || val == "SXID_IGNORE" || val == "NONE") { + security_level[top_ns,ns,tunable] = val + } + else { + printf("Line %d: Invalid value (%s) for security_level: %s, ", NR, val, + $0) + print("Allowed values are 'SXID_ERASE', 'SXID_IGNORE', or 'NONE'") + exit 1 + } + } + else if (attr == "default") { + if (types[top_ns,ns,tunable] == "STRING") { + default_val[top_ns,ns,tunable] = sprintf(".strval = \"%s\"", val); + } + else { + default_val[top_ns,ns,tunable] = sprintf(".numval = %s", val) + } + } +} + +END { + if (ns != "") { + print "Unterminated namespace. Is a closing brace missing?" + exit 1 + } + + print "/* AUTOGENERATED by gen-tunables.awk. */" + print "#ifndef _TUNABLES_H_" + print "# error \"Do not include this file directly.\"" + print "# error \"Include tunables.h instead.\"" + print "#endif" + print "#include <dl-procinfo.h>\n" + + # Now, the enum names + print "\ntypedef enum" + print "{" + for (tnm in types) { + split (tnm, indices, SUBSEP); + t = indices[1]; + n = indices[2]; + m = indices[3]; + printf (" TUNABLE_ENUM_NAME(%s, %s, %s),\n", t, n, m); + } + print "} tunable_id_t;\n" + + # Finally, the tunable list. + print "\n#ifdef TUNABLES_INTERNAL" + print "static tunable_t tunable_list[] attribute_relro = {" + for (tnm in types) { + split (tnm, indices, SUBSEP); + t = indices[1]; + n = indices[2]; + m = indices[3]; + printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m) + printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n", + types[t,n,m], minvals[t,n,m], maxvals[t,n,m], + default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]); + } + print "};" + print "#endif" +} diff --git a/scripts/install-sh b/scripts/install-sh index 0b0fdcbba6..ac159ceda4 100755 --- a/scripts/install-sh +++ b/scripts/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2013-12-25.23; # UTC +scriptversion=2017-09-23.17; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -271,15 +271,18 @@ do fi dst=$dst_arg - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. + # If destination is a directory, append the input filename. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst - dst=$dstdir/`basename "$src"` + dstbase=`basename "$src"` + case $dst in + */) dst=$dst$dstbase;; + *) dst=$dst/$dstbase;; + esac dstdir_status=0 else dstdir=`dirname "$dst"` @@ -288,6 +291,11 @@ do fi fi + case $dstdir in + */) dstdirslash=$dstdir;; + *) dstdirslash=$dstdir/;; + esac + obsolete_mkdir_used=false if test $dstdir_status != 0; then @@ -427,8 +435,8 @@ do else # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ + dsttmp=${dstdirslash}_inst.$$_ + rmtmp=${dstdirslash}_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 @@ -496,6 +504,6 @@ done # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/scripts/list-fixed-bugs.py b/scripts/list-fixed-bugs.py index 51f3c36e69..b62f3b2146 100755 --- a/scripts/list-fixed-bugs.py +++ b/scripts/list-fixed-bugs.py @@ -1,5 +1,5 @@ #!/usr/bin/python3 -# Copyright (C) 2015-2016 Free Software Foundation, Inc. +# Copyright (C) 2015-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # # The GNU C Library is free software; you can redistribute it and/or diff --git a/scripts/merge-test-results.sh b/scripts/merge-test-results.sh index 1175b20717..24f2b3fc81 100755 --- a/scripts/merge-test-results.sh +++ b/scripts/merge-test-results.sh @@ -1,6 +1,6 @@ #!/bin/sh # Merge test results of individual tests or subdirectories. -# Copyright (C) 2014-2016 Free Software Foundation, Inc. +# Copyright (C) 2014-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or diff --git a/scripts/mkinstalldirs b/scripts/mkinstalldirs index 55d537f872..a31ce6d029 100755 --- a/scripts/mkinstalldirs +++ b/scripts/mkinstalldirs @@ -1,7 +1,7 @@ #! /bin/sh # mkinstalldirs --- make directory hierarchy -scriptversion=2009-04-28.21; # UTC +scriptversion=2016-01-11.22; # UTC # Original author: Noah Friedman <friedman@prep.ai.mit.edu> # Created: 1993-05-16 @@ -157,6 +157,6 @@ exit $errstatus # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/scripts/move-if-change b/scripts/move-if-change index cd744a92f3..f15923613c 100755 --- a/scripts/move-if-change +++ b/scripts/move-if-change @@ -2,13 +2,13 @@ # Like mv $1 $2, but if the files are the same, just delete $1. # Status is zero if successful, nonzero otherwise. -VERSION='2012-01-06 07:23'; # UTC +VERSION='2017-09-13 06:45'; # UTC # The definition above must lie within the first 8 lines in order # for the Emacs time-stamp write hook (at end) to update it. # If you change this file with Emacs, please let the write hook # do its job. Otherwise, update this string manually. -# Copyright (C) 2002-2016 Free Software Foundation, Inc. +# Copyright (C) 2002-2018 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ VERSION='2012-01-06 07:23'; # UTC # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. usage="usage: $0 SOURCE DEST" @@ -39,7 +39,7 @@ Report bugs to <bug-gnulib@gnu.org>." version=`expr "$VERSION" : '\([^ ]*\)'` version="move-if-change (gnulib) $version Copyright (C) 2011 Free Software Foundation, Inc. -License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> +License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law." @@ -78,6 +78,6 @@ fi ## eval: (add-hook 'write-file-hooks 'time-stamp) ## time-stamp-start: "VERSION='" ## time-stamp-format: "%:y-%02m-%02d %02H:%02M" -## time-stamp-time-zone: "UTC" +## time-stamp-time-zone: "UTC0" ## time-stamp-end: "'; # UTC" ## End: diff --git a/scripts/rellns-sh b/scripts/rellns-sh index a57f601a90..9d4f4ab177 100755 --- a/scripts/rellns-sh +++ b/scripts/rellns-sh @@ -1,6 +1,6 @@ #!/bin/sh # rellns-sh - Simplified ln program to generate relative symbolic link. -# Copyright (C) 1996-2016 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # Written by Ulrich Drepper <drepper@cygnus.com>, October 1996 # # This program is free software; you can redistribute it and/or modify diff --git a/scripts/sysd-rules.awk b/scripts/sysd-rules.awk index cebc9d3e1b..c82e8fd607 100644 --- a/scripts/sysd-rules.awk +++ b/scripts/sysd-rules.awk @@ -50,11 +50,15 @@ BEGIN { split(pattern, td, ":"); target_pattern = td[1]; dep_pattern = td[2]; + # rtld objects are always PIC. + if (target_pattern ~ /^rtld/ && o != ".os") { + continue; + } if (target_pattern == "%") { command_suffix = ""; } else { prefix = gensub(/%/, "", 1, target_pattern); - command_suffix = " $(" prefix "CPPFLAGS)"; + command_suffix = " $(" prefix "CPPFLAGS)" " $(" prefix "CFLAGS)"; } target = "$(objpfx)" target_pattern o ":"; if (asm_rules) { diff --git a/scripts/test-installation.pl b/scripts/test-installation.pl index 5e84dd7184..b2e4ba7646 100755 --- a/scripts/test-installation.pl +++ b/scripts/test-installation.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -w -# Copyright (C) 1997-2016 Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1997. @@ -59,7 +59,7 @@ arglist: while (@ARGV) { $ARGV[0] eq "--vers" || $ARGV[0] eq "--versi" || $ARGV[0] eq "--versio" || $ARGV[0] eq "--version") { print "test-installation (GNU $PACKAGE)\n"; - print "Copyright (C) 2016 Free Software Foundation, Inc.\n"; + print "Copyright (C) 2018 Free Software Foundation, Inc.\n"; print "This is free software; see the source for copying conditions. There is NO\n"; print "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"; print "Written by Andreas Jaeger <aj\@arthur.rhein-neckar.de>\n"; @@ -79,10 +79,12 @@ arglist: while (@ARGV) { # We expect none or one argument. if ($#ARGV == -1) { + $dir = "."; $soversions="soversions.mk"; $config="config.make"; } elsif ($#ARGV == 0) { if (-d $ARGV[0]) { + $dir = $ARGV[0]; $soversions = "$ARGV[0]/soversions.mk"; $config = "$ARGV[0]/config.make"; } else { @@ -116,14 +118,13 @@ while (<SOVERSIONS>) { # Filter out some libraries we don't want to link: # - nss_ldap since it's not yet available # - libdb1 since it conflicts with libdb - # - libnss1_* from glibc-compat add-on # - libthread_db since it contains unresolved references # - it's just a test NSS module # - We don't provide the libgcc so we don't test it # - libmvec if it wasn't built next if ($build_mathvec == 0 && $name eq "mvec"); if ($name ne "nss_ldap" && $name ne "db1" - && !($name =~/^nss1_/) && $name ne "thread_db" + && $name ne "thread_db" && $name ne "nss_test1" && $name ne "libgcc_s") { $link_libs .= " -l$name"; $versions{$name} = $version; @@ -142,8 +143,8 @@ close SOVERSIONS; # Create test program and link it against all # shared libraries -open PRG, ">/tmp/test-prg$$.c" - or die ("Couldn't write test file /tmp/test-prg$$.c"); +open PRG, ">$dir/test-prg$$.c" + or die ("Couldn't write test file $dir/test-prg$$.c"); print PRG ' #include <stdio.h> @@ -155,7 +156,7 @@ int main(void) { '; close PRG; -open GCC, "$CC /tmp/test-prg$$.c $link_libs -o /tmp/test-prg$$ 2>&1 |" +open GCC, "$CC $dir/test-prg$$.c $link_libs -o $dir/test-prg$$ 2>&1 |" or die ("Couldn't execute $CC!"); while (<GCC>) { @@ -173,7 +174,7 @@ if ($?) { $ok = 1; %found = (); -open LDD, "ldd /tmp/test-prg$$ |" +open LDD, "ldd $dir/test-prg$$ |" or die ("Couldn't execute ldd"); while (<LDD>) { if (/^\s*lib/) { @@ -213,8 +214,8 @@ foreach (keys %versions) { &installation_problem unless $ok; # Finally execute the test program -system ("/tmp/test-prg$$") == 0 +system ("$dir/test-prg$$") == 0 or die ("Execution of test program failed"); # Clean up after ourselves -unlink ("/tmp/test-prg$$", "/tmp/test-prg$$.c"); +unlink ("$dir/test-prg$$", "$dir/test-prg$$.c"); diff --git a/scripts/test_printers_common.py b/scripts/test_printers_common.py new file mode 100644 index 0000000000..cf4de5ae23 --- /dev/null +++ b/scripts/test_printers_common.py @@ -0,0 +1,368 @@ +# Common functions and variables for testing the Python pretty printers. +# +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +"""These tests require PExpect 4.0 or newer. + +Exported constants: + PASS, FAIL, UNSUPPORTED (int): Test exit codes, as per evaluate-test.sh. +""" + +import os +import re +from test_printers_exceptions import * + +PASS = 0 +FAIL = 1 +UNSUPPORTED = 77 + +gdb_bin = 'gdb' +gdb_options = '-q -nx' +gdb_invocation = '{0} {1}'.format(gdb_bin, gdb_options) +pexpect_min_version = 4 +gdb_min_version = (7, 8) +encoding = 'utf-8' + +try: + import pexpect +except ImportError: + print('PExpect 4.0 or newer must be installed to test the pretty printers.') + exit(UNSUPPORTED) + +pexpect_version = pexpect.__version__.split('.')[0] + +if int(pexpect_version) < pexpect_min_version: + print('PExpect 4.0 or newer must be installed to test the pretty printers.') + exit(UNSUPPORTED) + +if not pexpect.which(gdb_bin): + print('gdb 7.8 or newer must be installed to test the pretty printers.') + exit(UNSUPPORTED) + +timeout = 5 +TIMEOUTFACTOR = os.environ.get('TIMEOUTFACTOR') + +if TIMEOUTFACTOR: + timeout = int(TIMEOUTFACTOR) + +try: + # Check the gdb version. + version_cmd = '{0} --version'.format(gdb_invocation, timeout=timeout) + gdb_version_out = pexpect.run(version_cmd, encoding=encoding) + + # The gdb version string is "GNU gdb <PKGVERSION><version>", where + # PKGVERSION can be any text. We assume that there'll always be a space + # between PKGVERSION and the version number for the sake of the regexp. + version_match = re.search(r'GNU gdb .* ([1-9]+)\.([0-9]+)', gdb_version_out) + + if not version_match: + print('The gdb version string (gdb -v) is incorrectly formatted.') + exit(UNSUPPORTED) + + gdb_version = (int(version_match.group(1)), int(version_match.group(2))) + + if gdb_version < gdb_min_version: + print('gdb 7.8 or newer must be installed to test the pretty printers.') + exit(UNSUPPORTED) + + # Check if gdb supports Python. + gdb_python_cmd = '{0} -ex "python import os" -batch'.format(gdb_invocation, + timeout=timeout) + gdb_python_error = pexpect.run(gdb_python_cmd, encoding=encoding) + + if gdb_python_error: + print('gdb must have python support to test the pretty printers.') + print('gdb output: {!r}'.format(gdb_python_error)) + exit(UNSUPPORTED) + + # If everything's ok, spawn the gdb process we'll use for testing. + gdb = pexpect.spawn(gdb_invocation, echo=False, timeout=timeout, + encoding=encoding) + gdb_prompt = u'\(gdb\)' + gdb.expect(gdb_prompt) + +except pexpect.ExceptionPexpect as exception: + print('Error: {0}'.format(exception)) + exit(FAIL) + +def test(command, pattern=None): + """Sends 'command' to gdb and expects the given 'pattern'. + + If 'pattern' is None, simply consumes everything up to and including + the gdb prompt. + + Args: + command (string): The command we'll send to gdb. + pattern (raw string): A pattern the gdb output should match. + + Returns: + string: The string that matched 'pattern', or an empty string if + 'pattern' was None. + """ + + match = '' + + gdb.sendline(command) + + if pattern: + # PExpect does a non-greedy match for '+' and '*'. Since it can't look + # ahead on the gdb output stream, if 'pattern' ends with a '+' or a '*' + # we may end up matching only part of the required output. + # To avoid this, we'll consume 'pattern' and anything that follows it + # up to and including the gdb prompt, then extract 'pattern' later. + index = gdb.expect([u'{0}.+{1}'.format(pattern, gdb_prompt), + pexpect.TIMEOUT]) + + if index == 0: + # gdb.after now contains the whole match. Extract the text that + # matches 'pattern'. + match = re.match(pattern, gdb.after, re.DOTALL).group() + elif index == 1: + # We got a timeout exception. Print information on what caused it + # and bail out. + error = ('Response does not match the expected pattern.\n' + 'Command: {0}\n' + 'Expected pattern: {1}\n' + 'Response: {2}'.format(command, pattern, gdb.before)) + + raise pexpect.TIMEOUT(error) + else: + # Consume just the the gdb prompt. + gdb.expect(gdb_prompt) + + return match + +def init_test(test_bin, printer_files, printer_names): + """Loads the test binary file and the required pretty printers to gdb. + + Args: + test_bin (string): The name of the test binary file. + pretty_printers (list of strings): A list with the names of the pretty + printer files. + """ + + # Load all the pretty printer files. We're assuming these are safe. + for printer_file in printer_files: + test('source {0}'.format(printer_file)) + + # Disable all the pretty printers. + test('disable pretty-printer', r'0 of [0-9]+ printers enabled') + + # Enable only the required printers. + for printer in printer_names: + test('enable pretty-printer {0}'.format(printer), + r'[1-9][0-9]* of [1-9]+ printers enabled') + + # Finally, load the test binary. + test('file {0}'.format(test_bin)) + + # Disable lock elision. + test('set environment GLIBC_TUNABLES glibc.elision.enable=0') + +def go_to_main(): + """Executes a gdb 'start' command, which takes us to main.""" + + test('start', r'main') + +def get_line_number(file_name, string): + """Returns the number of the line in which 'string' appears within a file. + + Args: + file_name (string): The name of the file we'll search through. + string (string): The string we'll look for. + + Returns: + int: The number of the line in which 'string' appears, starting from 1. + """ + number = -1 + + with open(file_name) as src_file: + for i, line in enumerate(src_file): + if string in line: + number = i + 1 + break + + if number == -1: + raise NoLineError(file_name, string) + + return number + +def break_at(file_name, string, temporary=True, thread=None): + """Places a breakpoint on the first line in 'file_name' containing 'string'. + + 'string' is usually a comment like "Stop here". Notice this may fail unless + the comment is placed inline next to actual code, e.g.: + + ... + /* Stop here */ + ... + + may fail, while: + + ... + some_func(); /* Stop here */ + ... + + will succeed. + + If 'thread' isn't None, the breakpoint will be set for all the threads. + Otherwise, it'll be set only for 'thread'. + + Args: + file_name (string): The name of the file we'll place the breakpoint in. + string (string): A string we'll look for inside the file. + We'll place a breakpoint on the line which contains it. + temporary (bool): Whether the breakpoint should be automatically deleted + after we reach it. + thread (int): The number of the thread we'll place the breakpoint for, + as seen by gdb. If specified, it should be greater than zero. + """ + + if not thread: + thread_str = '' + else: + thread_str = 'thread {0}'.format(thread) + + if temporary: + command = 'tbreak' + break_type = 'Temporary breakpoint' + else: + command = 'break' + break_type = 'Breakpoint' + + line_number = str(get_line_number(file_name, string)) + + test('{0} {1}:{2} {3}'.format(command, file_name, line_number, thread_str), + r'{0} [0-9]+ at 0x[a-f0-9]+: file {1}, line {2}\.'.format(break_type, + file_name, + line_number)) + +def continue_cmd(thread=None): + """Executes a gdb 'continue' command. + + If 'thread' isn't None, the command will be applied to all the threads. + Otherwise, it'll be applied only to 'thread'. + + Args: + thread (int): The number of the thread we'll apply the command to, + as seen by gdb. If specified, it should be greater than zero. + """ + + if not thread: + command = 'continue' + else: + command = 'thread apply {0} continue'.format(thread) + + test(command) + +def next_cmd(count=1, thread=None): + """Executes a gdb 'next' command. + + If 'thread' isn't None, the command will be applied to all the threads. + Otherwise, it'll be applied only to 'thread'. + + Args: + count (int): The 'count' argument of the 'next' command. + thread (int): The number of the thread we'll apply the command to, + as seen by gdb. If specified, it should be greater than zero. + """ + + if not thread: + command = 'next' + else: + command = 'thread apply {0} next' + + test('{0} {1}'.format(command, count)) + +def select_thread(thread): + """Selects the thread indicated by 'thread'. + + Args: + thread (int): The number of the thread we'll switch to, as seen by gdb. + This should be greater than zero. + """ + + if thread > 0: + test('thread {0}'.format(thread)) + +def get_current_thread_lwpid(): + """Gets the current thread's Lightweight Process ID. + + Returns: + string: The current thread's LWP ID. + """ + + # It's easier to get the LWP ID through the Python API than the gdb CLI. + command = 'python print(gdb.selected_thread().ptid[1])' + + return test(command, r'[0-9]+') + +def set_scheduler_locking(mode): + """Executes the gdb 'set scheduler-locking' command. + + Args: + mode (bool): Whether the scheduler locking mode should be 'on'. + """ + modes = { + True: 'on', + False: 'off' + } + + test('set scheduler-locking {0}'.format(modes[mode])) + +def test_printer(var, to_string, children=None, is_ptr=True): + """ Tests the output of a pretty printer. + + For a variable called 'var', this tests whether its associated printer + outputs the expected 'to_string' and children (if any). + + Args: + var (string): The name of the variable we'll print. + to_string (raw string): The expected output of the printer's 'to_string' + method. + children (map {raw string->raw string}): A map with the expected output + of the printer's children' method. + is_ptr (bool): Whether 'var' is a pointer, and thus should be + dereferenced. + """ + + if is_ptr: + var = '*{0}'.format(var) + + test('print {0}'.format(var), to_string) + + if children: + for name, value in children.items(): + # Children are shown as 'name = value'. + test('print {0}'.format(var), r'{0} = {1}'.format(name, value)) + +def check_debug_symbol(symbol): + """ Tests whether a given debugging symbol exists. + + If the symbol doesn't exist, raises a DebugError. + + Args: + symbol (string): The symbol we're going to check for. + """ + + try: + test('ptype {0}'.format(symbol), r'type = {0}'.format(symbol)) + + except pexpect.TIMEOUT: + # The symbol doesn't exist. + raise DebugError(symbol) diff --git a/scripts/test_printers_exceptions.py b/scripts/test_printers_exceptions.py new file mode 100644 index 0000000000..cf10a356de --- /dev/null +++ b/scripts/test_printers_exceptions.py @@ -0,0 +1,61 @@ +# Exception classes used when testing the Python pretty printers. +# +# Copyright (C) 2016-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +class NoLineError(Exception): + """Custom exception to indicate that a test file doesn't contain + the requested string. + """ + + def __init__(self, file_name, string): + """Constructor. + + Args: + file_name (string): The name of the test file. + string (string): The string that was requested. + """ + + super(NoLineError, self).__init__() + self.file_name = file_name + self.string = string + + def __str__(self): + """Shows a readable representation of the exception.""" + + return ('File {0} has no line containing the following string: {1}' + .format(self.file_name, self.string)) + +class DebugError(Exception): + """Custom exception to indicate that a required debugging symbol is missing. + """ + + def __init__(self, symbol): + """Constructor. + + Args: + symbol (string): The name of the entity whose debug info is missing. + """ + + super(DebugError, self).__init__() + self.symbol = symbol + + def __str__(self): + """Shows a readable representation of the exception.""" + + return ('The required debugging information for {0} is missing.' + .format(self.symbol)) diff --git a/scripts/update-abilist.sh b/scripts/update-abilist.sh index f9ffb954f9..28953bfe28 100644 --- a/scripts/update-abilist.sh +++ b/scripts/update-abilist.sh @@ -1,6 +1,6 @@ #!/bin/sh # Update abilist files based on differences on one architecture. -# Copyright (C) 2015-2016 Free Software Foundation, Inc. +# Copyright (C) 2015-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # # The GNU C Library is free software; you can redistribute it and/or @@ -20,9 +20,12 @@ set -e export LC_ALL=C -if [ $# -lt 3 ]; then +if [ $# -lt 2 ]; then echo "usage: $0 OLD-FILE NEW-FILE FILES-TO-BE-PATCHED..." 1>&2 exit 2 +elif [ $# -eq 2 ]; then + echo "info: no files to patch" 1>&2 + exit 0 fi old_file="$1" diff --git a/scripts/update-copyrights b/scripts/update-copyrights index 588041ce86..f048600e2a 100755 --- a/scripts/update-copyrights +++ b/scripts/update-copyrights @@ -1,6 +1,6 @@ #!/bin/sh # Update copyright year lists. -# Copyright (C) 2012-2016 Free Software Foundation, Inc. +# Copyright (C) 2012-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -54,7 +54,7 @@ for f in $files; do po/*.po) # Files imported verbatim from the Translation Project. ;; - INSTALL | intl/plural.c | locale/C-translit.h \ + INSTALL | locale/C-translit.h \ | locale/programs/charmap-kw.h | locale/programs/locfile-kw.h \ | po/libc.pot | sysdeps/gnu/errlist.c) # Generated files. diff --git a/scripts/versionlist.awk b/scripts/versionlist.awk index a9908033fa..fd51ff3fed 100644 --- a/scripts/versionlist.awk +++ b/scripts/versionlist.awk @@ -1,5 +1,5 @@ # Extract ordered list of version sets from Versions files. -# Copyright (C) 2014-2016 Free Software Foundation, Inc. +# Copyright (C) 2014-2018 Free Software Foundation, Inc. BEGIN { in_lib = ""; in_version = 0 } diff --git a/scripts/versions.awk b/scripts/versions.awk index 408f7d06fb..a3df316c70 100644 --- a/scripts/versions.awk +++ b/scripts/versions.awk @@ -1,5 +1,5 @@ # Combine version map fragments into version scripts for our shared objects. -# Copyright (C) 1998-2016 Free Software Foundation, Inc. +# Copyright (C) 1998-2018 Free Software Foundation, Inc. # Written by Ulrich Drepper <drepper@cygnus.com>, 1998. # This script expects the following variables to be defined: @@ -101,6 +101,17 @@ END { oldlib = ""; oldver = ""; + real_first_ver_header = buildroot "first-versions.h" + first_ver_header = real_first_ver_header "T" + printf("#ifndef _FIRST_VERSIONS_H\n") > first_ver_header; + printf("#define _FIRST_VERSIONS_H\n") > first_ver_header; + real_ldbl_compat_header = buildroot "ldbl-compat-choose.h" + ldbl_compat_header = real_ldbl_compat_header "T" + printf("#ifndef _LDBL_COMPAT_CHOOSE_H\n") > ldbl_compat_header; + printf("#define _LDBL_COMPAT_CHOOSE_H\n") > ldbl_compat_header; + printf("#ifndef LONG_DOUBLE_COMPAT\n") > ldbl_compat_header; + printf("# error LONG_DOUBLE_COMPAT not defined\n") > ldbl_compat_header; + printf("#endif\n") > ldbl_compat_header; printf("version-maps ="); while (getline < tmpfile) { if ($1 != oldlib) { @@ -127,11 +138,36 @@ END { printf(" ") > outfile; for (n = 3; n <= NF; ++n) { printf(" %s", $n) > outfile; + sym = $n; + sub(";", "", sym); + first_ver_macro = "FIRST_VERSION_" oldlib "_" sym; + if (!(first_ver_macro in first_ver_seen) \ + && oldver ~ "^GLIBC_[0-9]" \ + && sym ~ "^[A-Za-z0-9_]*$") { + ver_val = oldver; + gsub("\\.", "_", ver_val); + printf("#define %s %s\n", first_ver_macro, ver_val) > first_ver_header; + first_ver_seen[first_ver_macro] = 1; + if (oldlib == "libc" || oldlib == "libm") { + printf("#if LONG_DOUBLE_COMPAT (%s, %s)\n", + oldlib, ver_val) > ldbl_compat_header; + printf("# define LONG_DOUBLE_COMPAT_CHOOSE_%s_%s(a, b) a\n", + oldlib, sym) > ldbl_compat_header; + printf("#else\n") > ldbl_compat_header; + printf("# define LONG_DOUBLE_COMPAT_CHOOSE_%s_%s(a, b) b\n", + oldlib, sym) > ldbl_compat_header; + printf("#endif\n") > ldbl_compat_header; + } + } } printf("\n") > outfile; } printf("\n"); + printf("#endif /* first-versions.h */\n") > first_ver_header; + printf("#endif /* ldbl-compat-choose.h */\n") > ldbl_compat_header; closeversion(oldver, veryoldver); close_and_move(outfile, real_outfile); + close_and_move(first_ver_header, real_first_ver_header); + close_and_move(ldbl_compat_header, real_ldbl_compat_header); #system("rm -f " tmpfile); } |