Makefile: checking existence of files - bash

I'm working on a makefile that uses c source files and header files.
I would like to check if all those files exist before compiling, so that if one is missing, printing a customized message instead of the usual 'no rule to make target'.
The code is as follows:
PROG1=file1
PROG2=file2
INCLUDE=header
all: $(PROG1).x $(PROG2).x
%.x : %.c $(INCLUDE).c
$(CC) -o $/$# $^
# echo File $# has been successfully created from $^;
Where and how should I check that file1.c, file2.c and header.h exist to print a customized error message if any of them is missing?

PROG1=file1
PROG2=file2
INCLUDE=header
all: $(PROG1).x $(PROG2).x
%.x : %.c $(INCLUDE).c
$(CC) -o $/$# $^
#echo File $# has been successfully created from $^
%.c :
#echo Missing $#
%.h :
#echo Missing $#
Would that work? If those files don't exist you'd get something like the following output:
posey#DEATHSTAR:~$ make all
Missing file1.c
Missing header.c
cc -o file1.x file1.c header.c
cc: error: file1.c: No such file or directory
cc: error: header.c: No such file or directory
cc: fatal error: no input files
compilation terminated.
make: *** [file1.x] Error 4

Related

Makefile rule matching

In my gnu-make-3.81 Makefile, I wish to generate .o files from .s files if there is no .c source files. So I defined the following rules which I have simplified:
all::$(OBJS)
%.s: %.c
$(CC) $(CFLAGS) -o $# -S $<
%.o: %.s
$(CC) $(CFLAGS) -o $# -c $<
With gnu-make-3.81, when there is no .c source files, it will generate .o files using the second rule. But with gnu-make-3.82, there is a error:
make: *** No rule to make target `xxx.c', needed by `xxx.s'. Stop.
How can I make it work like gnu-make-3.81 ?

Error while executing makefile in c

I'm trying to create one makefile using c. For that I have main.c,add.c,minus.c,print.c and Functions.h header file.In this list other than main.c add files have simple add function, subtract function and print function. That Functions.h file have declarations for all functions.
my problem is I have written one makefile. In that I'm trying to redirect the object files into one directory. When I execute the makefile. It throws an error like
make: *** No rule to make target /%.c', needed byobj'. Stop
.
Make file has the lines
CFLAG :=-Wall -g
CC := gcc
INCLUDE:=-I include
OBJDIR:=obj
SRCDIR:=src
TARGET:=bin/Math
CFILES:=$(wildcard src/*.c)
OBJECTS:=$(patsubst src/%.c,obj/%.o,$(CFILES))
$(OBJDIR)/%.o:$(SRCDIR)/%.c
#$(CC) -c $(INCLUDE) -o $# $< $(CFLAG)
(TARGET):$(OBJECTS)
#$(CC) $(CFLAG) -o $# $(OBJECTS)
.PHONY : clean
clean :
-rm -f $(OBJDIR)/*.o
Please help me guys....

Makefile runs over C file twice

I have two files: assign1.c and ports.h.
FYI: I am using avr-gcc.
I built the following makefile, which I also use for another project (and other TARGET) where it works fine.
TARGET = assign2
LIB=
INCLUDE=ports.h
CFLAGS =-mmcu=atmega32 -Wall
CC = avr-gcc
SRC= $(TARGET).c
OBJ= $(SRC:.c=.o)
OBJCOPY = avr-objcopy
FORMAT = ihex
MSG_COMPILING = Compiling:
MSG_LINKING = Linking:
MSG_FLASH = Creating load file for flash:
all:elf hex
elf: $(TARGET).elf
hex: $(TARGET).hex
%.hex: %.elf
#echo $(MSG_FLASH) $#
#echo
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $#
$(RM) *.elf $(TARGET)
#echo
%.elf: $(OBJ) $(LIB)
#echo $(MSG_LINKING) $#
#echo
$(CC) $(CFLAGS) $^ -o $#
#echo
%.o: $(SRC) $(INCLUDE)
#echo $(MSG_COMPILING) $<
#echo
$(CC) $(CFLAGS) -c $<
#echo
.PHONY : clean
clean:
$(RM) *.o *.hex *.elf $(TARGET)
The terminal prints the following output.
C:\Project>make
Compiling: assign2.c
avr-gcc -mmcu=atmega32 -Wall -c assign2.c
In file included from assign2.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"
Linking: assign2.elf
avr-gcc -mmcu=atmega32 -Wall assign2.o -o assign2.elf
Compiling: assign2.c
avr-gcc -mmcu=atmega32 -Wall -c assign2.c
In file included from assign.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"
avr-gcc elf.o assign2.elf -o elf
avr-gcc: elf.o: No such file or directory
make: *** [elf] Error 1
rm assign2.o
C:\Project>
For some reason it seems to compile the first file, a second time and doing so crashes.
Can anyone correct me on my errors?
The problem is your pattern rules. You are writing pattern rules like this (after make expands the variables):
%.o: assign2.c ports.h
What this rule tells make is that ANY target it wants to build that matches the %.o pattern, can be built by compiling assign2.c. That's obviously not true: this rule build exactly one target: assign2.o.
So make reads your makefile and wants to build a file named elf. It sees that elf depends on $(TARGET).elf, so it builds that (that's the first compile and link, that works). Then make wants to build elf itself. You haven't declared it to be .PHONY, so make assumes it might be a real target.
Make looks through its built-in rules to find one that will let it build elf, and it finds a built-in rule: % : %.o which it can use to compile a program from a .o file with the same prefix. So now for target elf make wants to try to build a file elf.o. Oho! It sees there's a pattern rule that lets it build any .o file based on the assign2.c source file, so it runs that rule (that's the second compile) expecting it to build elf.o... which it doesn't, obviously.
Then make runs the built-in link recipe, using elf.o which doesn't exist, and fails.
The solution to your problem is two things:
First, you should always declare all your makefile targets that you don't actually want to build as .PHONY so make won't try to build them:
.PHONY: all elf hex
Second, you should never use pattern rules where the prerequisite is not also a pattern (this can be useful in certain very specific situations, but not in general). You should either change those pattern rules to explicit rules:
assign2.elf: $(OBJ) $(LIB)
...
$(OBJ): $(SRC) $(INCLUDE)
...
Or make them into full pattern rules by using the pattern in the prerequisites list as well:
%.elf : %.obj $(LIB)
...
%.o: %.c $(INCLUDE)
...

Makefile to support 2 executables

I am trying to update my Makefile to support building a binary of my project, and a binary of some Unit Tests.
My directory structure is the following
|-code/
|--|--src/
|--|--inc/
|
|-tests/
|--|--src/
|--|--inc/
My makefile compiles the binary from code well, but is having some issues with the test. The test folder contains some unit test that tests some classes in code/src/. I have a file main.cpp in code/src/ that contains the main() function, and also another file, called test.cpp in tests/src that contains its own main() function.
This led me to this complicated Makefile:
CC = g++
FLAGS = -g -c -Wall
INCLUDEDIR = -Icode/inc -Itests/inc
BUILDDIR = build
SOURCEDIR = code/src
SOURCES = $(wildcard $(addsuffix /*.cpp,$(SOURCEDIR)))
TEMP_OBJ = $(SOURCES:%.cpp=%.o)
NOT_DIR = $(notdir $(TEMP_OBJ))
OBJECTS = $(addprefix $(BUILDDIR)/, $(NOT_DIR))
TEST_DIR = tests/src
TEST_SOURCES = $(wildcard $(addsuffix /*.cpp,$(TEST_DIR)))
TEST_TEMP_OBJ = $(TEST_SOURCES:%.cpp=%.o)
TEST_NOT_DIR = $(notdir $(TEST_TEMP_OBJ))
TEST_OBJECTS = $(addprefix $(BUILDDIR)/, $(TEST_NOT_DIR))
EXECUTABLE = Client
TEST_EXECUTABLE = TestUnit
all: $(BUILDDIR) $(BUILDDIR)/$(EXECUTABLE) $(BUILDDIR)/$(TEST_EXECUTABLE)
$(BUILDDIR):
mkdir -p $#
$(BUILDDIR)/$(EXECUTABLE): $(OBJECTS)
$(CC) $^ -o $#
$(BUILDDIR)/%.o : code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
$(BUILDDIR)/$(TEST_EXECUTABLE): $(OBJECTS) $(TEST_OBJECTS)
#rm -f $(BUILDDIR)/main.o
$(CC) $^ -o $#
$(BUILDDIR)/%.o : tests/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
clean:
rm -rf $(BUILDDIR)
It fails with the error:
g++: error: build/main.o: No such file or directory
make: *** [build/TestUnit] Error 1
Which is because I have the line:
#rm -f $(BUILDDIR)/main.o
but otherwise I would get the error (there is main in main.cpp and test.cpp in code/src/ and tests/code/ respectively):
/tests/src/test.cpp:7: multiple definition of `main'
code/src/main.cpp:6: first defined here
collect2: error: ld returned 1 exit status
There is a lot of duplication in my Makefile, and I would love to get something more succinct that achieves the purpose of building 2 binaries from those 2 folders, although code is shared.
Any help would please be appreciated. Thank you very much!
There are a number of problems with this makefile.
First, there is no rule to build test object files, such as test.o. The only rule for building objects requires that the source be in code/src/; I don't know how you even get far enough to see a linker error.
Let's change the object rule to a static pattern rule:
$(OBJECTS) : $(BUILDDIR)/%.o : code/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
Then we can add an additional rule for the test objects:
$(TEST_OBJECTS) : $(BUILDDIR)/%.o : tests/src/%.cpp
$(CC) $(FLAGS) $< $(INCLUDEDIR) -o $#
(Never mind the redundancy for now-- we have to get it working first.)
Now we should see a linker error in this rule:
$(BUILDDIR)/$(TEST_EXECUTABLE): $(OBJECTS) $(TEST_OBJECTS)
...
In that list of prerequisites are two files, main.o and test.o fighting over who gets to define main(). We want test.o, so main.o must go:
$(BUILDDIR)/$(TEST_EXECUTABLE): $(filter-out build/main.o,$(OBJECTS)) $(TEST_OBJECTS)
...
Try this much and tell us the result. Once it's working we can slim it down.

make : source and binary same name

I have many file with extension .cpp
f001.cpp
abc.cpp
...
I try compile any file with this
%.cpp:
g++ -o $* $*.cpp
but I get
make: *** No hay objetivos. Alto.
Does this work?
f001.o:
%.o: %.cpp
g++ -o $# $<
EDIT:
Good! Now try this:
OBJETIVOS = f001.o abc.o def.o ghi.o
todos: $(OBJETIVOS)
%.o: %.cpp
g++ -o $# $<
There is one problem here. Usually abc is the executable binary file, and abc.o is the object file. You are building executable files, but calling them abc.o. If you want them to be executable files, it would be better to call them abc.
with the answer of #Beta, I solved with
files = $(basename $(shell ls *cpp))
all: $(files)
%: %.cpp
g++ -o $# $<
clean:
rm $(files)
https://gist.github.com/3726212

Resources