I have the following makefile:
CFLAGS=-c -Wall -std=c++11
MCFLAGS=-c -Wall -std=c++11
LDFLAGS= -shared
MLDFLAGS=
MSOURCES=main.cpp MCC.cpp Point3D.cpp
SOURCES= mainDLL.cpp MCC.cpp Point3D.cpp
OBJECTS=$(SOURCES:.cpp=.o)
MOBJECTS=$(MSOURCES:.cpp=.o)
EXECUTABLE=h2r.dll
MEXECUTABLE=h2r
CC=i686-w64-mingw32-g++
CC=g++
all: clean $(MSOURCES) $(MEXECUTABLE)
dll: clean $(SOURCES) $(EXECUTABLE)
$(MEXECUTABLE): $(MOBJECTS)
$(CC) $(MLDFLAGS) $(MOBJECTS) -o $#
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm *.o $(MEXECUTABLE) $(EXECUTABLE)
How can I initialize the CC with the cross compiler(CC=i686-w64-mingw32-g++) when the make dll command is emitted and how can I use the gnu compiler when the make all is emitted?
To set a variable based on what target is being executed you can do something like:
all: CC=g++
all: clean $(MSOURCES) $(MEXECUTABLE)
dll: CC=i686-w64-mingw32-g++
dll: clean $(SOURCES) $(EXECUTABLE)
Define two different CC instead of redefining the one. Since you have different rules for the all and dll, you can just use the other compiler in the other rule. Somehow like this:
CCDLL=i686-w64-mingw32-g++
CCALL=g++
all: clean $(MSOURCES) $(MEXECUTABLE)
dll: clean $(SOURCES) $(EXECUTABLE)
$(MEXECUTABLE): $(MOBJECTS)
$(CCALL) $(MLDFLAGS) $(MOBJECTS) -o $#
$(EXECUTABLE): $(OBJECTS)
$(CCDLL) $(LDFLAGS) $(OBJECTS) -o $#
Your overwriting whatever is in the CC variable. Why don't you just have:
CC_DLL=i686-w64-mingw32-g++
CC=g++
And simply use the relevant one in your targets.
Related
I have a Makefile which works well when there is not static library to compile:
CC = g++ -std=c++11
RM = rm -f
NAME = hello
SRCS = Main.cpp \
srcs/Controller.cpp \
...
srcs/Parser.cpp
OBJS = $(SRCS:.cpp=.o)
CPPFLAGS += -W -Wall -Wextra -Werror
all : $(NAME)
$(NAME) : $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(OBJS) -I./inc
clean :
$(RM) $(OBJS)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
This makefile works and doesn't relink (when I type twice "make", it doesn't recompile and output "Nothing to be done for all")
But when I want to compile a static library, the "make" command recompile the library without outputing "Nothing to be done for all", here is the new Makefile containing the static lib:
CC = g++ -std=c++11
RM = rm -f
NAME = hello
LIBNAME = libhello.a
SRCS = srcs/Controller.cpp \
...
srcs/Parser.cpp
OBJS = $(SRCS:.cpp=.o)
CPPFLAGS += -W -Wall -Wextra -Werror
all : $(NAME)
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
clean :
$(RM) $(OBJS)
$(RM) $(LIBNAME)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
How could I fix that problem to prevent the makefile to recompile when the static library has already been compiled and doesn't need to be recompiled ?
Thank you very much
regarding this recipe:
$(NAME) : $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(OBJS) -I./inc
it is expecting that the default compile statement will be used to generate the object files and make will generate those object files before executing the rule. and since it is not performing any compiles in this recipe, the parameter -I./inc is unneeded.
Without the header files being listed in the dependencies, changing a header file will fail to cause the associated source files to be recompiled.
Suggest:
HEADERS := ..
$(name): $(OBJS)
<tab> $(CC) -o $# $(OBJS) $(LFLAGS)
%.o:%.cpp $(HEADERS)
<tab> $(CC) $(CPPFLAGS) -c $< -o $# -I./inc
Note in the line:
CPPFLAGS += -W -Wall -Wextra -Werror
the -W turns off all the previously enabled warnings, probably not what you want, suggest removing that parameter.
Similar considerations need to be applied when creating the static library, similar to:
this line:
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
becomes:
HEADER := ...
all: $(LIBNAME) $(NAME)
$(LIBNAME): $(OBJS)
<tab> ar rc -o $# $^
%.o:%.cpp
<tab> $(CC) $(CPPFLAGS) -c $< -o $# -I./inc
$(NAME): main.o $(LIBNAME)
<tab> $(CC) $< -o $# $(LFLAGS) -l$(LIBNAME)
The issue is that $NAME is a phony target due to this rule:
all : $(NAME)
I think the issue can be resolved by instead changing it to an actual target:
all : $(LIBNAME)
Also, you have this rule:
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
It is a bit confusing: The library is built as $LIBNAME, but then it goes on to link an executable named $NAME. So everytime you make a change to Main.cpp, the library has to be rebuilt.
Your rule for $(NAME) doesn't actually make a file called $(NAME) (i.e. hello), so make will try and remake it every time. The recipe must match the rule (and this is why you should use automatic variables as in the last example below):
all: $(LIBNAME)
$(LIBNAME): $(OBJS)
ar rc $(LIBNAME) $(OBJS)
GNU make also has built-in archive functionality, although it doesn't play well with parallel make:
ARFLAGS := rc
all: $(LIBNAME)($(OBJS))
A more idiomatic, parallel-safe way would be something like
ARFLAGS := rc
.PHONY: all
all: $(LIBNAME)
$(LIBNAME): $(OBJS)
$(AR) $(ARFLAGS) $# $^
I have a makefile for my program but I got everything recompiled every time I run it, even if I modify nothing.
Every time I run make it recompiles simHwIntf.cpp showHelp.cpp and sendFromFile.cpp
This is my make file:
IDIR = inc
LDIR = -L/usr/lib/x86_64-linux-gnu/
SDIR = src
ODIR = obj
BINDIR = bin
LDLIBS = -luhd
OBJ = $(patsubst %,$(ODIR)/%,$(O_FILES))
CC = g++
CFLAGS = -Wall -std=c++11 -I $(IDIR) #-Werror
BINARIES= main
C_FILES = simHwIntf.cpp showHelp.cpp sendFromFile.cpp
H_FILES = simHwIntf.h
O_FILES = $(C_FILES:.cpp=.o)
all: $(BINARIES)
#echo "Make file executed"
$(BINARIES): $(O_FILES)
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(OBJ) $(LDIR) $(LDLIBS)
fileCreator: fileCreator.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/fileCreator.o
fileHandler: fileHandler.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/fileHandler.o
backYard: backYard.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/backYard.o
%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
clean:
-rm -rf $(ODIR)/*.o *~
distclean: clean
-rm -rf $(BINDIR)/*
Each time the output in the shell is:
g++ -Wall -std=c++11 -I inc -c -o obj/simHwIntf.o src/simHwIntf.cpp
g++ -Wall -std=c++11 -I inc -c -o obj/showHelp.o src/showHelp.cpp
g++ -Wall -std=c++11 -I inc -c -o obj/sendFromFile.o src/sendFromFile.cpp
g++ -Wall -std=c++11 -I inc -o bin/main obj/simHwIntf.o obj/showHelp.o obj/sendFromFile.o -L/usr/lib/x86_64-linux-gnu/ -luhd
Make file executed
I've already search and read this: (How do I make Makefile to recompile only changed files?) but didn't help much.
Anybody that could give me a hand with this ?
I have a doubt with the directories, maybe one or several directories are re-created each time I run make and this causes everything inside to look like new to the compiler.
Thanks
You can see what triggered the build by echoing the dependencies that changed. Add this to your %.o target :
#echo [triggered by changes in $?]
You should also use the VPATH special variable instead of specifying the sources path in your %.o target. See GNU make VPATH documentation
Please try replacing
%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
with
$(ODIR)/%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
Directories matter when you define targets.
If a define a rule
myexec: objdir/myexec.o
$(CC) $(CFLAGS) -o bindir/myexec objdir/myexec.o $(LDFLAGS)
Make believes that that this would create the file myexec in the working directory. When you rerun make the target myexec wasn't found, so it will be created again. Add the paths in the targets and it should work.
Try replacing
BINARIES= main
with
BINARIES= $(BINDIR)/main
and the rule
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(OBJ) $(LDIR) $(LDLIBS)
with
$(CC) $(CFLAGS) -o $# $^ $(LDIR) $(LDLIBS)
And change the other rules similarly.
Note, in general it is a bad idea to use $# in combination with a path when creating the target in some rule (as in $(BINDIR)/$#), because this will never create the actual target file. A bare $# should be sufficient.
What is the difference between .cpp.o:, .o: and %.o: %.c?
Here's a simple Makefile example:
CC=g++
CFLAGS=-c -Wall
SOURCES=file1.cpp file2.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=program
$(EXECUTABLE): $(OBJECTS)
$(CC) $(OBJECTS) -o $#
#.o:
#.cpp.o:
%.o: %.c
$(CC) $(CFLAGS) $< -o $#
all: $(SOURCES) $(EXECUTABLE)
clean:
rm -rf $(OBJECTS) $(EXECUTABLE)
I have noticed that the output is same, but I guess they are interpreted on a different way internally.
Is there a preferred way of doing this?
.cpp.o: # build *.o from *.cpp (old style notation)
%.o: %.c # build *.o from *.c (new style notation)
Both work but the new style is more powerful because it allows you to write more complicated constructions thanks to pattern matching:
%.uuu: %.vvv %.www
I am trying to write a makefile to compile and generate only object files from the source code. I have this so far:
CC=g++
CFLAGS=-c -Wall -std=c++11
SOURCES=$(wildcard *.h)
OBJECTS=$(SOURCES:.cpp=.o)
all: $(OBJECTS)
$(OBJECTS):
$(CC) $(CFLAGS) $< -o $#
when I call it, it prints:
make: Nothing to be done for `all'.
Obviously I am making a mistake, but I don't know which one, because I am seeing in the GNU make documentation page a very similar example.
Any help would be very appreciated.
Replace: SOURCES=$(wildcard *.h) with SOURCES=$(wildcard *.cpp)
and:
$(OBJECTS):
$(CC) $(CFLAGS) $< -o $#
with:
%.o: %.cpp
$(CC) $(CFLAGS) $< -o $#
This means that each {file}.o is depend on existence of {file}.cpp.
I have the following makefile:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = manager.o tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGETS) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<
Is there a way I can make my .o and bin files be built into a directory called build? I tried going through some tutorials, but I guess I just don't fully understand makefiles..
Don't feel too bad; I'm not sure anyone fully understands makefiles.
BUILD_DIR = build
OBJS = $(BUILD_DIR)/manager.o $(BUILD_DIR)/tcpcon.o
TARGETS = $(BUILD_DIR)/manager
...
$(BUILD_DIR)/%.o: %.cpp
$(CC) -c $(CCOPTS) -o $# $<