Makefile: computed variable name - makefile

In the following example Makefile:
EXTENS := .c .C .cc .c++ .cpp .cxx
SOURCES := 1.c 2.C 3.cc 4.c++ 5.cpp 6.cxx
OBJECTS := $(SOURCES)
REPLACE_EXTENS = $(foreach f,$(EXTENS),$(eval $(1) := $(patsubst %$(f),%.o,$($(1)))))
$(call REPLACE_EXTENS, OBJECTS)
all:
#echo $(SOURCES)
#echo $(OBJECTS)
I expect the line #echo $(OBJECTS) to output:
1.o 2.o 3.o 4.o 5.o 6.o
However it outputs nothing. What I am doing wrong and what would be the correct way to do it?

Change $(call REPLACE_EXTENS, OBJECTS) into $(call REPLACE_EXTENS,OBJECTS). No whitespace between arguments for call.

The right way to to do this is to throw out the EXTENS and REPLACE_EXTENS call completely, and write:
SOURCES := 1.c 2.C 3.cc 4.c++ 5.cpp 6.cxx
OBJECTS := $(addsuffix .o,$(basename $(SOURCES))
all:
#echo $(SOURCES)
#echo $(OBJECTS)

Related

GNU Make correct behaviour when including other makefiles

I have the following makefile in the root of the project:
Makefile
# Board version
# Available: 3
PI ?= 3
# Kernel binaries
ifeq ($(PI), 3)
KERNEL_IMG := kernel8.img
else ifeq ($(PI), 2)
KERNEL_IMG := kernel7.img
else ifeq ($(PI), 1)
KERNEL_IMG := kernel.img
else
$(error Unsupported Raspberry Pi version)
endif
KERNEL_ELF := $(patsubst %.img,%.elf,$(KERNEL_IMG))
# Directories/paths
BUILD_DIR := build
# Toolchain
TOOLCHAIN ?= aarch64-elf
OBJCOPY := $(TOOLCHAIN)-objcopy
LD := $(TOOLCHAIN)-ld
CC := $(TOOLCHAIN)-gcc
# Misc
LINKER_SCRIPT := linker.ld
# Flags
LDFLAGS := -T $(LINKER_SCRIPT)
ASFLAGS :=
CFLAGS :=
# Source files
C_SRC := $(wildcard *.c)
ASM_SRC := $(wildcard *.S)
# Include
include pi/$(PI)/mod.mk
# Object files
OBJECTS := $(patsubst %,$(BUILD_DIR)/%.o,$(C_SRC))
OBJECTS += $(patsubst %,$(BUILD_DIR)/%.o,$(ASM_SRC))
# Targets
.PHONY: all builddirs clean
all: $(BUILD_DIR)/$(KERNEL_IMG)
$(BUILD_DIR)/$(KERNEL_IMG): $(BUILD_DIR)/$(KERNEL_ELF)
$(OBJCOPY) $< -O binary $#
$(BUILD_DIR)/$(KERNEL_ELF): $(LINKER_SCRIPT) $(OBJECTS)
$(LD) $(OBJECTS) $(LDFLAGS) -o $#
$(OBJECTS): | builddirs
builddirs: $(BUILD_DIR)/pi/$(PI)
$(BUILD_DIR)/pi/$(PI):
mkdir -p $#
$(BUILD_DIR)/%.S.o: %.S
$(CC) -c $< $(ASFLAGS) -o $#
$(BUILD_DIR)/%.c.o: %.c
$(CC) -c $< $(CFLAGS) -o $#
clean:
$(RM) -r $(BUILD_DIR)
It includes pi/3/mod.mk
C_SRC +=
ASM_SRC += pi/3/start.S
$(BUILD_DIR)/pi/3/start.S.o: pi/3/start.S pi/3/include/cpu/sysregs.h
$(CC) -c $< $(ASFLAGS) -o $#
Now here's the problem: whenever I run 'make' in the root of a project, '$(BUILD_DIR)/pi/3/start.S.o' rule invokes, instead of 'all'. If I move 'include pi/$(PI)/mod.mk' to the very bottom of the root makefile, and replace 'C_SRC' and 'ASM_SRC' variables in 'pi/3/mod.mk' with 'OBJECTS += $(BUILD_DIR)/pi/3/start.S.o' and invoke 'make', this rule isn't even invoked, so I get an error that make doesn't know how to build start.S.o.
What am I doing wrong and what is the best way to handle this?
Make's default goal is the first target in your Makefile. In your case the first target is the one defined in the included Makefile: $(BUILD_DIR)/pi/3/start.S.o. Either invoke make all or move the all rule in your Makefile such that it becomes the first one, or tell make that the default goal is all:
.DEFAULT_GOAL := all
(see GNU make manual).

Need help in my makefile to compile a source code

I have 2 folders with their subfolders 04-Software Components / 03-Specific_sources and 08-Ext_Proj / SWC_ADC, SWC_PWM / 03-SRC
There are some .c and .h files in 03-Specific_sources and there is one .c file and their .h
files in both SWC_ADC / 03-SRC (which is ADC.c) and
SWC_PWM / 03-SRC (which is PWM.c)
And I want to compile them and link them all to get the output file.
so what I did is this:
EXEDIR_RELEASE := ../01-EXE\02-Release
OBJDIR_RELEASE := ../05-Obj\02-Release
SRCDIR := ../../../03-Specific_sources (This is the path from my make folder)
EXT_DIR := ../../08-Ext_Proj (This is the path from my make folder)
FIND_SRCS := $(wildcard $(EXT_DIR)/SWC_*/03-SRC/*.c)
INCLUDES := -I $(SRCDIR) $(foreach ext, $(wildcard $(EXT_DIR)/SWC*), -I $(ext)/03-SRC)
CSRCS := $(wildcard $(SRCDIR)/*.c) $(FIND_SRCS)
CSRCS := $(notdir $(CSRCS))
CROBJS := $(patsubst %.c, %.r34, $(CSRCS))
CROBJS := $(addprefix $(OBJDIR_RELEASE)/, $(CROBJS))
.PHONY: all
all: $(EXEDIR_RELEASE)/$(TARGET_RELEASE)
# Compiling
$(OBJDIR_RELEASE)/%.r34: $(FIND_SRCS)
#echo '$^ $#'
$(CC) $(CFLAGS) $(INCLUDES) -o $# $<
# Linking
$(EXEDIR_RELEASE)/Target.mot: $(CROBJS)
$(LD) $(MFLAGS) # These are the linker and its flags
The problem is that the compilation is not working. So when I do the echo I get this:
ADC_prg.c PWM_prg.c DDF_prg.r34
ADC_prg.c PWM_prg.c DFAN_prg.r34
ADC_prg.c PWM_prg.c DFN_prg.r34
ADC_prg.c PWM_prg.c DIO_prg.r34
ADC_prg.c PWM_prg.c DMIO_prg.r34
So I think that the mathing pattern %.r34 is not working and when I use
($(OBJDIR_RELEASE)/%.r34: $(FIND_SRCS)/%.c) it also not working because I can't use %
with a variable that has wildcard function performed on it.
I also used the foreach function but with no use.
So please I need your help guys, I have a delivery today... please respond asap.
Thanks in advance
SAM
This makefile has a lot of problems. Notably:
$(OBJDIR_RELEASE)/%.r34: $(FIND_SRCS)
#echo '$^ $#'
$(CC) $(CFLAGS) $(INCLUDES) -o $# $<
This pattern rule has no wildcard ("%") in the prerequisite list. Any r34 target depends on all sources in $(FIND_SRCS). If that isn't bad enough, look at where these variables come from:
SRCDIR := ../../../03-Specific_sources (This is the path from my make folder)
EXT_DIR := ../../08-Ext_Proj (This is the path from my make folder)
FIND_SRCS := $(wildcard $(EXT_DIR)/SWC_*/03-SRC/*.c)
...
CSRCS := $(wildcard $(SRCDIR)/*.c) $(FIND_SRCS)
CSRCS := $(notdir $(CSRCS))
CROBJS := $(patsubst %.c, %.r34, $(CSRCS))
CROBJS := $(addprefix $(OBJDIR_RELEASE)/, $(CROBJS))
In other words, you seem to expect that for every source file in one directory there will be a file of the same name in the other directory. According to your echo statements, there are no such matches.
There are other problems, but this is a good place to start. Try this:
CSRCS := $(wildcard $(SRCDIR)/*.c) $(EXT_DIR)/SWC_ADC/03-SRC/ADC.c $(EXT_DIR)/SWC_PWM/03-SRC/PWM.c
CSRCS := $(notdir $(CSRCS))
CROBJS := $(patsubst %.c, $(OBJDIR_RELEASE)/%.r34, $(CSRCS))
vpath %.c $(SRCDIR) $(EXT_DIR)/SWC_ADC/03-SRC $(EXT_DIR)/SWC_PWM/03-SRC
$(OBJDIR_RELEASE)/%.r34: %.c
$(CC) $(CFLAGS) $(INCLUDES) -o $# $<
Go down the list of object files you want to build, and try building each one:
make DDF_prg.r34
make DFAN_prg.r34
...
If that works, try linking them by hand, and if that works, take a look at the linking rule -- which looks completely wrong but which I can't really diagnose because I don't know what linker you're using.

Outputting obj files to obj directory in Makefile

Hi I wrote this Makefile by modifying this example: https://sites.google.com/site/michaelsafyan/software-engineering/how-to-write-a-makefile
program_NAME := bin/myprogram
SRC_DIR := src
#
#srces
#
program_C_SRCS := $(wildcard $(SRC_DIR)/*.c)
program_CXX_SRCS := $(wildcard $(SRC_DIR)/*.cpp)
#
#obj files
#
program_C_OBJS := ${program_C_SRCS:.c=.o}
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_C_OBJS) $(program_CXX_OBJS)
#
# include and library dirs; also libraries
#
program_INCLUDE_DIRS := inc
program_LIBRARY_DIRS :=
program_LIBRARIES :=
# flags
CPPFLAGS += $(foreach includedir,$(program_INCLUDE_DIRS),-I$(includedir))
LDFLAGS += $(foreach librarydir,$(program_LIBRARY_DIRS),-L$(librarydir))
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))
#
# targets
#
.PHONY: all clean distclean
all: $(program_NAME)
$(program_NAME): $(program_OBJS)
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
clean:
#- $(RM) $(program_NAME)
#- $(RM) $(program_OBJS)
distclean: clean
It works in the following way. The classes below are compiled into an executable "myprogram" which is output in the bin directory. The only issue is the object files are created inside the src folder, instead of the obj folder. How can I modify this makefile such that obj files are created in the obj folder? Thank you.
/project
Makefile
/src
Class1.cpp
Class2.cpp
main.cpp
/obj
/bin
myProgram
/inc
Class1.h
Class2.h
To start with, you could use e.g. the subst function to replace the source-file directory with the object-file directory:
program_OBJS = $(subst $(SRC_DIR),$(OBJ_DIR),$(program_C_OBJS))
program_OBJS += $(subst $(SRC_DIR),$(OBJ_DIR),$(program_CXX_OBJS))
Of course you now need to add a target for object-file creation, as these will not be put in the correct place otherwise:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c -o $# $<
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
Try with something like:
OUT_DIR=obj
program_bare_OBJS := $(program_C_OBJS) $(program_CXX_OBJS)
program_OBJS=$(addprefix $(OUT_DIR)/,$(program_bare_OBJS))

Having makefile related nightmare

If I try make all, I get:
make: ***No rule to make target 'src\SOURCES', needed by 'all'. Stop.
If I try make qwark, I get:
make: ***No rule to make target 'obj\src\SOURCES' needed by 'qwark'. Stop.
If I try make qwark.o, I get
Fatal error: can't create obj\qwark.o: No such file or directory
make: *** [qwark.o] Error 1
Here's my source code, for your viewing pleasure...
COMPILER := g++
CFLAGS :=
LDFLAGS :=
SOURCES := quark.cc
SOURCES := $(addprefix src\,SOURCES)
OBJECTS := $(addprefix obj\,$($(notdir SOURCES):.cc=.o))
EXECUTABLE := qwark.exe
DEBUG := bin\debug\$(EXECUTABLE)
NORMAL := bin\release\$(EXECUTABLE)
all: $(SOURCES) $(EXECUTABLE)
release: qwark
normal: qwark
qwark: $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
qwark.o: src\qwark.cc
$(CC) $(CFLAGS) -c src\qwark.cc -o obj\qwark.o
%.o: src\%.cc
$(CC) $(CFLAGS) -c $(input) -o obj\$(output)
Please, someone, tell me what it is I'm doing wrong..........
You're modifying a literal SOURCES word, instead of the corresponding variable value. Try the following:
SOURCES := quark.cc
SOURCES := $(addprefix src\,$(SOURCES))
OBJECTS := $(addprefix obj\,$(patsubst %.cc,%.o,$(notdir $(SOURCES))))
Or, much simpler:
SOURCES := quark.cc
OBJECTS := $(SOURCES:%.cc=obj\%.o)
SOURCES := $(SOURCES:%=src\%)
Expand the SOURCES variable when its on the rhs?
SOURCES := $(addprefix src\,$(SOURCES))
OBJECTS := $(addprefix obj\,$($(notdir $(SOURCES)):.cc=.o))

patsubst on makefile

I have to create different *.o files from a same set of *.c using various CFLAGS. I wanted to use patsubst to generate different *.o files from same *.c. I am doing something wrong the following statement, please help (I want to generate one set of object files having ($<)_O0.o and the other ($<)_O2.o from the same set of c source files):
$(CC) $(CFLAGS_02) -c $< -o $(patsubst %.c,%_O2.o,$<)
Thanks
Use patsubst to make lists of the objects that you want to build, and then use separate rules for each type of build.
Something like this:
SRC_FILES = source1.c source2.c
OBJ_FILES_O0 = $(patsubst %.c,%_O0.o,$(SRC_FILES))
OBJ_FILES_O2 = $(patsubst %.c,%_O2.o,$(SRC_FILES))
CFLAGS_O0 := -O0
CFLAGS_O2 := -O2
all: $(OBJ_FILES_O0) $(OBJ_FILES_O2)
$(OBJ_FILES_O0): %_O0.o: %.c
$(CC) $(CFLAGS_O0) -c $< -o $#
$(OBJ_FILES_O2): %_O2.o: %.c
$(CC) $(CFLAGS_O2) -c $< -o $#
You can also use wild cards to specify all files in the directory.
eg:
#Generic Makefile.
CC := g++
LD := g++
CFLAGS := -c
LDFLAGS := -L<path to lib> -l<libname> \
-L<path to lib> -l>libname> \
......................
ifeq (${TARGETARCH}, debug)
CFLAGS += -g -O0
elif
CFLAGS += -O4 -DNDEBUG
SRCFILES := $(wildcard *.cpp)
OBJFILES := $(patsubst %.cpp, %.o, ${SRCFILES})
all: main
main: ${OBJFILES}
#echo "[Linking]"$#
${LD} ${LDFLAGS} ${OBJFILES}
%.o: %.cpp
#echo "[Compiling]"$#
${CC} ${CFLAGS} $^ -o $#

Resources