I am trying to learn make using simply three files.
foo.h
#ifndef __foo_H_
#define __foo_H_
void print();
#endif
foo.c
#include <stdio.h>
#include "foo.h"
void print()
{
printf("Hello World !");
}
main.c
#include "foo.h"
int main()
{
print();
return 0;
}
When I use the following makefile, everything runs fine
makefile
CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o
.PHONY: clean
main: $(OBJ)
gcc -o $# $^ $(CFLAGS)
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
clean:
rm *.o
The above works because make by default runs the first target(Which I read basically everywhere).
If I use the below makefile
CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o
.PHONY: clean
clean:
rm *.o
main: $(OBJ)
gcc -o $# $^ $(CFLAGS)
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
Calling make on the above makefile runs only make clean because make by default runs the first rule.
The problem is with this makefile
CC = gcc
CFLAGS = -I.
DEPS = foo.h
OBJ = foo.o main.o
.PHONY: clean
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
main: $(OBJ)
gcc -o $# $^ $(CFLAGS)
clean:
rm *.o
In the above makefile using make I get
gcc -c -o foo.o foo.c -I.
gcc -c -o main.o main.c -I.
gcc -o main foo.o main.o -I.
Why doesn't make just build the .o files and stop since it is the first target, why does it go on to build main as well? There is no where that I've specified in the first rule to build main.
The "first target" rule only counts explicit targets. It doesn't count implicit targets, such as suffix rules or pattern rules.
Consider: how would make determine that it should build the .o files? Which .o files should it build? How would make understand that it should build the ones in the variable OBJ, versus any other variable?
I was looking for a good section of the manual to point you at but haven't found anything specific and concrete to use. The answer to the question, as far as I know, is that a pattern rule is not a target and the default target must, as its name indicates, be a target.
Were you using a static pattern rule (which does define targets) then your expectation would almost be correct as make would pick the first such file and build just that in this case (not all as you might expect just the first).
Related
This is a part of my makefile :
SRC = ./
DIRS = src libs/maths libs/struct
BIN_DIR = ./bin/
SRC_DIRS= $(foreach dir, $(DIRS), $(addprefix $(SRC), $(dir)))
SRC_TEST= $(sort $(SRC_DIRS))
SRCS = $(foreach msrc, $(SRC_DIRS), $(wildcard $(msrc)/*.c))
DEL_PRE = $(foreach target, $(SRCS), $(notdir $(target)))
ADD_PRE = $(foreach target, $(DEL_PRE), $(addprefix $(BIN_DIR), $(target)))
OBJS = $(ADD_PRE:.c=.o)
.PHONY: all clean re
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) -o $# $(LDLIBS)
$(OBJS): $(SRCS)
$(CC) -o $# -c $<
When i use make all, i have in output :
gcc -o bin/main.o -c src/main.c
gcc -o bin/cosin.o -c src/main.c
gcc -o bin/pears.o -c src/main.c
gcc -o bin/outil.o -c src/main.c
gcc -o bin/verif.o -c src/main.c
But i would like to have for each target, it assigned dependency :
gcc -o bin/main.o -c src/main.c
gcc -o bin/cosin.o -c libs/maths/cosin.c
gcc -o bin/pears.o -c libs/maths/pears.c
gcc -o bin/outil.o -c libs/struct/outil.c
gcc -o bin/verif.o -c libs/struct/verif.c
How can i fix it ?
This seems like a very common misconception; I just answered effectively this same question yesterday. I'm not sure where it comes from or how to combat it.
This rule:
$(OBJS): $(SRCS)
$(CC) -o $# -c $<
does not somehow magically combine the contents of the OBJS variable and the SRCS variable to figure out how they match up. The variable references are simply expanded, and the result is this:
bin/main.o bin/cosin.o ... : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
which is the same as if you'd written this:
bin/main.o : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
bin/cosin.o : src/main.c libs/maths/cosin.c ...
$(CC) -o $# -c $<
...
Now, you can hopefully see why you compile the same file: in every rule you have the same prerequisites, so $< is always the first one, which is always src/main.c.
There are multiple ways to work this but if you really want to have all the source files from different directories compiled into object files in the same directory your job is harder, because there's no common pattern that will match them all. In this case the simplest thing to do is use VPATH for directory search: replace the above rule with this:
$(BIN_DIR)/%.o : %.c
$(CC) -o $# -c $<
then tell make how to find your source files, like this:
VPATH := $(sort $(dir $(SRCS))
Be aware this method can't be used for any source files that are themselves generated output that make is expected to create.
I would like to make main-c to build main-c from main.c.
And make main-cpp to build main-cpp from main.cpp.
I have, all in the same folder:
main.c:
#include <stdio.h>
int main(int argc, char const *argv[]) {
printf("This ic C\n");
}
main.cpp:
#include <iostream>
int main(int argc, char const *argv[]) {
std::cout << "This is C++" << std::endl;
}
Makefile:
CFLAGS = -std=gnu11
CXXFLAGS = -std=gnu++11
CPPFLAGS = -g -Wall -O3
LDFLAGS =
LDLIBS =
OBJS = main.o
APP-C = main-c
APP-CPP = main-cpp
default:
echo "Check README.txt"
main-c: $(OBJS)
$(CC) $^ $(LDLIBS) -o $#
main-cpp: $(OBJS)
$(CXX) $^ $(LDLIBS) -o $#
clean:
-rm -Rf *.o
distclean: clean
-rm -Rf $(APP-C) $(APP-CPP)
So:
$ make main-c
cc -std=gnu11 -g -Wall -O3 -c -o main.o main.c
cc main.o -o main-c
But (also builds from .c):
$ make main-cpp
cc -std=gnu11 -g -Wall -O3 -c -o main.o main.c
c++ main.o -o main-cpp
I was expecting make main-cpp to use $(CXX) $^ $(LDLIBS) -o $# and build from .cpp. What am I missing?
I was expecting make main-cpp to use $(CXX) $^ $(LDLIBS) -o $# and build from .cpp.
It is. make main-cpp --debug will help you see what is going on.
The problem is you are relying on the default rule for making the main.o needed by both main-cpp and main-c target, but you want a different build when make-cpp target is invoked. In this case you'll need to define different non default rules to build the .o files. It's easiest if you just make make-cpp and main-c depend on a .o with a different name. Since they are different builds they should have different names anyway:
CFLAGS = -std=gnu11
CXXFLAGS = -std=gnu++11
CPPFLAGS = -g -Wall -O3
LDFLAGS =
LDLIBS =
APP-C = main-c
APP-CPP = main-cpp
default:
echo "Check README.txt"
main-c: %:%.o
$(CC) $^ $(LDLIBS) -o $#
main-cpp: %:%.o
$(CXX) $^ $(LDLIBS) -o $#
main-cpp.o: main.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $? -o $#
main-c.o: main.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $? -o $#
clean:
-rm -Rf *.o
distclean: clean
-rm -Rf $(APP-C) $(APP-CPP)
Both rules, main-c and main-cpp, require main.o to be created to complete, but you don't have a rule for creating main.o.
You're using make's implicit object file creation which is a built-in rule for creating a '.o' file from a source file. It can use either a '.c' or '.cpp/cc/C' file and will build using the appropriate variables. However, since you have both main.c and main.cpp, it looks like it defaults to using the C version.
You'd probably need to create explicit rules (and probably use different names) for each one.
I have seen questions like these on SO but everyone has different answers and directory structures that aren't working for me.
My makefile:
CC = g++
DEBUG = -g -std=c++11
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
start: clean BingResultSet.o main.o
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)
rm -f *.o
BingResultSet.o: BingResultSet.cpp BingResultSet.h
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c BingResultSet.cpp
main.o: main.cpp
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c main.cpp
clean:
rm -f $(OBJECT_FILES) $(TARGET)
My file structure:
/Desktop/DataMiner/.cpp, .h, and makefile
/Desktop/DataMiner/HTTPClientLib/include/HTTPClient.h
/Desktop/DataMiner/HTTPClientLib/lib/HTTPClient.a
What's the correct way to link my static lib in my makefile?
Here's my $0.02:
there was no static library involved. Assuming you meant the .o files
you mix dependencies and build rules, instead, avoid repeating build rules:
$(TARGET): $(OBJECT_FILES)
$(CXX) $(DEBUG) $(INC_PATH) $^ -o $# $(LIB_PATH)
%.o: %.cpp
$(CXX) $(DEBUG) $(INC_PATH) -c $< -o $#
You used CC for a C++ compiler. That's strange. Use CXX
You used LDFLAGS when you were just compiling
You hardcoded the source and destination paths. Instead use the automatic variables ($^, $< for source; $# for destination)
You tried to hardcode header dependencies. That's error-prone and messes up source specification (you don't want $^ to list .h files in your command line...). Instead, use gcc -MM¹ to generate the dependencies for you!
Next, do a conditional include of those dependencies:
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
It's usually handy to keep the .o files so you can speed up builds. Of course, this was not a good plan until you generated the header dependencies automatically. If you insist, you can comment the .PRECIOUS target. Intermediate targets are automatically deleted by GNU Make
Here's the integrated offering I ended up with:
CXX = g++
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
CPPFLAGS = -g -std=c++11
CPPFLAGS+= $(INC_PATH)
# standard derived flags:
CXXFLAGS+=$(CPPFLAGS)
LDFLAGS+=$(LIB_PATH)
start: .depends $(TARGET)
$(TARGET): $(OBJECT_FILES)
$(CXX) $(CXXFLAGS) $^ -o $# $(LDFLAGS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -f .depends $(OBJECT_FILES) $(TARGET)
# to keep the .o files:
.PRECIOUS: $(OBJECT_FILES)
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
On a very simple sample set of files you get:
$ make clean
rm -f .depends BingResultSet.o main.o main
$ make
g++ -MM -g -std=c++11 -I HTTPClientLib/include -c *.cpp > .depends
g++ -I HTTPClientLib/include -c BingResultSet.cpp -o BingResultSet.o
g++ -I HTTPClientLib/include -c main.cpp -o main.o
g++ -I HTTPClientLib/include BingResultSet.o main.o -o main -L HTTPClientLib/lib/
$ cat .depends
BingResultSet.o: BingResultSet.cpp BingResultSet.h
main.o: main.cpp BingResultSet.h
test.o: test.cpp
¹ (or similar, see man-page)
I am unable to figure out what is causing this error that I keep getting upon making my project:
i686-apple-darwin11-llvm-g++-4.2: -lncurses: linker input file unused because linking not done
And my make file looks like this:
CC = g++
LIB_FLAGS = -l ncurses
FLAGS = $(LIB_FLAGS)
DEPENDENCIES = window.o element.o
# FINAL OUTPUTS
main: main.cpp $(DEPENDENCIES)
$(CC) $(FLAGS) -o main.out main.cpp $(DEPENDENCIES)
# MODULES
window.o: main.h classes/window.cpp
$(CC) $(FLAGS) -c classes/window.cpp
element.o: main.h classes/element.cpp
$(CC) $(FLAGS) -c classes/element.cpp
# CLEAN
clean:
rm -rf *.o
rm main.out
Everything compiles okay, but I'm just curious what is causing this error message and what it means..
You are passing linker options to a compiler invocation together with -c, which means that linking is not performed and thereby -l options are unused. In your case, your LIB_FLAGS should not be in FLAGS, but instead specified in the the main: ... rule:
main: main.cpp
$(CC) $(FLAGS) $(LIB_FLAGS) ...
Do not give link flags when you compile (-c flag) your source files. Take a look for this example makefile (very similar as in makefile docs)
CPP = g++
CPPFLAGS =-Wall -g
OBJECTS = main.o net.o
PREFIX = /usr/local
.SUFFIXES: .cpp .o
.cpp.o:
$(CPP) $(CPPFLAGS) -c $<
.o:
$(CPP) $(CPPFLAGS) $^ -o $#
main: $(OBJECTS)
main.o: main.cpp
net.o: net.cpp net.h
.PHONY:
install: main
mkdir -p $(PREFIX)/bin
rm -f $(PREFIX)/bin/main
cp main $(PREFIX)/bin/main
clean:
rm -f *.o main
As has been mentioned already you're passing linker-related flags at the compile stage. Usually you want different flags for compiling and linking, e.g.
CC = g++
CPPFLAGS = -Wall -g -c -o $#
LDFLAGS = -l ncurses -o $#
DEPENDENCIES = main.o window.o element.o
# FINAL OUTPUTS
main: $(DEPENDENCIES)
$(CC) $(LDFLAGS) $(DEPENDENCIES)
# MODULES
main.o: main.h main.cpp
$(CC) $(CPPFLAGS) main.cpp
window.o: main.h classes/window.cpp
$(CC) $(CPPFLAGS) classes/window.cpp
element.o: main.h classes/element.cpp
$(CC) $(CPPFLAGS) classes/element.cpp
# CLEAN
clean:
-rm main $(DEPENDENCIES)
Currently, I have my makefile set up to compile and make a fairly large project. I have written a second cpp file with main function for running tests. I want these to run separately, but build together and they use the same files. How is this accomplished?
edit: As reference, here is my current makefile. I'm not sure how to adjust it.
CC=g++
CFLAGS=-c -Wall -DDEBUG -g
LDFLAGS=
SOURCES=main.cpp Foo.cpp Bar.cpp Test.cpp A.cpp B.cpp C.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=myprogram
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Normally you would just have multiple targets and do something like this:
.PHONY: all target tests
all: target tests
target: ...
...
tests: ...
...
Then you can just make (defaults to make all), or just make target or make tests as needed.
So for your makefile example above you might want to have something like this:
CC = g++
CFLAGS = -c -Wall -DDEBUG -g
LDFLAGS =
COMMON_SOURCES = Foo.cpp Bar.cpp A.cpp B.cpp C.cpp
TARGET_SOURCES = main.cpp
TEST_SOURCES = test_main.cpp
COMMON_OBJECTS = $(COMMON_SOURCES:.cpp=.o)
TARGET_OBJECTS = $(TARGET_SOURCES:.cpp=.o)
TEST_OBJECTS = $(TEST_SOURCES:.cpp=.o)
EXECUTABLE = myprogram
TEST_EXECUTABLE = mytestprogram
.PHONY: all target tests
all: target tests
target: $(EXECUTABLE)
tests: $(TEST_EXECUTABLE)
$(EXECUTABLE): $(COMMON_OBJECTS) $(TARGET_OBJECTS)
$(CC) $(LDFLAGS) $^ -o $#
$(TEST_EXECUTABLE): $(COMMON_OBJECTS) $(TEST_OBJECTS)
$(CC) $(LDFLAGS) $^ -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Here's one way to do it:
CXXFLAGS += -std=c++11 -Wall -O3
all: myprog mytest
myprog.cpp: main.cpp
cp -vf $< $#
myprog: myprog.o Foo.o Bar.o Test.o A.o B.o C.o
mytest.cpp: main.cpp
cp -vf $< $#
mytest.o: CPPFLAGS += -DDEBUG
mytest.o: CXXFLAGS += -O0 -g
mytest: mytest.o Foo.o Bar.o Test.o A.o B.o C.o
This works because built-in rules exist for compiling objects from c++ source (%.o: %.cpp) and linking main programs (%: %.o).
Also note the use of target-specific values for the variables CPPFLAGS and CXXFLAGS.