Makefile syntax error. Missing separator - c++

I need to understand the syntax of a makefile prior to modify it to fit my own needs. Searching through the net I have been able to understand most of it, but the last part is giving me a syntax error:
Makefile:119: *** missing separator. Stop.
line 119 is the first one here:
rm -rf $(CLEANFILES)
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCL) -c -o $# `test -f '$<' || echo '$(SRCDIR)/'`$<
.cpp.obj:
$(CXX) $(CXXFLAGS) $(INCL) -c -o $# `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(SRCDIR)/$<'; fi`
.c.o:
$(CC) $(CFLAGS) $(INCL) -c -o $# `test -f '$<' || echo '$(SRCDIR)/'`$<
.c.obj:
$(CC) $(CFLAGS) $(INCL) -c -o $# `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(SRCDIR)/$<'; fi`
I don't really get what's being done in these last lines, and I can't seem to find the information I need in the GNU make manual,
Thanks

Since you've cut-and-pasted from your actual Makefile it's hard to give a certain answer. If the first line you provided, rm -rf $(CLEANFILES) truly is line 119 and the makefile is valid until then, it's likely that you don't have a TAB preceding the rm -rf $(CLEANFILES). It should look like this:
clean:
rm -rf $(CLEANFILES)
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCL) -c -o $# `test -f '$<' || echo '$(SRCDIR)/'`$<
.cpp.obj:
$(CXX) $(CXXFLAGS) $(INCL) -c -o $# `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(SRCDIR)/$<'; fi`
.c.o:
$(CC) $(CFLAGS) $(INCL) -c -o $# `test -f '$<' || echo '$(SRCDIR)/'`$<
.c.obj:
$(CC) $(CFLAGS) $(INCL) -c -o $# `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(SRCDIR)/$<'; fi`
That is, the command lines in each recipe must have a literal TAB character at the start of the line.

Related

how to make the below output of the command pass not fail

how to make the below output of the regex command pass not fail
grep -E '^[[:space:]]*-a[[:space:]]+always,exit[[:space:]]+-F[[:space:]]+arch=b32[[:space:]]+-S[[:space:]]+creat[[:space:]]+-S[[:space:]]+open[[:space:]]+-S[[:space:]]+openat[[:space:]]+-S[[:space:]]+truncate[[:space:]]+-S[[:space:]]+ftruncate[[:space:]]+-F[[:space:]]+exit=-EACCES[[:space:]]+-F[[:space:]]+auid>=500[[:space:]]+-F[[:space:]]+auid!=4294967295[[:space:]]+-k[[:space:]]+access[[:space:]]*$' /etc/audit/rules.d/*.rules | /usr/bin/awk '{print} END {if (NR != 0) print "pass" ; else print "fail"}'
I tried the below and still fail
echo -e "-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access\n-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EACCES -F auid>=1000 -F auid!=4294967295 -k access\n-a always,exit -F arch=b64 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access\n-a always,exit -F arch=b32 -S creat -S open -S openat -S truncate -S ftruncate -F exit=-EPERM -F auid>=1000 -F auid!=4294967295 -k access" > /etc/audit/rules.d/access.rules

Sed replace a string in the first line of a paragraph

I am trying to automate the periodic detection and elimination of files, using fdupes. I got this beautiful script:
# from here:
# https://www.techrepublic.com/blog/linux-and-open-source/how-to-remove-duplicate-files-without-wasting-time/
OUTF=rem-duplicates_2019-01.sh;
echo "#! /bin/sh" > $OUTF;
find "$#" -type f -printf "%s\n" | sort -n | uniq -d |
xargs -I## -n1 find "$#" -type f -size ##c -exec md5sum {} \; |
sort --key=1,32 | uniq -w 32 -d --all-repeated=separate |
sed -r 's/^[0-9a-f]*( )*//;s/([^a-zA-Z0-9./_-])/\\\1/g;s/(.+)/#rm \1/;' >> $OUTF;
chmod a+x $OUTF; ls -l $OUTF
This produces a file with this structure:
#! /bin/sh
#rm ./directory_a/file_a
#rm ./directory_b/file_identical_to_a
#rm ./directory_a/file_b
#rm ./directory_b/file_identical_to_b
#rm ./directory_c/another_file_identical_to_b
#rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c
I want to remove the # tag from the first line of each paragraph to get
rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c
I have been trying to modify the next-to-last line, with variations of things like this:
sed -r 's/^[0-9a-f]*( )*//;s/([^a-zA-Z0-9./_-])/\\\1/g;s/(.+)/#rm \1/;s/\n\n#rm/\n\nrm/;' >> $OUTF;
But cannot manage SED to recognize the (\n\n) or any other pointer I can think of to the beginning of the paragraph. What am I doing wrong?
Edit: I am unable to edit the comment, so here is the final script:
TEMPF=temp.txt;
OUTF=rem-duplic_2019-01.sh
echo "#! /bin/sh" > $TEMPF;
find "$#" -type f -printf "%s\n" | sort -n | uniq -d |
xargs -I## -n1 find "$#" -type f -size ##c -exec md5sum {} \; |
sort --key=1,32 | uniq -w 32 -d --all-repeated=separate |
sed -r 's/^[0-9a-f]*( )*//;s/([^a-zA-Z0-9./_-])/\\\1/g;s/(.+)/#rm \1/' >> $TEMPF;
awk -v a=2 '/^$/{a=2}!--a{sub(/#/,"")}1' $TEMPF > $OUTF
chmod a+x $OUTF; ls -l $OUTF
rm $TEMPF
Use awk instead:
awk '/^$/{a=1} !a--{sub(/#/,"")} 1' a=1 file
/^$/ { a = 1 } means set a to 1 if current line is a blank one,
!a-- is a shorthand for a-- == 0, following action ({ sub(/#/, "") }) removes the first # from current line,
1 means print all lines,
a=1 is required to remove # from the line after shebang (i.e 2nd line).
With sed:
sed "1n;/^#/,/^$/{ s///;}" file
You can use this too:
sed '/^$\|^#!/{N;s/#r/r/}' input.txt
feel free to add the in-place opt if you want
This might work for you (GNU sed):
sed '/^#!\|^\s*$/{n;s/.//}' file
If the current line is a shebang or an empty line, print it and remove the first character of the next line.
Just use Perl with paragraph mode
perl -00 -pe ' s/^#// '
With inputs
$ cat yozzarian.txt
#! /bin/sh
#rm ./directory_a/file_a
#rm ./directory_b/file_identical_to_a
#rm ./directory_a/file_b
#rm ./directory_b/file_identical_to_b
#rm ./directory_c/another_file_identical_to_b
#rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c
$ perl -00 -pe ' s/^#// ' yozzarian.txt
! /bin/sh
#rm ./directory_a/file_a
#rm ./directory_b/file_identical_to_a
rm ./directory_a/file_b
#rm ./directory_b/file_identical_to_b
#rm ./directory_c/another_file_identical_to_b
rm ./directory_a/file_c
#rm ./directory_b/file_identical_to_c
#rm ./directory_c/another_file_identical_to_c
#rm ./directory_d/yet_another_file_identical_to_c
$

Using sed to replace multiple instances in the same line before a comment

I am trying to use sed to replace all instances of a command with a variable, expect when they come after a comment or is part of another word. I have gotten close, being able to replace one instance before a comment, but not if there is more than one.
I have a test file with the line:
rm rm # rm
I want to make this read:
$RM $RM # rm
This is what I have so far:
sed -i 's/\(^\|[^[#.*]]\)\brm\b/\1$RM/' file1
Which returns:
$RM rm # rm
Any help is much appreciated. Other solutions not involving sed are welcome, but I might need some help understanding them.
Thanks!
EDIT:
This is just an example of what I am looking for. Not every line will be formatted like this, and not every line will contain a command before the comment, or vise versa. I am just looking for a solution that will also cover a situation similar to this example. Sorry for the lack of explanation. Here is a slightly better example:
"$#" #rm
# rm
rm # rm
rm
"rm "
'rm '
`rm `
{rm }
$# rm # rm
rm rm # rm
rm # rm rm
rmremovermlink
Output should be:
"$#" #rm
# rm
$RM # rm
$RM
"$RM "
'$RM '
`$RM `
{$RM }
$# $RM # rm
$RM $RM # rm
$RM # rm rm
rmremovermlink
You can use this sed command:
sed ':a;s/^\([^#]*\)\<rm\>/\1$RM/;ta;' file
# ^ ^ ^ ^ ^ ^ ^---- go to label "a" if something is replaced
# | | | | | '---- back-reference to capture group 1
# | | | '---'---- word boundaries
# | | '---- capture group 1
# | '---- replacement (only one occurrence)
# '---- defines the label "a"
You can use this perl command for this substitution:
perl -pe 's/(?<!\$)#.*$(*SKIP)(*F)|\brm\b/\$RM/g' file
"$#" #rm
# rm
$RM # rm
$RM
"$RM "
'$RM '
`$RM `
{$RM }
$# $RM # rm
$RM $RM # rm
$RM # rm rm
rmremovermlink
RegEx Demo
\$[A-Z]{2}\s\$[A-Z]{2}\s\#\s[a-z]{2}
Let me know if this is what you're looking for. It matches :
$RM $RM # rm

Understanding a Makefile with automatic dependencies: Problems with 'sed' part

I have followed this tutorial. It explains the making of Makefile which take care of dependencies. I have made the following Makefile which works according to the following directory structure:
folder--|Makefile
|src----|(all .c and .h files here)
|obj----|(all objects file are made here)
|bin----|(target is made here)
The Makefile is:
TARGET = exec
CC = gcc
CFLAGS = -g -I.
LINKER = gcc -o
LFLAGS = -I. -lm -lpthread
BINDIR = bin
OBJDIR = obj
SRCDIR = src
INTERFACE = interface
STD = -std=c99
PROGRAMSOURCES := $(wildcard $(SRCDIR)/*.c)
PROGRAMINTERFACE:= $(wildcard $(INTERFACE)/*.h)
OBJECTS := $(PROGRAMSOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(BINDIR)/$(TARGET) : $(OBJECTS)
$(LINKER) $# $(LFLAGS) $(OBJECTS) $(STD)
#pull the dependencies to the .o files
-include $(OBJECTS:.o=.d)
#the -o $# says to put the output of the compilation in the file named on the left side of the :.
#the $< is the first item in the dependencies list. Basically the name of the .c file which is to be compiled.
$(OBJECTS) : $(OBJDIR)/%.o :$(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $# $(STD)
$(CC) $(CFLAGS) -MM $< > $*.d
#mv -f $*.d $*.d.tmp #changes file name
#sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d #Unable to understand
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d #Unable to understand
#rm -f $*.d.tmp
.PHONY : run
run :
./$(BINDIR)/$(TARGET) ${TYPE} ${INP_FILE}
print:
#echo $(OBJECTS)
I have understood that it is trying to pre-process the temp file to generate auto dependency. What I am unable to understand is how it is being done. Here are the two lines I want explanation of:
#sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d #Unable to understand
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \
sed -e 's/^ *//' -e 's/$$/:/' >> $*.d #Unable to understand
I have never used sed before so I am having problems.
Any help appreciated.
Suppose you are building obj/foo.o from src/foo.c, so the file foo.d.tmp contains:
foo.o: src/foo.c src/foo.h src/bar.h
Now the first sed statement:
#sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d
"Read foo.d.tmp, take everything up to a colon and change it to 'foo.o', and write the result to foo.d." So now foo.d contains:
foo.o: src/foo.c src/foo.h src/bar.h
(No change in this case.) Now the next command:
#sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d
"Read foo.d.tmp, remove everything up to (and including) a colon, remove the trailing \ if there is one. Take the result and put each word (i.e each prerequisite) on its own line. Then for each line, remove the leading spaces, put a colon at the end, and append the result to foo.d." So now foo.d contains:
foo.o: src/foo.c src/foo.h src/bar.h
src/foo.c:
src/foo.h:
src/bar.h:
The idea is to create an empty rule for each prerequisite, so that if the code has changed and a certain prerequisite is no longer needed -- and no longer present -- but it is still listed in the old foo.d, Make will not panic at being unable to build it.

If conditions in a Makefile, inside a target

I'm trying to setup a Makefile that will search and copy some files (if-else condition) and I can't figure out what exactly is wrong with it? (thou I'm pretty sure it's because a combination of spaces/tabs written in the wrong place).
Can I get some help with it, please?
Here's what I have currently:
obj-m = linuxmon.o
KDIR = /lib/modules/$(shell uname -r)/build
UNAME := $(shell uname -m)
all:
$(info Checking if custom header is needed)
ifeq ($(UNAME), x86_64)
$(info Yes)
F1_EXISTS=$(shell [ -e /usr/include/asm/unistd_32.h ] && echo 1 || echo 0 )
ifeq ($(F1_EXISTS), 1)
$(info Copying custom header)
$(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm/unistd_32.h > unistd_32.h)
else
F2_EXISTS=$(shell [[ -e /usr/include/asm-i386/unistd.h ]] && echo 1 || echo 0 )
ifeq ($(F2_EXISTS), 1)
$(info Copying custom header)
$(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm-i386/unistd.h > unistd_32.h)
else
$(error asm/unistd_32.h and asm-386/unistd.h does not exist)
endif
endif
$(info No)
endif
#make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
rm unistd_32.h
Anyways, that'll print "Yes", "Copying header" twice and then it will quit saying that sed can't read /usr/include/asm-i386/unistd.h (which of course it can't read as I'm on a x64 system).
I could say that make just isn't understanding the if/else and instead is running everything line by line.
You can simply use shell commands. If you want to suppress echoing the output, use the "#" sign. For example:
clean:
#if [ "test" = "test" ]; then\
echo "Hello world";\
fi
Note that the closing ; and \ at each line are necessary
(This is because make interpret each line as a seperate command unless it ends with \)
There are several problems here, so I'll start with my usual high-level advice: Start small and simple, add complexity a little at a time, test at every step, and never add to code that doesn't work. (I really ought to have that hotkeyed.)
You're mixing Make syntax and shell syntax in a way that is just dizzying. You should never let it get this big without testing. Let's start from the outside and work inward.
UNAME := $(shell uname -m)
all:
$(info Checking if custom header is needed)
ifeq ($(UNAME), x86_64)
... do some things to build unistd_32.h
endif
#make -C $(KDIR) M=$(PWD) modules
So you want unistd_32.h built (maybe) before you invoke the second make, you can make it a prerequisite. And since you want that only in a certain case, you can put it in a conditional:
ifeq ($(UNAME), x86_64)
all: unistd_32.h
endif
all:
#make -C $(KDIR) M=$(PWD) modules
unistd_32.h:
... do some things to build unistd_32.h
Now for building unistd_32.h:
F1_EXISTS=$(shell [ -e /usr/include/asm/unistd_32.h ] && echo 1 || echo 0 )
ifeq ($(F1_EXISTS), 1)
$(info Copying custom header)
$(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm/unistd_32.h > unistd_32.h)
else
F2_EXISTS=$(shell [[ -e /usr/include/asm-i386/unistd.h ]] && echo 1 || echo 0 )
ifeq ($(F2_EXISTS), 1)
$(info Copying custom header)
$(shell sed -e 's/__NR_/__NR32_/g' /usr/include/asm-i386/unistd.h > unistd_32.h)
else
$(error asm/unistd_32.h and asm-386/unistd.h does not exist)
endif
endif
You are trying to build unistd.h from unistd_32.h; the only trick is that unistd_32.h could be in either of two places. The simplest way to clean this up is to use a vpath directive:
vpath unistd.h /usr/include/asm /usr/include/asm-i386
unistd_32.h: unistd.h
sed -e 's/__NR_/__NR32_/g' $< > $#