Shell script not running through all files of certain extensions - bash

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

Related

Make error: The system cannot find the path specified

I'm getting a Make error when I run the mingw32-make command:
PS D:\> mingw32-make
cd src; mingw32-make
The system cannot find the path specified.
mingw32-make: *** [Makefile:4: all] Error 1
But when I list the actual command listed in the Makefile i.e. cd src; mingw32-make, the build is finished successfully.
PS D:\> cd src; mingw32-make
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c account.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c customer.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c display.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c main.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c passbook.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c security.cpp
g++ -std=c++17 -Wall -Wextra -Wpedantic -Wformat -Wchkp -I../include -c staff.cpp
g++ -o Bank account.o customer.o display.o main.o passbook.o security.o staff.o
However this issue is not present when I build using Make on Ubuntu.
This is the Makefile in my root directory:
DIR = src
all:
cd $(DIR); mingw32-make
clean:
cd $(DIR); mingw32-make clean
This is the Makefile in my src subdirectory:
# Compiler options
# -std=c++17 enables ISO C++ 17 standard
CC = g++
CCFLAGS = -std=c++17 -Wall -Wextra -Wpedantic -
Wformat -Wchkp
i = ../include
# LOCFLAGS used to set tell the compiler where to find a
# header that is not in the same directory as the source
file itself
# LOCFLAGS will be set in directory level makefiles as
needed
LOCFLAGS = -I../include
# The list of object files that can be made in this
subdirectory
# is assigned to the make macro named $OBJECTS
OBJECTS = account.o customer.o display.o main.o
passbook.o \
security.o staff.o
# This rule says that the target named "all" depends on
those
# files. Executing "make all" in this subdirectory will cause
# make to build the object files (.o) listed in the macro
$OBJECTS
# and create an executable named "Bank" by linking them
all: $(OBJECTS)
$(CC) -o Bank $(OBJECTS)
# rule that says how to make a .o object file from a .cpp
source file
# for a given source file in a given directory you could
compile it
# into an object file by executing "make filename.o"
# $< and $# are macros defined by make
# $< refers to the file being processed (i.e., compiled or
linked )
# $# refers to the generated file
%.o: %.cpp
$(CC) $(CCFLAGS) $(LOCFLAGS) -c $<
# target to clean up the object files, core files and
executables
# executing "make clean" in this subdirectory will remove
all
# files named core, "Bank" or any file ending in .o or
.stackdump
clean:
del $(OBJECTS) core *.stackdump Bank
On Windows you're running in a command.com shell, not a POSIX shell. In command.com, the syntax cd src; mingw32-make is not legal. For example if I open a command.com terminal on a Windows system I see:
C:\Users\build> cd src; echo hi
The system cannot find the path specified.
In Windows command.com the command separator is a single & not a semicolon.
If you want to change directories portably you can use the -C option to GNU make. Also you should always use the $(MAKE) variable, not write out the make command by hand:
all:
$(MAKE) -C $(DIR)

in makefile echoing "compiling" before the compilation

i thought it would be easy but i can't actually figure out nor find on internet, a solution to advertise "compilation of the objects file" (for instance) just before compiling, and avoiding relink in the same time
my makefile would be something like this :
libfrog.a: $(OBJS)
#echo "building the library"
ar -rc $# $^
%.o:%.c
gcc -i. -c -o $# $<
which produce, when prompt "make" :
gcc -I. -c -o file01.o file01.c
gcc -I. -c -o file02.o file02.c
gcc -I. -c -o file03.o file03.c
gcc -I. -c -o file04.o file04.c
gcc -I. -c -o file05.o file05.c
building library
ar -rc libfrog.a file01.o file02.o file03.o file04.o file05.o
but i would like to have :
compilation of the objects files
gcc -I. -c -o file01.o file01.c
gcc -I. -c -o file02.o file02.c
gcc -I. -c -o file03.o file03.c
gcc -I. -c -o file04.o file04.c
gcc -I. -c -o file05.o file05.c
building library
ar -rc libfrog.a file01.o file02.o file03.o file04.o file05.o
now :
1 - if i put an echo before the rule libfrog.a is called (say by creating another first rule), it will print even if i prompt "make" two times and nothing is to be done...
2 - if i put an echo in the rule %.o:%.c it will print for each file
3 - if i put an echo as a dependency of the first rule it will force to relink all the files when prompt "make" again, even when just one file has been modified libfrog.a: echo $(OBJS) (and a rule "echo" which echo the text)...
so I've tried to echo for each compilation but with changing the text to echo nothing, i failed... i tried to create an echo.txt file just to create a rule that would depend on its existence but i failed too. I have no idea if it's possible ?
It's not really simple to do. But if you're using GNU make you can do it with the help of order-only prerequisites:
%.o : %.c | announce
gcc -I. -c -o $# $<
.PHONY: announce
announce:
echo "compilation of the objects files"
Personally I don't think showing this message is needed and I wouldn't add even the above amount of complexity to support it in my makefiles.
But if you really want to do it and you don't want the message to be printed unless some object file needs to be made, you'll have to get really fancy and do something like this:
PRINTED :=
%.o : %.c
$(or $(PRINTED),$(eval PRINTED := :)echo "compilation of the objects files")
gcc -I. -c -o $# $<
Once it's working you'll want to add a # before the first recipe line.

How to execute multiple programs in Makefile

Here is part of my Makefile:
FLAGS = -Wall -Werror -std=c99
DEPENDENCIES = p.h
test: s d
#./s < input.dat > output.txt
#./d < output.txt
s: s.o helper.o
gcc -Wall -o $# $^
d: d.o helper.o
gcc -Wall -o $# $^
%.o: %.c ${DEPENDENCIES}
gcc -Wall -c $<
Why is error 1 showing up whenever I call "make test". Is this the proper way of compiling two programs and then executing it through Makefile?
The output:
cc -c -o s.o s.c
cc -c -o helper.o helper.c
gcc -Wall -Werror -std=c99 -o s s.o helper.o
cc -c -o d.o d.c
gcc -Wall -Werror -std=c99 -o d d.o helper.o
make: *** [test] Error 1

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).

Have bash echo the final form of executed command, can I?

I have a small bash script build1c.sh .
if [ "$1" = "" ]; then
echo "You must give a .c file to compile."
exit 1
fi
cfile=$1
stem=${cfile%.*}
set -o verbose
gcc -c -g -Wall $cfile
gcc -o $stem $stem.o common.o reentrant.o -lssl -lcrypto
set +o verbose # optional here
The intention is to only echo the gcc commands being executed. I work to some extend. When I call build1c.sh client2.c , I see output
gcc -c -g -Wall $cfile
gcc -o $stem $stem.o common.o reentrant.o -lssl -lcrypto
set +o verbose # optional here
Still wacky, right? Those var reference($cfile, $stem) do not get their final form, so the echoing becomes pretty useless.
You know, what I like to see is
gcc -c -g -Wall client2.c
gcc -o client2 client2.o common.o reentrant.o -lssl -lcrypto
Is there correct and concise way to address this?
BTW: Minor request: Can I suppress the echoing of set +o verbose itself?
Replace set -o verbose with set -x
function echo_and_execute {
echo "$#"
"$#"
}
echo_and_execute gcc -c -g -Wall $cfile
echo_and_execute gcc -o $stem $stem.o common.o reentrant.o -lssl -lcrypto

Resources