$(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.
Related
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.
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 $#
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.
I was going through the Makefile of X-Loader for craneboard. We'll have to cross compile it for ARM. I was stuck at the following code and couldn't proceed. Kindly guide me in what has been done.
x-load: $(OBJS) $(LIBS) $(LDSCRIPT)
UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
$(LD) $(LDFLAGS) $$UNDEF_SYM $(OBJS) \
--start-group $(LIBS) --end-group $(PLATFORM_LIBS) \
-Map x-load.map -o x-load
System.map: x-load
#$(NM) $< | \
grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \
sort > System.map
oneboot: x-load.bin
scripts/mkoneboot.sh
where,
OBJS = cpu/$(CPU)/start.o
LIBS is a set of library archives
PLATFORM_LIBS is GCC Library
LD = $(CROSS_COMPILE)ld
LDFLAGS are the corresponding flags
Also, what is the need for oneboot? The mkoneboot.sh converts x-load.bin.ift to x-load-signed.ift. In what scenario, this will be used instead of the usual x-load.bin.ift?
The System.map is used for the debugging purpose. What is the need for x-load.map?