I am trying to compile a program using this makefile:
GCCPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore
ASPARAMS = --32
objects = src/loader.o src/kernel.o
%.o: src/%.cpp
gcc $(GCCPARAMS) -c -o $# $<
%.o: src/%.s
echo $(ASPARAMS)
as $(ASPARAMS) -o $# $<
kernel.bin: linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: kernel.bin
sudo cp $< boot/mykernel.bin
The problem comes when doing make which prints the following:
as -o src/loader.o src/loader.s
src/loader.s: Assembler messages:
src/loader.s: Warning: end of file not at end of a line; newline inserted
src/loader.s:18: Error: operand type mismatch for `push'
src/loader.s:19: Error: operand type mismatch for `push'
make: *** [<builtin>: src/loader.o] Error 1
As you can se the variable is not properly set, instead, make puts a space where the variable should be. That causes the assembler compiler to think it's a 64 bit architecture and giving some errors.
Any idea of what is going on? I am doing this using WSL2 by the way.
The reason you see this is because your recipe rules are wrong.
You have these object files:
objects = src/loader.o src/kernel.o
and you have this rule:
%.o: src/%.s
echo $(ASPARAMS)
as $(ASPARAMS) -o $# $<
When trying to build src/loader.o what does the stem of the pattern %.o match? It will match src/loader of course. So then what will the prerequisite be? It will be src/%.s with the stem expanded, so it will be src/src/loader.s. I presume that this doesn't exist.
As a result of this, this pattern rule doesn't match. So what does make do? It looks for a different pattern rule, and it turns out that GNU make provides a default pattern rule to build a .s file, which uses a pattern %.o : %.s and that pattern DOES match, so that's used.
But that built-in rule uses the standard make variables, which are AS and ASFLAGS. You haven't set ASFLAGS, so no flags are used.
You can tell that it's not using your rule because your rule has an echo ... in it and make does not print that command out. Therefore, it's not running your rule.
Related
When I type make and hit enter, it says:
no rule to make target %.o, needed by all. stop'.
This is my makefile:
CC=g++
LDFLAGS=""
all: %.o %.h
$(CC) $< $(LDFLAGS) -o bin
%.o: %.cpp %.h
$(CC) -c $<
These are the contents of my directory:
$ ls
main.cpp makefile
I'm new to GNU make and just learned to use automatic variables. Can someone help me out?
% is for substituting patterns, which is what you want when defining a rule for a single module (like you did), but not what you want as the dependency list of 'all'. A % will expand to a single value.
Instead, you want an actual wildcard (like in the shell expansion) to match all *.o files. So, change your target definition to
all: *.o *.h
Not related to your question, but this is not right:
LDFLAGS=""
make doesn't parse quotes, so you've set the variable LDFLAGS to the literal string "" (two double-quotes). When you use that in your recipe:
$(CC) $< $(LDFLAGS) -o bin
it will be as if you'd typed:
g++ ... "" -o bin
which is a syntax error (you're passing an empty argument to g++. If you want an empty variable you just write:
LDFLAGS =
Now, your problem. This is not a pattern rule:
all: %.o %.h
A pattern rule must have a pattern in the target (left-hand side of the colon). Since this is an explicit rule, the prerequisites (the right-hand side of the colon) are the literal strings %.o and %.h. Make doesn't know how to build a file named %.o so it fails.
It's not really clear what you expect this rule to do, so I can't say more than that.
I have a pattern emerging for my tests in my makefile. I'm aware of the pattern matchers % and $<. I'm trying to compile some C++.
I have a snippet of a makefile that looks like:
diff-test: main-test.o diff.o test/diff-test.cpp
$(CC) $(FLAGS) $(BOOST_LINK_FLAGS) build/main-test.o build/diff.o test/diff-test.cpp -o build/diff-test
build/diff-test
walk-test: main-test.o walk.o test/walk-test.cpp
$(CC) $(FLAGS) $(BOOST_LINK_FLAGS) build/main-test.o build/%.o test/%-test.cpp -o build/%-test
build/walk-test
I tried something along the lines of:
%-test: main-test.o %.o test/%-test.cpp
$(CC) $(FLAGS) $(BOOST_LINK_FLAGS) build/main-test.o build/$<.o test/$<-test.cpp -o build/$<-test
build/$<-test
But that just couldn't match the tests I wanted:
make diff-test
make: *** No rule to make target `diff-test'. Stop.
I don't think you want $<. That expands to the first prerequisite which in this case is main-test.o which means you'll be building build/main-test.o-test using main-test.o.o and test/main-test.o-test.cpp which seems highly unlikely.
You probably mean $* instead.
However you can't use automatic variables in prerequisite lists: they are only defined inside the recipe itself.
Why not use the pattern in the prerequisite list; that's how pattern rules are supposed to work:
%-test: %.o test/%-test.cpp main-test.o
$(CC) $(FLAGS) $(BOOST_LINK_FLAGS) $^ -o build/$*-test
build/$*-test
I'm new to Makefiles. I've been making a simple C++ library using WiringPi for my RaspberyPi related projects. So far its very simple with things like an LED class, DuelLED, Motor, Button, etc (both .h and .cpp). I was able to piece together a Makefile but I am getting an error "No rule to make target RumPi.o needed by RumPi". (Note: The name of my library is called RumPi)
Thanks for all the help, Here is the final fix:
CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi
HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h Components/Headers/Relay.h
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o
default: RumPi
RumPi: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $#
%.o: Components/Implementations/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(OBJECTS): $(HEADERS)
clean:
-rm -f $(OBJECTS)
-rm -f RumPi
That message means make can't figure out how to build that target (RumPi.o). Do you have a Components/Implementations/RumPi.cpp file? Do all the header files you've listed in the $(HEADERS) variable actually exist? If either of those is not true, then your pattern rule will not match. If your pattern rule doesn't match (and the default rule doesn't match) then make can't figure out how to build the object file.
If you want full details you can run make -d and examine the debug output. You might want to redirect it to a file so you can look at it with less or a text editor since there's a lot of output.
By the way, you should not add the -lwiringPi option to your compile line. Libraries are only used at link time, not compile time.
ETA
Something else you should consider is rewriting your pattern rule so that only the source file is listed as a prerequisite and moving the headers to a separate line:
%.o: Components/Implementations/%.cpp
gcc -c $< -o $# -lwiringPi
$(OBJECTS): $(HEADERS)
The advantage to this is you'll get a clearer error message if one of the headers is not found. When you use a pattern rule, make will try to match all the patterns it can and if none match it tells you it doesn't know how to build the target. Since there are usually many different ways to build a target, make doesn't show an error for every one that doesn't match.
But if you declare a direct explicit prerequisite relationship between two files, rather than using a pattern that may or may not match, then if there is a missing file make will tell you directly.
ETA2
In your original makefile you had a rule like this:
RumPi: $(OBJECTS)
gcc $(OBJECTS) -o $# -lwiringPi
but then later you removed it. Why did you take this out? You need this rule to tell make how to link your executable file RumPi.
Also, you shouldn't be using gcc as the compiler/linker for C++ code; gcc is for C, not C++. You should use g++ for C++ code. And it's best to contain this information in variables so it's easy to find and modify (even from the command line if you like). The standard variable names for the C++ compiler is CXX etc.
Your makefile should look something like this:
CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi
HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h \
Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h \
Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h \
Components/Headers/Relay.h
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o
default: RumPi
RumPi: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $#
%.o: Components/Implementations/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(OBJECTS): $(HEADERS)
clean:
-rm -f $(OBJECTS)
-rm -f RumPi
Here's my problem : I have a makefile file containing the info to compile everything in my project to make my life easier, but it is giving me some headaches recently.
It can compile multiple files, such as this :
objects/io.o: sources/io.cpp
#g++ -c $< -o $# -std=c++11
objects/map.o: sources/map.cpp
#g++ -c $< -o $# -std=c++11
At the top of the makefile, I have variables declared as such :
IO="objects/io.o"
MAP="objects/map.o"
[... other object files ...]
ALL="$(IO) $(MAP) [...]"
When I want to compile my main file, I use this command :
main.exe: tests/main.cpp
#g++ $< $(ALL) -o $# -std=c++11
When I compile this problem manually (inputting everything in one line of command, instead of making make main.exe) it compiles without problems.
However, when I use the make command for the project, the following error pops up :
clang: error: no such file or directory: 'objects/io.o objects/map.o [...]'
make: *** [main.exe] Error 1
Can I not use variables this way ? I'm extremely confused. I know for a fact those files are compiled, it just seems the make utility doesn't understand file paths.
I think the problem is that you have quoted your variables. Try unquoting them and they won't expand a single parameter:
ALL = $(obj1) $(obj2) ...
Also, for those objects which use the same compilation process I generally define a single rule:
obj/%.o: %.cc
$(GCC) -o $# -c $< $(FLAGS)
Obviously that would require defining the extra variables GCC and FLAGS
It seems like make is ignoring my cflag options, as the compiler complains that I need to have -std=c++11 as a flag, but that option is included in my makefile.
CC=g++
# Flags for the C compiler
CXX_FLAGS= \
-Wall \
-std=c++11 \
-O2
# Linker Flags
LD_FLAGS=
# Sources to compile
SOURCES=main.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXE=HolidayLights.out
all: $(SOURCES) $(EXE)
# Primary build target
$(EXE): $(OBJECTS)
$(CC) $(LD_FLAGS) $(OBJECTS) -o $#
.o:
$(CC) -c $(CXX_FLAGS) -o $# $<
The output of the build commands of this makefile are:
g++ -c -o main.o main.cpp
I don't understand why it's not listing my flags in the output. Also, I know for a fact that it is ignoring -std=c++11 flag as it complains about non-static constant member, and it shouldn't with that flag enabled.
Edit0: Notation change
Your .o: rule is not being selected, change it to .cpp.o: instead.
By default (from the GNU make doco):
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form '$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c'
The reason why your rule is not working in the first case is that a single-suffix implicit rule is supposed to be the source type rather than the target type. Hence the rule would be .cpp: (again, from the make doco):
A double-suffix rule is defined by a pair of suffixes: the target suffix and the source suffix. It matches any file whose name ends with the target suffix. The corresponding implicit prerequisite is made by replacing the target suffix with the source suffix in the file name. A two-suffix rule whose target and source suffixes are '.o' and '.c' is equivalent to the pattern rule '%.o : %.c'.
A single-suffix rule is defined by a single suffix, which is the source suffix. It matches any file name, and the corresponding implicit prerequisite name is made by appending the source suffix. A single-suffix rule whose source suffix is '.c' is equivalent to the pattern rule '% : %.c'.
However, read that last sentence carefully. The .cpp: rule is only effective if you want to turn XYZZY.cpp into XYZZY. Since your target is of the form XYZZY.o, it won't be used.
Of course, the other alternative is to not touch the default rules at all, and instead just modify the variables they use:
CXX = g++
CPPFLAGS = -Wall -std=c++11 -O2
LD_FLAGS =
SOURCES = main.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXE = HolidayLights.out
all: $(SOURCES) $(EXE)
$(EXE): $(OBJECTS)
$(CXX) $(LD_FLAGS) $(OBJECTS) -o $#
And, if you want to use implicit rules, you should really use the preferred form, which is the newer pattern rules. They're a lot more powerful than the suffix ones.