As others have noted, what you use as a header guard isn't intrinsically important; it just needs to be unique across the set of headers that might ever be co-included.
You can create a UUID or GUID and use that as the header guard (or a hash of some sort — MD5, SHA1, SHA2, SHA3, …). The only trick is dealing with the possibility of a leading digit; that's easily worked around (I used H_ as a prefix).
Mostly though, I use a name based on the file name, and don't usually rename headers often enough that it is a problem.
Here's a script called hdrguard that I use for generating the header guard lines for a given header file:
#!/bin/sh
#
# @(#)$Id: hdrguard.sh,v 1.8 2016/05/09 18:41:57 jleffler Exp $
#
# Generate #ifndef sequence to guard header against multiple inclusion
arg0=$(basename $0 .sh)
usestr="Usage: $arg0 [-bdfhimV] header.h [...]"
usage()
{
echo "$usestr" 1>&2
exit 1
}
help()
{
echo "$usestr"
echo
echo " -b Use base name of file for guard"
echo " -d Use _DOT_H after name (instead of _H)"
echo " -f Use specified path name of file for guard (default)"
echo " -h Print this help message and exit"
echo " -i Omit _INCLUDED after name"
echo " -m Generate MD5 hash value as header guard"
echo " -V Print version information and exit"
exit 0
}
opt_incl=yes
opt_base=no
opt_dot=no
opt_md5=no
while getopts bdfhimV opt
do
case "$opt" in
(b) opt_base=yes;;
(d) opt_dot=yes;;
(f) opt_base=no;;
(h) help;;
(i) opt_incl=no;;
(m) opt_md5=yes;;
(V) echo "$arg0: HDRGUARD Version "'$Revision: 1.8 $ ($Date: 2016/05/09 18:41:57 $)' | rcsmunger; exit 0;;
(*) usage;;
esac
done
shift $(($OPTIND - 1))
[ $# -eq 0 ] && usage
for i in "$@"
do
if [ $opt_base = yes ]
then i=$(basename $i)
fi
if [ $opt_dot = yes ]
then i=$(echo "$i" | sed 's/\.h$/_dot_h/')
fi
i=$(echo $i | tr 'a-z' 'A-Z' | tr -s '/+.-' '____' | sed 's/^_//')
if [ $opt_incl = yes ]
then
case "$i" in
(*_INCLUDED)
: OK;;
(*)
i="${i}_INCLUDED";;
esac
fi
if [ $opt_md5 = yes ]
then
tmp=$(mktemp ./hdrgrd.XXXXXXXX)
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
echo "$i.$(isodate compact)" > "$tmp"
i=$(md5 "$tmp" | sed 'y/abcdef/ABCDEF/; s/\([^ ]*\) .*/H_\1/')
rm -f "$tmp"
trap 0 1 2 3 13 15
fi
echo
echo "#ifndef $i"
echo "#define $i"
echo
echo "#endif /* $i */"
echo
done
It doesn't have code for SHA1, SHA2 or SHA3 — it optionally uses MD5 (in the form of a command md5). It would not be very hard to add support for alternative hashing algorithms. It doesn't require the file to exist.
Example uses:
$ hdrguard header.h
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#endif /* HEADER_H_INCLUDED */
$ hdrguard -m header.h
#ifndef H_6DC5070597F88701EB6D2CCAACC73383
#define H_6DC5070597F88701EB6D2CCAACC73383
#endif /* H_6DC5070597F88701EB6D2CCAACC73383 */
$
I frequently use it from within vim, typing a command such as !!hdrguard % while the cursor is on an empty line to generate a header guard suitable for the header I'm editing. That's why it generates the blank lines top and bottom, too.
The command uses scripts isodate and rcsmunger. With the argument compact, the isodate command is equivalent to:
date +'%Y%m%d.%H%M%S'
The complete command supports a number of alternative formats and is more succinct than having to type the date command out everywhere. You're entirely at liberty to forego the use of a separate script and to just embed the expansion shown into hdrguard. Indeed, you could use just date and it would be OK; it is just seed material for the hashing operation to make the data being hashed unique.
$ isodate compact
20161228.185232
$
The rcsmunger command just converts RCS ID strings into a format I prefer for reporting version information:
#!/usr/bin/env perl -p
#
# @(#)$Id: rcsmunger.pl,v 1.9 2015/11/02 23:54:32 jleffler Exp $
#
# Remove the keywords around the values of RCS keywords
use strict;
use warnings;
# Beware of RCS hacking at RCS keywords!
# Convert date field to ISO 8601 (ISO 9075) notation
s%\$(Date:) (\d\d\d\d)/(\d\d)/(\d\d) (\d\d:\d\d:\d\d) \$%\$$1 $2-$3-$4 $5 \$%go;
# Remove keywords
s/\$([A-Z][a-z]+|RCSfile): ([^\$]+) \$/$2/go;
For example:
$ hdrguard -V
hdrguard: HDRGUARD Version 1.8 (2016-05-09 18:41:57)
$
You can regard the printing of version information as old-school version control; it has to be done differently if you use a DVCS such as git, which is one reason I've not done a wholesale migration to git for my personal software collection.