Reputation: 279
I have a big project I want to compile, but it uses some g++
flags that I don't want to use. Instead of editing Makefiles, I thought about writing small script, that would run be instead of compiler, process command line arguments and pass them to compiler.
#!/bin/bash
~/g++ `echo "$@" | sed "s/-Os//gi; s/-O0//gi; s/-O1//gi; s/-O2//gi;"` -O3
It worked great, until make
entered some directory with spaces in name, and g++
flooded my console with No such file or directory
errors. How can I replace text in every single argument, and pass it to compiler in it's original form (eg. with spaces)?
Upvotes: 2
Views: 1173
Reputation: 754060
I'm not convinced that your starting point is correct — you should be fixing the makefile
s so that they do what you want. Ideally, there'd be one file included by all the others which allows you to configure things like the compiler options. However, for the sake of discussion, we have to assume that you can't do that.
I think you need to use Bash arrays to achieve the task.
#!/bin/bash
i_args=( "$@" )
o_args=( "-O3" )
for arg in "${i_args[@]}"
do
case "$arg" in
(-O[0123s]) : OK;;
(*) o_args+=( "$arg" );;
esac
done
exec ~/g++ "${o_args[@]}"
This code also ensures that -O3
isn't repeated (by adding it to the list of dropped options). There's no particular harm in passing it twice, but there's no benefit either.
Replacing the last line with:
printf "%s\n" "${o_args[@]}"
and running the script as shown produces the output as shown:
$ bash x3.sh -o filtration -I$HOME/inc -I "/path/ with /blanks in names" -Os -O0 \
-Wall -O1 -Wextra -O2 -L /library/of/alexandria -O3 -lpapyrus
-O3
-o
filtration
-I/Users/jleffler/inc
-I
/path/ with /blanks in names
-Wall
-Wextra
-L
/library/of/alexandria
-lpapyrus
$
Upvotes: 2
Reputation: 4396
This is a really tricky problem because the script has to preserve the effect of quoting after the quotes have been removed.
I managed to come up with this. For testing I used the touch command instead of g++
You could probably refactor a few things but it seems to work at least!
#!/bin/bash
whitespace="[[:space:]]"
for i in "$@"
do
# Skip the options we don't want.
if [[ $i == "-Os" ]] || [[ $i == "-O0" ]] || [[ $i == "-O1" ]] || [[ $i == "-O2" ]]
then
continue
fi
# Escape any whitespace characters
if [[ $i =~ $whitespace ]]
then
i=$(printf %q "$i")
fi
# Build a command line
a=$a' '"$i"
done
# Build the final command line by adding the command we are stubbing.
cmd="touch "$a # In your case replace touch with g++
# Use eval to execute the command.
eval ${cmd}
Output:
$ ./stub.sh "two words" -Os oneword
$ ls -al
total 8
drwxr-xr-x+ 5 jcreasey staff 170 19 Jun 12:49 .
drwxr-xr-x+ 22 jcreasey staff 748 19 Jun 12:49 ..
-rwxr-xr-x+ 1 jcreasey staff 308 19 Jun 12:49 arg2.sh
-rw-r--r--+ 1 jcreasey staff 0 19 Jun 12:49 oneword
-rw-r--r--+ 1 jcreasey staff 0 19 Jun 12:49 two words
Upvotes: 1
Reputation: 4396
What about just telling make to use different CFLAGS? e.g.:
make CFLAGS='-g -O'
Upvotes: 1