Skip to content

Instantly share code, notes, and snippets.

@k-takata
Last active May 11, 2022 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save k-takata/cf7ad1244475ce6af04705d045e68262 to your computer and use it in GitHub Desktop.
Save k-takata/cf7ad1244475ce6af04705d045e68262 to your computer and use it in GitHub Desktop.
Reduce the install size of clang, llvm, lld and gcc on MSYS2
#!/bin/sh
# Convert the same files into hard links to reduce the install size of
# clang, llvm, lld and gcc on MSYS2.
ESC=$'\33'
GREEN="$ESC[32m"
YELLOW="$ESC[33m"
CYAN="$ESC[36m"
RESET="$ESC[m"
do_link()
{
TARGET=$1
LINK=$2
if [ -h $TARGET ] || [ -h $LINK ] || [ ! -f $TARGET ] || [ ! -f $LINK ]; then
# Skip symlinks and non-normal files.
return
fi
# Check i-node number
if gawk -v t=$TARGET -v l=$LINK '@load "filefuncs";
BEGIN{stat(t, f1); stat(l, f2);
exit f1["ino"] != f2["ino"]}'; then
echo "${CYAN}Already hard-linked:${RESET} $LINK - $TARGET"
return
fi
# Check if the content of files are exactly the same.
if diff $TARGET $LINK > /dev/null; then
# Convert to a hard link.
echo "${YELLOW}Linking:${RESET} $LINK - $TARGET"
ln -f $TARGET $LINK
fi
}
link_files()
{
if [ $# -lt 2 ]; then
return
fi
# 1. Check if all the i-node numbers are the same if the file sizes are the same.
# 2. Check the MD5 if the i-node numbers are different.
# 3. Link if the MD5 are the same.
stat -c '%s %i %n' "$@" | \
gawk '
{
name[$1][$3]
inode[$1][$2]
}
END {
for (i in inode) {
if (length(inode[i]) > 1) {
asorti(name[i], n)
for (j in n) {
print n[j]
}
}
}
}' | \
xargs md5sum 2> /dev/null | \
awk -F ' [* ]' '{if ($1 in a) {print a[$1], $2} else {a[$1]=$2}}' | \
while read LINE; do
eval do_link $LINE
done
}
do_gcc_bin()
{
GCC_BINDIR=$1
pushd $GCC_BINDIR > /dev/null
echo "${GREEN}Directory:${RESET} $GCC_BINDIR"
files=''
for i in *.exe; do
files="$files \"$i\" \"../../bin/$i\""
done
eval link_files $files
popd > /dev/null
}
do_top()
{
TOP=$1
TRIPLET=$2
if [ -d $TOP/$TRIPLET/bin ]; then
do_gcc_bin $TOP/$TRIPLET/bin
fi
BINDIR=$TOP/bin
if ! [ -d $BINDIR ]; then
return
fi
pushd $BINDIR > /dev/null
echo "${GREEN}Directory:${RESET} $BINDIR"
link_files *
popd > /dev/null
}
do_top /mingw32 i686-w64-mingw32
do_top /mingw64 x86_64-w64-mingw32
do_top /ucrt64 x86_64-w64-mingw32
do_top /clang32 NONE
do_top /clang64 NONE
do_top /usr x86_64-pc-msys
@k-takata
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment