I have makefile that compiles all *.c files in subfolder:
objects := $(patsubst %.c,%.o,$(wildcard *.c))
cobj: $(objects)
$(objects): %.o: %.c
$(CC) -c $< -o $#
I am having trouble trying to do the same from parent folder. Lets say my .c files are in the folder 'csrc'
objects := $(addprefix, csrc/, $(patsubst %.c,%.o,$(wildcard *.c)))
cobj: $(objects)
$(objects): csrc/%.o: %.c
$(CC) -c $< -o $#
i always see "nothing to do for cobj... Any ideas?
Your pattern rule csrc/%.o: %.c translates e.g. csrc/foo.o into foo.c, not csrc/foo.c. Presumably, that is not what you want.
Why not just %.o: %.c?
What Oli Charlesworth said is correct, but there's another mistake. The wildcard function only checks the current directory. As it is now, $(objects) will be empty (I assume there are no source files in the current, parent directory). You will have to specify the path: $(wildcard csrc/*.c)
Related
This question already has answers here:
'make' does not recompile when source file has been edited
(3 answers)
Closed 4 years ago.
I have two .c files and one .h file which is included in both .c files.
I have make file :
CC=gcc
CFLAGS=-I.
OBJ = hellofunc.o hellomake.o
DEPS := $(OBJ:.o=.d)
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -MM -MT $# -MF $(patsubst %.o,%.d,$#) $<
$(CC) -c -o $# $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
$(CC) -o $# $^
I modified hellomake.h header file and then ran above make file. It is compiling only the first file which is assigned to DEPS variable, Which is hellofunc.c
FYI, When i change the order of DEPS variable it is compiling hellomake.o , Seems like make is only picking first file assigned to DEPS variable.
Is there anything wrong in my makefile.. Please help.
As #tripleee noted in the comments, make will by default build the first target it encounters. Since the include files are included directly, as if they were cut-and-pasted in place, the first target in the first .d file (which I'm guessing you'll find to be hellofunc.c) is the first target that make encounters, so that's what make aims to build.
If you move the include line to the end of the file, then the first target in the file will be hellomake, and so that's the target make will attempt to build by default.
Meta remark: if you can, I'd say it's better to avoid this pattern of depending on .d files, and instead aim to express sufficiently many of the dependencies ‘by hand’ directly in the makefile. Doing it this .d way does work (ie, I'm not saying what you're doing is wrong) and appears to be labour-saving, but in my experience it tends to be a little brittle, partly because if you don't have the .d files to hand then you suddenly have zero dependencies. In order to have the .d files to hand, you'll have to check them in to your code repository (you are using a repository, aren't you?), but that will mean they'll frequently be trivially out of date, and... it can turn into a bit of a mess.
EDIT: considered MadScientist's comment and blog post about separate recipe for .d files.
You could tell make how to generate the .d files with a separate rule instead of putting this in another recipe (but see the above mentioned blog post for several reasons for not doing so).
And you should probably tell make that your default goal is hellomake:
.DEFAULT_GOAL := hellomake
CC=gcc
CFLAGS=-I.
OBJ = hellofunc.o hellomake.o
DEPS := $(OBJ:.o=.d)
-include $(DEPS)
%.d: %.c
$(CC) $(CFLAGS) -MM -MT $# -MF $# $<
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
$(CC) -o $# $^
And it would probably be even better if you were letting make find the source files and deduce the rest:
.DEFAULT_GOAL := hellomake
CC := gcc
CFLAGS := -I.
SRCS := $(wildcard *.c)
OBJS := $(patsubst %.c,%.o,$(SRC))
DEPS := $(patsubst %.c,%.d,$(SRC))
-include $(DEPS)
%.d: %.c
$(CC) $(CFLAGS) -MM -MT $# -MF $# $<
%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJS)
$(CC) -o $# $^
Finally, following MadScientist's advices, a better, more efficient, less prone to failures solution could be:
.DEFAULT_GOAL := hellomake
CC := gcc
CFLAGS := -I.
SRCS := $(wildcard *.c)
OBJS := $(patsubst %.c,%.o,$(SRC))
DEPS := $(wildcard $(patsubst %.c,%.d,$(SRC)))
include $(DEPS)
%.o: %.c %.d
$(CC) -MT $# -MMD -MP -MF $*.Td $(CFLAGS) -c -o $# $<
mv -f $*.Td $*.d && touch $#
hellomake: $(OBJS)
$(CC) -o $# $^
%.d: ;
.PRECIOUS: %.d
I have a recipe in my makefile that relies on several object files. I would like it to simply link the them, but they are always recompiling.
I've googled around and found information I did not know(marked with #) and changed it a bit, but the problem persisted.
I am led to believe make expects the name of the recipe be the name of the file, and I am failing to accomplish that. The problem is I do not what else to try and fix this. I would appreciate any help
CC = g++
#.PHONY: sfml-app
LIBS = -lsfml-graphics -lsfml-window -lsfml-system
APPLICATION = sfml-app
INCLUDE_DIR = -I include/
SOURCE_DIR = source
OUTPUT_DIR = bin
SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
OBJECTS = $(notdir $(patsubst %.cpp, %.o, $(SOURCES)))
#$(OUTPUT_DIR)/$(APPLICATION): $(OBJECTS)
#bin/sfml-app: $(OBJECTS)
#sfml-app: $(OBJECTS)
#$(APPLICATION): $(OBJECTS)
$(CC) $(OUTPUT_DIR)/*.o $(LIBS) -o $(OUTPUT_DIR)/$(APPLICATION)
%.o: $(SOURCE_DIR)/%.cpp
$(CC) -c $< $(INCLUDE_DIR) -o $(OUTPUT_DIR)/$#
clean:
rm $(OUTPUT_DIR)/*
print-% : ; #echo $* = $($*)
This rule doesn't create the file it promises to:
%.o: $(SOURCE_DIR)/%.cpp
$(CC) -c $< $(INCLUDE_DIR) -o $(OUTPUT_DIR)/$#
See that -o $(OUTPUT_DIR)/$#? That's instructing the compiler to create a file in $(OUTPUT_DIR) instead of in the working directory.
If you really want your object files to go in $(OUTPUT_DIR), you need to make sure that your rule indicates that:
$(OUTPUT_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(CC) -c $< $(INCLUDE_DIR) -o $#
Or better, to act like the standard %.o: %.c rule (which will include CFLAGS etc):
$(OUTPUT_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(COMPILE.c) $(OUTPUT_OPTION) $<
I note your input files are named *.cpp - usually, that convention is for C++ files (i.e. to be compiled with $(COMPILE.cc), which will invoke $(CXX) rather than $(CC)). Check that you've not mixed up your C and C++ sources!
``I am pretty new to Makefile and I am trying to build a project.
This is the structure of my project:
-Project
|-generic
| |-include
| |-src
|-specific
| |-include
| |-src
|-Makefile
|-bin
Here generic contains mainly interface classes (virtual), and files in specific may depends on those.
I want to compile all sources and put their corresponding .o files in bin and also create a static library in bin.
EDIT:
CC=k1-g++
CPPFLAGS=-c -I$(GENERIC_INCLUDE_DIR) -I$(SPECIFIC_INCLUDE_DIR) -Os -std=gnu++11 -mos=nodeos
CXXFLAGS=-c -I$(GENERIC_INCLUDE_DIR) -I$(SPECIFIC_INCLUDE_DIR) -Os -std=gnu++11 -mos=nodeos
LFLAGS=-pthread -lnodeos
GENERIC_INCLUDE_DIR=generic/include
SPECIFIC_INCLUDE_DIR=specific/include
GENERIC_SRC_DIR=generic/src
SPECIFIC_SRC_DIR=specific/src
LIB = libengine.a
BIN_DIR=bin
vpath %.cpp $(GENERIC_SRC_DIR) $(SPECIFIC_SRC_DIR)
SOURCES := $(wildcard $(GENERIC_SRC_DIR)/*.cpp $(SPECIFIC_SRC_DIR)/*.cpp)
#SOURCES := $(wildcard $(GENERIC_SRC_DIR)/*.cpp $(SPECIFIC_SRC_DIR)/*.cpp)
SOURCES := $(notdir $(SOURCES))
OBJECTS := $(patsubst %.cpp,$(BIN_DIR)/%.cpp.o,$(SOURCES))
all: $(OBJECTS) $(LIB)
$(LIB): $(OBJECTS)
ar -cvq $(BIN_DIR)/$# $^
#$(BIN_DIR)/%.cpp.o: $(GENERIC_SRC_DIR)/%.cpp
# $(CC) $(CPPFLAGS) $< $(LFLAGS) -o $#
$(BIN_DIR)/%.cpp.o: %.cpp
$(CC) $(CPPFLAGS) $< $(LFLAGS) -o $#
.PHONY: clean
clean:
rm -f $(BIN_DIR)/*
Any help would be appreciated
Suppose you have generic/src/foo.cpp and specific.src/bar.cpp.
This:
$(BIN_DIR)/%.o: %.cpp
$(CC) $(CPPFLAGS) $*.cpp -o $#
is pretty close to what you need (I've replaced $(BIN_DIR)/$*.o with the automatic variable $#, which expands to the name of the target); the only problem is that it doesn't work. This rule tells Make it can build obj/foo.o from foo.cpp, but there is no foo.cpp. There's a generic/src/foo.cpp, but Make doesn't know that that's what you meant. We could write a rule like this:
$(BIN_DIR)/%.o: $(GENERIC_SRC_DIR)/%.cpp
$(CC) $(CPPFLAGS) $*.cpp -o $#
But a tidier way is to use the vpath directive:
vpath %.cpp $(GENERIC_SRC_DIR) $(SPECIFIC_SRC_DIR)
$(BIN_DIR)/%.o: %.cpp
$(CC) $(CPPFLAGS) $*.cpp -o $#
This will do nicely for building any one object file, but you say you want to compile "all sources". That isn't always a good idea, but if that's what you want it isn't hard, we use wildcard to obtain a list of all the sources, then convert that into a list of corresponding object files, then build them all:
SOURCES := $(wildcard $(GENERIC_SRC_DIR)/*.cpp $(SPECIFIC_SRC_DIR)/*.cpp)
SOURCES := $(notdir $(SOURCES))
OBJECTS := $(patsubst %.cpp,%.o, $(SOURCES))
# We could have done that all in one line, but this way is easier to read.
all: $(OBJECTS)
Now for the library:
vpath %.o $(BIN_DIR)
$(BIN_DIR)/$(LIB): $(OBJECTS)
ar -cvq $# $^
Further refinements are possible, but that should keep busy for a while.
I have simple makefile here:
SOURCES= $(wildcard *.c)
OBJECTS= $(patsubst %.c, %.o, $(SOURCES))
NAMES= $(patsubst %.c, %, $(SOURCES))
CC=gcc
CFLAGS= -Wall -c -o
TASKS_IN_DIRS= $(addprefix obj/,$(OBJECTS)) $(addprefix bin/,$(NAMES))
all: $(NAMES)
$(NAMES): %: %.o $(OBJECTS)
$(CC) -o bin/$# obj/$^
$(OBJECTS): %.o: %.c
$(CC) $(CFLAGS) obj/$# $<
clean:
rm -rf $(TASKS_IN_DIRS)
Getting all the c files names.
Making from them simple names(without extension) and object names.
Doing things
And what matters - all works, but works every time i print make(compiling and linking all the files). even if i don't changed anything and i do it few times in row, is something wrong with dependencies?
I expected something like "blabla is up to date" instead.
$(OBJECTS): %.o: %.c
$(CC) $(CFLAGS) obj/$# $<
is looking in your current directory for your .o files. Since they're not there it's rebuilding them.
The following does what you want.
SOURCES= $(wildcard *.c)
OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
OBJECTS:= $(addprefix obj/,$(OBJECTS))
NAMES:= $(patsubst %.c, %, $(SOURCES))
NAMES:= $(addprefix bin/,$(NAMES))
CC=gcc
CFLAGS= -Wall -c -o
TASKS_IN_DIRS=$(OBJECTS) $(NAMES)
all: $(NAMES)
$(NAMES): $(OBJECTS)
$(CC) -o $# $<
obj/%.o: %.c
$(CC) $(CFLAGS) $# $<
clean:
rm -rf $(TASKS_IN_DIRS)
You lied to make. You promised that each of the$(NAMES) targets creates its object file in the current directory, but due to $(CC) -o bin/$# obj/$^ it is created in the bin directory.
At the next make invocation, it can't find the object files and runs each command again.
Hard and Fast Rule for Makefiles: each non-PHONY target must use a plain $# somewhere in its commands to indicate the file it creates.
I need to create Makefile that compiles .c files with a lot of subdirs (sources directory goes in around 5 level depth) and I need to place the object files in the mirrored build directory. So far, I have created this Makefile:
CC := gcc.exe
AS := as.exe
CFLAGS = -DCORE_SW_VERSION='"$(CORE_SW_VERSION)"' -Wall -mA6 -c -fmessage-length=0 -Hsdata0
CFLAGS += -fgnu89-inline -mno-volatile-cache $(INCLUDE) -Hon=each_function_in_own_section -Xcrc -std=c99 -O1
CORE_SW_VERSION:=CORE.07.01.04.01.03.01.R
HAL_SW_VERSION:=16.01.06.01.06.00
MODE_CORE := dev
MODE_HAL := dev
OBJDIR := $(shell pwd)/$(TARGET12) #TARGET12 is a make parameter
INCLUDE := $(shell cat ./$(TARGET12)_include.txt)
SOURCEDIR := ../sources
CSRC := $(shell find $(SOURCEDIR) -name '*.c')
EXCLUDES := $(shell cat ./$(TARGET12)_exclude.txt)
OBJ := $(CSRC:.c=.o)
OBJS := $(patsubst ../%.c,$(OBJDIR)/%.o,$(CSRC))
.PHONY: $(TARGET12)
$(TARGET12): $(OBJS)
$(AR) -r $(CORE_SW_VERSION).a $(OBJS)
$(OBJS): $(CSRC)
mkdir -p $(dir $#)
$(CC) $(CFLAGS) $< -o $(patsubst ../%,$(OBJDIR)/%,$#)
If I define rule for $(OBJS) this way, $< is always the first .c file in $(CSRC).
If I define $(OBJS) this way:
$(OBJS): %.o: %.c
mkdir -p $(dir $#)
$(CP) $< $#
I get error that there is no rule to make target for .c file. But I see that make is looking for .c file in build mirrored directory, and it should look at the source dir. Do you maybe know how this could be arranged?
Thanks you in advance!
The rule $(OBJS): %.o: %.c means something like this: when trying to create a .o file, use this rule if the corresponding .c file exists. For example: when make is looking for a way to create $(OBJDIR)/foo.o, it will look for $(OBJDIR)/foo.c.
In your case this file does not exists, so the rule is ignored.
What you want is rather something like this:
$(OBJS): $(OBJDIR)/%.o: $(SOURCEDIR)/%.c
mkdir -p $(dir $#)
$(CP) $< $#
The first rule for $(OBJS) you tried, states that every object file individually depends on all source files. Surely that's not correct.
Your second attempt is better, although the recipe is weird. Fix that and use VPATH to make make find the sources.