How to write specific rule for a target in makefile? - c++

I know the title is quite ambiguous but I just don't know how to describe my problem concisely. Please edit that if you want.
Currently my makefile is like the following:
CC = g++
CFLAGS = -Wall -g
TARGET = foobar
SRC_FILES = foo.cpp bar.cpp main.cpp
OBJ_FILES := $(SRC_FILES:.cpp=.o)
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.cpp %.h
$(CC) $(CFLAGS) -c $<
clean:
rm -rf *.o $(TARGET)
The problem is that this structure requires main.cpp to have a main.h header file, which I don't really have. How can I handle this nicely?

GCC (and probably Clang) can build a list of dependencies for you; This way, you can simply make your object files from their source (cpp) file:
depend: .depend
.depend: $(SRC_FILES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
You might also find interest in the makedepend tool.

Related

Makefile compiling even though header files doesn't change

I have a makefile which compiles a program with many dependencies like this:
CXX=g++
IDIR=lib
CFLAGS=-Wall -O2 -std=c++11 -I$(IDIR)
UDIR=utils
CFILES=Utils.cpp Structs.cpp Registry.cpp Dealer.cpp
CFILES:=$(patsubst %.cpp,$(UDIR)/%.cpp,$(CFILES))
DEPS=$(wildcard $(IDIR)/*.hh)
ODIR=obj
OBJ:=$(patsubst $(UDIR)/%.cpp,$(ODIR)/%.o,$(CFILES))
CDIR=strategies
EXTRA_CFILES=$(wildcard $(CDIR)/Strategy*.cpp)
CFILES += $(EXTRA_CFILES)
EXTRA_OBJ:=$(patsubst $(CDIR)/%.cpp,$(ODIR)/%.o,$(EXTRA_CFILES))
OBJ += $(EXTRA_OBJ)
all: create_header environment.exe
create_header:
chmod +x create_headers.sh
bash create_headers.sh
$(ODIR)/%.o: $(UDIR)/%.cpp $(DEPS)
$(CXX) -c -o $# $< $(CFLAGS)
$(ODIR)/%.o: $(CDIR)/%.cpp $(DEPS)
$(CXX) -c -o $# $< $(CFLAGS)
environment.o: environment.cpp $(OBJ)
$(CXX) -c -o $# $< $(CFLAGS)
environment.exe: environment.o $(OBJ)
$(CXX) $(CFLAGS) $^ -o $#
m='Auto'
git_upload:
git add -A
git commit -m "$(m)"
git push
.PHONY: clean
clean:
rm -rf $(ODIR)/*.o *.exe
However, when I type make, it is always compiling everything. I only want it to compile the dependencies when a change has been made, either to header or implementation files. The problem is, it is always compiling everything even though I haven't changed anything.

Using Makefile compile multiple .cpp in diferent folders to a single build/ directory [duplicate]

GNU Make 3.82
gcc 4.7.2
c89
I have the following make file:
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS) bin
find . -name "*~" -exec rm {} \;
find . -name "*.o" -exec rm {} \;
My directory structure is like this project/src project/bin. My Makefile is in the project (root) folder, and all my *.h and *.c are in the src directory. Currently I have only one source file called timeout.c
I get this error:
gcc: error: src/timeout.o: No such file or directory
I have used this to get all the source files:
SOURCES=$(wildcard src/*.c)
And the object files:
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
However, the make seems to create the object file in the project root folder where the Makefile is. Should it not put it in the src directory?
You have two problems in this rule (well, three):
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
You haven't noticed yet, but the rule makes each object dependent on all sources, and tries to build that way. Not a problem as long as you have only one source. Easy to fix with a static pattern rule and an automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)
Also, the command ("$(CC)...") doesn't specify an output file name, so gcc will infer it from the source file name; if you give it src/timeout.c, it will produce timeout.o (in the working directory, project/). So you should specify the desired path to the output file. Easy to do with another automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $#
Use gcc's -o option to write the output file to a particular location. For instance, you could say:
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)
Unfortunately, there's a problem with this line: if there is more than one source file in $(SOURCES), it won't work, since $(OBJECTS) will also contain multiple file names, and the -o option only binds to the first argument.
A way to compile each file in a list of source code files is to use implicit rules. In gmake, you would write:
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
where $< is replaced with name of the input file and $# is replaced with the name out the output file.
I solved this request and here is my Makefile and directory tree.
PROJECT := main.exe
DIR_SRC += .
DIR_SRC += ./src
DIR_INC += -lpthread
DIR_INC += -I./inc
DIR_INC += $(addprefix -I, $(DIR_SRC))
SRC_C += $(wildcard $(addsuffix /*.c, $(DIR_SRC)))
#OBJ := $(filter %.o, $(SRC_C:.c=.o))
OBJ := $(patsubst %.c, %.o, $(SRC_C))
EXE := $(PROJECT)
CC_PREFIX :=
CC := $(CC_PREFIX)gcc
CFLAG =
CLIB = -L .
.PHONY:all
all:$(OBJ) $(EXE)
%.o: %.c
$(CC) $(CFLAG) $(DIR_INC) -c $< -o $#
$(EXE): $(OBJ)
$(CC) $(CFLAG) $(CLIB) $(OBJ) -o $#
clean:
rm -r $(EXE) $(OBJ)
See my directory tree:

compile only objects by default with makefile

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.

How to change my makefile to build into a separate folder

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 $# $<

a couple of Makefile issues

I've got this Makefile:
CFLAGS = -c -Wall
CC = g++
EXEC = main
SOURCES = main.cpp listpath.cpp Parser.cpp
OBJECTS = $(SOURCES: .cpp=.o)
EXECUTABLE = tp
DIR_SRC = /src/
DIR_OBJ = /obj/
all: $(SOURCES) $(OBJECTS)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm $(OBJECTS) $(EXECUTABLE)
Note this:
I'm in the directory "." which contains the makefile
The folder "./src" EXISTS, and has all the .h and .cpp files
The folder "./obj" doesn't exist, I want makefile to create it and put all the .o there
The error I get is:
No rules to build "main.cpp", necessary for "all". Stopping.
Help!
All right, from the top:
CFLAGS = -c -Wall
CC = g++
# EXEC = main never used, not needed
SOURCES = main.cpp listpath.cpp Parser.cpp
So far, so good. Note that this SOURCES doesn't mention DIR_SRC, so we'll have to make that connection later (and $(DIR_SRC)$(SOURCES) won't work, because the path must be appended to each member of the list). But OBJECTS really needs paths (e.g. /obj/main.o):
OBJECTS = $(patsubst %.cpp, $(DIR_OBJ)%.o, $(SOURCES))
EXECUTABLE = tp
DIR_SRC = /src/
DIR_OBJ = /obj/
(Personally I don't like putting the trailing slash in the variable, but it's a matter of taste.) The first target is the default target, so it should build what you actually want built:
all: $(EXECUTABLE)
Don't worry about listing the sources as prerequisites; they will sort themselves out later.
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $# # <-- note the automatic variable $^
The .cpp.o convention doesn't really work here; we'll have to spell it out. And we must tell Make to search $(DIR_SRC) for .cpp files:
$(OBJECTS): $(DIR_OBJ)%.o: %.cpp $(DIR_OBJ)
$(CC) $(CFLAGS) $< -o $#
$(DIR_OBJ):
mkdir $#
vpath %.cpp $(DIR_SRC)
And tell Make that clean is not a real target, just to be safe:
.PHONY: clean
clean:
rm $(OBJECTS) $(EXECUTABLE)
EDIT:
I shouldn't have attempted so much in one step. Let's try something simpler:
$(DIR_OBJ)%.o: $(DIR_SRC)%.cpp $(DIR_OBJ)
$(CC) $(CFLAGS) $< -o $#
Edit the SOURCES to include the source directory (e.g. src/main.cpp etc.).
For the object files, consider something like this:
OBJECTS = $(subst src/,obj/,$(SOURCES:%.cpp=%.o))
# ...
all: $(SOURCES) build
.PHONY: build
build: pre_build $(EXECUTABLE)
.PHONY: pre_build
pre_build: obj
obj:
-mkdir obj
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $#