Makefile crash on providing multiple dependencies - windows

This is a simple Makefile I had written. To get it working on mingw32-make I had to replace the #if [ ! -d $(OUTDIR) ]; then mkdir -p $(notdir $(OUTDIR)); fi calls with ifneq constructs. This is the file as now:
# This Makefile will build an application using the DLL.
SRCTREE := ./
CXX ?= g++
AR ?= ar
SRCDIR := $(SRCTREE)src
OUTDIR := $(SRCTREE)bin
OBJDIR := $(SRCTREE)obj
LIBDIR := $(SRCTREE)lib
INCDIR := $(SRCTREE)include
CFLAGS := -O3 -std=c++11 -Wall -pedantic
CFLAGS_EXTRA := -coverage
LFLAGS := -lgcov --coverage
dirs:
ifeq ("$(wildcard $(OBJDIR)/.)", "")
-mkdir $(notdir $(OBJDIR))
endif
ifeq ("$(wildcard $(LIBDIR)/.)", "")
-mkdir $(notdir $(LIBDIR))
endif
ifeq ("$(wildcard $(OUTDIR)/.)", "")
-mkdir $(notdir $(OUTDIR))
endif
all: dirs use-static
use-shared: CFLAGS_EXTRA += -pthread -DMATRIX_USE_DLL -DDLL_IMPORTS
use-shared: LFLAGS := -L$(SRCTREE) -l:$(OUTDIR)/Matrix.so
use-shared: main
use-static: CFLAGS_EXTRA += -pthread
use-static: LFLAGS := $(LIBDIR)/Matrix.a
use-static: main
%.o: $(SRCDIR)/%.cpp
$(CXX) -c $(CFLAGS) -I $(INCDIR) $(CFLAGS_EXTRA) -o $(OBJDIR)/$# $<
main: main.o
$(CXX) -o $(OUTDIR)/$# $(patsubst %,$(OBJDIR)/%,$^) $(LFLAGS) -s -pthread
clean:
-rm -f $(OBJDIR)/main.o
-rm -f $(OUTDIR)/main
-rm -f $(LIBDIR)/Matrix.a
-rm -f $(OUTDIR)/Matrix.so
When I run it like mingw32-make all -n, if the directories are not present, I get crash like: mingw32-make: Interrupt/Exception caught (code = 0xc0000005, addr = 0x00007FFE854CF15C). I cannot find what the problem could be. Could someone suggest what might be wrong?

Related

Makefile: ignore file in automatically generated dependencies

I have the following makefile, (mostly) generated by STM32CubeMX and slightly modified:
##########################################################################################################################
# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Mon Jun 06 11:00:27 SGT 2022]
##########################################################################################################################
# ------------------------------------------------
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
######################################
# target
######################################
TARGET := mytarget
######################################
# building variables
######################################
# debug build?
DEBUG := 1
# optimization
OPT := -Og
#######################################
# paths
#######################################
# Build path
BUILD_DIR := build
######################################
# source
######################################
# Generated directories
CORE_SOURCES := $(filter-out Core/Src/main.c,$(wildcard Core/**/*.c))
DRIVER_SOURCES := $(wildcard Drivers/STM32WBxx_HAL_Driver/**/*.c)
C_SOURCES := $(CORE_SOURCES) $(DRIVER_SOURCES)
# ASM sources
ASM_SOURCES := startup_stm32wb55xx_cm4.s
# C++ sources
CXX_SOURCES := $(wildcard App/**/*.cpp App/*.cpp)
#######################################
# binaries
#######################################
PREFIX := arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC := $(GCC_PATH)/$(PREFIX)gcc
CXX := $(GCC_PATH)/$(PREFIX)g++
AS := $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP := $(GCC_PATH)/$(PREFIX)objcopy
SZ := $(GCC_PATH)/$(PREFIX)size
else
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
AS := $(PREFIX)gcc -x assembler-with-cpp
CP := $(PREFIX)objcopy
SZ := $(PREFIX)size
endif
HEX := $(CP) -O ihex
BIN := $(CP) -O binary -S
#######################################
# CFLAGS
#######################################
# cpu
CPU := -mcpu=cortex-m4
# fpu
FPU := -mfpu=fpv4-sp-d16
# float-abi
FLOAT-ABI := -mfloat-abi=hard
# mcu
MCU := $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
# macros for gcc
# AS defines
AS_DEFS :=
# C defines
C_DEFS := \
-DUSE_HAL_DRIVER \
-DSTM32WB55xx
# AS includes
AS_INCLUDES :=
# C includes
C_INCLUDES := \
-isystem Core/Inc \
-isystem Drivers/STM32WBxx_HAL_Driver/Inc \
-isystem Drivers/STM32WBxx_HAL_Driver/Inc/Legacy \
-isystem Drivers/CMSIS/Device/ST/STM32WBxx/Include \
-isystem Drivers/CMSIS/Include
# compile gcc flags
ASFLAGS := $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CXXFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -fdata-sections -ffunction-sections -std=c++2a -Wall -Wextra -Wpedantic -Werror
MAKEFLAGS += --jobs=12
ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
CXXFLAGS += -g -gdwarf-2
endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(#:%.o=%.d)"
CXXFLAGS += -MMD -MP -MF"$(#:%.o=%.d)"
#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT := stm32wb55xx_flash_cm4.ld
# libraries
LIBS := -lc -lm -lnosys
LIBDIR :=
LDFLAGS := $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
info: $(info $(VPATH))
#######################################
# build the application
#######################################
# list of C objects
OBJECTS := $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of C++ objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(CXX_SOURCES:.cpp=.o)))
vpath %.cpp $(sort $(dir $(CXX_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $#
$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
$(CXX) -c $(CXXFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $#
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $#
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
$(CXX) $(OBJECTS) $(LDFLAGS) $(CXXFLAGS) -o $#
$(SZ) $#
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $#
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $#
$(BUILD_DIR):
mkdir $#
#######################################
# clean up
#######################################
clean:
-rm -rf $(BUILD_DIR)
#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
Now, the C_SOURCES directory (Core/Src/, etc) contains main.c that I want to ignore (which I have tried to do, with filter-out). I have reimplemented all of it in main.cpp in CXX_SOURCES, i.e. App/Src/, which I want to compile instead.
However, it looks like the automatic dependency generation still finds, compiles and links Core/Src/main.c instead of App/Src/main.cpp. I am very new to makefiles as a whole and am not sure how to handle this. What can I do?

makefile error: “make: *** No rule to make target …”

I'm trying to use GCC (linux) with a makefile to compile my project.
I get the following error
"No rule to make target 'output/src/main.o', needed by 'test'. Stop."
This is the makefile:
COMPILE_PREX ?=
CC = $(COMPILE_PREX)gcc
SOURCE = $(wildcard src/*.c)
OBJS = $(addprefix ./output/, $(patsubst %.c, %.o, $(SOURCE)))
INCLUDES = -I ./src
CFLAGS += -O2 -Wall -g
LDFLAGS += -lpthread
TARGET = test
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $(TARGET)
%.o: %.c
#mkdir -p ./output
$(CC) $(CFLAGS) $(INCLUDES) -o $(addprefix ./output/, $#) -c $<
clean:
rm -rf ./output
This should work. Note the use of mkdir $(#D) to create output directories as needed.
COMPILE_PREX ?=
CC = $(COMPILE_PREX)gcc
SOURCE = $(wildcard src/*.c)
OBJS = $(addprefix output/, $(patsubst %.c, %.o, $(SOURCE)))
INCLUDES = -I src
CFLAGS += -O2 -Wall -g
LDFLAGS += -lpthread
TARGET = test
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $(TARGET)
output/%.o: %.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) $(INCLUDES) -o $# -c $<
clean:
rm -rf output
Running it here with make clean test:
rm -rf output
gcc -O2 -Wall -g -I src -o output/src/hello.o -c src/hello.c
gcc output/src/hello.o -lpthread -o test

What does “linker input file unused because linking not done” mean?

This is weird. The compiler throws this warning though everything works as expected.
This is the makefile that throws the warning:
TARGET = $(notdir $(shell pwd))
LIBS = -lm -lev3dev-c
D_BIN = Build-Assets
ifeq ($(OS),Windows_NT)
LIBS := $(LIBS) -lws2_32
D_BIN := $(D_BIN)/mingw
endif
D_H = ../../source/ev3
CFLAGS = $(addprefix -I, $(D_H)) -O2 -std=gnu99 -W -Wall -Wno-comment
ifeq ($(OS),Windows_NT)
CC = gcc
else
CC = arm-linux-gnueabi-gcc
endif
ifeq ($(OS),Windows_NT)
E_BIN = .exe
else
E_BIN =
endif
F_BIN = $(TARGET)$(E_BIN)
OBJECTS = $(addprefix $(D_BIN)/, $(patsubst %.c, %.o, $(wildcard MotorControl/*.c)))
.PHONY: default all clean
default: $(F_BIN)
all: default
$(OBJECTS): $(D_BIN)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(F_BIN) $(OBJECTS)
$(F_BIN): $(OBJECTS)
$(CC) $(OBJECTS) -c -Wall $(LIBS) -o $#
clean:
-rm -f $(D_BIN)/*.o
-rm -f $(F_BIN)
I should add that I have no idea what I'm doing... I am just starting out with C and those damn makefiles are very overwhelming.
The -c option skips the final link and produces a relocatable object file:
$(F_BIN): $(OBJECTS)
$(CC) $(OBJECTS) -c -Wall $(LIBS) -o $#
This is why linker input files are not used at this stage. You should be able to remove the -c option, and the command will produce an executable as a result.

Automatic dependency processing in Makefile

I have a simple makefile.
IDIR =./include
CC=gcc
CFLAGS=-I$(IDIR)
SRCDIR = ./src
ODIR=obj
LDIR =./lib
LIBS=-lm
SRC = hellomake hellofunc
OBJ = ${SRC:%=$(ODIR)/%.o}
_DEPS = hellomake.h
DEPS = ${_DEPS:%=$(IDIR)/%}
$(ODIR)/%.o: $(SRCDIR)/%.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ hellomake
What I don't like about this Makefile is that the dependency generation.
.c.o
Is it possible to teach make file that the .c is in src directory, and .o is in obj directory to make this simple one?
.c.o:
$(CC) -c -o $# $< $(CFLAGS)
header dependency
Is it possible to teach make file that all the c files are recompiled automatically when header files that the c file contains is changed?
Preliminaries
Generating dependencies
gcc's -MM -MG can be used to create the dependencies: gcc -MM -MG src/hellofunc.c -I./include will create hellofunc.o: src/hellofunc.c include/hellomake.h. However, we need to include the .d file itself into the .d file, so we use sed to achieve that goal.
gcc -MM -MG src/hellofunc.c -I./include | sed -e 's#^\(.*\)\.o:#\1.d \1.o:#'
The results will be as follows:
hellofunc.d hellofunc.o: src/hellofunc.c include/hellomake.h
When we want to change the content to include the different directory location, we can modify the sed script.
gcc -MM -MG src/hellofunc.c -I./include | sed -e 's#^\(.*\)\.o:#obj/\1.d obj/\1.o:#'
The results will be as follows:
obj/hellofunc.d obj/hellofunc.o: src/hellofunc.c include/hellomake.h
include
-include $(DEPS) will include the files in DEPS directory, the - in front of the include teaches the make to ignore when the directories does not exits.
Pattern matching and replacement
We can substitute any pattern (%) or pattern that ends with c (%.c) as follows:
OBJDIRS := $(patsubst %, $(OBJDIR)/%, $(MODULES))
OBJS := $(patsubst %.c, $(OBJDIR)/%.o, $(SRCS))
We also can have shorthand form.
DEPS := $(OBJS:.o=.d)
filter
We can select only some of the files with filter, this is an example:
OBJ := $(patsubst %.c, %.o, $(filter %.c, $(SRC)))
Method 1
In this method, we specify the dependency (.d depends on .c), and include the created dependency file with include.
.PHONY: clean depend
CC := gcc
CXX := g++
LD := g++
CP := cp
PROG := hellomake
MODULES := src
OBJDIR := obj
default: $(PROG)
OPTFLAGS := -g -O
CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES))
GARBAGE := core core.* *.stackdump ./tags $(PROG)
include $(patsubst %, %/module.make, $(MODULES))
OBJ := \
$(patsubst %.c, %.o, $(filter %.c, $(SRC)))
DEP := $(OBJ:.o=.d)
# implicit rules
%.d: %.c
./depends.sh $(CC) `dirname $*.c` $(CFLAGS) $*.c > $#
-include $(DEP)
# Actual targets
depend: $(DEP)
clean:
rm -rf $(PROG) $(OBJ) $(GARBAGE) $(DEP) depends
$(PROG): $(OBJ)
$(LD) -o $# $^ $(LIBS)
Each module should contain the make file (module.make) to specify what files are included in the SRC variable.
`SRC += src/hellofunc.c \
src/hellomake.c`.
This is the script to generate the dependency file:
#!/bin/sh
#echo "## Got: $*"
CC="$1"
DIR="$2"
shift 2
case "$DIR" in
"" | ".")
$CC -MM -MG "$#" | sed -e 's#^\(.*\)\.o:#\1.d \1.o:#'
;;
*)
$CC -MM -MG "$#" | sed -e "s#^\(.*\)\.o:#$DIR/\1.d $DIR/\1.o:#"
;;
esac
This method is simple, but the object files and dependency files are created in the same src directory with these statements.
SRC += src/hellofunc.c src/hellomake.c
OBJ := $(patsubst %.c, %.o, $(filter %.c, $(SRC)))
DEP := $(OBJ:.o=.d)
Method 2
This method creates the object directory, and puts all the generated (intermediate) files into the directory.
It enlists all the modules to specify the actions both for object file and dependency file generation.
In the example, we have only one module, but with multiple modules, we need to duplicate the statements.
obj/src/%.o: src/%.c
$(CC) -c $< -o $# $(CFLAGS)
obj/src/%.d: src/%.c
gcc -MM -MG $< $(CFLAGS) | sed -e 's#^\(.*\)\.o:#obj/src/\1.d obj/src/\1.o:#' > $#
This is the makefile:
.SUFFIX = .o .c
.PHONY: clean
CC := gcc
LD := gcc
PROG := hellomake
OBJDIR = obj
MODULES := src
SRCS := src/hellofunc.c src/hellomake.c
OBJDIRS := $(patsubst %, $(OBJDIR)/%, $(MODULES))
OBJS := $(patsubst %.c, $(OBJDIR)/%.o, $(SRCS))
DEPS := $(OBJS:.o=.d)
default: $(PROG)
CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES))
CXXFLAGS += $(CFLAGS)
obj/src/%.o: src/%.c
$(CC) -c $< -o $# $(CFLAGS)
$(PROG): $(OBJDIRS) $(OBJS)
$(LD) $(filter %.o, $^) -o $(PROG)
-include $(DEPS)
obj/src/%.d: src/%.c
gcc -MM -MG $< $(CFLAGS) | sed -e 's#^\(.*\)\.o:#obj/src/\1.d obj/src/\1.o:#' > $#
depend: $(DEPS)
GARBAGE := core core.* *.stackdump ./tags $(PROG)
clean:
rm -rf $(PROG) obj/*
$(OBJDIRS):
mkdir -p $#
References
Create directories when generating object files in gcc
How to place object files in separate subdirectory
make deleting dependency files
http://scottmcpeak.com/autodepend/autodepend.html
IDIR = ./include
CC = gcc
CFLAGS = -I$(IDIR)
SRCDIR = src
ODIR = obj
LDIR = ./lib
LIBS = -lm
SRC = hellomake hellofunc
OBJ = ${SRC:%=$(ODIR)/%.o}
_DEPS = hellomake.h
DEPS = ${_DEPS:%=$(IDIR)/%}
%.o: ../$(SRCDIR)/%.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ) $(DEPS)
gcc -o $# $^ $(CFLAGS) $(LIBS)

Can not create shared object from object files

I have wrote a makefile to compile a dynamic library. However, output .so file does not contains all of the methods.
I have used this Makefile:
CC=g++
CFLAGS=-fPIC -g
LDFLAGS=-shared
SRCDIR=src
SOURCES=$(shell echo $(SRCDIR)/*.cpp)
HEADERS=$(shell echo $(SRCDIR)/*.h)
OBJECTS=$(SOURCES:.cpp=.o)
LIBDIR=lib
INCDIR=include
LIBRARIES=-lboost_filesystem -lboost_system -lopencv_core -lopencv_highgui -lopencv_imgproc
OUT=$(LIBDIR)/libAgeGender.so
all: $(SOURCES) $(HEADERS) $(OUT)
.cpp.o:
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
$(OUT): $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) $(LIBRARIES) -o $# $(LDFLAGS)
clean:
rm -f $(SRCDIR)/*.o *~ $(SRCDIR)/*~ $(OUT)
Then i executed this command to see functions inside of an .o file.
nm SDaisy.o | grep ' T '
00000000000070d6 T _ZN6SDaisy11convolutionERKN2cv3MatESt6vectorIfSaIfEEi
000000000000933e T _ZN6SDaisy12extractDaisyERKN2cv3MatE
0000000000007498 T _ZN6SDaisy14gaussianFilterERKN2cv3MatEff
000000000000854a T _ZN6SDaisy16smoothHistogramsERN2cv3MatE
000000000000c088 T _fini
0000000000005960 T _init
When we look into shared object, we can't see methods.
$ nm libAgeGender.so | grep ' T '
0000000000000578 T _fini
0000000000000438 T _init
How can i make it correctly?
Use the right variables and functions, and let make handle the compilation of .o files.
SRCDIR := src
LIBDIR := lib
INCDIR := include
SRC := $(wildcard $(SRCDIR)/*.cpp)
OBJ := $(SRC:.cpp=.o)
OUT := $(LIBDIR)/libAgeGender.so
CXXFLAGS := -fPIC -g
LDFLAGS := -shared
LDLIBS := -lboost_filesystem -lboost_system \
-lopencv_core -lopencv_highgui -lopencv_imgproc
all: $(OUT)
$(OUT): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#

Resources