Makefile non-recursive method issues - makefile

I am trying to build using Makefile below code structure using non-recursive method as per the guidance I received in
link description
work
├── code
| |
| └── main.h and test.h files here
│ └── main.c and test.c files here
| └── subdir.mk
|
├── _Build/
│ └── Makefile here
Below is the Makefile
-include ../code/subdir.mk
all : target_file
target_file : ../code/main.o ../code/test.o
#echo Building ...
#echo Linking files ...
gcc -Llib ../code/main.o ../code/test.o -lm -o target_file
clean:
rm -rv ../code/*.o
Below is the subdir.mk file
../code/test.o : ../code/test.c ../code/test.h
#echo Building test.c ...
gcc -Werror -Wall -c ../code/test.c -o ../code/test.o
../code/main.o : ../code/main.c ../code/main.h ../code/test.h
#echo Building main.c ...
gcc -Werror -Wall -c ../code/main.c -o ../code/main.o
The output I am getting while running make command is below
Building test.c ...
gcc -Werror -Wall -c ../code/test.c -o ../code/test.o
There is no error I am getting nor main.o is getting generated. Also in Makefile the linking command is not executed.

That's likely because make by default builds the first target it encounters. Since you include the subdir.mk before your all : target_file line, the first target named in subdir.mk is built, and nothing else. Solution: place the subdir.mk inclusion last, e.g. near the end.

Related

MAKEFILE header file error when try to generate dependency file

Code structure
work
├── code
| |
| ├──inc/
| | └── main.h
| |
| └── main.c
├── _Build/
│ └── Makefile
Below is the Makefile code
WORKSPACE = ..
DIR_CODE = $(WORKSPACE)/code
DIR_BIN = $(WORKSPACE)/bin
DIR_OBJ = $(WORKSPACE)/obj
C_SRC_WITH_PATH = $(shell find $(DIR_CODE) -iname *.c)
C_SRC_ONLY_PATH = $(patsubst %/,%,$(sort $(dir $(C_SRC_WITH_PATH))))
TARGET = $(DIR_BIN)/application
.PHONY : all run clean
all : $(TARGET)
$(TARGET) : ../obj/main.o | $(DIR_BIN) ../deps
gcc $^ -o $#
../obj/main.o : ../code/main.c ../deps | $(DIR_OBJ)
gcc -c -o $# $< -MMD -MP -MF ../deps/main.d
$(DIR_BIN) $(DIR_OBJ) ../deps :
mkdir -p $#
run :
$(TARGET)
clean :
rm -rf $(DIR_BIN) $(DIR_OBJ) ../deps
-include ../deps/main.d
I am getting below error
gcc -c -o ../obj/main.o ../code/main.c -MMD -MF ../deps/main.d
../code/main.c:2:10: fatal error: main.h: No such file or directory
2 | #include "main.h"
| ^~~~~~~~
compilation terminated.
make: *** [Makefile:26: ../obj/main.o] Error 1
Although I am trying to generate the dependency file in the makefile, the file main.d is not generated and getting error for main.h file which is included in main.c file.
Any guidance is deeply appreciated.
This doesn't have anything to do with .d files etc. The compiler can't find your header file, because you haven't add the correct directory to the compile line. If your headers live in ../code/inc then you have to add this to your compile line, else how can the compiler find them?
Since you're not using any make variables to hold the compiler or flags, you'll have to add it directly to your recipe:
../obj/main.o : ../code/main.c ../deps | $(DIR_OBJ)
gcc -I../code/inc -c -o $# $< -MMD -MP -MF ../deps/main.d
There are a lot of weird things about this makefile but at least this will solve your compile error.

Makefile recursive method issue

Below is my code structure with Makefile and source codes
work
├── code
| |
| └── main.h and test.h files here
│ └── main.c and test.c files here
| └── subdir.mk
|
├── _build/
└── Makefile here
Makefile looks like below
all : ../code/target_file
../code/target_file : ../code/main.o ../code/test.o
#echo Building ...
#echo Linking files ...
gcc -Llib ../code/main.o ../code/test.o -lm -o ../code/target_file
.PHONY:subdir
../code/main.o ../code/test.o:subdir;
subdir:
#echo Building object files ...
cd ../code && $(MAKE) -f subdir.mk
clean:
rm -rv ../code/*.o ../code/*.exe
subdir.mk code is
main.o : main.c main.h test.h
#echo Building main.c ...
gcc -Werror -Wall -c main.c -o main.o
test.o : test.c test.h
#echo Building test.c ...
gcc -Werror -Wall -c test.c -o test.o
I am trying to use recursive make as per the tutorials and suggestions in the forum.
The error I am getting is
Building object files ...
cd ../code && make -f subdir.mk
make[1]: Entering directory '/f/My_Work/C/VSC/makefile_test/Recursive/test_mulltiple_2020_09_19/code'
Building main.c ...
gcc -Werror -Wall -c main.c -o main.o
make[1]: Leaving directory '/f/My_Work/C/VSC/makefile_test/Recursive/test_mulltiple_2020_09_19/code'
Building ...
Linking files ...
gcc -Llib ../code/main.o ../code/test.o -lm -o ../code/target_file
____________________________________________________________
gcc.exe: error: ../code/test.o: No such file or directory |
|
make: *** [Makefile:7: ../code/target_file] Error 1 |
____________________________________________________________|
main.o is generated but test.o didn't.
Any suggestions for removing the error?
Your subdir.mk file lists two targets. Make will always build either the target(s) you give on the command line, or else the first target in the makefile if you don't specify.
So you either have to create an initial target in your subdir.mk like this:
all: main.o test.o
so that it will build both, or else tell the recursive make invocation you want to build them both:
subdir:
#echo Building object files ...
cd ../code && $(MAKE) -f subdir.mk test.o main.o

Failing to link to SFML libraries using Makefile even though it works as a one liner

Here is my directory structure :
.
├── a.out
├── assets
│   └── ...
├── build
│   ├── apps
│   └── objects
├── include
│   └── engine
│   └── Class.h
├── Makefile
└── src
├── engine
│   └── Class.cpp
└── program.cpp
I can compile program.cpp into a.out using the following command :
g++ src/engine/*.cpp src/program.cpp -Iinclude/ -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system -Wall
While this works, this project is likely to grow and obviously making a serious Makefile would be preferable to direct compiling with a one liner. So I've used a Makefile format that I've used many times before, and that works perfectly fine but I've never linked it to outside libraries in the past. Here is the Makefile I'm using :
CXX := -g++
CXXFLAGS := -std=gnu++0x -g -Wall
LDFLAGS := -L/usr/lib -lstdc++ -lm -lsfml-graphics -lsfml-window -lsfml-system
BUILD := ./build
OBJ_DIR := $(BUILD)/objects
APP_DIR := $(BUILD)/apps
TARGET := program
INCLUDE := -Iinclude/
SRC := $(wildcard src/engine/*.cpp) $(wildcard src/*.cpp)
OBJECTS := $(SRC:%.cpp=$(OBJ_DIR)/%.o)
all: build $(APP_DIR)/$(TARGET)
$(OBJ_DIR)/%.o: %.cpp
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) $(INCLUDE) -o $# -c $<
$(APP_DIR)/$(TARGET): $(OBJECTS)
#mkdir -p $(#D)
$(CXX) $(CXXFLAGS) $(INCLUDE) $(LDFLAGS) -o $(APP_DIR)/$(TARGET) $(OBJECTS)
.PHONY: all build clean debug release
build:
#mkdir -p $(APP_DIR)
#mkdir -p $(OBJ_DIR)
debug: CXXFLAGS += -DDEBUG -g
debug: all
release: CXXFLAGS += -O2
release: all
clean:
-#rm -rvf $(OBJ_DIR)/*
-#rm -rvf $(APP_DIR)/*
However, this leads to compilation errors, in the form of undefined references to SFML methods :
./build/objects/src/engine/Class.o: In function `Class::draw()':
/dir/Class.cpp:60: undefined reference to `sf::RenderTarget::getView() const'
I'm confused as to why this happens given that the one liner above compiles fine. The Makefile also works just fine if I remove all references to SFML from my code. Were the added LDFLAGS not enough even though they're all that's needed to make my one liner link to SFML ? If so, what else is needed ?
From gcc link options
-llibrary
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
So put the libraries (-l<lib_1> ... -l<lib_x>) last on the line, after your object files.

Using suffix rules in Makefile

Suppose there are a.c, b.c, c.c, tt/at.c, tt/bt.c, fff/af.c, fff/bf.c. So I make Makefile like this:
OBJS=a.o b.o c.o
SRCS=$(OBJS:.o=.cc)
OBJS_TT=at.o bt.o
SRCS_TT=tt/at.c tt/bt.c
OBJS_FFF=af.o bf.o
SRCS_FFF=fff/af.c fff/bf.c
TARGET=test
.cc.o:
gcc -c $<
$(OBJS_TT):
gcc -c $(SRCS_TT)
$(OBJS_FFF):
gcc -c $(SRCS_FFF)
all:
gcc -o $(TARGET) $(OBJS) $(OBJS_TT) $(OBJS_FFF)
If C files in tt directory are added, I have to add file name in SRCS_TT & OBJS_TT.
Is there a way to improve make file?
How do I do all c files (including files in directory) using suffix rules ?
One common solution when source files reside in different directories is to build an isomorphic directory structure in the build directory. This way you can have multiple sources with the same file name (e.g. util.cc) but in different directories and the object files won't collide because they get built into different directories.
A working example that creates an isomorphic build directory structure also with auto-generated header dependencies:
build_dir := build
all : ${build_dir}/test
.SECONDEXPANSION:
.SECONDARY:
test_srcs := a.cc b.cc x/c.cc y/d.cc
${build_dir}/test : ${test_srcs:%.cc=${build_dir}/%.o} | ${build_dir}/
g++ -o $# ${LDFLAGS} ${LDLIBS} $^
# Include the auto-generated dependencies.
-include ${test_srcs:%.cc=${build_dir}/%.d}
# Compile and generate dependency files.
${build_dir}/%.o : %.cc | $$(dir $$#)
g++ -o $# -c -MD -MP ${CPPFLAGS} ${CXXFLAGS} $<
# Directory build rules. while loop to handle races on mkdir during parallel builds.
${build_dir}/%/ : | ${build_dir}/
while ! mkdir -p $#; do true; done
# Build root directory rule.
${build_dir}/ :
mkdir -p $#
# Don't try to rebuild these, these are generated when compiling.
${build_dir}/%.d : ;
clean :
rm -rf ${build_dir}
.PHONY : all clean
Usage example:
$ mkdir x y
$ touch b.cc x/c.cc y/d.cc
$ echo "int main() {}" > a.cc
$ make
mkdir -p build/
g++ -o build/a.o -c -MD -MP a.cc
g++ -o build/b.o -c -MD -MP b.cc
while ! mkdir -p build/x/; do true; done
g++ -o build/x/c.o -c -MD -MP x/c.cc
while ! mkdir -p build/y/; do true; done
g++ -o build/y/d.o -c -MD -MP y/d.cc
g++ -o build/test build/a.o build/b.o build/x/c.o build/y/d.o
$ tree build/
build/
├── a.d
├── a.o
├── b.d
├── b.o
├── test
├── x
│   ├── c.d
│   └── c.o
└── y
├── d.d
└── d.o
2 directories, 9 files
$ make
make: Nothing to be done for 'all'.
$ make clean
rm -rf build

Writing a makefile for ARM project

My project structure looks like:
.
├── build
├── src
| ├── rbpi
| | └── gpio.h
| ├── boot.c
| ├── boot.s
| └── kernel.c
└── linker.ld
This is a simple raspberry pi kernel that makes a LED blink!
I currently use a simple bat file with the following content to build it:
arm-none-eabi-gcc -g -O0 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7-a -mtune=cortex-a7 -nostartfiles -Wl,-T,linker.ld src/kernel.c src/boot.c src/boot.s -o build/kernel.elf
arm-none-eabi-objcopy build/kernel.elf -O binary build/kernel7.img
Since I will add more files to this project, I would have to append every file to my "buildscript".
If possible, I'd like to use a makefile.
How should my makefile look like if I want the following "rules"?
Before compilation, clean all *.elf and *.img files from the build directory.
Compile all *.c and *.s files from the src directory.
Output the kernel.elf file into the build directory.
Use the linker script linker.ld.
After compilation, run objcopy to generate a binary file.
A typical Makefile may look like... Wait there's a documentation about GNU Make here with a nice simple Makefile:
http://www.gnu.org/software/make/manual/make.html#Simple-Makefile
So for you a simple one to start may be:
SRC := $(wildcard src/*.c src/*.s)
CFLAGS := -g -O0 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7-a -mtune=cortex-a7 -nostartfiles -Wl,-T,linker.ld
all: build/kernel.img
build/kernel.elf: $(SRC)
arm-none-eabi-gcc $(CFLAGS) $(SRC) -o $#
%.img: %.elf
arm-none-eabi-objcopy $< -O binary $#
clean:
rm -f build/*.elf build/*.img
(Be carefull, recipes have to start with a tab, not four spaces like here, it's important for make to understand your file, so copying-pasting won't work.)
You don't actually need to remove elf and img files before compiling, that's the GNU Make role to know if it has to rebuild or not according to file modification times.
Here it is, working:
$ tree
.
├── build
├── Makefile
└── src
├── boot.c
├── boot.s
└── kernel.c
$ make
arm-none-eabi-gcc -g -O0 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7-a -mtune=cortex-a7 -nostartfiles -Wl,-T,linker.ld src/boot.c src/kernel.c src/boot.s -o build/kernel.elf
arm-none-eabi-objcopy build/kernel.elf -O binary build/kernel.img
$ tree
.
├── build
│   ├── kernel.elf
│   └── kernel.img
├── Makefile
└── src
├── boot.c
├── boot.s
└── kernel.c
$ make
make: Nothing to be done for 'all'.
$ touch src/boot.c # If I touch a file, make will have to rebuild evrything:
$ make
arm-none-eabi-gcc -g -O0 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7-a -mtune=cortex-a7 -nostartfiles -Wl,-T,linker.ld src/boot.c src/kernel.c src/boot.s -o build/kernel.elf
arm-none-eabi-objcopy build/kernel.elf -O binary build/kernel.img
You should really take a look at the documentation which is really nice: http://www.gnu.org/software/make/manual/make.html you won't be able to ask on stackoverflow for any modification you'll need to do on your makefile, starting from this "bootstrap makefile" you should be able to modify it to learn step by step, with the documentation as a reference.

Resources