The trap
is too late to be much use here. If the program fails (either during compilation, or when it's run), you'll exit before the trap has been set, and so fail to clean up. It's best to set the trap as soon as you know the file's name:
#!/bin/sh
prog="$(mktemp programXXXXXX)"
trap "rm -f '$prog'" EXIT
gcc -o "$prog" -x 'c' - <<'END_OF_SOURCE'
# (C code here) #
END_OF_SOURCE
./"$prog" "$@"
# script now exits with the return status of the program above,
# after running the 'rm' command in the trap
A couple of other changes made above:
- I've used
<<
rather than <<-
to allow the leading whitespace through to the compiler. This makes very little difference in C, but may help you understand any quoted code in error messages more clearly. Also, I've quoted the delimiter, as we don't need the shell to perform expansion of the program source.
- I've used
"$@"
rather than $@
so that the arguments are passed through intact without further word-splitting.
- There's no need to save the exit status in a variable - the shell's exit status is that of the last command executed in the script. (Note that trap handlers don't affect the exit status).
- Avoid uppercase names for variables - we use uppercase as we do in C, to draw attention (in this case to environment variables, which have effects "at a distance").
- We don't depend on any non-POSIX shell features, so we can safely use
/bin/sh
for increased portability. (Note that mktemp
isn't in POSIX, but is fairly widely available).
Alternatively, if you choose to require Bash, and are willing to have it expand shell variables in your C source, you could make your compiler warnings/errors more useful by telling it where your source is:
gcc -Wall -o "$prog" -x 'c' - <<END_OF_SOURCE
#line $(($LINENO + 2)) "${BASH_SOURCE[0]}"
#include <stdio.h>
int main(int argc, char* argv[])
{
int i;
puts("Hello, world! I am a pseudoportable C program.");
for (i = 1; i < argc; ++i)
{
printf("Argument %d: %s\n", i, argv[i]);
}
return argc - 1;
}
END_OF_SOURCE
The +2
is necessary because $LINENO
expands to the line number of the start of gcc
command, but the preprocessor is being told the line number immediately after the #line
directive.