User:Daniel Santos/Distcc cflags script

From Gentoo Wiki
Jump to: navigation, search

This is a script that wrangles clean machine-specific CFLAGS out of the GCC x86 sources and is expected to break if major changes are made to the GCC sources. It has only been tested on x86 and the other back-ends likely use very different code. Please report any errors to the talk page or fix them and just edit the script.

Revision History

  • v0.1 Initial release

Script

FILE clean-machine-cflags.shScript for generating clean CFLAGS for distcc
#!/bin/bash
# clean-machine-cflags.sh v0.1
#   A horrible script for deriving clean specific CFLAGS from gcc
#   sources for use distcc.
# Copyright (C) 2017  Daniel Santos <daniel.santos@pobox.com>
#
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 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/>.

src="$1"
debug=0

usage () {
    echo "USAGE: $0 [src_file]" >&2
    echo >&2
    echo "  Where src_file is the path to i386.c"
    echo >&2
    echo "Example: $0 /tmp/gcc-6.3.0/gcc/config/i386/i386.c" >&2
    exit 1
}

debugmsg () {
    ((debug)) && echo "$*" >&2
}

if [[ $# > 1 || "$1" = "-h" || "$1" = "--help" ]]; then
    usage
fi

if [[ $# == 0 ]]; then
    url="https://github.com/gcc-mirror/gcc/raw/master/gcc/config/i386/i386.c"
    src=/tmp/i386.c
    if [[ ! -f "$src" ]]; then
	wget -O /tmp/i386.c "$url" || exit
    fi
fi

if [[ ! -r "$src" ]]; then
    echo "$src not a file or not readable." >&2
    usage
fi

# Get the native flags that are ugly
nativeflags=$(
    gcc -v -E -x c -march=native -mtune=native - < /dev/null 2>&1 |
    grep cc1 |
    perl -pe 's/^.* - //g; s/\s+/\n/g;'
)
debugmsg nativeflags = $nativeflags
debugmsg

arch=$(
    grep -- '^-march=' <(echo "$nativeflags") |
    perl -pe 's/^-march=//g;'
)
debugmsg arch = $arch
debugmsg

# Extract all native -mno-* flags
native_mno_flags=$(
    grep '^-mno-' <(echo "$nativeflags") |
    perl -pe 's/^-mno-//g;'
)
debugmsg native_mno_flags = $native_mno_flags
debugmsg

# Extract all native -m* flags other than -march, -mtune and -mno-*
native_mflags=$(
    grep '^-m' <(echo "$nativeflags") |
    grep -v -E -- '-m(arch|tune|no-)' |
    perl -pe 's/^-m//g;'
)
debugmsg native_mflags = $native_mflags
debugmsg

# Extract the constant base name (upper case) for each CPU extension that
# $arch has.
ext_consts=$(
    cat "$src" | perl -pe '
	# Remove all carriage returns.
	s/\n//g;
    ' |
    perl -pe '
	# Remove everything up to the start of the processor_alias_table
	s/^.*const processor_alias_table.+?{\s+{/{/g;

	# Remove everything after it
	s/"generic",\s+PROCESSOR_GENERIC.*$//g;

	# Re-add line separators where we want them
	s/},/},\n/g;
    ' |

    # Extract line for $arch
    grep "{\"$arch\"," |

    # Extract the PTA_* flags
    awk -F, '{print $4}' |

    # Remove the PTA_ prefix and clean them up.
    perl -pe '
	s/\}//g;
	s/\sPTA_(\w)/$1/g;
	s/\s*\|\s*/\n/g;
    '
)
debugmsg ext_consts = $ext_consts
debugmsg

if [[ -z "$ext_consts" ]]; then
    echo "ERROR: Didn't find arch '$arch' in file '$src'" >&2
    echo "This means this script is broken." >&2
    exit 1
fi

# Convert the constant base name into the actual CLI text (minus the -m)
marchexts=$(
    for e in $ext_consts; do
	grep -E "{\s*\"-m.*OPTION_MASK_ISA_$e" $src |
	awk -F\" '{print $2}' |
	perl -pe 's/^-m//g;' |
	sort
    done
)
debugmsg marchexts = $marchexts
debugmsg

unset real_mno_flags
unset real_mflags

for mno_flag in $native_mno_flags; do
    if grep -- "^$mno_flag$" <(echo "$marchexts") > /dev/null; then
    	real_mno_flags="$real_mno_flags -mno-$mno_flag"
    fi
done

for mflag in $native_mflags; do
    if grep -- "^$mflag$" <(echo "$marchexts") > /dev/null; then
    	dummy=smarty
    else
    	real_mflags="$real_mflags -m$mflag"
    fi
done

debugmsg real_mflags = $real_mflags
debugmsg real_mno_flags = $real_mno_flags
debugmsg

echo "CFLAGS=\"$(
    gcc -v -E -march=$arch $real_mflags $real_mno_flags -mtune=native - < /dev/null 2>&1 |
    grep cc1 |
    perl -pe 's/^.* - //g;'\
)\""

See also