Redirecting input separated with spaces - bash

Hi I've a question about feeding inputs to this simple bash script I wrote. All it does is add a set of flags to my compile operation to save me having to write them in myself every time. I can run it by using echo myprogram.c -o myprogram -llibrary | ./Compile.
But I can't find a way to run it in the way I expected to be able to, ./Compile < myprogram.c -o myprogram -llibrary
I've tried a few combinations of quotes and brackets to no avail, can anyone tell me how to feed the same input as produced by echo using the redirect input command.
#!/bin/bash
# File name Compile
#Shortcut to compile with all the required flags, name defaulting to
#first input ending in .c
echo "Enter inputs: "
read inputs
gcc -Wall -W -pedantic -std=c89 -g -O $inputs
exit 0

Just change your shell to:
#!/bin/bash
gcc -Wall -W -pedantic -std=c89 -g -O "$#"
Then you can only write(no redirection needed):
./Compile myprogram.c -o myprogram -llibrary
BTW, don't explicitly write exit 0 at end of this shell. It is redundant when gcc succeeds, and is wrong when gcc fails(exit code 1 will be overwritten).

You can use process substitution:
./Compile < <( echo myprogram.c -o myprogram -llibrary )
the above line produces the same result as your original command:
echo myprogram.c -o myprogram -llibrary | ./Compile

Related

Shell script not running through all files of certain extensions

I wrote a shell script that searches the directory that it is in for files that match any suffixes in the env var SUFFIXES.
#!/bin/bash
SUFFIXES=$(SUFFIXES:-'.c .cpp .cc'}
CC=${CC:-gcc}
CFLAGS=${CFLAGS:-"-Wall -Werror"}
VERBOSE=${VERBOSE:-1}
for i in *$SUFFIXES
do
$CC $CLAGS -o ${i%$SUFFIXES} $i 2> /dev/null
if [ $VERBOSE == 1 ]
then
echo "$CC $CLAGS -o ${i%$SUFFIXES} $i"
fi
done
Say I have a directory with hello.c, hey.c, howdy.cc, and hallo.cpp. Whenever the script is ran without changing the environment variables in the terminal, I get the following output:
gcc -Wall -Werror -o hello.c hello.c
gcc -Wall -Werror -o hey.c hey.c
gcc -Wall -Werror -o .cc .cc
gcc -Wall -Werror -o .cpp .cpp
The output that I am trying to get is:
gcc -Wall -Werror -o hello hello.c
gcc -Wall -Werror -o hey hey.c
gcc -Wall -Werror -o howdy howdy.cc
gcc -Wall -Werror -o hallo hallo.cpp
How would I go about fixing this?
Except for a few typos in your code that probably occurred here, you have some mistake in your loop
i in *$SUFFIXES means that *.c .cpp .cc, so it won't work on file.cpp or file .cc
${i%$SUFFIXES} try to cut all suffixes that you defined, from end of file name, while you have one of them in each file name
maybe an inner loop will helpful
for i in $SUFFIXES
do
for j in *$i
do
$CC $CFLAGS -o ${j%$i} $j 2> /dev/null
if [ $VERBOSE == 1 ]
then
echo "$CC $CFLAGS -o ${j%$i} $j"
fi
done
done

gnatmake -o flag produces incorrect object file name

I am attempting to compile a .adb file with gnatmake, and the -o flag isn't producing the object file name I want:
$ gnatmake --GCC=g++ -D bin/src/ghdl_grt/ -f -u -c src/ghdl_grt/grt-vstrings_io.adb -o bin/src/ghdl_grt/grt-vstrings_io.adb.o
g++ -c -Isrc/ghdl_grt/ -I- -o /home/jon/controlix-code/bin/src/ghdl_grt/grt-vstrings_io.o src/ghdl_grt/grt-vstrings_io.adb
As you can see, it gets the path correct, but the filename should end with .adb.o and it only ends with .o. Any ideas?
For gnatmake, -o 'chooses an alternate executable name'. But even using gcc (or g++) on its own fails, at any rate on macOS, because gnat1: incorrect object file name.
I found that you can compile to assembler and then compile that. Using a local file I happened to have lying about,
$ g++ -D $PWD -c gator2.adb -S -o gator2.adb.s
$ g++ -D $PWD -c gator2.adb.s
Well, that's a weird naming scheme, but...
gnatmake only allows you to specify alternate executable names with -o:
-o name Choose an alternate executable name
You can, however, tell gnatmake to pass on options to the compiler:
-cargs opts opts are passed to the compiler
And similarly, to the binder and linker:
-bargs opts opts are passed to the binder
-largs opts opts are passed to the linker
Thus,
$ gnatmake --GCC=g++ -D bin/src/ghdl_grt/ -f -u -c src/ghdl_grt/grt-vstrings_io.adb -cargs -o bin/src/ghdl_grt/grt-vstrings_io.adb.o

How to compile a test snippet nicely with gnu make?

I don't have a configure stage in my baseline (for various reasons), but I need to check whether my C compiler can support the -mavx2 flag or not.
If I have an empty file, call it test.cc then I can do something like:
$(CC) -mavx2 -c test.cc -o test.o
And check the return status code. Obviously I don't want to leave those test.* files lying around though, but can't think of a good way to generate/test/delete them outside of a recipe. Does anyone know of a good pattern to do this?
Or, you could just take input from stdin, and output to /dev/null:
SUPPORTS_MAVX2:=$(shell echo 'void main(){}' | \
gcc -x c -maxv3 -o /dev/null - 2>/dev/null; \
echo $$?)
Then there are no artifact files to be deleted. The -x c is necessary to tell gcc what language it is (as it can't determine that from the filename in this case), and you need the trailing - as well.
Turns out you can use "eval" to remove the temporary file and return the status code, so this works:
AVX2 = $(shell touch test.cc; $(CC) -mavx2 -c test.cc -o /dev/null >& /dev/null; eval "rm -f test.cc; echo $$?")
Edit and without the temporary file (assuming a sane system):
AVX2 = $(shell $(CC) -mavx2 -c /usr/include/stdlib.h -o /dev/null >& /dev/null; echo $?)

Script for compiling C++

I want to make a script that would make compiling things quicker to write. I want to compile a XYZ.cpp file and the I want the output to be XYZ.out.
Here's my script:
#!/bin/bash
# getting the part before .cpp
var1=`echo "$1" | cut -d"." -f1`
# compile
g++ -std=c++11 -Wall -pedantic -Wno-long-long "$1" -o "$var1.out" -lm
I run it: ccc program.cpp
The script runs but the output still is a.out. What am I doing wrong?
Just use one of bash's built-in parameter expansion features to remove any trailing portion of $1 that matches ".cpp":
#!/bin/bash
g++ -std=c++11 -Wall -pedantic -Wno-long-long -o "${1%%.cpp}.out" -lm "$1"
I've also moved the source file to be the last parameter to g++, so that it's clear where the options are (and end).

missing operand after `homework1' - Makefile

I keep getting an error message that says "diff: missing operand after `homework1'", but I have included a bash file. Can someone take a look at my makefile and give me a hint on how to fix it? Thanks!
#
# $RCSfile$
# $Revision$
# $Author$
# $Date$
# $Log$
#
CC=gcc
DEBUG=-g
CFLAGS=#(DEBUG) -Wall -Wshadow -Wunreachable-code -Wredundant-decls -Wmissing-declarations -Wold-style-definition -Wmissing-prototypes -Wdeclaration-after-statement
PROGS=homework1
all: $(PROGS) test
homework1: homework1.o
$(CC) $(CFLAGS) -o homework1 homework1.o
homework1.o: homework1.c
$(CC) $(CFLAGS) -c homework1.c
test: *
diff $(PROGS) $(example.bash) || exit 0
clean:
rm -f $(PROGS) *.o *~
You've referenced a make variable $(example.bash) but there is no variable example.bash set in your makefile. Did you mean the file example.bash? You shouldn't use make variable syntax, if that's true:
test: *
diff $(PROGS) example.bash || exit 0
(why do you have * as a prerequisite here? That doesn't seem useful)
To compare the output of two commands using diff, you need the output of at least one of those two commands redirected to a file while the output of another command is piped to the input stream of diff. Here is an example that replaces $(PROGS) with its output file:
./$(PROGS) > progs_output
bash example.bash | diff progs_output - || exit 0
It executes the value of $(PROGS), sending its output to a file called progs_output. Then the bash script is executed, with its output piped to the standard input stream of the diff utility, which compares progs_output with the stuff coming from its standard input stream. Everything else is your doing. Why would you use exit 0 though? If the test fails, wouldn't you want make to tell you?
Also, what's with the asterisk (*) as a prerequisite for the test target?

Resources