Skip to content

Instantly share code, notes, and snippets.

@jwakely
Last active January 11, 2024 12:16
Show Gist options
  • Save jwakely/5579a4be12a86495d47cb5519f671b12 to your computer and use it in GitHub Desktop.
Save jwakely/5579a4be12a86495d47cb5519f671b12 to your computer and use it in GitHub Desktop.
Various shell and git tools for GCC development
#!/usr/bin/awk -f
# Usage: badtests.awk [-v std_mode=NN] FILE...
# Check each FILE for logic errors in dejagnu directives.
# This is intended for the libstdc++ testsuite and not tested on other tests.
BEGINFILE {
dgrequire = dgdo = compile = xfail = options = addoptions = verify = testbool = 0
if (std_mode == 0)
std_mode = 17 # default -std of GCC release being tested
}
/{ dg-require/ { ++dgrequire }
/{ dg-do .* } / {
++dgdo
if (dgrequire)
print FILENAME " has dg-do after dg-require-*"
}
/{ (dg-do .* target|dg-require-effective-target) c\+\+(17|2.) / {
match($0, "target c\\+\\+(..)", a)
if (a[2] > std_mode)
print FILENAME " will not run without a suitable -std option"
}
/{ dg-do compile .* }/ { ++compile }
/{ dg-do [^r].* xfail .* }/ { ++xfail }
/{ dg-options/ {
++options
if (addoptions)
print FILENAME " has dg-options after dg-add-options"
if (match($0, "-std=(gnu|c)\\+\\+(17|2.)", a) != 0) {
std_mode = a[2]
}
}
/{ dg-add-options/ { ++addoptions }
/VERIFY/ { ++verify }
/bool test .*attribute.*unused/ { ++testbool }
ENDFILE {
if (dgdo > 1)
print FILENAME " has multiple dg-do directives"
if (compile > 0 && verify > 0)
print FILENAME " uses VERIFY in a compile-only test"
if (xfail > 0)
print FILENAME " uses 'xfail' when do-what-keyword != 'run'"
if (options > 1)
print FILENAME " has multiple dg-options directives"
if (testbool > 1 && verify == 0)
print FILENAME " has bool test but doesn't use VERIFY"
}
fails () { egrep '^(FAIL|XPASS|UNRESOLVED|ERROR)' ${1:-testsuite/libstdc++.sum} ; }
errors () { pattern="^(FAIL|XPASS|UNRESOLVED|ERROR)" ; sed -E -n -e "/$pattern/,/(^$|^Executing)/s/^[^P]/&/p" -e "/^terminate called/,/$pattern/s/^[^P]/&/p" ${1:-testsuite/libstdc++.log} | egrep --color "$pattern?" ; }
sumtest () { awk '/^(X?PASS|X?FAIL|UN|ERROR)/{counts[$1] += 1} END{ for (i in counts) printf "%-15s %d\n", i, counts[i] }' ${1:-testsuite/libstdc++.sum} ; }
retry_fails() { ( awk '$1=="FAIL:" {print $2}' testsuite/libstdc++.sum > testsuite/testsuite_files ; trap "rm testsuite/testsuite_files" EXIT ; make check "$@" ) ; }
# useful for e.g. make check $RTF=23_containers/*
export RTF=RUNTESTFLAGS=conformance.exp
# Run tests.
# $1 is a shell glob naming which tests to run.
# $2 is a list of space-separated or /-separated extra compiler options.
# Additional options are passed straight to make.
# e.g. check 23_containers/*insert* -O1/-fno-inline -j4
check() {
local glob="$1"
local target_list="${2+ --target_board=unix/${2// /\/}}"
shift ${2+2}
DEJAGNU=/dev/null make -C testsuite check $RTF="$glob${target_list} --all" "$@"
sumtest
}
#!/bin/sh
# Annotate the output of 'git branch' with GCC Bugzilla descriptions.
#
# Usage: git branch | brann
# Or using: git config --add alias.brann '!f(){ git branch | brann; }; f'
cachedir=/var/tmp/gcc-pr
stylesheet=$cachedir/brann.xsl
set -e
mkdir -p $cachedir
if [[ $1 == --clean ]]
then
[ -d "$cachedir" ] && rm "$cachedir"/*
shift
fi
write_stylesheet() {
cat > "$stylesheet" <<-STYLESHEET
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="/bugzilla/bug/short_desc"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="/bugzilla/bug/bug_status"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="/bugzilla/bug/resolution"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
STYLESHEET
}
fetch() { wget -q -O $2 $1 ; }
create() {
[ -s $cachedir/$1 ] && return
[ -s $cachedir/$stylesheet ] || write_stylesheet
[ -s $cachedir/$1.xml ] || fetch "https://gcc.gnu.org/bugzilla/show_bug.cgi?ctype=xml&id=$1" "$cachedir/$1.xml"
xsltproc --novalid --output "$cachedir/$1" "$stylesheet" "$cachedir/$1.xml"
}
# re="^. ([[:alnum:]].*/)?pr([0-9]+)"
re="^. pr([0-9]+)"
# This dir should contain a clone of https://github.com/cplusplus/LWG.git
lwgdir=$HOME/src/cplusplus/LWG/xml
if [[ -d $lwgdir ]]
then
lwgre="^. lwg([0-9]+)"
else
lwgre=
fi
while read
do
if [[ $REPLY =~ $re ]]
then
id=${BASH_REMATCH[1]}
create $id
read desc < "$cachedir/$id"
printf "%-18s %s\n" "$REPLY" "$desc" | sed \
-e 's/RESOLVED [[:upper:]]*$/&/' \
-e 's/UNCONFIRMED$/&/' \
-e 's/NEW$/&/' \
-e 's/REOPENED$/&/' \
-e 's/ASSIGNED$/&/'
elif [[ $lwgre ]] && [[ $REPLY =~ $lwgre ]]
then
id=${BASH_REMATCH[1]}
desc=$(xpath $lwgdir/issue$id.xml 'string(/issue/title)' 2>/dev/null)
printf "%-18s %s\n" "$REPLY" "$desc"
else
echo "$REPLY"
fi
done | sed -e 's/^\* \([[:print:]]*\)/* \1/'
#!/bin/sh
# Verify feature test macros are defined consistently.
: ${CXX:=$HOME/gcc/latest/bin/g++}
get_feature_macros()
{
cxx="$1"
$cxx -E -dD -xc++ - | awk '
/^[[:blank:]]*#[[:blank:]]*define[[:blank:]]*__cpp_/ {
name = $(NF-1)
value = $NF
if (name in macros)
if (macros[name] != value)
print name " redefined from " macros[name] " to " value > "/dev/stderr"
macros[name] = value
}
/^[[:blank:]]*#[[:blank:]]*undef[[:blank:]]*__cpp_/ { delete macros[$NF] }
END { for (name in macros) print "#define " name " " macros[name] }
' | sort
}
for cxx in "$CXX" "clang++ --gcc-toolchain=$HOME/gcc/latest"
do
echo "Compiler: $cxx"
for dialect in c++ gnu++
do
for i in 98 11 14 17 2a 2b;
do
echo ===$dialect$i===
cxx_std="$cxx -std=$dialect$i"
printf '#include <bits/stdc++.h>\n#if __has_include(<execution>)\n#include <execution>\n#endif\n' | get_feature_macros "$cxx_std -D_GLIBCXX_VERSION_INCLUDED" > /tmp/perfilemacros
echo '#include <version>' | get_feature_macros "$cxx_std" > /tmp/versionmacros
diff -up /tmp/perfilemacros /tmp/versionmacros
done
done
done
[core]
filemode = true
bare = false
logallrefupdates = true
#sparseCheckout = true
whitespace = trailing-space,space-before-tab,tabwidth=8,indent-with-non-tab
[diff]
wsErrorHighlight = old,new
# wsErrorHighlight = all
[diff "cpp"]
# xfuncname = "^[[:space:]]*[[:word:]_][[:word:][:digit:]_]*[[:space:]]*.*[[:space:]]*[[:word:]_][[:word:][:digit:]_]*[[:space:]]*\\(.*\\)[[:space:]]*$"
[diff "md"]
xfuncname = ^\\(define.*$
[merge]
renamelimit = 9001
[push]
default = simple
[remote "origin"]
url = git+ssh://gcc.gnu.org/git/gcc.git
fetch = +refs/heads/*:refs/remotes/origin/*
[gcc-config]
upstream = origin
mklog-hook-type = smart-amend
[alias]
gcc-show="!f() { git show $(git gcc-undescr $1); }; f"
# Add gcc-descr tags to log
gcc-log = "!f() { git log \"${@}\" | awk '/^commit / { \"git gcc-descr \" $2 | getline descr ; if (!descr) descr=\"not upstream\" ; printf \"%s [%s]\\n\", $0, descr ; } !/^commit / { print }'; } ; f"
# Find a commit by SVN revision
svn-rev = "!f() { rev=$1; shift; git gcc-log --all --grep=\"^From-SVN: r\\\\?$rev\\\\b\" \"${@}\"; } ; f"
srev = "!f() { git svn-rev $1 -1 ; }; f"
sshow = "!f(){ git svn-rev $1 -1 -p ; }; f"
# Run git command (diff, show etc.), filtering out modifications to ChangeLog files and generated files
filter = "!f(){ git $@ | filterdiff -x '*/ChangeLog' -x '*/Makefile.in' -x '*/configure' -x '*/config.h.in' -x '*/doc/html/*' | sed -e '/^diff.*ChangeLog/{N;d}' ; }; f"
# Write commits to /dev/shm/patch, filtering out modifications to ChangeLog files and generated files
pp = "!f(){ git filter show --diff-algorithm=histogram ${*:-HEAD} > /dev/shm/patch.txt; }; f"
# Write unpushed local commits to /dev/shm/patch.txt
lgpp = "!git pp @{u}.."
# Email last commit to gcc lists
mailpatch = "!f() { commit=${1:-HEAD}; draft=/dev/shm/draft.mail; set -e ; git pp ${commit} ; git log --pretty=email -1 ${commit} > $draft ; git merge-base --is-ancestor $commit @{upstream} && sed -i '/^Subject:/s/PATCH/committed/' $draft && printf '\nTested %s. Committed to trunk.\n\n' ${2:-powerpc64le-linux} >> $draft ; mutt -H $draft -a /dev/shm/patch.txt -- libstdc++@gcc.gnu.org gcc-patches@gcc.gnu.org; }; f"
# update remote git repo
tup = "!f(){ hosts=${*:-wraith}; cur=`git cbr`; for host in $hosts; do git push $host +$cur || continue ; if [[ $host == wraith ]]; then remotedir=$PWD; else remotedir=src/gcc; fi; ssh $host 'cd '$remotedir' && git checkout -f'; done; }; f"
# show branch names with bugzilla info
bra = "!git br | $HOME/src/gcc/scripts/brann"
brac = "!git br | $HOME/src/gcc/scripts/brann --clean"
braf = "!git bra | grep"
# Regenerate configury (using old autotools if branch doesn't contain r265695)
regen = "!f(){ cd ${GIT_PREFIX:-.} && if git merge-base --is-ancestor 22e052725189a472e4e86ebb6595278a49f4bcdd HEAD ; then /opt/autotools-gcc/bin/autoreconf; else /opt/autotools-gcc8/bin/autoreconf; fi; }; f"
rebodge = rebase -i --autosquash
addcl = add ChangeLog
check-backport = "!f() { git pull --ff-only --quiet && git log --name-only --pretty=format: -1 $1 | grep -v ChangeLog | xargs git log $1..master -- ; }; f"
backport = "!f() { git pull --ff-only --quiet || return ; git cherry-pick -n $1 ; r=$? ; ~/src/gcc/scripts/backport libstdc++-v3/ChangeLog ; [[ $r = 0 ]] && git add libstdc++-v3/ChangeLog ; }; f"
#release-branch = "!f() { [[ $# == 1 ]] || return 1; git svn fetch svn && git fetch origin && git branch $1-branch origin/$1-branch && git config --add svn-remote.svn.fetch branches/$1-branch:refs/remotes/origin/$1-branch && git worktree add ~/src/gcc/$1 $1-branch ; }; f"
release-branch = "!f() { [[ $# == 1 ]] && git fetch origin && git worktree add -b $1 ~/src/gcc/$1 origin/releases/$1 ; }; f"
# Amend previous commit with all changes in tree.
caa = commit -a --amend -C HEAD
# Amend previous commit and push for testing.
caat = "!f() { git caa && git tup $@ ; }; f"
# Same as caat but runs editor to change commit log.
retup = "!f() { git add -u && git ci --amend && git tup $@ ; }; f"
# Usage: git changed-files <commit> [<commit>]
# List files changed in a commit (or between two commits).
changed-files = "!f() { git diff --stat --name-only ${2:-$1^} $1 | xargs git ls-tree --full-tree $1 ; }; f"
# The branch being tracked by the current branch.
track = "!f() { if p=$(git rev-parse --symbolic-full-name '@{u}' 2>/dev/null); then echo origin/${p##*/}; fi; }; f"
remaster = !$HOME/src/miscripts/gcc/remaster_branch.sh
fetch-user = "!f() { echo git fetch origin refs/users/$1/heads/${2:-*}:refs/remotes/origin/$1/${2:-*} ; }; f"
gcc-descr = "!f() { if test ${1:-no} = --full; then c=${2:-master}; r=$(git describe --all --abbrev=40 --match 'basepoints/gcc-[0-9]*' $c | sed -n 's,^\\(tags/\\)\\?basepoints/gcc-,r,p'); expr match ${r:-no} '^r[0-9]\\+$' >/dev/null && r=${r}-0-g$(git rev-parse ${2:-master}); else c=${1:-master}; r=$(git describe --all --match 'basepoints/gcc-[0-9]*' $c | sed -n 's,^\\(tags/\\)\\?basepoints/gcc-\\([0-9]\\+\\)-\\([0-9]\\+\\)-g[0-9a-f]*$,r\\2-\\3,p;s,^\\(tags/\\)\\?basepoints/gcc-\\([0-9]\\+\\)$,r\\2-0,p'); fi; if test -n $r; then o=$(git config --get gcc-config.upstream); rr=$(echo $r | sed -n 's,^r\\([0-9]\\+\\)-[0-9]\\+\\(-g[0-9a-f]\\+\\)\\?$,\\1,p'); if git rev-parse --verify --quiet ${o:-origin}/releases/gcc-$rr >/dev/null; then m=releases/gcc-$rr; else m=master; fi; git merge-base --is-ancestor $c ${o:-origin}/$m && \\echo ${r}; fi; }; f"
gcc-undescr = "!f() { o=$(git config --get gcc-config.upstream); r=$(echo $1 | sed -n 's,^r\\([0-9]\\+\\)-[0-9]\\+$,\\1,p'); n=$(echo $1 | sed -n 's,^r[0-9]\\+-\\([0-9]\\+\\)$,\\1,p'); test -z $r && echo Invalid id $1 && exit 1; h=$(git rev-parse --verify --quiet ${o:-origin}/releases/gcc-$r); test -z $h && h=$(git rev-parse --verify --quiet ${o:-origin}/master); p=$(git describe --all --match 'basepoints/gcc-'$r $h | sed -n 's,^\\(tags/\\)\\?basepoints/gcc-[0-9]\\+-\\([0-9]\\+\\)-g[0-9a-f]*$,\\2,p;s,^\\(tags/\\)\\?basepoints/gcc-[0-9]\\+$,0,p'); git rev-parse --verify $h~$(expr $p - $n); }; f"
redate = rebase --ignore-date
up = "!f() { git pull --rebase && contrib/gcc_update --silent --touch ; }; f"
push-ci = "!git cherry-pick travis && { git push --force-with-lease github HEAD:ci-candidate ; git reset --hard HEAD^ ; }"
gcc-verify = "!f() { \"`git rev-parse --show-toplevel`/contrib/gcc-changelog/git_check_commit.py\" $@; } ; f"
gcc-mklog = "!f() { \"`git rev-parse --show-toplevel`/contrib/mklog.py\" $@; } ; f"
gcc-backport = "!f() { \"`git rev-parse --show-toplevel`/contrib/git-backport.py\" $@; } ; f"
gcc-commit-mklog = "!f() { GCC_FORCE_MKLOG=1 git commit \"$@\"; }; f"
[rerere]
enabled = true
[branch]
autosetupmerge = always
[log]
date = local
#!/bin/bash
set -e
gcc_common_args='--enable-languages=c++ --disable-nls --without-isl --disable-libcc1 --disable-libgomp --disable-libsanitizer --disable-libitm --without-lto --disable-multilib'
# Native GCC compiler
mkdir -p ~/build-canada/gcc-native
cd ~/build-canada/gcc-native
$skip1 ~/src/gcc/configure --prefix=$HOME/gcc/12 $gcc_common_args --disable-bootstrap
make -j10 && make install
# Use the new native GCC
PATH=$HOME/gcc/12/bin:$PATH
# Cross binutils
mkdir -p ~/build-canada/binutils
cd ~/build-canada/binutils
$skip2 ~/src/binutils-gdb/configure --prefix=$HOME/gcc/aarch64 --disable-gdb --disable-sim --disable-werror \
--target=aarch64-none-linux-gnu \
--build=x86_64-pc-linux-gnu \
--with-sysroot=/home/iains/cross-roots/aarch64-none-linux-gnu
make -j10 && make install
# Cross GCC
mkdir -p ~/build-canada/gcc-cross
cd ~/build-canada/gcc-cross
$skip3 ~/src/gcc/configure --prefix=$HOME/gcc/aarch64 $gcc_common_args \
--target=aarch64-none-linux-gnu \
--build=x86_64-pc-linux-gnu \
--with-sysroot=/home/iains/cross-roots/aarch64-none-linux-gnu
make -j10 && make install
# Use new aarch64-none-linux-gnu-ld and aarc64-none-linux-gnu-g++ etc
PATH=$PATH:$HOME/gcc/aarch64/bin
# "Native cross" GCC
mkdir -p ~/build-canada/gcc-native-cross
cd ~/build-canada/gcc-native-cross
$skip4 ~/src/gcc/configure --prefix=/not/going/to/install $gcc_common_args \
--target=aarch64-none-linux-gnu \
--host=aarch64-none-linux-gnu \
--build=x86_64-pc-linux-gnu \
--with-sysroot=/home/iains/cross-roots/aarch64-none-linux-gnu
make -j10
Various shell and git tools I use for GCC development
(with a focus on libstdc++ development).
Mostly shell functions and git aliases to automate my
workflow. They might not work for you.
#!/bin/bash
# Generate files for https://gcc.gnu.org/onlinedocs/gcc-$1/libstdc++/manual/
# and https://gcc.gnu.org/onlinedocs/gcc-$1/libstdc++/api/ using old version
# of Doxygen from Fedora 31. This was needed due to some bugs in Doxygen
# markup in releases 10.3.0 and 9.4.0 (and older).
set -e
test $# -eq 1
version=$1
cd $(mktemp -d /tmp/docs.XXXX)
cat > Dockerfile <<EOT
FROM docker.io/fedorapackaging/builder:fedora31
RUN sudo dnf install -y git gcc-c++ gmp-devel mpfr-devel libmpc-devel
RUN sudo dnf install -y doxygen graphviz dblatex texlive-latex texlive-makeindex docbook5-style-xsl texlive-xtab texlive-tabu texlive-hanging texlive-adjustbox texlive-stackengine texlive-listofitems texlive-tocloft texlive-newunicodechar texlive-etoc
RUN git config --global advice.detachedHead false
RUN git clone --depth 1 --branch releases/gcc-$version git://gcc.gnu.org/git/gcc ~/gcc
RUN mkdir ~/docout
RUN sed -i -e 's/--disable-gcc/& --disable-multilib/' ~/gcc/maintainer-scripts/generate_libstdcxx_web_docs
RUN sed -i -e 's/.*user.cfg.in/-e "s;LATEX_CMD_NAME.*;LATEX_CMD_NAME = lualatex;" &/' ~/gcc/libstdc++-v3/scripts/run_doxygen
RUN ~/gcc/maintainer-scripts/generate_libstdcxx_web_docs ~/gcc ~/docout
RUN tar -C ~ -czf ~/v3-docs-$version.tar.gz docout/
EOT
podman build -t docs-$version .
id=$(podman create -i docs-$version)
podman cp $id:/home/build/v3-docs-$version.tar.gz .
podman rm $id
podman rmi docs-$version
echo "Created: $PWD/v3-docs-$version.tar.gz"
echo "Run: tar xf v3-docs-$version.tar.gz && rsync -a docout/. gccadmin:/www/gcc/htdocs/onlinedocs/gcc-$version/."
#!/bin/bash
#
# A hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
fail=
for i in `git diff --name-only --cached`
do
# Skip removed files
test -f $i || continue
if [[ $i = libstdc++-v3/acinclude.m4 ]]
then
macro=`grep --with-filename --line-number 'AC_DEFINE.*_GLIBCXX_HAVE_' $i` \
&& {
echo "configure macro will get transformed to _GLIBCXX_GLIBCXX_HAVE_:" >&2
echo "$macro" >&2
}
if [[ $macro ]]
then
fail=1
fi
elif [[ $i == libstdc++-v3/testsuite/* ]]
then
if grep -qF '<filesystem>' $i && ! grep -q dg-require-filesystem-ts $i
then
# Whitelist of tests that don't need any OS support from the filesystem:
case $i in
# Test utils header doesn't need the dg-require:
libstdc++-v3/testsuite/util/testsuite_fs.h ) ;;
# std::filesystem::path doesn't need any special support:
libstdc++-v3/testsuite/27_io/filesystem/path/* ) ;;
libstdc++-v3/testsuite/libstdc++-prettyprinters/cxx17.cc ) ;;
*)
echo "$i:" missing '{ dg-require-filesystem-ts "" }' >&2
fail=1
;;
esac
fi
if ! ~/src/gcc/scripts/badtests.awk $1 > /dev/null
then
case $1 in
*/23_containers/unordered_set/allocator/ext_ptr.cc) ;;
*) fail=1 ;;
esac
fi
fi
done
exit $fail
#!/bin/sh
# Copyright (C) 2020 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC 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, or (at your option)
# any later version.
#
# GCC 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 GCC; see the file COPYING. If not, write to
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
# We might be on a branch before the file was added.
if ! [ -x contrib/mklog.py ]; then exit 0; fi
# Can't do anything if $COMMIT_MSG_FILE isn't a file.
if ! [ -f "$COMMIT_MSG_FILE" ]; then exit 0; fi
# Don't do anything unless configured to do so.
hook_type=$(git config gcc-config.mklog-hook-type)
case "$hook_type" in
always|smart-amend) ;;
*) exit 0 ;;
esac
check_existing_log()
{
if [ "$hook_type" = "smart-amend" ]; then
# Check if the existing message still describes the staged changes.
f=$(mktemp /tmp/git-commit.XXXXXX) || exit 1
printf "From: Me <me@example.com>\n" > $f
printf "Date: %s\nSubject: [PATCH] " "$(date -R)" >> $f
sed '/^#/d' $2 >> $f
printf '\n---\n\n' >> $f
git $1 >> $f
if contrib/gcc-changelog/git_email.py "$f" >/dev/null 2>&1; then
# Existing commit message is still OK for amended commit.
rm $f
exit 0
fi
rm $f
fi
}
if [ -z "$COMMIT_SOURCE" ] || [ $COMMIT_SOURCE = template ]; then
# No source or "template" means new commit.
cmd="diff --cached"
elif [ $COMMIT_SOURCE = message ]; then
# "message" means -m; assume a new commit if there are any changes staged.
if ! git diff --cached --quiet; then
cmd="diff --cached"
else
cmd="diff --cached HEAD^"
fi
check_existing_log "$cmd" $COMMIT_MSG_FILE
elif [ $COMMIT_SOURCE = commit ]; then
# The message of an existing commit. If it's HEAD, assume --amend;
# otherwise, assume a new commit with -C.
if [ $SHA1 = HEAD ]; then
cmd="diff --cached HEAD^"
check_existing_log "$cmd" $COMMIT_MSG_FILE
else
cmd="diff --cached"
fi
else
# Do nothing for merge or squash.
exit 0
fi
# Save diff to a file if requested.
DIFF_FILE=$(git config gcc-config.diff-file)
if ! [ -z "$DIFF_FILE" ]; then
tee="tee $DIFF_FILE"
else
tee="cat"
fi
git $cmd | $tee | git gcc-mklog -c "$COMMIT_MSG_FILE"
# adapted from http://aaroncrane.co.uk/2009/03/git_branch_prompt/
# Not as full featured as the official Git prompt for Bash, or liquidprompt,
# but optimised for large repositories due to:
# - avoiding calling non-builtin commands where possible
# - not recalculating the prompt when no command is run (i.e. hitting Enter)
# - optionally caching the last status and only updating after a git command
# If GIT_PROMPT_STATUS and GIT_PS1_SHOWDIRTYSTATE are both empty, do nothing.
# If GIT_PROMPT_STATUS="short" only show a single '*' character to indicate
# there are uncommitted, unstaged or untracked changes, otherwise indicate
# which types of changes are present.
# If the file .git/git-prompt-cache exists then the prompt will only be updated
# if the first word of the previous command was 'git'.
# Indicate presence of staged (+), unstaged (*) and untracked (%) changes.
function git_status_summary() {
if [[ $GIT_PROMPT_STATUS = 'short' ]]; then
# Just prints '*' or nothing:
git status -s | read && echo '*'
else
# Indicates presence of staged/unstaged/untracked changes.
local staged='+'
local unstaged='*'
local untracked='%'
git status -s | awk -v "I=$staged" -v "W=$unstaged" -v "U=$untracked" '
/^[[:upper:]]/ { i=I }
/^.[[:upper:]]/ { w=W ; next }
/^\?\?/ { u=U ; exit 0 }
END{ printf "%s%s%s", i, w, u}'
fi
}
# Set PS1_git_status to a summary of 'git status' output.
function find_git_status {
# do nothing if GIT_PROMPT_STATUS is not set
if [[ -z $GIT_PROMPT_STATUS && -z $GIT_PS1_SHOWDIRTYSTATE ]]; then
unset PS1_git_status
return
fi
# $1 should be the .git dir
local cache=$1/git-prompt-cache
# 'git status' can be slow so only run it after a new command
local -a lastcmd=(`HISTTIMEFORMAT= history 1`)
if ! [[ $PS1_git_last_cmd = ${lastcmd[0]} ]]; then
PS1_git_last_cmd=${lastcmd[0]}
if [ -w $cache ]; then
# use .git/git-prompt-cache to cache status
if ! [[ ${lastcmd[1]} = git ]]; then
# use cached status
PS1_git_status=$(< $cache)
else
# Find (and cache) new status after a git command.
PS1_git_status=$(git_status_summary | tee $cache)
fi
else
PS1_git_status=$(git_status_summary)
fi
fi
}
# Set PS1_git_branch to name of current git branch
# and call find_git_status to set PS1_git_status.
# Doing it by hand is faster than `git rev-parse --git-dir`
# and `git rev-parse --symbolic-full-name HEAD` subprocesses.
function find_git_branch {
local dir=. head gitdir
until [ "$dir" -ef / -o "$dir" -ef ~ ]; do
if [ -f "$dir/.git" ]; then
gitdir=$(awk '/^gitdir:/{print $2}' $dir/.git)
elif [ -f "$dir/.git/HEAD" ]; then
gitdir=$dir/.git
else
dir="../$dir"
continue
fi
head=$(< "$gitdir/HEAD")
if [[ $head ]]; then
if [[ $head == ref:\ refs/heads/* ]]; then
PS1_git_branch="${head#*/*/}"
else
PS1_git_branch='(detached)'
fi
find_git_status $gitdir
else
PS1_git_branch='(unknown)'
PS1_git_status='!'
fi
return
done
PS1_git_branch=''
PS1_git_status=''
}
if ! [[ "$PROMPT_COMMAND" =~ find_git_branch ]]; then
PROMPT_COMMAND="find_git_branch; $PROMPT_COMMAND"
fi
PS1_git_orig=${PS1_git_orig:-$PS1}
PS1='${PS1_git_branch:+\[\e[32m\]$PS1_git_branch${PS1_git_status:+\[\e[31m\]$PS1_git_status}\[\e[m\] }'"$PS1_git_orig"
# vim:sw=4 et:
[color]
ui = true
[alias]
st = status -s
ci = commit
br = branch
co = checkout
ff = pull --ff-only --no-rebase
dir = rev-parse --git-dir
log1 = log -n 1
lol = log --graph --decorate --pretty=oneline --abbrev-commit
lols = lol @{u}..
amend = commit --amend -C HEAD
# The current branch.
cbr = "!f(){ expr $( ( git symbolic-ref -q HEAD || cat $(git dir)/rebase-merge/head-name ) 2>/dev/null ) : 'refs/heads/\\(.*\\)'; }; f"
# Show all the local commits on this branch.
lg = log -p --diff-algorithm=histogram @{u}..
# Write all the local commits to /dev/shm/patch, filtering out modifications to ChangeLog files
lgp = "!git log -p --diff-algorithm=histogram @{u}.. | filterdiff -x '*/ChangeLog' | sed -e '/^diff.*ChangeLog/{N;d}' > /dev/shm/patch.txt"
# Show all the local changes on this branch as one big diff.
df = "!git diff $(git merge-base @{u} HEAD)"
dfc = diff --cached
# Reorganize the local commits on this branch.
rb = rebase -i @{u}
rc = rebase --continue
# 'git rmerge mybranch' to reintegrate a temporary branch onto the top of the current branch
rmerge = "!f(){ cur=`git cbr`; git rebase $cur $1; git rebase $1 $cur; }; f"
last = "!f() { git log HEAD~$1.. ; }; f"
lastp = "!f() { git log -p HEAD~$1.. ; }; f"
vc = "!f() { git diff $1^..$1 ; }; f"
gh-pr = "!f() { git fetch origin refs/pull/$1/head:pr/$1; } ; f"
cherries = cherry -v
resolve = "!f() { git status -s | awk '/^UU/ { print $2 }' | xargs gvim ; } ; f"
pushf = push --force-with-lease
brlast = branch --sort=-authordate
v = "!f() { git \"$@\" | gview - ; }; f"
[rerere]
enabled = true
[push]
default = simple
[color "branch"]
remote = yellow dim
[merge]
tool = diffconflicts
[mergetool "diffconflicts"]
cmd = diffconflicts \"gvim -f\" $BASE $LOCAL $REMOTE $MERGED
trustExitCode = true
[mergetool]
keepBackup = false
# Build a mingw-w64 cross compiler on Fedora.
# Use mingw64 binutils and sysroot from Fedora repo.
sudo dnf install mingw64-{binutils,gcc,gcc-c++,zlib,winpthreads-static}
PREFIX=$HOME/gcc/mingw
# Most options copied from the Fedora package.
../gcc/configure --prefix=$PREFIX \
--with-gnu-as --with-as=/usr/bin/x86_64-w64-mingw32-as \
--with-gnu-ld --with-ld=/usr/bin/x86_64-w64-mingw32-ld \
--without-newlib --disable-multilib --disable-plugin \
--disable-libstdcxx-pch --with-system-zlib --disable-nls \
--without-included-gettext --disable-win32-registry \
--enable-threads=posix --enable-libgomp \
--target=x86_64-w64-mingw32 \
--with-sysroot=/usr/x86_64-w64-mingw32/sys-root \
--with-gxx-include-dir=$PREFIX/include/c++ \
target_alias=x86_64-w64-mingw32 --enable-libstdcxx-debug \
--enable-languages=c,c++
make -j10 && make install
#!/bin/sh
# Read pathnames of libstdc++ tests from standard input,
# compile each test using a mingw cross-compiler,
# and if it's a "dg-do run" test, run the executable using wine.
# For debugging, see
# https://stackoverflow.com/questions/39938253/how-to-properly-debug-a-cross-compiled-windows-code-on-linux
# Simplest is "winedbg -gdb foo.exe" and works pretty well.
CXX=${CXX:-$HOME/gcc/mingw/bin/x86_64-w64-mingw32-g++}
GCC_SRC_DIR=$HOME/src/gcc/gcc
STD="${STD:--std=c++26}"
LDLIBS="${LDLIBS:--lstdc++_libbacktrace}"
CPPFLAGS="-I$GCC_SRC_DIR/libstdc++-v3/testsuite/util $CPPFLAGS"
CXXFLAGS="-g -Wall -Wextra $CXXFLAGS $STD $LDLIBS"
# Use colours if outputting to a terminal
if [ -t 1 ]
then
fail=''
pass=''
normal=''
else
fail=
pass=
normal=
fi
# Run a headless X server
Xvfb :9 -screen 0 1024x768x16 &
trap 'kill %1' EXIT
# Start wine on the dummy X server, running a simple program.
# This means that each "wine a.exe" below won't start wine again.
DISPLAY=:9.0 WINEDEBUG=fixme-all wine view.exe &
trap 'kill -INT %2 && sleep 2 && kill -INT %1' EXIT
# Or use 'wineserver -p 30' as a better way to get a persistent server.
# DISPLAY=:9.0 WINEDEBUG=fixme-all wineserver -p 30
# trap 'wineserver -k' EXIT
while read test
do
# Skip commented out lines
[[ ${test:0:1} == '#' ]] && continue
echo $test
c=''
run=wine
if grep -F -q 'dg-do compile' $test
then
c='-c -Wfatal-errors'
run=:
elif grep -F -q 'dg-do link' $test
then
run=:
fi
options=$(sed -n 's@// { dg-options "\(.*\)" }@\1@p' $test)
if grep --silent tracker_allocator $test; then
options="$options $HOME/src/gcc/gcc/libstdc++-v3/testsuite/util/testsuite_allocator.cc"
fi
result=PASS
if grep --silent '{ dg-require-target-fs-symlinks "" }' $test
then
result=UNSUPPORTED
# link once dynamically (to detect undefined refs)
elif ! $CXX $CPPFLAGS $CXXFLAGS $LDFLAGS $c $test $options $LDLIBS
then
if grep -q 'dg-error' $test
then
result=PASS
else
result=FAIL
fi
# and then link again statically (so no .dll needed to run the tests)
elif ! $CXX $CPPFLAGS $CXXFLAGS $LDFLAGS $c $test $options -static -O2 $LDLIBS
then
result=FAIL
# Workaround problem with binutils producing invalid executable for DWARF-5:
# elif ! /usr/bin/x86_64-w64-mingw32-strip a.exe ; then result=FAIL
elif ! WINEDEBUG=fixme-font $run a.exe
then
if grep -q 'dg-xfail-if.*mingw' $test
then
result=XFAIL
else
result=FAIL
fi
fi
if [[ $result == FAIL ]]
then
decorate="$fail"
else
decorate="$pass"
fi
echo "$decorate$result: $test$normal"
# [[ $result == FAIL ]] && break
done
#!/bin/bash
# Script to create a new libstdc++ test
YEAR=$(date +%Y)
DO=${1:-run}
STD=${2:-c++11}
shift 2
if [[ $STD = "c++17" ]] && false
then
OPTS='// { dg-options "-std=gnu++17'"${1:+ }$*"'" }
'
fi
if [[ $STD = "c++2a" ]]
then
OPTS='// { dg-options "-std=gnu++2a'"${1:+ }$*"'" }
'
fi
if [[ $DO == run ]]
then
HOOKS='#include <testsuite_hooks.h>
'
fi
if [[ $DO != compile ]]
then
MAIN='
int
main()
{
test01();
}'
fi
cat <<EOT
// Copyright (C) $YEAR Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library 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, or (at your option)
// any later version.
// This 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 General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
${OPTS}// { dg-do $DO { target $STD } }
#include <>
$HOOKS
void
test01()
{
}$MAIN
EOT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment