Need to make multiple times in order to work - makefile

I've this:
include makefile_vars.mk
# Target
TARGET := $(OBJ)/$(TARGETNAME)
# Move objects to ../Obj
OBJECTS := $(addsuffix .obj,$(SOURCES))
override OBJECTS := $(OBJECTS:$(SRC)/%.obj=$(OBJ)/%.obj)
# Objects o
OBJ_INC_DIRS := $(sort $(dir $(OBJECTS)))
# Target
all: $(TARGET)
$(TARGET): $(OBJECTS)
# Objects
$(OBJ)/%.c.obj: $(SRC)/%.c | $(OBJ_INC_DIRS)
#echo Compiling $(<F) ...
$(OBJ)/%.a66.obj: $(SRC)/%.a66 | $(OBJ_INC_DIRS)
#echo Compiling $(<F) ...
$(OBJ_INC_DIRS):
mkdir -p $#
The first time I launch it, it says me that there is no rule to make the target MyFile.c.obj, when running again (whitout modifying anything) the rule is found and the compilation goes on.
What am I doing wrong?

I'm not sure that this will work, but I would move $(OBJ_INC_DIRS) order-only prerequisite out from the pattern rules:
$(OBJECTS) : | $(OBJ_INC_DIRS)
$(OBJ)/%.c.obj: $(SRC)/%.c
#echo Compiling $(<F) ...
...

Related

Makefile wildcard for makefile variables, to define generic rules

Background, I suspect XY problem
I have simpler C modules in a directory. I want to write unit tests for these in a sub-directory test/. These unit tests are no more than C programs linking to the module under test, one directory above. I want a Makefile that defines several build targets and lets me build and run the test executables in one step, or separately.
My attempted solution
I've attempted the following:
CC = gcc
CFLAGS = -ggdb -Wall -Wextra -Werror -O3 -std=c99
PARAM_LIST_TARGET = parameter_list_test
PARAM_LIST_SOURCE_FILES = \
../parameter_list.c \
parameter_list_test.c
PARAM_LIST_OBJECT_FILES := $(addsuffix .o,$(basename $(PARAM_LIST_SOURCE_FILES)))
TARGETS = $(PARAM_LIST_TARGET)
all: $(TARGETS)
$(%_TARGET): $(%_OBJECT_FILES)
$(CC) $(CFLAGS) $^ -o $#
.c.o:
$(CC) -c $< -o $# $(CFLAGS)
clean:
$(RM) *.o $(TARGETS)
test: all
#for t in $(TARGETS) ; do ./$$t ; done
This doesn't work, and it's because of the $(%_TARGET): row. Not surprising, I didn't expect it to work, but I hope this illustrates what I'm trying to achieve.
I want to create more chunks of the form _TARGET, _SOURCE_FILES, and _OBJECT_FILES, to test other modules besides PARAM_LIST, for example:
PARAM_LIST_TARGET = parameter_list_test
PARAM_LIST_SOURCE_FILES = \
../parameter_list.c \
parameter_list_test.c
PARAM_LIST_OBJECT_FILES := $(addsuffix .o,$(basename $(PARAM_LIST_SOURCE_FILES)))
OTHER_MODULE_TARGET = other_module_test
OTHER_MODULE_SOURCE_FILES = \
../other_module.c \
other_module_test.c
OTHER_MODULE_OBJECT_FILES := $(addsuffix .o,$(basename $(OTHER_MODULE_SOURCE_FILES)))
I understand that % works on filenames, so attempting to use it on variables fails:
$(%_TARGET): $(%_OBJECT_FILES)
$(CC) $(CFLAGS) $^ -o $#
How can I write a rule that matches the Makefile variables _TARGET to their associated _OBJECT_FILES, without creating one per test target?
Or more importantly, how should I do it totally differently?
Edit: I've seen this, however it seems it's only working with a single source file per executable.
You can always access make variables by constructing their names:
MY_VAR := "my var"
HIS_VAR := "his var"
HER_VAR := "her var"
CATS_VAR := "cats var"
DOGS_VAR := "dogs var"
ALL_PERSONS := MY HIS HER CATS DOGS
ALL_VARS := $(foreach p,$(ALL_PERSONS),$($(p)_VAR))
$(info $(ALL_VARS))
Output:
$ make
"my var" "his var" "her var" "cats var" "dogs var"
Defining the dependencies separately seems to work, thanks to this answer:
TARGETS = $(PARAM_LIST_TARGET) $(OTHER_MODULE_TARGET)
all: $(TARGETS)
$(PARAM_LIST_TARGET): $(PARAM_LIST_OBJECT_FILES)
$(OTHER_MODULE_TARGET): $(OTHER_MODULE_OBJECT_FILES)
$(TARGETS):
$(CC) $(CFLAGS) $^ -o $#
This eliminates the need for a duplicate rule (one per target). Still, the definition of dependencies for each target looks like duplicates, a pattern match for these would be nice.
More than that, the OBJECT_FILES variable becomes unnecessary. This works:
PARAM_LIST_TARGET = parameter_list_test
PARAM_LIST_SOURCE_FILES = \
../parameter_list.c \
parameter_list_test.c
$(PARAM_LIST_TARGET): $(addsuffix .o,$(basename $(PARAM_LIST_SOURCE_FILES))) # The dependencies directly
It would still feel nice to have this last row as one rule for all targets. Something like "for all variables ending with TARGET, build a dependency to the content of the variable with the same name, but ending with SOURCE_FILES instead".

compiling *.C and *.S sources from same directory 'make'

I have been working with a project that only compiles C sources but I've found I need some assembler too, I'm reticent to inline the asm code in a C file as GCC may not interpret it correctly.
My predecesor created the makefile for the project (apologies, it's fairly long):
# Compiler and options
CC := sparc-rtems-gcc
# The application software binary
TARGET := icu_asw
# Source and build directories
SRCDIR := src
BUILDDIR := obj
TARGETDIR := bin
HDSWROOT := ../../hdsw
BSWTOOLS := ../../bsw/sw/tools
SRCEXT := c
DEPEXT := d
OBJEXT := o
MRAMEXT := img.elf
# Flags, libraries and includes
CFLAGS := -std=gnu99 -Wall -Wextra -g
LIBDRV := $(HDSWROOT)/lib/libdrv.a
INCFLAGS := -I$(HDSWROOT)/include -I$(HDSWROOT)/osal/rtems
# Debug flags
DEBUGFLAGS = -DLOGERROR=1 -DLOGWARN=1 -DLOGDEBUG=1 -DLOGINFO=1 -DMAKECHECKS=1
NODEBUGFLAGS = -DLOGERROR=1 -DLOGWARN=0 -DLOGDEBUG=0 -DLOGINFO=0 -DMAKECHECKS=1
#-----------------------------------------------------------------------
# Build instructions
#-----------------------------------------------------------------------
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))
# Default make
all: $(TARGET)
# Remake
remake: cleaner all
# Clean only objects
clean:
#$(RM) -rf $(BUILDDIR)
# Full clean (objects and binaries)
cleaner: clean
#$(RM) -rf $(TARGETDIR)
# Pull in dependency info for *existing* .o files
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
# Link (uses an order-only prerequisite for the directories so that they
# don't affect the use of the $^)
$(TARGET): $(OBJECTS) | directories
$(CC) -o $(TARGETDIR)/$(TARGET) $^ $(LIBDRV)
# Make the build and target directories
directories:
#mkdir -p $(TARGETDIR)
#mkdir -p $(BUILDDIR)
# Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(dir $#)
$(CC) $(CFLAGS) $(INCFLAGS) $(NODEBUGFLAGS) -c -o $# $<
#$(CC) $(CFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT)
#cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
#sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
#sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
#rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
# Non-File Targets
.PHONY: all remake clean cleaner
I want to also bring in and compile two .S files, so, I edited the following line
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT) -or -name *.$(ASMEXT))
To bring in the .S files, then I edited the OBJECTS to also include the ASM sources ("*.S")
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)),$(SOURCES:.$(ASMEXT)=.$(OBJEXT)))
But when recompiling with 'make all' I'm getting:
$ make all
make: *** No rule to make target `obj/asi_access.S', needed by `icu_asw'. Stop.
I don't suppose someone could spot where I am going wrong? I think I have not correctly added to the OBJECTS line!
Thanks
The expression $(var:.ext1=.ext2) does not filter by .ext1, i.e.
$(SOURCES:.$(SRCEXT)=.$(OBJEXT)) $(SOURCES:.$(ASMEXT)=.$(OBJEXT))
gives for a test source list the following result
a.o b.o c.S a.c b.c c.o
I.e. you duplicated your files and you have source files in the OBJECTS definition.
The following would be a correct approach:
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%, \
$(patsubst %.$(SRCEXT),%.$(OBJEXT), \
$(patsubst %.$(ASMEXT),%.$(OBJEXT),$(SOURCES)) \
) \
)
UPDATE: you should consider to use 2 separate object lists, so that you can apply different rules for them, e.g.
SOURCES_C := $(filter %.$(SRCEXT),$(SOURCES))
OBJECTS_C := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES_C:%.$(SRCEXT)=%.$(OBJEXT)))
SOURCES_ASM := $(filter %.$(ASMEXT),$(SOURCES))
OBJECTS_ASM := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES_ASM:%.$(ASMEXT)=%.$(OBJEXT)))
$(OBJECTS_C): $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
.... C compiler recipe ....
$(OBJECTS_ASM): $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(ASMEXT)
.... assembler recipe ....
$(TARGET): $(OBJECTS_C) $(OBJECTS_ASM) | directories

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).

Gnu Make target out of expanded list of files

I am grouping some type of files like:
https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html
about 100 sub directories...
CC_FILES_TO_BUILD += $(wildcard $(SRC_DIR)/01-Application/*.c)
ASM_FILES_TO_BUILD += $(wildcard $(PROJECT_ROOT)/01-Sources/07-Target/01-MC9S12G/04-STARTUP/01-CPL_LIB/*.s)
When I dump for example CC_FILES_TO_BUILD per rule, I get nice lists of files names:
E:\1983_1\02-Safety>make dump-CC_FILES_TO_BUILD
make[1]: Entering directory `E:/1983_1/02-Safety/01-Application'
E:\1983_1\02-Safety\01-Application/01-Sources//01-Application/01-INIT/app_init.c E:\1983_1\02-Safety\01-Application/01-Sources//01-Applicat
ion/02-MAIN/app.c E:\1983_1\02-Safety\01-Application/01-Sources//01-Application/03-FM/fm.c E:\1983_1\02-Safety\01-Application/01-Sources//01
-Application/05-SMCM/SMCM.c E:\1983_1\02-Safety\01-Application/01-Sources//01-Application/06-LIM/LIM.c E:\1983_1\02-Safety\01-Application/0
1-Sources//02-Services/01-CanM/can_user.c E:\1983_1\02-Safety\01-Application/01-Sources//02-Services/01-CanM/v_par.c E:\1983_1\02-Safety\01-
Application/01-Sources//02-Services/01-CanM/vstdlib.c E:\1983_1\02-Safety\01-Application/01-Sources//02-Services/01-CanM/sip_vers.c ...
......make[1]: Leaving directory `E:/1983_1/02-Safety/01-Application'
I then build new lists out these by normal subst to get the corresponding lists of depend and obj files, like:
CC_TO_MAK_BUILD_LIST = $(call unique, $(foreach src,$(CC_FILES_TO_BUILD ),
$(DEP_PATH)\$(basename $(notdir$(subst,\,/,$(SRC)))).$(MAK_FILE_SUFFIX)))
I then want to use these depend and obj lists as targets in rules like:
$(filter-out $(GCC_IGNORE_LIST), $(CC_TO_MAK_BUILD_LIST)) :$(DEP_OUTPUT_PATH)\\%.$(MAK_FILE_SUFFIX):$(DEPEND_FORCE) | $(DEPEND_CPP_OPTIONS_FILE) $(DIRECTORIES_TO_CREATE)
$(SEPARATOR) [depend] $(notdir $#)
$(CPP) #$(DEPEND_CPP_OPTIONS_FILE) -undef -MM -MF "$#" -MT "$(call depend_get_target,$#)" -MT "$#" "$(getSourceFile)"
Then the target depend:
depend: $(LIB_TO_MAK_BUILD_LIST) $(CC_TO_MAK_BUILD_LIST) | $(DEPEND_CPP_OPTIONS_FILE) $(DIRECTORIES_TO_CREATE)
and the output:
E:\1983_1\02-Safety\01-Application>make depend
* [build] depend.cpp_options
E:\1983_1\02-Safety\01-Application>
apparently nothing to be done although the dependcies files(*.mak) are not there. No force or phony could solve it for me.

Make Target Name From Another

Have problem in dynamically "create" target name with .SECONDEXPANSION:
Small Makefile to reproduce problem:
CONFIGS = test1 test2 test3
.SECONDEXPANSION:
all: $(CONFIGS)
OBJECTS=$$(CFG_NAME)_OBJECTS
$(CONFIGS) : CFG_NAME=$#
$(CONFIGS) : $(OBJECTS)
#echo $(CFG_NAME) $# from $^
$(OBJECTS):
#echo OBJECTS $# from $^
#echo DO IT
It says: "No rule to make target 'test1_OBJECTS'.
How can I solve this problem?
EDIT: CHANGE OF THE ANSWER
Thank you much for the answer. It was the simple variant for my task.
So I try to answer in another way.
CONFIGS = test1 test2 test3
PLATFORMS = x86 ppc arm
#will be test1x86 test2x86 ... test1ppc ... test3arm,
#so it is long way to enumarate all variants
VARIANTS = $(foreach c, $(CONFIGS), $(foreach p, $(PLATFORMS), $(c)$(p)))
#C FILE LIST
CFILES:=$(shell /bin/find -name "*.c")
.SECONDEXPANSION:
all: $(VARIANTS)
#More Comlex Rule
#Want to corresponding objects be in bins/test1x86/
OBJECTS:=$(CFILES:%.c=bins/$$(CFGNAME)%.o)
$(CONFIGS) : CFG_NAME=$#
$(CONFIGS) : $(OBJECTS)
#echo $(CFG_NAME) $# from $^
#More complex prerequisites
#I understand that $$(CFGNAME) will be resolve incorrect.
#For each *.c file in subdir I would have object in corresponding path.
#For example, '1/2/3/test.c' will use for generate
#object file 'bins/test1x86/1/2/3/test.o',
#when I call 'make testx86' or 'make all' (it will build all VARIANTS),
#in 'bins/test1x86/1/2/3/'.
#So what have I do?
$(OBJECTS): bins/$$(CFGNAME)_OBJECTS/%o : %.c
#echo OBJECTS $# from $^
#echo DO IT
So, I would like to avoid recursive make calls. Can you help me?
Thank you.
You have a rule for $(OBJECTS), but that target expands to $(CFG_NAME)_OBJECTS, which is not expanded again (ever), so it can't match anything. Try this instead:
test1_OBJECTS test2_OBJECTS test3_OBJECTS:
#echo OBJECTS $# from $^
#echo DO IT
Or better:
OBJECT_SETS = $(addsuffix _OBJECTS, $(CONFIGS))
$(OBJECT_SETS):
#echo OBJECTS $# from $^
#echo DO IT
(And I'm sure you realize your example doesn't really need SECONDEXPANSION at all.)
EDIT:
That should be a separate question, but I'll try to answer it here. (And please use punctuation in the comments in your makefile; they are very difficult to understand.)
There is more than one solution to your problem. Here is one:
vpath %.c $(dir $(CFILES))
CFILES := $(notdir $(CFILES))
I've gotcha it.
CONFIGS = test1 test2 test3
PLATFORMS = p1 p2
#Will be testp1 test1p2 .. test3p2
VARIANTS = $(foreach c, $(CONFIGS), $(foreach p, $(PLATFORMS), $(c)$(p)))
.SECONDEXPANSION:
#.c files list in all subfolders
cfiles = $(shell /bin/find -name "*.c")
#objects for these .c files for custom VARIANT
objects = $(patsubst %.c,%.o,$(addprefix bins/$1/,$(cfiles)))
#Get .c source for object (e.g. bins/test1p1/tests/main_test.o => tests/main_test.c)
get_src=$(shell echo $1 | sed 's/[^\/]*\/[^\/]*\/\(.*\)/\1.c/')
#Build All Variants
all: $(VARIANTS)
#Build objects. Target list contains all objects for all variants.
#Prerequisites get .c sources from the pattern rule for targets
$(foreach v, $(VARIANTS), $(call objects,$(v))) : %.o : $$(call get_src,$$*)
#echo OBJECTS $# FROM $^
#Variants rule, depends on objects
$(VARIANTS): $(call objects,$$#)
#echo $# from $^
Thank you, Beta. You only have tried. :)
Maybe anyone have style or efficiency suggestions.

Resources