foreach duplicate include in makefile - makefile

I'm trying to include some headers using Makefile.
Here's the code I did:
# Add .h and .hpp to the preprocessor build
HEADERS += $(wildcard src/*.h)
HEADERS += $(wildcard src/*.hpp)
HEADERS += $(wildcard src/**/*.h)
HEADERS += $(wildcard src/**/*.hpp)
INCLUDES = $(foreach HEADERS, $(HEADERS), -I$(dir $(HEADERS)))
# FLAGS will be passed to both the C and C++ compiler
FLAGS +=
CFLAGS +=
CXXFLAGS += $(INCLUDES)
But once I build, that's what it execute:
g++ -Isrc/ -Isrc/ -Isrc/ -Isrc/misc/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Isrc/widgets/ -Wsuggest-override -std=c++11 -DSLUG=NWK -fPIC -I../../include -I../../dep/include -O3 -DVERSION=0.6.4 -MMD -MP -g -march=nocona -ffast-math -fno-finite-math-only -Wall -Wextra -Wno-unused-parameter -DARCH_WIN -D_USE_MATH_DEFINES -c -o build/src/plugins/MyPlug.cpp.o src/plugins/MyPlug.cpp
It seems that, for each .h/.hpp it found, it replicate the HEADER flag.
How would you fix it?

A simple solution is to just pass your search through $(sort ...). In make, $(sort ...) removes any duplicates:
INCLUDES = $(sort $(foreach HEADERS, $(HEADERS), -I$(dir $(HEADERS))))
One note -- sort does change the order of the include directories, which in turn will change the order the directories will be searched, however, the method you are using to populate your lists does not seem to be order dependent, so you should be good.

Related

Why is STM32CubeIDE not showing SFR registers when debugging?

I imported a project in STM32CubeIDE with the option "Makefile Project with Existing Code". I created this project without using any IDE, so I had to write my own makefile.
CC = arm-none-eabi-gcc -c
LD = arm-none-eabi-gcc
LIBNAME_OPENCM3 = opencm3_stm32f1
OPT = -Os
DEFS += -DSTM32F1
DIR_OPENCM3 = ./libopencm3
DIR_INC = ./inc
DIR_OBJ = ./obj
DEBUG = -ggdb3
LDSCRIPT = stm32f1.ld
DIR_FLAGS = -I$(DIR_INC)
ARCH_FLAGS = -mthumb -mcpu=cortex-m3
LDFLAGS += --static -nostartfiles
LDFLAGS += -T$(LDSCRIPT)
LDFLAGS += $(ARCH_FLAGS) $(DEBUG)
LDFLAGS += -Wl,-Map=$(*).map -Wl,--cref
LDFLAGS += -Wl,--gc-sections
ifeq ($(V),99)
LDFLAGS += -Wl,--print-gc-sections
endif
LDFLAGS += -u _printf_float
LDFLAGS += -L$(DIR_OPENCM3)/lib
LDLIBS += -l$(LIBNAME_OPENCM3)
LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
CFLAGS += $(OPT) $(DEBUG) $(ARCH_FLAGS)
CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration
CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
CFLAGS += -fno-common -ffunction-sections -fdata-sections
CFLAGS += -std=c11
DEFS += -I$(DIR_OPENCM3)/include
PREPFLAGS = -MD -Wall -Wundef $(DEFS)
OBJS = $(DIR_OBJ)/main.o \
$(DIR_OBJ)/bmp180.o
main.elf : $(OBJS) $(LDSCRIPT)
$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o main.elf
$(DIR_OBJ)/%.o : %.c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) $(DIR_FLAGS) $(PREPFLAGS) $< -o $#
clean :
rm -rf $(DIR_OBJ) *.elf *.map *.d
all :
make
The project is compiled successfully and it's running, but when I started to debug, this IDE didn't show the SFR registers. That window is empty.
I created a different project, this time with the IDE, and it shows me the registers.
I suppose that it has something to do with my makefile. Is there an extra flag that I need to add or why is this happenning?
coming up on this after some time since i JUST faced the exact same problem (using STM32CubeIDE 1.9.0 on Win10)
It all generated when I imported an existing makefile project into the IDE...
Was able to debug from within the IDE (using STLINK) but SFR view was oddly empty...
I resolved by playing with the "Project Nature" settings, despite the threatening messages from the IDE itself ( too bad :S )
after the import, the project got configured with 3 natures: ccnature, managedBuildNature, ScannerConfigNature
I added a 4th nature: MCUProjectNature (select STM32CubeIDE Project from the list in the dialog which shows up)
ta-da!!!
The project Properties (finally!) started to show the CMSIS-SVD settings tab which allows me to point to the .SVD device file describing the MCU used
I specified this string (copied from a project generate completely inside the IDE):
platform:/plugin/com.st.stm32cube.ide.mcu.productdb.debug/resources/cmsis/STMicroelectronics_CMSIS_SVD/STM32xxxx.svd
(replace xxxx with your MCU micro, search your STM32CubeIDE installation plugin folder for *.svd)
I hope this can relief the pain from banging one's head against the wall in search for a fix

Simplifying a makefile

I have written a scary-looking Makefile by copy/pasting suggestions from Stack Overflow. However, I have read that it might not be necessary to provide explicit compiler invocations so many times (for example, the -O3 flag is everywhere). How can I simplify this Makefile?
CFLAGS = -Weverything -Wno-padded -Wno-unused-parameter -Wno-unused-variable -Wno-sign-conversion
all: fianchetto.o util.o ttable.o movegen.o
clang -O3 $(CFLAGS) -D NDEBUG $^ -o fianchetto
debugf: fianchetto.o ttable.o movegen.o
clang -O3 $(CFLAGS) -g3 $^ -o fianchetto
clean:
rm *.o && rm *.gch & rm fianchetto && rm -rf fianchetto.dSYM
%.o: %.c
clang -O3 -c $(CFLAGS) $< -o $#
fianchetto.o: fianchetto.c
ttable.o: ttable.h ttable.c
movegen.o: movegen.h movegen.c
util.o: util.h util.c
I am mystified by a lot of the syntax, and would appreciate links or explanations of why simplifications work!
CFLAGS and defines (which should be in CPPFLAGS anyway) are useless when linking
You're reinventing make's built-in rules, make will automatically link a target if one of its dependencies is "target.o" (in this case fianchetto: fianchetto.o). Make also knows how to compile C source files (as long as the source and object path match), so your pattern rule is superfluous too.
The object prerequisites aren't necessary as both clang and GCC can generate dependencies for you with the -M set of flags.
Compiling release and debug builds in the same dir makes for a more simple makefile, although you will need to remember to clean the object files when switching.
By default make assigns cc to CC, and cc should be a link to your system's default compiler, so you might not even need the first line below
CC := clang
CPPFLAGS := -MMD -MP
CFLAGS := -Weverything -Wno-padded -Wno-unused-parameter -Wno-unused-variable -Wno-sign-conversion -O3
objs := fianchetto.o util.o ttable.o movegen.o
deps := $(objs:.o=.d)
.PHONY: all debugf clean
all: CPPFLAGS += -DNDEBUG
debugf: CFLAGS += -g3
all debugf: fianchetto
fianchetto: $(objs)
clean: ; $(RM) $(objs) $(deps) fianchetto fianchetto.dSYM
-include $(deps)

CXXFLAGS changes not being honored?

I have the following in my GNU makefile:
# CXXFLAGS ?= -DNDEBUG -g2 -O3
CXXFLAGS ?=
# Add -DNDEBUG if nothing specified
ifeq ($(filter -DDEBUG -DNDEBUG,$(CXXFLAGS)),)
$(info Adding -DNDEBUG to CXXFLAGS)
CXXFLAGS += -DNDEBUG
endif
# Add a symolize if nothing specified
ifeq ($(filter -g -g1 -g2 -g3 -Oz,$(CXXFLAGS)),)
$(info Adding -g2 to CXXFLAGS)
CXXFLAGS += -g2
endif
# Add an optimize if nothing specified
$(info Adding -O3 to CXXFLAGS)
ifeq ($(filter -O -O0 -O1 -O2 -O3 -Og -Os -Oz -Ofast,$(CXXFLAGS)),)
CXXFLAGS += -O3
endif
When I run it:
$ make CXXFLAGS="-g3"
Adding -DNDEBUG to CXXFLAGS
Adding -O3 to CXXFLAGS
g++ -g3 -c foo.cpp
...
In fact, if I uncomment the CXXFLAGS ?= -DNDEBUG ..., then I can append again. But that's not very helpful since I'm trying to make arguments optional (but with sane defaults).
And if I type just make, then it works (-fPIC -march=native -Wall -Wextra -pipe is added later by the same makefile, and it has always worked):
$ make
Adding -DNDEBUG to CXXFLAGS
Adding -g2 to CXXFLAGS
Adding -O3 to CXXFLAGS
g++ -DNDEBUG -g2 -O3 -fPIC -march=native -Wall -Wextra -pipe -c serpent.cpp
...
According to the manual and 6.6 Appending More Text to Variables:
Often it is useful to add more text to the value of a variable already defined. You do this with a line containing ‘+=’, like this:
objects += another.o
Why is make not adding the values to the variable? How can I achieve the behavior I want?
By passing a variable via command-line, you're telling make that you are overriding any definitions in the file, which allows a user to compile as they intend rather than as you intend. Ignoring the restriction of user freedom, you can use the override directive:
To append more text to a variable defined on the command line, use:
override variable += more text
Variable assignments marked with the override flag have a higher priority
than all other assignments, except another override. Subsequent
assignments or appends to this variable which are not marked override
will be ignored.
I would discourage you from using override when possible because it's annoying to realize that -O0 was needed to disable the optimizations that you enabled when I don't want them enabled (after all, I specify my own flags for a reason). Of course, if no flags were specified at all, then defaults are perfectly reasonable. In fact, Automake projects seem to default to -g -O2 when no compilation flags are specified.
There are exceptions to this advice of course, such as adding a directory to search for includes/libs or preprocessor definitions for compiling a conditional section of code on a certain platform.

gmake compile and link source files in different directories

I'm trying to compile and link several files in different folders using gfortran, and GNU Make 3.81 on a windows machine. I learned how to use wildcards from this reference:
gmake compile all files in a directory
And I want to do something similar to this reference:
Makefiles with source files in different directories
But the difference is that I want to build only one executable in my root directory from the source files in several other directories. I tried reading the make manual:
http://www.gnu.org/software/make/manual/make.html
But it seems primarily directed towards c/c++ programming and non-windows syntax.
My current makefile looks like this:
FC = gfortran
MOD_DIR = "bin"
FCFLAGS = -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized
TARGET = test
SRCS_C = $(wildcard *.f90) $(TARGET).f90
OBJS_C = $(patsubst %.f90,%.o,$(SRCS_C))
all: $(TARGET)
$(TARGET): $(OBJS_C)
$(FC) -o $# $(FCFLAGS) $(OBJS_C)
$(OBJS_C): $(SRCS_C)
$(FC) $(FCFLAGS) -c $(SRCS_C)
clean:
del *.o $(MOD_DIR)\*.mod
Which works fine when all of my source files are in the root directory. And so I thought this would work:
FC = gfortran
MOD_DIR = "bin"
FCFLAGS = -O0 -Og -Wall -pedantic -fbacktrace -fcheck=all
# FCFLAGS += -J$(MOD_DIR) -I$(INCLUDE_DIR) -fopenmp -fimplicit-none -Wuninitialized
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized
TARGET = test
SRCS_C =\
"solvers/"$(wildcard *.f90) \
"user/"$(wildcard *.f90) \
$(wildcard *.f90) $(TARGET).f90
OBJS_C = $(patsubst %.f90,%.o,$(SRCS_C))
all: $(TARGET)
$(TARGET): $(OBJS_C)
$(FC) -o $# $(FCFLAGS) $(OBJS_C)
$(OBJS_C): $(SRCS_C)
$(FC) $(FCFLAGS) -c $(SRCS_C)
clean:
del *.o $(MOD_DIR)\*.mod
Where I don't mind just entering the names of the folders where a list of source files can be taken from. I've also tried using -I$(INCLUDE_DIR), but this didn't work either. The error from what I have above is:
gmake: *** No rule to make target `"user/"gridFun.f90', needed by `"user/"gridFu
n.o'. Stop.
Any help is greatly appreciated!
To accomplish what you want with SRCS_C, consider using:
SRCS_C =\
$(wildcard solvers/*.f90) \
$(wildcard user/*.f90) \
$(wildcard *.f90) $(TARGET).f90
Also note that (TARGET).f90 will also be matched by $(wildcard *.f90), in your cases causing test.f90 to be included twice in SRCS_C. You can safely omit $(TARGET).f90 in this example.

Creating a simple Makefile to build a shared library

I am trying to create a very basic hand crafted Makefile to create a shared library to illustrate a point.
This is what I have so far:
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99 -Iinclude
CFLAGS = -fPIC -pedantic -Wall -Wextra -march=native -ggdb3
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(shell echo src/*.c)
HEADERS = $(shell echo include/*.h)
OBJECTS = $(SOURCES:.c=.o)
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
When I run make, it attempts to build an application - and ld fails because it can't resolve main().
Problem seems to be with CFLAGS - I have specified -fPIC but that is not working - what am I doing wrong?
Edit
I added the -shared flag as suggested, when I run make, I got this error:
gcc -std=gnu99 -Iinclude -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3 -O0 -D _DEBUG -o example.so src/example.o
/usr/bin/ld: src/example.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
src/example.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [example.so] Error 1
Which seems to be suggesting to revert back to -fPIC only.
BTW, my new CFLAGS setting is:
CFLAGS = -fPIC -shared -pedantic -Wall -Wextra -march=native -ggdb3
I am running gcc v4.4.3 on Ubuntu 10.0.4.
The solution was to modify the XXFLAGS as follows:
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
Compile with -shared:
gcc -o libfoo.so module1.o module2.o -shared
(This also works on MingW under Windows to produce DLLs.)
Example for C++ files. I've also included a clean target.
.PHONY : clean
CPPFLAGS= -fPIC -g
LDFLAGS= -shared
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo *.h)
OBJECTS=$(SOURCES:.cpp=.o)
FIKSENGINE_LIBDIR=../../../../lib
FIKSENGINE_INCDIR=../../../../include
TARGET=$(FIKSENGINE_LIBDIR)/tinyxml.so
all: $(TARGET)
clean:
rm -f $(OBJECTS) $(TARGET)
$(TARGET) : $(OBJECTS)
$(CC) $(CPPFLAGS) $(OBJECTS) -o $# $(LDFLAGS)
Since you try to build so file, you probably need -shared.
this is my goto makefile rule for so files:
%.so: %.o ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
can be used like so
CFLAGS+=-fPIC
libmyfoo.so: # create from libmyfoo.o
# or
libmyfoo.so: myfoo.o # create from myfoo.o

Resources