How to organize big number of header include paths within makefile? - c

I'm relatively new to makefiles and I have to write a makefile for a large project to compile the project with the gnu gcc compiler.
The relevant header files for the source files are organized in different subdirectories like this:
D:\MyProject\SubProject1\Modules\APP\StateManager\Include
D:\MyProject\Tools\
D:\MyProject\Common\Public
D:\MyProject\Function\Modules\FSW\Public
D:\MyProject\SubProject1\Modules\Version\Include
D:\MyProject\SubProject1\Modules\APP\AC\Include
D:\MyProject\SubProject1\Modules\APP\DBDTmanager\Public
D:\MyProject\SubProject1\Modules\APP\Diag\Include\
D:\MyProject\SubProject1\Modules\APP\FunTTT\Include
D:\MyProject\SubProject1\Modules\Basis_SW\Adc\Include
D:\MyProject\SubProject1\Modules\Basis_SW\Func2\Include
D:\MyProject\SubProject1\Modules\Basis_SW\Stubs\Include
D:\MyProject\SubProject1\Modules\Basis_SW\DTC\Include
D:\MyProject\SubProject1\Modules\Basis_SW\Generated\Include
D:\MyProject\SubProject1\Modules\Basis_SW\Generated_BSM\Include
D:\MyProject\SubProject1\Modules\Basis_SW\Functions\Include
D:\MyProject\SubProject1\Modules\BistTests\Include
D:\MyProject\SubProject1\Modules\BistTests\Include\WatchDog\Include
D:\MyProject\App\ssw\common\Public
D:\MyProject\Bit\Modules\Timer\Include
Any idea how to define the includes in the makefile in a "clearly" and "overseeable" way?
Thx for any suggestions!

Assuming you don't have any other requirements here and just want a fairly clean way of getting all of those entries into your CFLAGS value you could do something like this:
PROJDIR := D:\MyProject
SUBPROJDIR := $(PROJDIR)\SubProject1\Modules
CFLAGS += -I$(PROJDIR)\SubProject1\Modules\APP\StateManager\Include
CFLAGS += -I$(PROJDIR)\Tools\
CFLAGS += -I$(PROJDIR)\Common\Public
CFLAGS += -I$(PROJDIR)\Function\Modules\FSW\Public
CFLAGS += -I$(SUBPROJDIR)\Version\Include
CFLAGS += -I$(SUBPROJDIR)\APP\AC\Include
CFLAGS += -I$(SUBPROJDIR)\APP\DBDTmanager\Public
CFLAGS += -I$(SUBPROJDIR)\APP\Diag\Include\
CFLAGS += -I$(SUBPROJDIR)\APP\FunTTT\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\Adc\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\Func2\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\Stubs\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\DTC\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\Generated\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\Generated_BSM\Include
CFLAGS += -I$(SUBPROJDIR)\Basis_SW\Functions\Include
CFLAGS += -I$(SUBPROJDIR)\BistTests\Include
CFLAGS += -I$(SUBPROJDIR)\BistTests\Include\WatchDog\Include
CFLAGS += -I$(PROJDIR)\App\ssw\common\Public
CFLAGS += -I$(PROJDIR)\Bit\Modules\Timer\Include
etc.

Use this
INC=-I<header-path-1> -I<header-path-2> -I<header-path3>
PS: they all are seperated by spaces

Related

GDB Debugger - "malloc" not defined. Trying to assign C array with debugger

I've got some software compiled to run on an embedded NRF24 target, using a gcc-arm-none-eabi toolchain from here (a custom one that provides gdb with support for python3) . I'm trying essentially, malloc an array from the GDB debugger console at runtime, then fill it with elements that I provide.
I have a pointer defined in a .c file like: static float32_t *array;.
I want to then call a cmd like: call (void*) malloc(num_of_elements*sizeof(float32_t)) from inside the GDB console to allocate an array at runtime, and then fill it with elements with something like maybe: call (void*) memcpy(array, {var1, var2... var n}, n)
My issue is the GDB debugger cannot find the malloc stdlib function. If I do something like:
break malloc
Function "malloc" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
It can't find this function, although it is fine with finding <string.h> fns, like memcpy for example and I can't quite work out why this is.
I have a feeling it could be something to do with linking, the program is built with a Makefile, the flags towards the end may be of interest:
LIB_FILES += \
$(SDK_ROOT)/components/toolchain/cmsis/dsp/GCC/libarm_cortexM4lf_math.a \
# Optimization flags
OPT = -O0 -g3
# Uncomment the line below to enable link time optimization
#OPT += -flto
# C flags common to all targets
CFLAGS += $(OPT)
CFLAGS += -DBOARD_PCA10056
CFLAGS += -DARM_MATH_CM4
CFLAGS += -DBSP_DEFINES_ONLY
CFLAGS += -DCONFIG_GPIO_AS_PINRESET
CFLAGS += -DFLOAT_ABI_HARD
CFLAGS += -DNRF52840_XXAA
CFLAGS += -mcpu=cortex-m4
CFLAGS += -mthumb -mabi=aapcs
CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# keep every function in a separate section, this allows linker to discard unused ones
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin -fshort-enums
CFLAGS += -DDEV8_PINOUT
CFLAGS += -DNUM_FLASH_BLOCKS=128
CFLAGS += -DDEBUG
CFLAGS += -DNRF_LOG_ENABLED=1
CFLAGS += -DNRF_LOG_BACKEND_UART_ENABLED=1
# C++ flags common to all targets
CXXFLAGS += $(OPT)
# Assembler flags common to all targets
ASMFLAGS += $(OPT)
ASMFLAGS += -mcpu=cortex-m4
ASMFLAGS += -mthumb -mabi=aapcs
ASMFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
ASMFLAGS += -DBOARD_PCA10056
ASMFLAGS += -DBSP_DEFINES_ONLY
ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
ASMFLAGS += -DFLOAT_ABI_HARD
ASMFLAGS += -DNRF52840_XXAA
ASMFLAGS += -DARM_MATH_CM4
# Linker flags
LDFLAGS += $(OPT)
LDFLAGS += -mthumb -mabi=aapcs -L$(SDK_ROOT)/modules/nrfx/mdk -T$(LINKER_SCRIPT)
LDFLAGS += -mcpu=cortex-m4
LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
# let linker dump unused sections
LDFLAGS += -Wl,--gc-sections
# use newlib in nano version
LDFLAGS += --specs=nano.specs
LDFLAGS += -Wl,--print-memory-usage
nrf52840_xxaa: CFLAGS += -D__HEAP_SIZE=8192
nrf52840_xxaa: CFLAGS += -D__STACK_SIZE=8192
nrf52840_xxaa: ASMFLAGS += -D__HEAP_SIZE=8192
nrf52840_xxaa: ASMFLAGS += -D__STACK_SIZE=8192
# Add standard libraries at the very end of the linker input, after all objects
# that may need symbols provided by these libraries.
LIB_FILES += -lc -lnosys -lm
To debug I'm using GDB with a Jlink server type setup.
Your code needs to explicitly reference the symbol to force it to link, and you need to prevent link optimisation from removing unused references. Rather then doing a dummy call with potential unwanted side effects, you can simply refer to the symbol via a function pointer instantiation thus:
void* (*volatile force_malloc_link)(size_t) = &malloc ;
Or more simply since you will not actually invoke the function through the pointer:
volatile void* force_link_malloc = &malloc ;
You could make it generic with a macro for any symbol you wish to link:
#define FORCE_LINK( sym ) volatile void* force_link_ ## sym = &sym
You can also force the entire library to be linked (if you have the space) - How to force gcc to link an unused static library. One of the answers there explains how you can also unpack the static library and link individual object files.
It can't find this function
The function may not be linked into your binary.
Does your binary call malloc elsewhere?
Do you link against libc.so or libc.a?
Does nm a.out | grep ' malloc' find it?
it is fine with finding <string.h> fns, like memcpy
If your binary calls memcpy and you link against libc.a, then memcpy implementation will be linked in. Using the same nm command from above will show that the memcpy symbol is present and malloc is not.
If you want to call malloc at runtime, you need to make sure it's linked in. One way to achieve this is to add:
const char *argv0;
int main(int argc, char *argv[])
{
argv0 = strdup(argv[0]); // This should guarantee that malloc is linked in.
// rest of the program
}

Can I use a #define representation of a stdlib function?

I kinda liked the idea of having my own sprintf function without the string.h or stdio.h bloatware.
#define sprintf(x) my_sprintf(x)
void my_sprintf(const char * string);
int main(void)
{
sprintf("abc");
}
These are my LD flags:
LDFLAGS += -lgcc
LDFLAGS += --specs=nano.specs
LDFLAGS += -mthumb
LDFLAGS += -mcpu=cortex-m4
# LDFLAGS += --gc-sections
# LDFLAGS += -nostartfiles
# LDFLAGS += -nodefaultlibs
# LDFLAGS += -gc-sections
As you see, I have the nostartfiles and nodefaultlibs options unset. So, even if I had the idea of including string.h or stdio.h, The compiler might find a definition/reference of the sprintf function.
So I'd like to know what if the #define will still refer to the "redefinition" if it is the same than an existing function name.
Any help is warmly welcome.
Yes, but an easier way would be to use a freestanding environment:
gcc -ffreestanding ...
If you want to know if your approach will take effect across files (i.e. #define function(x) y in file1.c and function(z) in file2.c), then no, it won't.

"make all" twice in a row doesn't return "make: Nothing to be done for 'all'."

I've noticed a lot of questions about people having the message "make: Nothing to be done for 'all'.", however my problem is the opposite.
Here is my makefile:
#################
## VARIABLES ##
#################
# Environment
OS := $(shell uname)
# Output
NAME := libft.a
DYNAMIC_NAME := ${NAME:a=so}
# Compiler
CC := gcc
ifneq ($(OS), Linux)
FLAGS += -Wall -Wextra -Werror
endif
DYN_FLAG := -shared
HEADERS := -I ./includes/
O_FLAG := -O2
# Directories
ADDITIONAL_FUNCTIONS = $(addprefix ./additional_functions/, $(ADDITIONAL))
BONUS_FUNCTIONS = $(addprefix ./bonus_functions/, $(BONUS))
LIBC_FUNCTIONS = $(addprefix ./libc_functions/, $(LIBC))
PERSONAL_FUNCTIONS = $(addprefix ./personal_functions/, $(PERSONAL))
DYN_OBJDIR = dyn_build/
OBJDIR := build/
# Sources
ADDITIONAL += ft_itoa.c
ADDITIONAL += ft_memalloc.c ft_memdel.c
ADDITIONAL += ft_putchar.c ft_putchar_fd.c
ADDITIONAL += ft_putendl.c ft_putendl_fd.c
ADDITIONAL += ft_putnbr.c ft_putnbr_fd.c
ADDITIONAL += ft_putstr.c ft_putstr_fd.c
ADDITIONAL += ft_strclr.c ft_strdel.c
ADDITIONAL += ft_strnew.c ft_strjoin.c
ADDITIONAL += ft_strequ.c ft_strnequ.c
ADDITIONAL += ft_striter.c ft_striteri.c
ADDITIONAL += ft_strmap.c ft_strmapi.c
ADDITIONAL += ft_strsplit.c ft_strsub.c ft_strtrim.c
BONUS += ft_lstadd.c ft_lstnew.c
BONUS += ft_lstdel.c ft_lstdelone.c
BONUS += ft_lstiter.c ft_lstmap.c
LIBC += ft_atoi.c
LIBC += ft_isalnum.c ft_isalpha.c ft_isascii.c
LIBC += ft_isdigit.c ft_isprint.c
LIBC += ft_memcpy.c ft_memccpy.c ft_memchr.c ft_memcmp.c
LIBC += ft_bzero.c ft_memmove.c ft_memset.c
LIBC += ft_strcat.c ft_strlcat.c ft_strncat.c
LIBC += ft_strchr.c ft_strrchr.c
LIBC += ft_strcmp.c ft_strncmp.c
LIBC += ft_strcpy.c ft_strncpy.c ft_strdup.c
LIBC += ft_strlen.c
LIBC += ft_strstr.c ft_strnstr.c
LIBC += ft_tolower.c ft_toupper.c
PERSONAL += ft_intlen.c
PERSONAL += ft_invert.c ft_islower.c ft_isupper.c
PERSONAL += ft_lstgetnode.c ft_lstsize.c
PERSONAL += ft_kill.c ft_putuchar.c ft_putuchar_fd.c
PERSONAL += ft_strrev.c ft_strrevcpy.c
PERSONAL += get_next_line.c
DYN_OBJECTS = $(patsubst %.c,$(DYN_OBJDIR)%.o,$(SRCS))
OBJECTS = $(patsubst %.c,$(OBJDIR)%.o,$(SRCS))
SRCS += $(ADDITIONAL_FUNCTIONS)
SRCS += $(BONUS_FUNCTIONS)
SRCS += $(LIBC_FUNCTIONS)
SRCS += $(PERSONAL_FUNCTIONS)
#################
## RULES ##
#################
all: $(NAME)
$(NAME): $(OBJECTS)
#ar rcs $# $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(SRCS)))
ranlib $#
#echo "Static library created."
$(OBJECTS): | $(OBJDIR)
$(OBJDIR):
#mkdir -p $#
$(OBJDIR)%.o: %.c
$(CC) $(FLAGS) $(O_FLAG) -c $< $(HEADERS) -o $(OBJDIR)$(notdir $#)
$(DYN_OBJECTS): | $(DYN_OBJDIR)
$(DYN_OBJDIR):
#mkdir -p $#
$(DYN_OBJDIR)%.o: %.c
$(CC) $(FLAGS) $(O_FLAG) -c $< $(HEADERS) -fpic -o $(DYN_OBJDIR)$(notdir $#)
clean:
#/bin/rm -rfv $(OBJDIR)
#/bin/rm -rfv $(DYN_OBJDIR)
fclean: clean
#/bin/rm -fv $(NAME)
#/bin/rm -fv $(DYNAMIC_NAME)
re: fclean all
so: $(DYN_OBJECTS)
#$(CC) $(DYN_FLAG) -o $(DYNAMIC_NAME) $(patsubst %.c,$(DYN_OBJDIR)%.o,$(notdir $(SRCS)))
#echo "Dynamic library created."
.PHONY: all build clean dynbuild fclean re so
The makefile works perfectly fine. It takes every .c in the different directories, creates an object directory, build/ if the library is static and dyn_build/ if it is dynamic, put the object files inside said directory and compile the library from them.
My issue is that if I run make twice in a row, nothing should be done the second time as the object files and the library are still there and up to date. But, somehow doing make twice in a row results in the second make repeating the operation.
What is causing this and is there a way to fix it?
Your problem can be reduced to this:
ADDITIONAL += ft_strsplit.c
BONUS += ft_lstadd.c
ADDITIONAL_FUNCTIONS = $(addprefix ./add/, $(ADDITIONAL))
BONUS_FUNCTIONS = $(addprefix ./bonus/, $(BONUS))
SRCS += $(ADDITIONAL_FUNCTIONS)
SRCS += $(BONUS_FUNCTIONS)
OBJECTS = $(patsubst %.c,./build/%.o,$(SRCS))
# OBJECTS contains ./build/./add/ft_strsplit.o and ./build/./bonus/ft_lstadd.o
all: $(OBJECTS)
$(OBJDIR)%.o: %.c
$(CC) ...
So Make runs the last rule with e.g. build/./add/ft_strsplit.o as the target, and add/ft_strsplit.c as the prerequisite. The question is how to write the recipe so as to build build/ft_strsplit.o.
As #user657267 has pointed out, it is a mistake to have a (non-PHONY) rule that does not build a file whose name is the target of the rule. So let's first ask Make for the files we actually want:
ADDITIONAL += ft_strsplit.c
BONUS += ft_lstadd.c
SRCS += $(ADDITIONAL)
SRCS += $(BONUS)
OBJECTS = $(patsubst %.c,./build/%.o,$(SRCS))
# OBJECTS contains ./build/ft_strsplit.o and ./build/ft_lstadd.o
So far so good, but now how can Make find the sources? When we ask Make to build ./build/ft_strsplit.o, how can it know where ft_strsplit.c is?
We use vpath:
vpath %.c add bonus
Now the makefile works correctly. And to write that vpath line automatically, we can just pull the directory names out of the assignments:
# Directories
ADDITIONAL_DIR := ./additional_functions
BONUS_DIR := ./bonus_functions
...
ADDITIONAL_FUNCTIONS = $(addprefix $(ADDITIONAL_DIR)/, $(ADDITIONAL))
BONUS_FUNCTIONS = $(addprefix $(BONUS_DIR)/, $(BONUS))
...
vpath %.c $(ADDITIONAL_DIR)
vpath %.c $(BONUS_DIR)
...

Weak alias to mock

I'm trying to mock a fn say foo using
#ifdef UT_TEST
void foo(void) __attribute__ ((weak, alias ("foo_impl")));
#else
void foo(void);
#endif
However, is there a way to do this # runtime instead of compile time? I cannot use C++, for historical reasons.
In the past I've mostly seen this problem solved at the build system level instead, which I feel is a cleaner solution. Doing it this way allows to avoid most ifdefs and instead work with full files. In make, it might look something like this:
OBJS += file1.o file2.o
ifeq ($(UNIT_TEST),y)
OBJS += dummy_implementation.o
else
OBJS += real_implementation.o
endif
myprog: $(OBJS)
or in more classic make idiom:
OBJS-y += file1.o file2.o
OBJS-$(UNIT_TEST) += dummy_implementation.o
OBJS-$(REAL_BUILD) += real_implementation.o
OBJS = $(OBJS-y)
myprog: $(OBJS)
dummy_implementation.c and real_implementation.c would share a header file in this case.

conditional compilation flags in make

How to solve the following problem with make?
SRCS1 = a.c b,c
SRCS2 = d.c e.c
SRCS= $(SRCS1) $(SRCS2)
OBJS1 = $(subst .c,.o,$(SRCS1))
OBJS2 = $(subst .c,.o,$(SRCS2))
OBJS = $(OBJS1) $(OBJS2)
include ../Makeconf
(which contains CPPFLAGS=-Dfoo) (the main Makefile is also in ../)
Now I want to compile SRCS1 with foo defined and SRCS2 with foo not defined.
I tried
ifneq (,$(findstring $(OBJS2),$(OBJS)))
CPPFLAGS += -Ufoo
endif
but that adds -Ufoo to all files when compiled. Any ideas?
You haven't shown us enough of the makefile(s) to give a complete answer, but I think this is what you're looking for:
$(OBJS2): CPPFLAGS += -Ufoo

Resources