Make-File: compile multiple SRC-Folders to single OBJ-Folder - c

I got a project hierarchy that looks like this:
+Makefile
+---src
| main.c
| ...
| +---block
| | air.c
| | ...
| |
| +---entity
| | esc.c
| | esc.h
| | ...
| |
| \---world
| \---gen
| noise.c
| ...
| xyz.c
| ...
\---obj
main.o
air.o
esc.o
noise.o
xyz.o
...
I want to compile all the .c files in the hierarchy into one obj folder using make.
So far I got:
UNAME_S = $(shell uname -s)
CC = clang
CFLAGS = -std=c11 -O3 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing
CFLAGS += -Wno-pointer-arith -Wno-newline-eof -Wno-unused-parameter -Wno-gnu-statement-expression
CFLAGS += -Wno-gnu-compound-literal-initializer -Wno-gnu-zero-variadic-macro-arguments
CFLAGS += -Ilib/cglm/include -Ilib/glad/include -Ilib/glfw/include -Ilib/stb -Ilib/noise -fbracket-depth=1024
LDFLAGS = lib/glad/src/glad.o lib/cglm/libcglm.a lib/glfw/src/libglfw3.a lib/noise/libnoise.a -lm
# GLFW required frameworks on OSX
ifeq ($(UNAME_S), Darwin)
LDFLAGS += -framework OpenGL -framework IOKit -framework CoreVideo -framework Cocoa
endif
ifeq ($(UNAME_S), Linux)
LDFLAGS += -ldl -lpthread
endif
OBJ_DIR = obj
SRC = $(wildcard src/**/*.c) $(wildcard src/*.c) $(wildcard src/**/**/*.c) $(wildcard src/**/**/**/*.c)
OBJ = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(notdir $(basename $(SRC)))))
SRC_DIRS = $(sort $(dir $(SRC)))
BIN = bin
.PHONY: all clean
all: dirs libs game
libs:
cd lib/cglm && cmake . -DCGLM_STATIC=ON && make
cd lib/glad && $(CC) -o src/glad.o -Iinclude -c src/glad.c
cd lib/glfw && cmake . && make
cd lib/noise && make
dirs:
mkdir -p ./$(BIN) ./$(OBJ_DIR)
run: all
$(BIN)/game
game: $(OBJ)
$(CC) -o $(BIN)/game $^ $(LDFLAGS)
$(OBJ_DIR)/%.o: src/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/block/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/entity/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/gfx/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/ui/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/util/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/world/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/world/gen/%.c
$(CC) -o $# -c $< $(CFLAGS)
clean:
rm -rf $(BIN) $(OBJ_DIR)
Is there any way to get this done in a more efficient way? Especially the $(OBJ_DIR)/%.o cases?
Variable $(SRC_DIRS) stores all src folders
Variable $(SRC) stores all .c files with their paths
Variable $(OBJ) stores all .o file paths and names

The best way to do this is using VPATH.
For example:
SRC := $(wildcard src/*/*.c) $(wildcard src/*.c) $(wildcard src/*/*/*.c) $(wildcard src/*/*/*/*.c)
OBJ := $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(notdir $(basename $(SRC)))))
SRC_DIRS := $(sort $(dir $(SRC)))
VPATH := $(SRC_DIRS)
...
$(OBJ_DIR)/%.o: %.c
$(CC) -o $# -c $< $(CFLAGS)
You just need the one pattern rule.

Related

How can I make my Makefile build to the obj/ folder, not the src/ folder?

I am extending an old school project, and I have the Makefile the course staff made for us. I have reorganized the directory structure of the project like this.
+-----obj
|
+-----src
| |
| +-Makefile
| +-allocator.h
| +-debug_break.h
| +-rbtree_clrs.c
| +-rbtree_linked.c
| +-rbtree_stack.c
| +-rbtree_topdown.c
| +-rbtree_unified.c
| +-segment.c
| +-segment.h
| +-test_harness.c
| +-my_optional_program.c
|
+------scripts
The Makefile currently prepends the heap allocators I wrote (files starting with rbtree_) with either test_ or my_optional_program and puts them in the same directory as the Makefile. I can then run my different heap allocator implementations on the scripts in the scripts folder. Instead, I want this:
+-----obj
| +-my_optional_program_rbtree_clrs
| +-my_optional_program_rbtree_linked
| +-my_optional_program_rbtree_stack
| +-my_optional_program_rbtree_topdown
| +-my_optional_program_rbtree_unified
| +-test_rbtree_clrs
| +-test_rbtree_linked
| +-test_rbtree_stack
| +-test_rbtree_topdown
| +-test_rbtree_unified
|
+-----src
| |
| +-Makefile
| +-allocator.h
| +-debug_break.h
| +-rbtree_clrs.c
| +-rbtree_linked.c
| +-rbtree_stack.c
| +-rbtree_topdown.c
| +-rbtree_unified.c
| +-segment.c
| +-segment.h
| +-test_harness.c
| +-my_optional_program.c
|
+------scripts
What do I need to add or change in the Makefile so that it will build to the obj/ folder?
# They had us try different optimization levels here (-O0, -O2, etc).
rbtree_clrs.o: CFLAGS += -O0
rbtree_unified.o: CFLAGS += -O0
rbtree_linked.o: CFLAGS += -O0
rbtree_stack.o: CFLAGS += -O0
rbtree_topdown.o: CFLAGS += -O0
ALLOCATORS = rbtree_clrs rbtree_unified rbtree_stack rbtree_linked rbtree_topdown
PROGRAMS = $(ALLOCATORS:%=test_%)
MY_PROGRAMS = $(ALLOCATORS:%=my_optional_program_%)
all:: $(PROGRAMS) $(MY_PROGRAMS)
# I had to use gcc-11 on mac to be able to build this project.
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC = gcc-11
else
CC = gcc
endif
CFLAGS = -g3 -std=gnu99 -Wall $$warnflags -fcf-protection=none -fno-pic -no-pie
export warnflags = -Wfloat-equal -Wtype-limits -Wpointer-arith -Wlogical-op -Wshadow -Winit-self -fno-diagnostics-show-option
LDFLAGS =
LDLIBS =
$(PROGRAMS): test_%:%.o segment.c test_harness.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(MY_PROGRAMS): my_optional_program_%:my_optional_program.c %.o segment.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean::
rm -f $(PROGRAMS) $(MY_PROGRAMS) *.o callgrind.out.*
.PHONY: clean all
.INTERMEDIATE: $(ALLOCATORS:%=%.o)
Update: This Makefile has solved the issue. I took Renaud Pacalet's Makefile (thanks!) and adjusted the paths to achieve the desired result. It seems not going up one level in the directories was an issue. Then I had to add the path I wanted to the ALLOCATORS in the PROGRAMS variable. I have no idea if this is how it should be done but it worked. I can update this if there is a better way.
SRCDIR = ../src
OBJDIR = ../obj
SRC := $(wildcard $(SRCDIR)/*.c)
OBJ := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o,$(SRC))
# They had us try different optimization levels here (-O0, -O2, etc).
$(filter $(OBJDIR)/rbtree_%.o,$(OBJ)): CFLAGS += -O0
ALLOCATORS = rbtree_clrs rbtree_unified rbtree_stack rbtree_linked rbtree_topdown
PROGRAMS = $(addprefix $(OBJDIR)/test_,$(ALLOCATORS))
MY_PROGRAMS = $(addprefix $(OBJDIR)/my_optional_program_,$(ALLOCATORS))
all:: $(PROGRAMS) $(MY_PROGRAMS)
# I had to use gcc-11 on mac to be able to build this project.
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC = gcc-11
else
CC = gcc
endif
CFLAGS = -g3 -std=gnu99 -Wall $$warnflags -fcf-protection=none -fno-pic -no-pie
export warnflags = -Wfloat-equal -Wtype-limits -Wpointer-arith -Wlogical-op -Wshadow -Winit-self -fno-diagnostics-show-option
LDFLAGS =
LDLIBS =
$(OBJ): $(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c -o $# $<
$(PROGRAMS): $(OBJDIR)/test_%: $(OBJDIR)/%.o segment.c test_harness.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(MY_PROGRAMS): $(OBJDIR)/my_optional_program_%: my_optional_program.c $(OBJDIR)/%.o segment.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean::
rm -f $(PROGRAMS) $(MY_PROGRAMS) $(OBJ) callgrind.out.*
You don't have a compilation rule so make uses its implicit rule for compilation which puts the object files in the same directory as the source files.
Simply add a rule of your own and rework a bit all references to object files:
OBJDIR := ../obj
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,$(OBJDIR)/%.o,$(SRC))
# They had us try different optimization levels here (-O0, -O2, etc).
$(filter $(OBJDIR)/rbtree_%.o,$(OBJ)): CFLAGS += -O0
ALLOCATORS = rbtree_clrs rbtree_unified rbtree_stack rbtree_linked rbtree_topdown
PROGRAMS = $(ALLOCATORS:%=$(OBJDIR)/test_%)
MY_PROGRAMS = $(ALLOCATORS:%=$(OBJDIR)/my_optional_program_%)
all:: $(PROGRAMS) $(MY_PROGRAMS)
# I had to use gcc-11 on mac to be able to build this project.
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC = gcc-11
else
CC = gcc
endif
CFLAGS = -g3 -std=gnu99 -Wall $$warnflags -fcf-protection=none -fno-pic -no-pie
export warnflags = -Wfloat-equal -Wtype-limits -Wpointer-arith -Wlogical-op -Wshadow -Winit-self -fno-diagnostics-show-option
LDFLAGS =
LDLIBS =
$(OBJ): $(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o '$#' '$<'
$(PROGRAMS): $(OBJDIR)/test_%: $(OBJDIR)/%.o segment.c test_harness.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(MY_PROGRAMS): $(OBJDIR)/my_optional_program_%: my_optional_program.c $(OBJDIR)/%.o segment.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean::
rm -f $(PROGRAMS) $(MY_PROGRAMS) $(OBJ) callgrind.out.*
Note that you should also manage the dependencies between object and header files (which the above does not, just like the original version). If it's simple enough you'll easily modify the proposed Makefile. Else consider reading this very interesting post about Auto-Dependency Generation by the current GNU make main maintainer.

Multi target makefile with subfolders

My project has the following structure:
\---Project
+ Makefile
|
+---source
| +---target1
| | t1_lib.c
| | t1_main.c
| |
| +---target2
| | t2_lib.c
| | t2_main.c
| |
| \---common
| common_lib.c
|
+---headers
+---target1
| t1_lib.h
|
+---target2
| t2_lib.h
|
\---common
common_lib.h
I am trying to write a makefile which allows me to run 'make target1' or 'make target2' and compile target1 source code with common source code or compile target2 source code with common source code respectively.
In my project, target1 is call 'ue' and target2 is call 'enb'.
This is what I have in my current makefile:
# Author: j0lama
# COMPILER
CC = gcc
#FLAGS
CFLAGS = -c -Wall -ansi -g -std=c99 -D_DEBUG
#LIB FLAGS
LIBFLAGS = -lgc -rdynamic -lcrypto -lpthread
#LINK FLAGS
LINKFLAGS = -lsctp
# PATHS
UE_SOURCE_DIRECTORY = source/ue/
UE_INCLUDE_DIRECTORY = headers/ue/
ENB_SOURCE_DIRECTORY = source/enb/
ENB_INCLUDE_DIRECTORY = headers/enb/
COMMON_SRC_DIRECTORY = source/common/
COMMON_HDR_DIRECTORY = headers/common/
OBJECT_DIRECTORY = objects/
BUILD_DIRECTORY = build/
COMMON_CFILES= $(wildcard $(COMMON_SRC_DIRECTORY)*.c)
COMMON_OBJECTS= $(patsubst $(COMMON_SRC_DIRECTORY)%.c, $(OBJECT_DIRECTORY)%.o, $(COMMON_CFILES))
CFILES = $(COMMON_CFILES)
OBJECTS = $(COMMON_OBJECTS)
all: clean ue enb
ue: setup_ue $(OBJECT_DIRECTORY) $(TARGET) ue_emulator
enb: setup_enb $(OBJECT_DIRECTORY) $(TARGET) enb_emulator
setup_ue:
$(eval CFILES += $(wildcard $(UE_SOURCE_DIRECTORY)*.c))
$(eval OBJECTS += $(patsubst $(UE_SOURCE_DIRECTORY)%.c, $(OBJECT_DIRECTORY)%.o, $(wildcard $(UE_SOURCE_DIRECTORY)*.c)))
$(eval INCLUDE_DIRECTORY = $(UE_INCLUDE_DIRECTORY))
setup_enb:
$(eval CFILES += $(wildcard $(ENB_SOURCE_DIRECTORY)*.c))
$(eval OBJECTS += $(patsubst $(ENB_SOURCE_DIRECTORY)%.c, $(OBJECT_DIRECTORY)%.o, $(wildcard $(ENB_SOURCE_DIRECTORY)*.c)))
$(eval INCLUDE_DIRECTORY = $(ENB_INCLUDE_DIRECTORY))
$(OBJECT_DIRECTORY):
#mkdir $(OBJECT_DIRECTORY)
#echo "Building objects directory..."
ue_emulator: $(OBJECTS)
#echo "Building $#..."
#$(CC) $(OBJECTS) $(LIBFLAGS) $(LINKFLAGS) -o $#
enb_emulator: $(OBJECTS)
#echo "Building $#..."
#$(CC) $(OBJECTS) $(LIBFLAGS) $(LINKFLAGS) -o $#
$(OBJECT_DIRECTORY)%.o: $(SOURCE_DIRECTORY)%.c $(COMMON_SRC_DIRECTORY)%.c
#echo "Building $#..."
#$(CC) -I $(COMMON_HDR_DIRECTORY) -I $(INCLUDE_DIRECTORY) $(CFLAGS) $(LIBFLAGS) $< -o $#
.PHONY: clean
clean:
#echo "Removing objects files"
#rm -rf $(OBJECT_DIRECTORY) $(TARGET)
Somehow this makefile does not compile any file.

makefile - no rule to make a target c

This case has been opened many times, I have checked up all of the answers but didn't really help.
I'm posting it here may someone can help me.
My working architecture is :
| ( I'm Here )
+- matamzone.c
+- amountset.c
+- product.c
+- order.c
+- matamzone.h
+- amount.h
+- p.h
+- order.h
+- TEST-folder
+- amount_set_main.c
+- amount_set_main.h
+- amount_set_tests.c
+- amount_set_tests.h
The makefile have to support running amount_set_main.c by writing make amount_set.
My make file code:
CC = gcc
COMP_FLAGS = -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG
COMP_NEW = -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG /tests
OUR_FILES = amount_set.c matamazom.c order.c product.c matamazom_print.c
OUR_NFILES = amount_set_main.c amount_set_test.c
OBJS = amount_set.o matamazom.o order.o product.o matamazom_print.o
TEST_OBJS = amount_set_main.o amount_set_test.o
EXEC = matamazom.exe
TESTROOMEXE = amount_set
$(TESTROOMEXE) : $(TEST_OBJS)
$(CC) -o $# $(COMP_FLAGS) $(TEST_OBJS) -L. -lmtm
matamazom.o: matamazom.c matamazom.h list.h product.h order.h amount_set.h matamazom_print.h
$(CC) -c $(COMP_FLAGS) $(OUR_FILES) $*.c
amount_set.o: amount_set.c amount_set.h
$(CC) -c $(COMP_FLAGS) $(OUR_FILES) $*.c
order.o: order.c order.h amount_set.h
$(CC) -c $(COMP_FLAGS) $(OUR_FILES) $*.c
product.o: product.c matamazom.h
$(CC) -c $(COMP_FLAGS) $(OUR_FILES) $*.c
matamazom_print.o: matamazom_print.c matamazom_print.h
$(CC) -c $(COMP_FLAGS) $(OUR_FILES) $*.c
amount_set_main.o: amount_set_main.c amount_set_tests.h test_utilities.h
$(CC) -c $(COMP_NEW) $(OUR_NFILES) $*.c
amount_set: amount_set_main.c amount_set_tests.h amount_set.h
$(CC) -o $# $(COMP_NEW) $(TEST_OBJS) -L. -lmtm
amount_set_test.o: amount_set_tests.c amount_set_tests test_utilities.h ../amount_set.h
$(CC) -c $(COMP_NEW) $(OUR_NFILES) $*.c
clean:
rm -f $(OBJS) $(EXEC) $(TESTS) $(TEST_O)
For some reason I get:
**make: *** No rule to make target `amount_set_main.c', needed by `amount_set_main.o'. Stop.**
Any help :(

Make: "The system cannot find the path specified" only when compiling with makefile?

I have a C-application that i'm trying to build with a makefile. When I call make I get:
Compiling file: nrf_drv_rtc.c
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -Wall -O0 -g3 -mfloat-abi=soft -ffunction-sections -fdata-sections -fno-strict-aliasing -c -o build/nrf_drv_rtc.o nrf51_sdk/drivers_nrf/rtc/nrf_drv_rtc.c
"C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2015q1/bin/arm-none-eabi-gcc" -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -Wall -O0 -g3 -mfloat-abi=soft -ffunction-sections -fdata-sections -fno-strict-aliasing -c -o build/nrf_drv_rtc.o nrf51_sdk/drivers_nrf/rtc/nrf_drv_rtc.c
The system cannot find the path specified.
make[1]: *** [build/nrf_drv_rtc.o] Error 1
And true enough no "build/nrf_drv_rtc.o" file is build. Strange thing is that if i copy the line:
arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -Wall -O0 -g3 -mfloat-abi=soft -ffunction-sections -fdata-sections -fno-strict-aliasing -c -o build/nrf_drv_rtc.o nrf51_sdk/drivers_nrf/rtc/nrf_drv_rtc.c
to cmd and runs it, it compiles fine and generate "build/nrf_drv_rtc.o"?
Here's my makefile:
PROJECT_NAME := ble_app_hrs_s110_pca10028
export OUTPUT_FILENAME
#MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_NAME := $(MAKEFILE_LIST)
MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) )
TEMPLATE_PATH = nrf51_sdk/toolchain/gcc
ifeq ($(OS),Windows_NT)
include $(TEMPLATE_PATH)/Makefile.windows
else
include $(TEMPLATE_PATH)/Makefile.posix
endif
MK := mkdir
RM := rm -rf
#echo suspend
ifeq ("$(VERBOSE)","1")
NO_ECHO :=
else
NO_ECHO := #
endif
# Toolchain commands
CC := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-gcc"
AS := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-as"
AR := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ar" -r
LD := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-ld"
NM := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-nm"
OBJDUMP := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objdump"
OBJCOPY := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-objcopy"
SIZE := "$(GNU_INSTALL_ROOT)/bin/$(GNU_PREFIX)-size"
#function for removing duplicates in a list
remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1))))
#source common to all targets
C_SOURCE_FILES += \
nrf51_sdk/drivers_nrf/rtc/nrf_drv_rtc.c \
Drivers/NRF51_BLEDriver.c \
(..... a lot more files ....)
#assembly files common to all targets
ASM_SOURCE_FILES = nrf51_sdk/toolchain/gcc/gcc_startup_nrf51.s
#includes common to all targets
INC_PATHS = -I Application/
(..... a lot more include paths.......)
OBJECT_DIRECTORY = _build
LISTING_DIRECTORY =$(OBJECT_DIRECTORY)
OUTPUT_BINARY_DIRECTORY =$(OBJECT_DIRECTORY)
# Sorting removes duplicates
BUILD_DIRECTORIES := $(sort $(OBJECT_DIRECTORY) $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY) )
#flags common to all targets
CFLAGS = -DSOFTDEVICE_PRESENT
CFLAGS += -DNRF51
CFLAGS += -DS110
CFLAGS += -DBOARD_PCA10028
CFLAGS += -DBLE_STACK_SUPPORT_REQD
CFLAGS += -mcpu=cortex-m0
CFLAGS += -mthumb -mabi=aapcs --std=gnu99
CFLAGS += -Wall -O0 -g3
CFLAGS += -mfloat-abi=soft
# keep every function in separate section. This will allow linker to dump unused functions
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
#CFLAGS += -flto -fno-builtin
# keep every function in separate section. This will allow linker to dump unused functions
LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map
LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m0
# let linker to dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs -lc -lnosys
# Assembler flags
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DNRF51
ASMFLAGS += -DS110
ASMFLAGS += -DBOARD_PCA10028
ASMFLAGS += -DBLE_STACK_SUPPORT_REQD
#default target - first one defined
#default: clean nrf51422_xxac_s110
#building all targets
all: #clean
#$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e cleanobj
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e nrf51422_xxac_s110
#target for printing all targets
help:
#echo following targets are available:
#echo nrf51422_xxac_s110
#echo flash_softdevice
C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES))
C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) )
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILE_NAMES:.c=.o) )
ASM_SOURCE_FILE_NAMES = $(notdir $(ASM_SOURCE_FILES))
ASM_PATHS = $(call remduplicates, $(dir $(ASM_SOURCE_FILES) ))
ASM_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(ASM_SOURCE_FILE_NAMES:.s=.o) )
vpath %.c $(C_PATHS)
vpath %.s $(ASM_PATHS)
OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS)
nrf51422_xxac_s110: OUTPUT_FILENAME := nrf51422_xxac_s110
nrf51422_xxac_s110: LINKER_SCRIPT=ble_app_hrs_gcc_nrf51.ld
nrf51422_xxac_s110: $(BUILD_DIRECTORIES) $(OBJECTS)
#echo Linking target: $(OUTPUT_FILENAME).out
$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
$(NO_ECHO)$(MAKE) -f $(MAKEFILE_NAME) -C $(MAKEFILE_DIR) -e finalize
## Create build directories
$(BUILD_DIRECTORIES):
echo $(MAKEFILE_NAME)
$(MK) $#
# Create objects from C SRC files
$(OBJECT_DIRECTORY)/%.o: %.c
#echo Compiling file: $(notdir $<)
#echo arm-none-eabi-gcc $(CFLAGS) $(INC_PATHS) -c -o $# $<
$(NO_ECHO)$(CC) $(CFLAGS) $(INC_PATHS) -c -o $# $<
# Assemble files
$(OBJECT_DIRECTORY)/%.o: %.s
#echo Compiling file: $(notdir $<)
$(NO_ECHO)$(CC) $(ASMFLAGS) $(INC_PATHS) -c -o $# $<
# Link
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out: $(BUILD_DIRECTORIES) $(OBJECTS)
#echo Linking target: $(OUTPUT_FILENAME).out
$(NO_ECHO)$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
## Create binary .bin file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
#echo Preparing: $(OUTPUT_FILENAME).bin
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
$(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex: $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
#echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
finalize: genbin genhex echosize
genbin:
#echo Preparing: $(OUTPUT_FILENAME).bin
$(NO_ECHO)$(OBJCOPY) -O binary $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).bin
## Create binary .hex file from the .out file
genhex:
#echo Preparing: $(OUTPUT_FILENAME).hex
$(NO_ECHO)$(OBJCOPY) -O ihex $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).hex
echosize:
-#echo ""
$(NO_ECHO)$(SIZE) $(OUTPUT_BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
-#echo ""
clean:
$(RM) $(BUILD_DIRECTORIES)
cleanobj:
$(RM) $(BUILD_DIRECTORIES)/*.o
flash: $(MAKECMDGOALS)
#echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex
nrfjprog --reset --program $(OUTPUT_BINARY_DIRECTORY)/$<.hex)
## Flash softdevice
flash_softdevice:
#echo Flashing: s110_softdevice.hex
nrfjprog --reset --program nrf51_sdk/softdevice/s110/hex/s110_softdevice.hex
Turns out, that the include: include $(TEMPLATE_PATH)/Makefile.windows defined the GNU_INSTALL_ROOT variable as a compiler version that wasn't installed on my computer. So I corrected it, and everything works like a charm .

Compile specific source list and generate dependency

I have below file list:
fd1/foo.c
fd2/foo.c
fd2/bar.c
fd2/bar.h
I want to compile fd1/foo.c and fd2/bar.c. fd2/foo.c is an excluded one. If I use vapth to select all source files, the fd2/foo.c will be compiled. So I want to specify the source list:
SRC_C = fd1/foo.c fd2/bar.c
Since I can't use vpath, so I can only compile SRC_C something like this:
SRC_O = $(patsubst %.c,%.o,$(SRC_C))
SRC_C_LIST = $(notdir $(SRC_C))
OBJ_LIST = $(patsubst %.c,%.o,$(SRC_C_LIST) )
.PHONY: all
all: $(OBJ_LIST)
ar rvs foobar.a $(OBJ_LIST)
$(SRC_O): %.o : %.c
gcc -c $< -I inc/ -MM -MF $(patsubst .o,.d,$(notdir $#)) -o $(notdir $#)
But I also want add dependency rules. But the dependency file seems only contain object target without original folder names:
foo.o : src/foo.c inc/bar.h
How do I to use dependency file in this case? Thanks.
Solutions
Per suggestion from Joachim, I modify my solution as below. Seems work:
SRC_C = fd1/foo.c fd2/bar.c
SRC_O = $(patsubst %.c,%.o,$(SRC_C))
SRC_C_LIST = $(notdir $(SRC_C))
OBJ_LIST = $(patsubst %.c,%.o,$(SRC_C_LIST) )
SRC_D_LIST = $(patsubst %.o,%.d,$(OBJ_LIST))
.PHONY:all
all: $(SRC_O)
ar rvs foobar.a $(OBJ_LIST)
$(SRC_O): %.o : %.c
arm-none-eabi-gcc -c $< -I inc/ -o $# -MM -MT $# -MF $(notdir $(patsubst %.o,%.d,$#))
-include $(SRC_D_LIST)
Using implicit rules, if you do not mind having the .o and .d files along the corresponding .c files:
LIB := foobar.a
SRC := fd1/foo.c fd2/bar.c
OBJ := $(SRC:.c=.o)
DEP := $(OBJ:.o=.d)
CC := arm-none-eabi-gcc
ARFLAGS := rvs
CPPFLAGS := -MMD -MP -I inc
.PHONY: all
.PRECIOUS: $(OBJ)
all: $(LIB)
$(LIB): $(LIB)($(OBJ))
-include $(DEP)

Resources