How to write Makefile to include multi directories - gcc

I have the following setup. Two folders named /driverlib and /inc on the main folder and on the same folder I have a linker file and two c files, startup_gcc and blink.c.
I followed a template I found online for STM32F4. I modified it and tried to include both directories on my folder. However I am getting the following error:
C:\Users\D\Documents\ARM-Tiva\blinky3>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
Can somebody explain to me how to include both directories so that the /inc folder is visible to the /driverlib folder.
Here's the makefile:
OBJCOPY = $(TC)-objcopy
OBJDUMP = $(TC)-objdump
SIZE = $(TC)-size
###################################################
# Set Include Paths
INCLUDES = -I /inc
INCLUDES = -I /driverlib
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) startup_gcc.o
# Set Libraries
LIBS = -lm -lc
###################################################
# Set Board
MCU = -mthumb -mcpu=cortex-m4
DEFINES = -DPART_LM4F120H5QR -DTARGET_IS_BLIZZARD_RA1
# Set Compilation and Linking Flags
CFLAGS = $(MCU) $(FPU) $(DEFINES) $(INCLUDES) \
-g -Wall -std=gnu90 -O0 -ffunction-sections -fdata-sections
ASFLAGS = $(MCU) $(FPU) -g -Wa,--warn -x assembler-with-cpp
LDFLAGS = $(MCU) $(FPU) -g -gdwarf-2 \
-Ttivalinker.ld \
-Xlinker --gc-sections -Wl,-Map=$(PROJ_NAME).map \
$(LIBS) \
-o $(PROJ_NAME).elf
###################################################
# Default Target
all: $(PROJ_NAME).bin info
# elf Target
$(PROJ_NAME).elf: $(LIB_OBJS) $(USER_OBJS)
#$(CC) $(LIB_OBJS) $(USER_OBJS) $(LDFLAGS)
#echo $#
# bin Target
$(PROJ_NAME).bin: $(PROJ_NAME).elf
#$(OBJCOPY) -O binary $(PROJ_NAME).elf $(PROJ_NAME).bin
#echo $#
#$(PROJ_NAME).hex: $(PROJ_NAME).elf
# #$(OBJCOPY) -O ihex $(PROJ_NAME).elf $(PROJ_NAME).hex
# #echo $#
#$(PROJ_NAME).lst: $(PROJ_NAME).elf
# #$(OBJDUMP) -h -S $(PROJ_NAME).elf > $(PROJ_NAME).lst
# #echo $#
# Display Memory Usage Info
info: $(PROJ_NAME).elf
#$(SIZE) --format=berkeley $(PROJ_NAME).elf
# Rule for .c files
.c.o:
#$(CC) $(CFLAGS) -c -o $# $<
#echo $#
# Rule for .s files
.s.o:
#$(CC) $(ASFLAGS) -c -o $# $<
#echo $#
# Clean Target
clean:
$(RM) $(LIB_OBJS)
$(RM) $(USER_OBJS)
$(RM) $(PROJ_NAME).elf
$(RM) $(PROJ_NAME).bin
$(RM) $(PROJ_NAME).map
The issue is obviously at this paragraph:
###################################################
# Set Include Paths
INCLUDES = -I /inc
INCLUDES = -I /driverlib
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) startup_gcc.o
I cannot understand why driverlib does not include the inc directory files.
EDIT
I wanted to clarify my setup for future reference: On the main folder called blinky I have three folders : driverlib, inc and src. The driverlib and inc folders are taken from the TivaWARE folder while the src folder contains the blinky.c and startup_gcc.c file. Given the following if you use make you obtain the following :
C:\Users\D\Documents\ARM-Tiva\blinky>make
driverlib/adc.c:49:24: fatal error: inc/hw_adc.h: No such file or directory
compilation terminated.
make: *** [driverlib/adc.o] Error 1
This shows that the file adc.c in the driverlib folder cannot include the file hw_adc.h in
I modified the Makefile following the suggestions below:
# Set Sources
LIB_SRCS = $(wildcard driverlib/*.c)
USER_SRCS = $(wildcard src/*.c)
# Set Objects
LIB_OBJS = $(LIB_SRCS:.c=.o)
USER_OBJS = $(USER_SRCS:.c=.o) src/startup_gcc.o
# Set Include Paths
INCLUDES = -Idriverlib/ \
-Iinc \
-Isrc/
Betas solution was helpful , the only issue was that I did not want to edit all the files in the driverlib folder. The naming convention of the directories was not my decision. If you can see all the files in the driverlib folder you'll find out that each driver file , CAN driver for example or ADC) follows this convention :
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"
So right now I understand where the issue is but I lack the understanding to edit the Makefile.
Normally if files can.c and can.h are in folder driverlib using #include "can.h" would suffice so I do not understand what's the point of using #include "driverlib/can.h" if all .h and .c files are in the same driverlib folder . If I edit all the inc/ header then I can get a working binary file. The aim however was not to modify the default stock driver files and folders obtained from TI but to use the Makefile.
So to clarify if you follow Betas solution and edit all the files , or if you put all the files in one big directory then you can get a working binary file. Also for future reference I found I could use Energia for what I am doing since it uses the same compiler and TIVA includes the complete peripheral library burned on ROM.

I don't know the cause of the error exactly, but this is not correct:
INCLUDES = -I /inc
# Now INCLUDES is "-I /inc"
INCLUDES = -I /driverlib
# Now INCLUDES is "-I /driverlib", and inc has been forgotten.
I think you mean this:
INCLUDES = -I /inc
INCLUDES += -I /driverlib
EDIT:
It's generally a bad idea to spell out paths in the #include directives. In adc.c, change this:
#include "inc/hw_adc.h"
to this:
#include "hw_adc.h"
and in the makefile remove the leading slashes (since you won't always be in the root directory):
INCLUDES = -I inc
INCLUDES += -I driverlib

The most helpful thing would have been if you had provided the actual complete path of one of the header files which is not being found, in your question, and an example compile line run by make in addition to the error message. Given that information it's trivial to see what's wrong.
It looks like some miscommunication is happening. You write two folders named /driverlib and /inc on the main folder. A folder name that begins with a / is by definition at the root of the directory structure, not within any other folder. I don't know what you mean by on the main folder.
The first thing I'll say is that you're using Windows (as can be seen by your command line prompt), and so you need to be sure that the version of make you're using will do the right thing converting Windows pathnames to UNIX pathnames. For example if you're using Cygwin version of GNU make, then I think the paths you're using are not correct.
Second, I note that you are using -I /inc; that is, the inc directory is at the root of your filesystem. Is that what you intended? Beta's answers have changed that to -I inc, which means the directory inc as a subdirectory of the current working directory, which could be quite different.
Third, if the pathname to the headers is /inc/hw_adc.h and you have -I /inc on your command line and #include "inc/hw_adc.h", I'm sure you can see how this will absolutely not work. The compiler will be looking for header files named /inc/inc/hw_adc.h. If you want to keep the relative pathname inc/hw_adc.h in your #include line, and the path to the header file is /inc/hw_adc.h, then you should use just -I / (the root directory) on the compile command line.
Lastly, I'll say that I actually don't agree with Beta's suggestion that it's a bad idea to spell out paths in include lines. This is common: if you are using a library that contains a lot of header files then typically the header files are collected in a subdirectory (consider things like Boost, or X11, etc.) and it's, IMO, good practice to use the name of the subdirectory in your #include lines in the source code.
On the other hand, though, I will agree with Beta that a directory name like inc is utterly lame and is of pretty much no use whatever. That directory should have a name which is somehow evocative of the kinds of headers that can be found inside it, not something uselessly generic like "inc".

Related

Makefile to generate a binary file for each source file

I have the following structure in my project.
/
src/
bin/
Makefile
In src directory there will be multiple src files (each has a main function). I need to write makefile such that when I run
make program1
It should search for program1.c in src folder and compile the executable as program1* in bin folder.
I have came across this question How can Makefile use separate directories for source code and binaries?
But, it seems that I need to manually enter all program names into PROG variable.
I just need to supply binary name with make and it should do the compilation for that respective src file?
Okay, after a bit of experimentation with my Makefile. I finally got the solution for my problem.
Current Build System
CC = gcc
CFLAGS = -g -Wall
SRC = ./src/
BIN = ./bin/
%: $(SRC)%.c
$(CC) $(CFLAGS) $< -o $(BIN)$#
.PHONY: clean
clean:
rm $(BIN)*

Makefile: compiling several unit test *.out files into a single test executable (C++)

Please forgive me if this is a repeat question. I am fairly new to writing Makefiles, and so I was not really sure how to find what I am looking for.
I am getting acquainted with Boost.Test and am writing unit tests on a file-per-file basis.
This is my directory structure:
- cpp
- sim
- Makefile
- bin
- src
- ExampleClass.cpp
- tests
- Makefile
- bin
- src
-ExampleClass_T.cpp
Essentially, I would like to write individual *.cpp test case files using Boost, as displayed above.
Here is the content of my tests/Makefile:
CC = g++
CPPFLAGS = -g -v -Wall -I$(ODIR_TEST) -I$(SDIR_TEST) \
-I$(SDIR) -I$(ODIR) -I$(BOOST_ROOT)
ODIR_TEST = ./bin
SDIR_TEST = ./src
ODIR = ../sim/bin
SDIR = ../sim/src
%.out : $(SDIR_TEST)/%.cpp
$(CC) $(CPPFLAGS) -o $< $#
executing make generates a No targets. Stop. error message. Any ideas as to why make thinks there is no target? Wouldn't %.out act as the target here, or can a wildcard not act in that manner?
I recognize that in the Makefile above, I am attempting to generate a *.out file for each *.cpp file; in addition, I would like to generate a final executable that is a culmination of all generated *.out files. Is this possible, or am I approaching this incorrectly?
Any other advice or Makefile best practices, especially with regards to test automation, would be highly appreciated.
I have seemed to have found a workaround, though it can likely be optimized.
PROG = main
CC = g++
CPPFLAGS = -g -Wall -I$(ODIR_TEST) -I$(SDIR_TEST) \
-I$(SDIR) -I$(ODIR) -I$(BOOST_ROOT)
ODIR_TEST = ./bin
SDIR_TEST = ./src
OUTDIR = ./execs
ODIR = ../sim/bin
SDIR = ../sim/src
TEST_EXEC_NAMES = $(notdir $(basename $(wildcard $(SDIR_TEST)/*.cpp)))
# default rule (main.cpp)
$(OUTDIR)/$(PROG) : $(SDIR_TEST)/main.cpp $(TEST_EXEC_NAMES)
$(CC) $(CPPFLAGS) -o $# $<
% : $(SDIR_TEST)/%.cpp
$(CC) $(CPPFLAGS) -o $(OUTDIR)/$# $<
I specify a default target in my first rule. I include $(TEST_EXEC_NAMES) as a prereq to make sure that all of my individual test executables are built using the pattern rule.
Specifying my executable filenames from their .cpp counterparts is done with a series of function calls (wildcard, basename, and notdir).
Again, this is surely not the fastest way I could accomplish my task, but it has gotten me onto compilation errors.

makefile .mod compilation rule

I'm modifying makefile of a code. After compiling, I see that some *.mod files are generated. looking online, I figured out they are module files, but I don't see a compilation rule for them. I'm trying to change the directory in which these files are generated. I can change the rule for object files, but I can't find the rule that generates *.mod files.
Looking at the makefile, can someone advise me if a line in this file generates them or how to change their directory. Here is the makefile:
# GNU Makefile
# Paths
SDIR=./solver
ODIR=./obj
_CASE=./WorkCases/problem
CASE=$(SDIR)/$(_CASE)
TOP = .
FC = ifort
FFLAGS = -fpp -O1 -DPTR_INTEGER8 -warn nousage
# Define rule to make .f90
$(ODIR)/%.o : $(SDIR)/%.f90
$(FC) -c $(FFLAGS) $< -o $#
# set executable name
EXEC = $(dir ${CASE})/$(basename $(notdir ${CASE})).out
# shared global variables
_SHARED_OBJ = shared_modules.o main_vars.o debug_vars.o
SHARED_OBJ = $(patsubst %,$(ODIR)/%,$(_SHARED_OBJ))
OBJ = ${_SHARED_OBJ} $(_CASE).PARAMS.o
OBJ = $(patsubst %,$(SDIR)/%,$(_OBJ))
MAIN_OBJ = $(ODIR)/main.o
main : ${SHARED_OBJ} $(OBJ) $(MAIN_OBJ)
$(FC) ${FFLAGS} $(OBJ) $(MAIN_OBJ) -o $(EXEC) -lstdc++ -shared-intel
You can specify the destination directory for the .mod files by using the -module compiler option.
-module <directory>
See the ifort documentation here:
You can use the module path compiler option to specify the directory
in which to create the module files. If you do not use this option,
module files are created in the current directory.

How to compile files that reside in different directory in Makefile?

I have seen this questions asked before but was not able to decipher those answers.
Lets say I reside in working directory, lets call it proj and this proj directory contains src folder which contains all the *.cpp files. I want to compile those file staying on the proj directory because in future I will be creating bin directory and placing the *.o and binary in bin.
So my proj directory currently contains : Makefile and src
What I have done so far is :
SOURCE = src
# This gives the path to the proj directory
CURRENT_DIR = $(shell pwd)
# This gives list of all the *.cpp files
SRC = $(shell cd $(SOURCE) && echo *.cpp)
# Here all the name of the files stored in SRC are converted from *.cpp to *.o
OBJS = $(SRC:.cpp=.o)
.PHONY: all
all: $(TARGE)
# use the content of SRC to compile
$(TARGET): $(OBJS)
$(info $(OBJS))
$(OBJS): $(SRC)
$(CC) $(FLAGS) -c $?
When I try to run the make command it says
make: *** No rule to make target 'xxx.cpp', needed by 'xxx.o'. Stop
Now I know what it is trying to say. It gives error because although it knows the name of the file, since the file is not in the current directory makefile does not know about src folder and hence have no clue about the *.cpp files.
So my question is: Is there any macros or trick to use in makefile to make sure makefile see the xxx.cpp in src folder while staying in the current directory( I don't want to specify the folder by hand here)?

Makefile not finding the include file

I Have a folder structure like this.
Gif_Utility
-> Makefile
-> include ( all .h files are over here)
-> Src ( all .c files are over here).
I am writing a makefile.
Makefile
VPATH = src:include
INC = -I ./include
gif_objects = gif_display.o \
gif_lzw.o \
gif_read.o \
sysm.o \
x86_main.o
gif_display.0 : gif_display.c
gcc -I /export/home/joshis1/MakeTutorial/GIF_Utility/include -c $<
#gif_lzw.0 : gif_lzw.c
# gcc $(INC) -c src/gif_lzw.c
#gif_read.0 : gif_read.c
# gcc -I ./include/ -c $<
#sysm_main.0 : sysm_main.c
# gcc -I ./include/ -c $<
#x86_main.0 : x86_main.c
# gcc -I ./include/ -c $<
On command prompt:
$ make gif_display.o
cc -c -o gif_display.o src/gif_display.c
src/gif_display.c:2:17: fatal error: sysm.h: No such file or directory
compilation terminated.
make: *** [gif_display.o] Error 1
On the other hand, If i do like this it compiles fine
$make
-> this creates the gif_display.o
I don't know why it is throwing error on specifying the rule. Am I missing something, please help.
I am using Ubuntu machine to build my code.
Your makefile has a .0 (zero) suffix instead of the correct .o (letter oh).
When you run just make it attempts to build the first target in the Makefile, and so runs the recipe which contains the correct -I include path. The fact that it produces an .o file, not a .0 file, is acceptable to make, although I suppose it could at least print a warning in this scenario.
When you run make gif_display.o it uses Make's built-in productions for .o files, which do not contain your include path.
Given that make already has built-in rules for .o files, your rules are basically superfluous. It would be better to just add the -I include parameter to the default rules, with something like
CFLAGS += -I include
So the entire Makefile could be as simple as this:
VPATH = src:include
CFLAGS += -I ./include
gif_objects = gif_display.o \
gif_lzw.o \
gif_read.o \
sysm.o \
x86_main.o
I don't see anything to alert your Makefile to changes in .h files, so you might want to add a separate dependency for that. If you just have a few shared header files between all your object files, maybe this will be all you need:
$(gif_objects): $(wildcard include/*.h)
This basically makes the include component of the VPATH superfluous.

Resources