I'm trying to make a library for my project but I am very very new to Makefiles. I tried several configurations and adding -I but none worked.
I have the following three:
libft/
../includes/
....libft.h
../lst
....ft_lstnew.c
....ft_lstadd_front.c
....ft_lstadd_back.c
.... [...]
../src
....ft_isalpha.c
....ft_isalnum.c
.... [...]
And the following makefile:
NAME=libft.a
LIBSO=libft.so
CC=gcc
CFLAGS=-Wall -Wextra -Werror
SRC_DIR=src/
BONUS_DIR=lst/
OBJ_DIR=obj/
SRC_FILES= ft_bzero.c \
ft_isalmun.c \
ft_isalpha.c \
ft_isascii.c \
ft_isdigit.c \
ft_isprint.c \
ft_memchr.c \
ft_memcpy.c \
ft_memmove.c \
ft_memset.c \
ft_strchr.c \
ft_strlcat.c \
ft_strlcpy.c \
ft_strlen.c \
ft_strncmp.c \
ft_strrchr.c \
ft_tolower.c \
ft_toupper.c
BONUS_FILES=ft_lstadd_back.c \
ft_lstadd_front.c \
ft_lstdelone.c \
ft_lstclear.c \
ft_lstiter.c \
ft_lstlast.c \
ft_lstmap.c \
ft_lstnew.c \
ft_lstsize.c
SRC_PATH=$(addprefix $(SRC_DIR), $(SRC_FILES))
BONUS_PATH=$(addprefix $(BONUS_DIR), $(BONUS_FILES))
SRC_NAMES=$(SRC_FILES:.c=.o)
BONUS_NAMES=$(BONUS_FILES:.c=.o)
SRC_PATH_O=$(addprefix $(SRC_DIR), $(SRC_NAMES))
BONUS_PATH_O=$(addprefix $(BONUS_DIR), $(BONUS_NAMES))
HDR_NAME=libft.h
HDR_DIR=includes/
HDR= $(addprefix $(HDR_DIR),$(HDR_NAME))
all: $(NAME)
$(NAME): $(SRC_PATH_O)
ar rc $# $<
ranlib $#
$(OBJ_DIR):
mkdir $#
$(OBJ_DIR)%.o: $(SRC_DIR)%.c $(HDR_NAME)
$(CC) $(CFLAGS) -c $< -o $# -I $(HDR)
clean:
rm -rf $(OBJ_DIR)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re
And I keep getting this each time I type make on the terminal:
gcc -Wall -Wextra -Werror -c -o src/ft_bzero.o src/ft_bzero.c
src/ft_bzero.c:1:10: fatal error: libft.h: No such file or directory
1 | #include "libft.h"
| ^~~~~~~~~
compilation terminated.
make: *** [<builtin>: src/ft_bzero.o] Error 1
Am I missing something? It's literally my first time.
Yes, you're missing some things.
First, look at the command line make shows:
gcc -Wall -Wextra -Werror -c -o src/ft_bzero.o src/ft_bzero.c
Note that the output here is not right for the recipe of the pattern rule you created: there's no -I option, and the object file is being written to src/ not obj/.
From this you should realize that your pattern rule is not being used at all, and instead make is using its built-in rule for building object files.
Why isn't your pattern rule being used? Let's look at it:
$(OBJ_DIR)%.o: $(SRC_DIR)%.c $(HDR_NAME)
what is this after variable expansion?
obj/%.o: src/%.c libft.h
This pattern (like all patterns) can only match if ALL the prerequisites either already exist or can be built. The src/%.c exists, after the pattern substitution. What about libft.h? No, that doesn't exist. What does exist is includes/libft.h but that's not the same thing.
So, this rule fails to match and make goes back to using its default rules.
If you want to say that every object file depends on that header, you have to use the correct path to the header file when you write the pattern.
Next, this is wrong:
$(CC) $(CFLAGS) -c $< -o $# -I $(HDR)
What is $(HDR)? It's the name of the file: include/libft.h. You don't include header file names with -I; you include directories that headers are looked for in. So you need $(HDR_DIR) here instead.
Related
My currently working makefile uses gcc to compile and link in one step. It is 600 lines long so I have cut it down to just show you the 'compile and link' and hex stages (very cut down code here!)
$(PROGRAM_ELF): \
$(BSP_DIR)/install/lib/$(CONFIGURATION)/libmetal.a \
$(BSP_DIR)/install/lib/$(CONFIGURATION)/libmetal-gloss.a \
$(BSP_DIR)/metal.$(LINK_TARGET).lds
mkdir -p $(dir $#)
$(MAKE) -C $(SRC_DIR) $(basename $(notdir $#)) \
PORT_DIR=$(PORT_DIR) \
AR=$(RISCV_AR) \
CC=$(RISCV_GCC) \
CXX=$(RISCV_GXX) \
ASFLAGS="$(RISCV_ASFLAGS)" \
CCASFLAGS="$(RISCV_CCASFLAGS)" \
CFLAGS="$(RISCV_CFLAGS)" \
CXXFLAGS="$(RISCV_CXXFLAGS)" \
XCFLAGS="$(RISCV_XCFLAGS)" \
LDFLAGS="$(RISCV_LDFLAGS)" \
LDLIBS="$(RISCV_LDLIBS)" \
PROJ_SRC="$(PROJ_SRC)"
$(PROGRAM_HEX): \
$(PROGRAM_ELF)
$(RISCV_OBJCOPY) -O ihex $(PROGRAM_ELF) $#
mv $(PROGRAM_HEX) $(PROGRAM_TMP)
$(RISCV_OBJCOPY) -O verilog $(PROGRAM_ELF) $#
cp $(PROGRAM_HEX) $(PROGRAM_MEM)
mv $(PROGRAM_TMP) $(PROGRAM_HEX)
However, I need the 'compile and link stage' to be in 2 steps now as I'll be using a different compiler which has separate compile and link exes. How would I do this ? So the above would need to be split into 2. Examples online are a bit vague.
at its simplest, you use the gcc (or g++) -c option to compile the source without linking. This will generate an object file - which you can use in the linker state. Here is a simple example:
SOURCE = test.cpp
OBJECT = test.o
OUTPUT = run
all:
#g++ $(SOURCE) -c -o $(OBJECT) <------ Compile test.cpp, produces test.o
#g++ $(OBJECT) -o $(OUTPUT) <------ Links test.o into executable `run`
clean:
#$(RM) -rf $(OBJECT) $(OUTPUT)
That's it...
I did this which seemed to work:
#list of all files
PROJ_SRC = $(SRC_DIR)/plsi2c_riscv.c \
$(SRC_DIR)/SimSpi.c \
etc
#assume BUILD_FOLDER defined already
OBJ_FILES = $(addprefix $(BUILD_FOLDER)/,$(PROJ_SRC:.c=.o))
$(BUILD_FOLDER)/%.o: %.c
#Create the folder structure for the output file
#mkdir -p $(dir $#)
$(MY_CC) $(CCFLAGS) $< -o $#
$(BUILD_FOLDER)/example: $(OBJ_FILES)
mkdir -p $(dir $#)
#echo Linking $(notdir $#)
$(MY_LINK) $(LFLAGS) $^ $(LDLIBS) -o $#
$(obj)u-boot: depend $(SUBDIRS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \
--start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
-Map u-boot.map -o u-boot
what does "depend" do here in the dependency line?
In this example, depend seems to simply be an arbitrary label which identifies another target further down in the file.
I have following folder structure
--Makefile
--source/
--boot.s
--kernel.c
--linker.ld
--build/
and I compile my sources using following Makefile
###############################################################################
#
# A makefile script for generation of raspberry pi kernel images.
#
###############################################################################
# The toolchain to use. arm-none-eabi works, but there does exist
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
CFLAGS = -march=armv8-a+crc \
-mcpu=cortex-a53 \
-mtune=cortex-a53 \
-mfpu=crypto-neon-fp-armv8 \
-mfloat-abi=hard \
-ftree-vectorize \
-funsafe-math-optimizations \
-O2 -pipe -ffreestanding
LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib
# The name of the output file to generate.
TARGET = kernel.img
.PHONY: all clean run
# Rule to make everything.
all: $(TARGET)
# Rule to remake everything. Does not include clean.
rebuild: clean all
#Rule to invoke qemu
run:
qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf
$(TARGET): kernel.elf
arm-none-eabi-objcopy $(BUILD)kernel.elf -O binary $(BUILD)kernel.img
kernel.elf: boot.o kernel.o
$(LD) $(LDFLAGS) -o $(BUILD)kernel.elf $(BUILD)boot.o $(BUILD)kernel.o
boot.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o
kernel.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)kernel.c -o $(BUILD)kernel.o
# Rule to clean files.
clean :
-rm -f $(BUILD)*
-rm -f *.o
-rm -f *.elf
-rm -f *.img
How to write pattern based rules ? I tried many stack overflow answers but couldn't make it work.
First I listed my source using wild cards but couldn't write proper target as sources list had [source/boot.s source/kernel.c] and it would create object files in source folder it self.
I was facing difficulty while keeping sources and build directory different. Any help is appreciated.
----------Complete solution as per #MadScientist -----------
###############################################################################
#
# A makefile script for generation of raspberry pi kernel images.
#
###############################################################################
# The toolchain to use. arm-none-eabi works, but there does exist
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc
# The intermediate directory for compiled object files.
BUILD = build/
# The directory in which source files are stored.
SOURCE = source/
CFLAGS = -march=armv8-a+crc \
-mcpu=cortex-a53 \
-mtune=cortex-a53 \
-mfpu=crypto-neon-fp-armv8 \
-mfloat-abi=hard \
-ftree-vectorize \
-funsafe-math-optimizations \
-O2 -pipe -ffreestanding
LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib
SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))
# The name of the output file to generate.
TARGET = kernel.img
.PHONY: all clean run
# Rule to make everything.
all: $(BUILD)$(TARGET)
# Rule to remake everything. Does not include clean.
rebuild: clean all
#Rule to invoke qemu
run:
qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf
$(BUILD)%.o : $(SOURCE)%.s
$(CC) $(CFLAGS) -c $< -o $#
$(BUILD)%.o : $(SOURCE)%.c
$(CC) $(CFLAGS) -c $< -o $#
$(BUILD)$(TARGET): $(BUILD)kernel.elf
arm-none-eabi-objcopy $< -O binary $#
$(BUILD)kernel.elf: $(OBJECTS)
$(LD) $(LDFLAGS) -o $# $^
# Rule to clean files.
clean :
-rm -f $(BUILD)*
-rm -f *.o
-rm -f *.elf
-rm -f *.img
This is wrong:
boot.o: $(SOURCE)boot.s
$(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o
You are telling make that your recipe will build a file named boot.o, but it doesn't: it creates a file named $(BUILD)boot.o, which is completely different. Same with your rules to build kernel.img and kernel.elf.
If you want to write a pattern rule the % can match only identical parts. Since SOURCE and BUILD are not identical, they won't match the % part. So you have to write this:
$(BUILD)%.o : $(SOURCE)%.s
$(CC) $(CFLAGS) -c $< -o $#
Since you're building $(BUILD)xxx.o you have to use that as a prerequisite as well, so you have to write:
$(BUILD)$(TARGET): $(BUILD)kernel.elf
arm-none-eabi-objcopy $< -O binary $#
$(BUILD)kernel.elf: $(BUILD)boot.o $(BUILD)kernel.o
$(LD) $(LDFLAGS) -o $# $^
ETA
If you want to get the source files via wildcard you can, but you have to substitute the directory as well not just the suffix, like this:
SOURCES := $(wildcard $(SOURCE)*.s)
OBJECTS := $(patsubst $(SOURCE)%.s,$(BUILD)%.o,$(SOURCES))
If you have both assembly and C source files (you didn't show any C source files in your example makefile) you can use this:
SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))
I am trying to run a makefile with gfortran in my mac. It compiles without problem in Fedora 18, but I can't make it work in Mac OS 10.8.4 with the last gfortran from HPC.
I am newbie on fortran, so some light would be appreciated.
Here is the Make file:
# Makefile made to work with GNU Make
.DEFAULT:
BIN=bin
OBJ=obj
vpath= %$(OBJ)/.o $(OBJ)
vpath= %.mod $(OBJ)
EXES= pasos \
pasosng \
pasosm \
trans \
cost \
lcal \
fluj \
loc \
eval \
impas \
imptra \
mats \
imploc \
matesp \
dimen
FC=gfortran
LN=gfortran
FCFLAGS=$(USER_FCFLAGS) -g3 -B $(OBJ) -J $(OBJ) #fc_options #fc_warnings
LFLAGS=$(USER_LFLAGS)
ifdef SystemRoot
dotexe=.exe
endif
ifdef F_PROFILE
FCFLAGS:=$(FCFLAGS) -pg
LFLAGS:=$(LFLAGS) -pg
endif
ifdef F_TEST
FCFLAGS:=-O0 -fbounds-check $(FCFLAGS)
else
FCFLAGS:=-O3 $(FCFLAGS)
endif
COMPILE=$(FC) $(FCFLAGS) -o $# -c $<
LINK=$(LN) $(LFLAGS) -o $# -Wl,-Map=$#.map $^
%.o : %.f90
$(COMPILE)
all: prepare $(EXES)
$(OBJ)/%.o : %.f90
$(COMPILE)
clean:
rm -rf $(OBJ) $(BIN)
prepare: $(BIN) $(OBJ)
$(BIN):
mkdir $(BIN)
$(OBJ):
mkdir $(OBJ)
pasos: prepare $(BIN)/pasos$(dotexe)
#echo $#
$(BIN)/pasos$(dotexe) : $(OBJ)/pasos.o \
$(OBJ)/nodes.o \
$(OBJ)/io_list.o \
$(OBJ)/rcomm.o \
$(OBJ)/tparc.o \
$(OBJ)/zcomm.o \
$(OBJ)/rcomm.o \
$(OBJ)/pcomm.o \
$(OBJ)/getoptm.o \
$(OBJ)/control.o \
$(OBJ)/heap.o \
$(OBJ)/gener.o \
$(OBJ)/param.o \
$(OBJ)/ascii.o \
$(OBJ)/pcomm.o \
$(OBJ)/mensamod.o \
$(OBJ)/optionsm.o \
$(OBJ)/debugm.o
$(LINK)
The file is longer, but I dont know if it is needed to understand the error. The error I get when I run make over the directory is:
tcapelle$ gnumake
gfortran -o bin/pasos -Wl,-Map=bin/pasos.map obj/pasos.o obj/nodes.o obj/io_list.o obj/rcomm.o obj/tparc.o obj/zcomm.o obj/pcomm.o obj/getoptm.o obj/control.o obj/heap.o obj/gener.o obj/param.o obj/ascii.o obj/mensamod.o obj/optionsm.o obj/debugm.o
ld: unknown option: -Map=bin/pasos.map
collect2: error: ld returned 1 exit status
gnumake: *** [bin/pasos] Error 1
Edit:
I changed in the makefile
LINK=$(LN) $(LFLAGS) -o $# -Wl,-Map=$#.map $^
to
LINK=$(LN) $(LFLAGS) -o $# $^
and it compiles with some errors, but it worked.
What does this -Wl,-Map= thing do?
The problem is that the BSD linker (in contrast to the GNU linker) does not recognize options, if they are separated from the corresponding value by an equal sign (instead of a whitespace). So
ld -Map test.map
is fine, while
ld -Map=test.map
is not. Therefore, you must make sure, the compiler passes the linker options to the linker in the latter form. For that you need
gfortran -Wl,-Map,test.map ...
which you can achieve by changing the definition of the LINK variable to:
LINK=$(LN) $(LFLAGS) -o $# -Wl,-Map,$#.map $^
My simple little makefile is exhibiting behavior which I'm not able to understand. If I touch any source file except Dictionary.cpp then no targets are built, and if I touch Dictionary.cpp then it compiles but doesn't link. Source files are in src/ object (.o) and dependencies (.d) are in obj/ and binary goes into bin/
If I rm obj/* then everything builds OK but the timestamps don't seem to be being picked up. Can anyone tell me where I'm going wrong?
The .d files seem to be being created correctly, here's Dictionary.d:
obj/Dictionary.o: src/Dictionary.cpp src/pch.h src/Types.h src/Util.h \
src/Refcount.h src/Dictionary.h
src/Dictionary.cpp:
src/pch.h:
src/Types.h:
src/Util.h:
src/Refcount.h:
src/Dictionary.h:
Which looks correct to me. Here's the makefile:
sources = Dictionary.cpp \
Util.cpp \
Tile.cpp \
Board.cpp \
Vec2.cpp \
Letter.cpp \
Random.cpp \
Server.cpp \
main.cpp
objects = $(patsubst %.cpp,obj/%.o,$(sources))
depends = $(patsubst %.cpp,obj/%.d,$(sources))
CXX = g++
CPPFLAGS = -Isrc -std=c++0x
CXXFLAGS = -c
-include $(depends)
bin/dictionary: $(objects)
#echo Link...
$(CXX) $(CPPFLAGS) $(objects) -o bin/dictionary -lrt
obj/%.o: src/%.cpp
#echo [$*]
#$(CXX) $(CPPFLAGS) $(CXXFLAGS) src/$*.cpp -o obj/$*.o
#$(CXX) $(CPPFLAGS) -MM src/$*.cpp -MF obj/$*.d
#mv -f obj/$*.d obj/$*.d.tmp
#sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d
#sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | sed -e 's/^ *//' -e ' s/$$/:/' >> obj/$*.d
#rm -f obj/$*.d.tmp
You have to move the include to the end, or put the bin/dictionary rule before it, or add an all: bin/dictionary rule before the include, or something.
Or, resign yourself to always running make bin/dictionary, which will work as well.
Remember make, by default, tries to build the first target in the makefile. Because you have the include line before any other target, the first target defined by an included file will be considered the default goal, and that happens to be obj/Dictionary.o.