SRCDIR=src
OUTDIR=bin
CXX=g++
CXXFLAGS=-Wall -Wextra -O0 -g -MD -fmodules-ts
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
CODEFILES := $(call rwildcard,src,*.cpp)
OBJFILES := $(subst $(SRCDIR),,$(CODEFILES:%.cpp=%.obj))
$(info $(OBJFILES))
all: $(OBJFILES)
$(CXX) -o $# $^
%.obj:%.cpp
$(CXX) $(CXXFLAGS) -c -o $(OUTDIR)/$# $(SRCDIR)/$<
Outputs:
/hello.obj /main.obj /some/bye.obj
make: *** No rule to make target '/hello.obj', needed by 'all'. Stop.
It's my first time using a Makefile and I'm stuck on this problem. What did I do wrong?
PS: This is on Windows.
EDIT:
$(info $(CODEFILES))
gives:
PS F:\CLionFiles\modules> make
src/hello.cpp src/main.cpp src/some/bye.cpp
make: *** No rule to make target '/hello.obj', needed by 'all'. Stop
The elements of CODEFILES all start with src/. When you define OBJFILES with subst, you strip off SRCDIR (which is src) which leaves the resultant file paths starting with /.
You want to put the object files in OUTDIR. So, you need to do
OBJFILES := $(subst $(SRCDIR),$(OUTDIR),$(CODEFILES:%.cpp=%.obj))
You then need to change the final recipe to
$(OUTDIR)/%.obj: $(SRCDIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
Related
This is my makefile for a particular C++ project, but when I run make all, I get:
/bin/sh: 1: Syntax error: Unterminated quoted string
Makefile:28: recipe for target '"system' failed
make: *** ["system] Error 2
When I change exe to something with no spaces, it works fine.
EDIT #1: The reason I used quotes was so I could use spaces in the output file name.
cc = g++
exe = "system software version 1.0"
src_dir = src
obj_dir = obj
src = $(wildcard $(src_dir)/*.cpp)
obj = $(patsubst $(src_dir)/%.cpp, $(obj_dir)/%.o, $(src))
libs = -lallegro -lallegro_primitives
include_paths = -I "include" -I "~/allegro5/include/"
lib_paths = -L "/usr/lib/"
flags = -Wall -Wextra -Wpedantic -g -std=c++14
all: $(exe)
play: all
$(exe)
$(exe): $(obj)
$(cc) $(lib_paths) $^ $(libs) -o $#
compile_only: $(obj)
$(obj_dir)/%.o: $(src_dir)/%.cpp
$(cc) $(flags) $(include_paths) -c $^ -o $#
clean:
rm -f $(obj_dir)/*.o
build: all
rebuild: clean build
.PHONY: all clean rebuild
You cannot use paths containing whitespace with make. There are crazy tricks that can make some limited things work, but basically it's simply not supported.
See this recent question and answer: https://stackoverflow.com/a/56411000/939557
I can't get what's wrong with my makefile:
DIST_PATH = ../dist/libs
BUILD_PATH = ../build
MKDIR_P = mkdir -p
.PHONY: all
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99
CFLAGS = -fPIC -pedantic -Wall -Werror
LDFLAGS = -shared
LOG_SRCS = $(shell echo log/*.c)
LOG_HEADERS = $(shell echo log/*.h)
LOG_OBJS = $(addprefix $(BUILD_PATH)/, $(notdir $(LOG_SRCS:.c=.o)))
LOG_TARGET = $(DIST_PATH)/liblog.so
all: dirs $(LOG_TARGET)
dirs :
$(MKDIR_P) $(DIST_PATH)
$(MKDIR_P) $(BUILD_PATH)
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $(LDFLAGS)
I need to build a shared library from sources in log/ folder to ../dist/libs and put obj file in ../build but I am getting the error:
make: *** No rule to make target '../build/log.o', needed by '../dist/libs/liblog.so'. Stop.
P.S. I know there are many similar questions but I couldn't get from these questions how to resolve my problem.
The problem is that the source and object files are supposed to be placed in different directories, and there's no implicit rule for that.
You need to add a rule for how to translate a source file to an object file:
$(BUILD_PATH)/%.o: log/%.c
Now make knows how to create the object files from the source files.
There's another problem though:
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $(LDFLAGS)
The command doesn't list any input files, you need to add all the object files to be linked:
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $^ $(LDFLAGS)
# ^^
# List of all "prerequisites" (object files) to be linked
I have the following makefile:
CC ?= gcc
LD := gcc
CFLAGS := -Wall -Wextra -Werror -Wfatal-errors
LDFLAGS :=
LIBRARIES := m c
INCLUDEDIRS := .
LIBS = $(addprefix -l,$(LIBRARIES))
INCLUDES = $(addprefix -I,$(INCLUDEDIRS))
SRC := $(wildcard *.c)
TARGET = $(TARGETDIR)/test
OBJDIR = $(TARGETDIR)/obj/
OBJ = $(addprefix $(OBJDIR),$(SRC:%.c=%.c.o))
.SUFFIXES:
.SUFFIXES: .c.o
.PHONY: all debug i7avx i7avx-debug
all: TARGETDIR := generic
all: CFLAGS += -O3
all: LDFLAGS += -s
all: $(TARGET)
debug: CFLAGS += -Og
debug: TARGETDIR := generic/dbg
debug: $(TARGET)
$(OBJDIR):
#mkdir -p $(OBJDIR)
$(OBJ): | $(OBJDIR)
$(OBJDIR)%.c.o : %.c
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
$(TARGET) : $(OBJ)
$(LD) $(LDFLAGS) -o $# $^ $(LIBS)
The special thing here is that the output directory depends on the target.
Currently, only all and debug is defined, but the idea is to support a whole slew of architectures, and to define an outputdir per target.
Problem: this does not work. If I run this, I get:
cc -Wall -Wextra -Werror -Wfatal-errors -O3 -I. -c main.c -o /obj/main.c.o
Assembler messages:
Fatal error: can't create /obj/main.c.o: No such file or directory
make: *** [Makefile:37: /obj/main.c.o] Error 1
Which implies that the TARGETDIR variable was expanded too late.
If I replace the automatic variables with real variables, it does work:
$(OBJ): | $(OBJDIR)
$(OBJDIR)%.c.o : %.c
$(CC) $(CFLAGS) $(INCLUDES) -c $(SRC) -o $(OBJ)
$(TARGET) : $(OBJ)
$(LD) $(LDFLAGS) -o $(TARGET) $(OBJ) $(LIBS)
running this:
cc -Wall -Wextra -Werror -Wfatal-errors -O3 -I. -c main.c -o generic/obj/main.c.o
gcc -s -o generic/test generic/obj/main.c.o -lm -lc
Sooo, how can I make the autmatic variables expand after the TARGETDIR was defined?
Make does handle wildcards very deftly, or this would be a much easier problem.
As it is, I think the best solution is to use recursive Make. Just change this:
all: $(TARGET)
debug: $(TARGET)
to this:
all debug:
$(MAKE) $(TARGET) TARGETDIR=$(TARGETDIR) CFLAGS+='$(CFLAGS)' LDFLAGS=$(LDFLAGS)
First, the reason why it does not work :
You're using target-specific variables, but those are only available in the context of a target recipe (I'm quoting the manual here), not during the rules evaluation :
Make will first read your Makefile, evaluate your $(OBJDIR) and $(TARGET) rules (at this point $(TARGETDIR)is not yet defined) then, it will try to update all, and at this point set $(TARGETDIR) to the target-specific value for all (which explains why you're second example work, but it should rebuild every time).
I may have some hints to achieving what you're trying to do (I'm actually planning on doing a similar thing soon) :
you could use the eval function to generate one rule for each build/archi, like this:
#define TARGET_RULE
$(TARGET) : $(OBJ)
$$(RECIPE)
#endif
$(foreach TARGETDIR, $(BUILD_LIST), $(eval $(TARGET_RULE))
($$ is needed for the recipe to avoid it being expanded during the rule evaluation)
You should also be able to define only the rule or rules for the target you are currently building (not sure if that would make a signifiant perf difference).
I just began learning about GNU make yesterday. As the title says, it appears that the % sign in my Makefile is not being recognised. Or perhaps I am using it the wrong way. Can someone enlighten me?
CXX = clang++
EXE = Invaders
SDL = -F./lib
LDFLAGS = $(SDL)
SRCDIR = src
OBJDIR = obj
SRC = $(SRCDIR)/main.cpp $(wildcard $(SRCDIR)/util/*.cpp) $(wildcard $(SRCDIR)/misc/*.cpp)
OBJ = $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRC))
all: $(EXE)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) -o bin/$# $^
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(SRCDIR)/%.h
$(CXX) -c -o $# $<
Console output:
make: *** No rule to make target `obj/main.o', needed by `Invaders'. Stop.
Tree view of my entire project with directories /obj and /src expanded
Thanks!
This rule:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(SRCDIR)/%.h
$(CXX) -c -o $# $<
does not fit obj/main.o, because there is no src/main.h.
(Also, please put the necessary information in the body of the question, don't rely on a link to an image.)
I've this folder structure
project
|_src
| |_test
| |_main.cpp
|_Makefile
This is my makefile (trying to adapt from this link):
CC = g++
RM = rm
WFLAGS = -c -Wall -W
LDFLAGS =
SRCTESTD = src/test
EXECUTABLE = test
OBJD = .obj
DEPD = .dep
SRCSTEST = $(SRCTESTD)/main.cpp
OBJECTSTEST = $(patsubst %.cpp, $(OBJD)/test/%.o, $(notdir $(SRCSTEST)))
DEPDSTEST = $(patsubst %.cpp, $(DEPD)/test/%.d, $(notdir $(SRCSTEST)))
all: $(SRCSTEST) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTSTEST)
$(CC) $(LDFLAGS) $(OBJECTSTEST) -o $#
.cpp.o:
$(CC) $(WFLAGS) $< -o $#
It does not work, and I've this error
make: *** No rule to make target `.obj/test/main.o', needed by `test'. Stop.
What I'm doing wrong? Sorry for trivial question, but I'm a make newbie.
The link shows outdated methods, such as suffix rules. Making dependencies can also be done during compilation by gcc/g++.
As for the rest, here is it :
EXE := test
SRCDIR := src
OBJDIR := .obj
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEP := $(OBJ:.o=.d)
LDLIBS := # -l flags
LDFLAGS := # -L flags
CPPFLAGS := -MMD -MP # -I flags also
CXXFLAGS := -W -Wall # no -c flag here
.PHONY: all clean fclean re
all: $(EXE)
clean:
$(RM) -r $(OBJDIR)
fclean: clean
$(RM) $(EXE)
re: fclean all
-include $(DEP)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
No redefinition of internally defined variables, no suffix rules, correct linking step and dependencies generation.
Update: To avoid calling mkdir for every source file, one should use order-only prerequisites and the special target .SECONDEXPANSION.
Change this block:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
To this:
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(#D)/
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
%/:
mkdir $*
The error means make can't find a correct rule to build your object files. Your tree structure lacks some informations: only one file ? Where are the others ? Anyway, here are some hints:
In the last two lines, you are using an obsolete feature of make: suffix rules. I suggest you switch to a pattern rule, which is functionaly equivalent.
Say something like:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
Another thing (that shouldn't be a problem here): you are using the variable CC which is internally defined as the default C compiler. It's okay because you redefine it, but as your sources seem to be C++ files, why not use the variable CXX, that is internally defined as the C++ compiler ?
Lastly, to make sure your set of files are correctly defined, you can print them with a dummy show target, see here.
show:
#echo "OBJECTSTEST=$(OBJECTSTEST)"
...