I'm using gmake on Windows with MinGW. This is a snippet of the makefile:
SRCS = ..\path\to\srcs\*.c*
SRCS := $(wildcard $(SRCS))
OBJS := $(addsuffix .o,$(basename $(SRCS)))
$(OBJS) : $(SRCS)
$(CC) $(FLGAS) $(INCLUDES) "$<"
I'm getting the following:
gmake: *** No targets. Stop.
If I define SRCS, for instance, as ..\path\to\srcs\a.c, it works.
Am I using wildcard in the correct manner?
I'm using GNU Make 3.81.
make doesn't cope well with backslashes; you need to double each, or (better) switch to forward slashes instead.
Your recipe overrides the built-in rules for creating object files from C files with a broken one, though.
Your recipe claims that all $(OBJS) will be produced from a single compilation which has all the $(SRCS) as dependencies, but only reads the first one ($< pro $^). It's probably better to just say what you want and let make take it from there.
.PHONY: all
all: $(OBJS)
%.o: ../path/to/srcs/%.c
Related
I have a project where you can build for multiple platforms, architectures, etc. I need to be able to set various variables based on the target before compiling any source files. But what's happening is the non-platform specific files are getting compiled immediately and then the platform specific ones didn't get compiled at all.
Below calling "make foobar_mac", foo.o gets created but bar.mac.o does not and therefore during the final link bar.mac.o is missing.
OBJS = foo.c bar.$(PLATFORM).c
%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
foobar_mac: PLATFORM := mac
foobar_mac: $(OBJS)
foobar_win: PLATFORM := win
foobar_win: $(OBJS)
There are various ways to get what you want. One way is to use secondary expansion to delay the expansion until after the target-specific variable is in scope.
Like this:
.SECONDEXPANSION:
OBJS = foo.c bar.$$(PLATFORM).c
%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
foobar_mac: PLATFORM := mac
foobar_mac: $(OBJS)
foobar_win: PLATFORM := win
foobar_win: $(OBJS)
Note how we added .SECONDEXPANSION, then we escaped the $(PLATFORM) reference in OBJS as $$(PLATFORM) so it would not be expanded when GNU make parses the makefile.
There are various other ways to do this as well.
I need help, simply because I need help:
SRC=src/main.c
OBJ_PATH=bin
OBJS := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
all:$(OBJ_PATH)/target.exe
$(OBJ_PATH)/target.exe: $(OBJ_PATH) $(OBJS)
$(CC) $(OBJS) -o $(OBJ_PATH)/target.exe
$(OBJ_PATH):
mkdir -p bin
$(OBJ_PATH)/%.o:%.c
mkdir -p bin
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
.PHONY: clean
clean:
rm -f $(OBJ_PATH)/*
when running it gives this:
make: *** No rule to make target 'bin/main.o', needed by 'bin/target.exe'. Stop.
If I leave the objects in the same folder as the c files, it works.
I just need some help, maybe it is something simple that I am not seeing.
Thanks guys.
This is wrong:
$(OBJ_PATH)/%.o: %.c
When make wants to build a file bin/main.o. It matches the target pattern bin/%.o, with a stem of main (the part that matches the %). After replacing the prerequisite pattern %.c with main, make will try to find the prerequisite main.c.
But, that file doesn't exist and make has no idea how to create it. So, that pattern doesn't match and make tries to find a different pattern that will build bin/main.o, but there isn't one, so make says there's no way to build that target.
You need to make your pattern rule:
$(OBJ_PATH)/%.o: src/%.c
so that when make replaces % in the prerequisite pattern it yields src/main.c, which exists, and this will work.
There are other problems with your makefile; for example this is a bad idea:
$(OBJ_PATH)/target.exe: $(OBJ_PATH) $(OBJS)
You never(*) want to use a directory like $(OBJ_PATH) as a simple prerequisite.
Also, this:
OBJS := $(addprefix $(OBJ_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
can be more easily written:
OBJS := $(patsubst src/%.c,$(OBJ_PATH)/%.o,$(SRC))
(*) There can indeed be very specific situations where having a directory as a prerequisite can be useful but they are rare and you shouldn't do it unless you fully understand why it's usually not what you want.
I have a Makefile that looks like this:
CC=cc
CFLAGS=-g -std=c99 -Wfatal-errors
OBJS=$(wildcard *.o)
all: main.o cmdargs.o io.o
$(CC) -o app $(OBJS)
main.o: main.c
$(CC) -c main.c $(CFLAGS)
cmdargs.o: cmdargs.c
$(CC) -c cmdargs.c $(CFLAGS)
io.o: io.c
$(CC) -c io.c $(CFLAGS)
clean:
#rm -rf app $(OBJS)
Whenever I run make all after a clean, there's an error saying
cc -o
undefined reference to `main'
But when I run it a second time everything works as expected. What is wrong with the script, and how can we fix it?
The previous respondents gave good answers but not complete. So let me post one too.
First of all, it is a bad idea to use wildcard in makefiles. It is much better to not be lazy and list your files explicitly.
If you must be lazy, the way to use wildcard is, as shawncorey writes, to use it for sources.
Also, do not have a recipe for phony targets such as all. In your example, the recipe for all will always run, which is inefficient.
CC := gcc
SRCS := $(wildcard *.c)
OBJS := $(SRCS:c=o)
.PHONY: all clean
all: app
app: $(OBJS) Makefile
$(CC) -o $# $(OBJS)
$(OBJS): %.o: %.c Makefile
$(CC) -c $< $(CFLAGS)
clean:
#rm -rf app $(OBJS)
You can automatically create the names of the objects files if you're careful about including all the source files.
# --------------------------------------
# list all source files
CPP_SOURCES := $(wildcard *.cpp)
C_SOURCES := $(wildcard *.c)
# other source files here
# consolidate all sources
SOURCES := $(CPP_SOURCES) $(C_SOURCES)
# --------------------------------------
# list all object files
CPP_OBJECTS := $(CPP_SOURCES:.cpp=.o)
C_OBJECTS := $(C_SOURCES:.c=.o)
# other object files here
# consolidate all objects
OBJECTS := $(CPP_OBJECTS) $(C_OBJECTS)
all:
echo $(SOURCES)
echo $(OBJECTS)
PS: A more compact makefile:
# list all source files
SOURCES := $(wildcard *.cpp) $(wildcard *.c)
# determine all object files
OBJECTS := $(addsuffix .o, $(basename $(notdir $(SOURCES))))
all:
echo $(SOURCES)
echo $(OBJECTS)
The statement
OBJS=$(wildcard *.o)
collects all the *.o files currently in the file system, but it doesn't know about any object files that might be created in the future.
When you run make for the first time, there are no .o files around, so the variable OBJS will be an empty string and the final linking command does not get passed into the command that would tell it which object files to use. But all the other compilation steps are run nevertheless. Upon the second invocation make will skip the compilation phases, because the object files are already there, but because linking failed and the final binary is missing, it will run that step, which will now produce something, because there have been files to collect by the wildcard.
Lesson learned: Don't use file system wildcards in Makefile, it's just causing trouble. Instead learn about implicit rules if you want to save yourself from work.
I have a question to this expression:
%.out: %.cpp Makefile
g++ $< -o $# -std=c++0x
What does it mean? I know, that it is defined target for *.o files but what does it mean %.cpp Makefile and $< and $#?
And:
What is differenece between:
all: $(patsubst %.cpp, %.o, $(wildcard *.cpp))
and:
all:
$(patsubst %.cpp, %.o, $(wildcard *.cpp))
The second doesn't works.
For the first part of your question:
%.out: %.cpp Makefile
g++ $< -o $# -std=c++0x
This is a pattern rule, and means: "for all files with a .cpp extension, compile (if needed) a corresponding .out file using the command g++ $< -o $# -std=c++0x
In this line, $< is the prerequisite (the .cpp file) , $# is the name of the target (the .out file). See here.
The rule also adds the makefile itself as a prerequisite, which means that all the files will be rebuild (even if they are already compiled) when you issue a make target command, if you make changes to the makefile.
For the second part of the question, your are mixing two things. A make rule is made of three parts:
target: dependencies
commands
The second one you show cannot work because there is no command. The line just produces a bunch of filenames, that your shell cannot understand.
The first one adds to the list of dependencies all the object files, whose names are deduced from all the .ccp files. But you are missing a command, so nothing should happen (unless you didn't give us the whole rule ?)
Edit: ouch, missed something, this rule actually should work fine, as make will evaluate all the prerequisite targets, thus call the pattern rule described above. I got confused by the fact that this structure is usually written like this:
targetname: $(OUTFILES)
#echo "- Done target $#"
with the variable defined above as:
OUTFILES = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
or even as:
INFILES = $(wildcard *.cpp)
OUTFILES = $(patsubst %.cpp, %.o, $(INFILES))
I suggest you find a good make tutorial, or read the manual, you seem to have lots of concepts to learn...
I have the following rule:
EXECS = $(sort $(patsubst %.cpp,%$(EXESUFFIX), $(patsubst %.c,%$(EXESUFFIX), $(filter-out $(IGNORESRCS), $(EXECSRCS)))))
SRCS = $(sort $(filter-out $(EXECSRCS), $(filter-out $(IGNORESRCS), $(wildcard *.c) $(wildcard *.cpp) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.cpp) $(wildcard $(DIR)/*.c) ) )))
#OBJS = $(addprefix $(OBJDIR), $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS))))
OBJS = $(patsubst %.cpp,%$(OBJSUFFIX), $(patsubst %.c,%$(OBJSUFFIX), $(SRCS)))
RESOURCE_SRCS= $(sort $(filter-out $(IGNORESRCS), $(wildcard *.rc) $(foreach DIR,$(SUBDIRS),$(wildcard $(DIR)/*.rc) ) ))
RESOURCES = $(patsubst %.rc,%$(OBJSUFFIX), $(RESOURCE_SRCS))
%$(EXESUFFIX) : %.cpp $(LIBS) $(RESOURCES)
$(CXX) $(DEFINES) $(CFLAGS) $(INCLUDES) $(LIBPATH) -o $(BINDIR)/$* $< $(RESOURCES) $(LIBINCLUDES)
The problem is that $(RESOURCES) doesnt exist for all platforms. The %$(EXESUFFIX) : %.cpp rule doesnt run, instead it tries to run g++ exec.cpp -o exec which as far as I can tell isnt a rule that I declared anywhere.
How do I get the rule to still build despite the fact that it is empty (and build the resources if it is not empty)?
If the variable is empty it has no effect on the rule. It should just work as written. What is the actual error you're seeing?
ETA:
Your question is very unclear in what, exactly, you mean by $(RESOURCES) doesn't exist. My answer was assuming you meant that the variable was empty. But given your comment below about how the makefile behaves, I now suspect what you mean is that the variable is still set to a list of files, but that those files are not present.
Because they're not there, and make doesn't know how to build them, make decides that this pattern rule cannot be used at all and it chooses a different rule.
If you want these files to only have any impact if they exist, then you can use the $(wildcard ...) function to expand only to those files that exist:
%$(EXESUFFIX) : %.cpp $(LIBS) $(wildcard $(RESOURCES))
$(CXX) ...
One critical point here: the contents of $(RESOURCES) MUST be source files. They cannot be derived files (files that are supposed to be created by make). If they are derived, the situation is far more complex.