I have below file list:
fd1/foo.c
fd2/foo.c
fd2/bar.c
fd2/bar.h
I want to compile fd1/foo.c and fd2/bar.c. fd2/foo.c is an excluded one. If I use vapth to select all source files, the fd2/foo.c will be compiled. So I want to specify the source list:
SRC_C = fd1/foo.c fd2/bar.c
Since I can't use vpath, so I can only compile SRC_C something like this:
SRC_O = $(patsubst %.c,%.o,$(SRC_C))
SRC_C_LIST = $(notdir $(SRC_C))
OBJ_LIST = $(patsubst %.c,%.o,$(SRC_C_LIST) )
.PHONY: all
all: $(OBJ_LIST)
ar rvs foobar.a $(OBJ_LIST)
$(SRC_O): %.o : %.c
gcc -c $< -I inc/ -MM -MF $(patsubst .o,.d,$(notdir $#)) -o $(notdir $#)
But I also want add dependency rules. But the dependency file seems only contain object target without original folder names:
foo.o : src/foo.c inc/bar.h
How do I to use dependency file in this case? Thanks.
Solutions
Per suggestion from Joachim, I modify my solution as below. Seems work:
SRC_C = fd1/foo.c fd2/bar.c
SRC_O = $(patsubst %.c,%.o,$(SRC_C))
SRC_C_LIST = $(notdir $(SRC_C))
OBJ_LIST = $(patsubst %.c,%.o,$(SRC_C_LIST) )
SRC_D_LIST = $(patsubst %.o,%.d,$(OBJ_LIST))
.PHONY:all
all: $(SRC_O)
ar rvs foobar.a $(OBJ_LIST)
$(SRC_O): %.o : %.c
arm-none-eabi-gcc -c $< -I inc/ -o $# -MM -MT $# -MF $(notdir $(patsubst %.o,%.d,$#))
-include $(SRC_D_LIST)
Using implicit rules, if you do not mind having the .o and .d files along the corresponding .c files:
LIB := foobar.a
SRC := fd1/foo.c fd2/bar.c
OBJ := $(SRC:.c=.o)
DEP := $(OBJ:.o=.d)
CC := arm-none-eabi-gcc
ARFLAGS := rvs
CPPFLAGS := -MMD -MP -I inc
.PHONY: all
.PRECIOUS: $(OBJ)
all: $(LIB)
$(LIB): $(LIB)($(OBJ))
-include $(DEP)
Related
I am extending an old school project, and I have the Makefile the course staff made for us. I have reorganized the directory structure of the project like this.
+-----obj
|
+-----src
| |
| +-Makefile
| +-allocator.h
| +-debug_break.h
| +-rbtree_clrs.c
| +-rbtree_linked.c
| +-rbtree_stack.c
| +-rbtree_topdown.c
| +-rbtree_unified.c
| +-segment.c
| +-segment.h
| +-test_harness.c
| +-my_optional_program.c
|
+------scripts
The Makefile currently prepends the heap allocators I wrote (files starting with rbtree_) with either test_ or my_optional_program and puts them in the same directory as the Makefile. I can then run my different heap allocator implementations on the scripts in the scripts folder. Instead, I want this:
+-----obj
| +-my_optional_program_rbtree_clrs
| +-my_optional_program_rbtree_linked
| +-my_optional_program_rbtree_stack
| +-my_optional_program_rbtree_topdown
| +-my_optional_program_rbtree_unified
| +-test_rbtree_clrs
| +-test_rbtree_linked
| +-test_rbtree_stack
| +-test_rbtree_topdown
| +-test_rbtree_unified
|
+-----src
| |
| +-Makefile
| +-allocator.h
| +-debug_break.h
| +-rbtree_clrs.c
| +-rbtree_linked.c
| +-rbtree_stack.c
| +-rbtree_topdown.c
| +-rbtree_unified.c
| +-segment.c
| +-segment.h
| +-test_harness.c
| +-my_optional_program.c
|
+------scripts
What do I need to add or change in the Makefile so that it will build to the obj/ folder?
# They had us try different optimization levels here (-O0, -O2, etc).
rbtree_clrs.o: CFLAGS += -O0
rbtree_unified.o: CFLAGS += -O0
rbtree_linked.o: CFLAGS += -O0
rbtree_stack.o: CFLAGS += -O0
rbtree_topdown.o: CFLAGS += -O0
ALLOCATORS = rbtree_clrs rbtree_unified rbtree_stack rbtree_linked rbtree_topdown
PROGRAMS = $(ALLOCATORS:%=test_%)
MY_PROGRAMS = $(ALLOCATORS:%=my_optional_program_%)
all:: $(PROGRAMS) $(MY_PROGRAMS)
# I had to use gcc-11 on mac to be able to build this project.
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC = gcc-11
else
CC = gcc
endif
CFLAGS = -g3 -std=gnu99 -Wall $$warnflags -fcf-protection=none -fno-pic -no-pie
export warnflags = -Wfloat-equal -Wtype-limits -Wpointer-arith -Wlogical-op -Wshadow -Winit-self -fno-diagnostics-show-option
LDFLAGS =
LDLIBS =
$(PROGRAMS): test_%:%.o segment.c test_harness.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(MY_PROGRAMS): my_optional_program_%:my_optional_program.c %.o segment.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean::
rm -f $(PROGRAMS) $(MY_PROGRAMS) *.o callgrind.out.*
.PHONY: clean all
.INTERMEDIATE: $(ALLOCATORS:%=%.o)
Update: This Makefile has solved the issue. I took Renaud Pacalet's Makefile (thanks!) and adjusted the paths to achieve the desired result. It seems not going up one level in the directories was an issue. Then I had to add the path I wanted to the ALLOCATORS in the PROGRAMS variable. I have no idea if this is how it should be done but it worked. I can update this if there is a better way.
SRCDIR = ../src
OBJDIR = ../obj
SRC := $(wildcard $(SRCDIR)/*.c)
OBJ := $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o,$(SRC))
# They had us try different optimization levels here (-O0, -O2, etc).
$(filter $(OBJDIR)/rbtree_%.o,$(OBJ)): CFLAGS += -O0
ALLOCATORS = rbtree_clrs rbtree_unified rbtree_stack rbtree_linked rbtree_topdown
PROGRAMS = $(addprefix $(OBJDIR)/test_,$(ALLOCATORS))
MY_PROGRAMS = $(addprefix $(OBJDIR)/my_optional_program_,$(ALLOCATORS))
all:: $(PROGRAMS) $(MY_PROGRAMS)
# I had to use gcc-11 on mac to be able to build this project.
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC = gcc-11
else
CC = gcc
endif
CFLAGS = -g3 -std=gnu99 -Wall $$warnflags -fcf-protection=none -fno-pic -no-pie
export warnflags = -Wfloat-equal -Wtype-limits -Wpointer-arith -Wlogical-op -Wshadow -Winit-self -fno-diagnostics-show-option
LDFLAGS =
LDLIBS =
$(OBJ): $(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c -o $# $<
$(PROGRAMS): $(OBJDIR)/test_%: $(OBJDIR)/%.o segment.c test_harness.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(MY_PROGRAMS): $(OBJDIR)/my_optional_program_%: my_optional_program.c $(OBJDIR)/%.o segment.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean::
rm -f $(PROGRAMS) $(MY_PROGRAMS) $(OBJ) callgrind.out.*
You don't have a compilation rule so make uses its implicit rule for compilation which puts the object files in the same directory as the source files.
Simply add a rule of your own and rework a bit all references to object files:
OBJDIR := ../obj
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,$(OBJDIR)/%.o,$(SRC))
# They had us try different optimization levels here (-O0, -O2, etc).
$(filter $(OBJDIR)/rbtree_%.o,$(OBJ)): CFLAGS += -O0
ALLOCATORS = rbtree_clrs rbtree_unified rbtree_stack rbtree_linked rbtree_topdown
PROGRAMS = $(ALLOCATORS:%=$(OBJDIR)/test_%)
MY_PROGRAMS = $(ALLOCATORS:%=$(OBJDIR)/my_optional_program_%)
all:: $(PROGRAMS) $(MY_PROGRAMS)
# I had to use gcc-11 on mac to be able to build this project.
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
CC = gcc-11
else
CC = gcc
endif
CFLAGS = -g3 -std=gnu99 -Wall $$warnflags -fcf-protection=none -fno-pic -no-pie
export warnflags = -Wfloat-equal -Wtype-limits -Wpointer-arith -Wlogical-op -Wshadow -Winit-self -fno-diagnostics-show-option
LDFLAGS =
LDLIBS =
$(OBJ): $(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c -o '$#' '$<'
$(PROGRAMS): $(OBJDIR)/test_%: $(OBJDIR)/%.o segment.c test_harness.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(MY_PROGRAMS): $(OBJDIR)/my_optional_program_%: my_optional_program.c $(OBJDIR)/%.o segment.c
$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean::
rm -f $(PROGRAMS) $(MY_PROGRAMS) $(OBJ) callgrind.out.*
Note that you should also manage the dependencies between object and header files (which the above does not, just like the original version). If it's simple enough you'll easily modify the proposed Makefile. Else consider reading this very interesting post about Auto-Dependency Generation by the current GNU make main maintainer.
Hi I know there is some other posts with the same title, but they are not in the same context. So: I have a library named mlx and the library file is named libmlx.dylib: when I try to compile it with a simple main using gcc main.c libmlx.dylib it compiles well and the lib is working, but when I try to compile it with my project using my makefile the compilation doesn't throw any error but when I launch the program I get this error message:
dyld: Library not loaded: libmlx.dylib
Referenced from: /Users/leo/Documents/42-cursus/so_long/./so_long
Reason: image not found
[1] 8313 abort ./so_long
Here is my makefile:
SHELL = /bin/sh
NAME = so_long
.SUFFIXES = .c .o .h .dylib
SRCDIR = src
INCDIR = inc
LIBDIR = lib
OBJDIR = .obj
SRC = $(addsuffix $(word 1, $(.SUFFIXES)),\
$(addprefix exception/,\
exception\
bad_alloc\
invalid_arguments\
invalid_map\
runtime_error)\
$(addprefix parsing/,\
get_map)\
$(addprefix rendering/,\
render_map)\
$(addprefix utils/,\
init_image\
make_color)\
$(addprefix cleaning/,\
mlx_clear)\
$(addprefix get_next_line/,\
get_next_line\
get_next_line_utils)\
main)
INC = $(addsuffix $(word 3, $(.SUFFIXES)),\
get_next_line\
mlx\
exception\
so_long)
LIB = mlx\
ft
OBJ = $(SRC:$(word 1, $(.SUFFIXES))=$(word 2, $(.SUFFIXES)))
CC = gcc
CFLAGS = -Wall -Wextra -Werror -I $(INCDIR)
LCFLAGS = $(addprefix -L, $(LIBDIR)) $(addprefix -l, $(lib))
#### COLORS ####
KNRM = \x1B[0m
KRED = \x1B[31m
KGRN = \x1B[32m
KYEL = \x1B[33m
KBLU = \x1B[34m
KMAG = \x1B[35m
KCYN = \x1B[36m
KWHT = \x1B[37m
######################
all: $(OBJDIR) $(NAME)
#printf "$(KGRN)\`$(NAME)\` is up to date.\n$(KNRM)"
$(OBJDIR):
#printf "$(KYEL)➤ "
mkdir -p $#/exception $#/parsing $#/rendering $#/utils $#/cleaning $#/get_next_line
#printf "$(KNRM)"
$(NAME): $(addprefix $(OBJDIR)/, $(OBJ))
#printf "$(KCYN)[ Linking ]\n➤ "
$(CC) $(CFLAGS) $^ -o $# $(LCFLAGS)
#printf "$(KNRM)"
$(OBJDIR)/%$(word 2, $(.SUFFIXES)): $(SRCDIR)/%$(word 1, $(.SUFFIXES)) $(addprefix $(INCDIR)/, $(INC))
#printf "$(KMAG)[ Compiling ]\n➤ "
$(CC) $(CFLAGS) -c $< -o $#
#printf "$(KNRM)"
clean:
#printf "$(KRED)➤ "
rm -rf $(OBJDIR)
#printf "$(KNRM)"
fclean: clean
#printf "$(KRED)➤ "
rm -f $(NAME)
#printf "$(KNRM)"
re: fclean all
I'm linking it with the flags -L $(LIBDIR) -lmlx. What did I do wrong ?
I found that for dynamic libraries you need to have the .dylib in the same directory as your target, I let the post in case some people face the same problem.
I got a project hierarchy that looks like this:
+Makefile
+---src
| main.c
| ...
| +---block
| | air.c
| | ...
| |
| +---entity
| | esc.c
| | esc.h
| | ...
| |
| \---world
| \---gen
| noise.c
| ...
| xyz.c
| ...
\---obj
main.o
air.o
esc.o
noise.o
xyz.o
...
I want to compile all the .c files in the hierarchy into one obj folder using make.
So far I got:
UNAME_S = $(shell uname -s)
CC = clang
CFLAGS = -std=c11 -O3 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing
CFLAGS += -Wno-pointer-arith -Wno-newline-eof -Wno-unused-parameter -Wno-gnu-statement-expression
CFLAGS += -Wno-gnu-compound-literal-initializer -Wno-gnu-zero-variadic-macro-arguments
CFLAGS += -Ilib/cglm/include -Ilib/glad/include -Ilib/glfw/include -Ilib/stb -Ilib/noise -fbracket-depth=1024
LDFLAGS = lib/glad/src/glad.o lib/cglm/libcglm.a lib/glfw/src/libglfw3.a lib/noise/libnoise.a -lm
# GLFW required frameworks on OSX
ifeq ($(UNAME_S), Darwin)
LDFLAGS += -framework OpenGL -framework IOKit -framework CoreVideo -framework Cocoa
endif
ifeq ($(UNAME_S), Linux)
LDFLAGS += -ldl -lpthread
endif
OBJ_DIR = obj
SRC = $(wildcard src/**/*.c) $(wildcard src/*.c) $(wildcard src/**/**/*.c) $(wildcard src/**/**/**/*.c)
OBJ = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(notdir $(basename $(SRC)))))
SRC_DIRS = $(sort $(dir $(SRC)))
BIN = bin
.PHONY: all clean
all: dirs libs game
libs:
cd lib/cglm && cmake . -DCGLM_STATIC=ON && make
cd lib/glad && $(CC) -o src/glad.o -Iinclude -c src/glad.c
cd lib/glfw && cmake . && make
cd lib/noise && make
dirs:
mkdir -p ./$(BIN) ./$(OBJ_DIR)
run: all
$(BIN)/game
game: $(OBJ)
$(CC) -o $(BIN)/game $^ $(LDFLAGS)
$(OBJ_DIR)/%.o: src/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/block/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/entity/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/gfx/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/ui/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/util/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/world/%.c
$(CC) -o $# -c $< $(CFLAGS)
$(OBJ_DIR)/%.o: src/world/gen/%.c
$(CC) -o $# -c $< $(CFLAGS)
clean:
rm -rf $(BIN) $(OBJ_DIR)
Is there any way to get this done in a more efficient way? Especially the $(OBJ_DIR)/%.o cases?
Variable $(SRC_DIRS) stores all src folders
Variable $(SRC) stores all .c files with their paths
Variable $(OBJ) stores all .o file paths and names
The best way to do this is using VPATH.
For example:
SRC := $(wildcard src/*/*.c) $(wildcard src/*.c) $(wildcard src/*/*/*.c) $(wildcard src/*/*/*/*.c)
OBJ := $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(notdir $(basename $(SRC)))))
SRC_DIRS := $(sort $(dir $(SRC)))
VPATH := $(SRC_DIRS)
...
$(OBJ_DIR)/%.o: %.c
$(CC) -o $# -c $< $(CFLAGS)
You just need the one pattern rule.
I've created a makefile for a project, but I think it's only showing linking error and not the compilation errors themselves. Can anyone review my Makefile and spot any mistake I may have made?
# =========== vars ===========
objects = directories user server
CC = gcc
OUT_DIR = bin
USER_EXEC = ${OUT_DIR}/user
SERVER_EXEC = ${OUT_DIR}/server
CFLAGS = -g -D_REENTRANT -pthread -Wall
SRC = $(wildcard ./src/*.c)
USER_SRC = $(wildcard ./src/user/*.c) $(SRC)
SERVER_SRC = $(wildcard ./src/server/*.c) $(SRC)
USER_OBJ = $(USER_SRC:.c=.o)
SERVER_OBJ = $(SERVER_SRC:.c=.o)
# =========== targets ===========
all: $(objects)
directories:
mkdir -p $(OUT_DIR)
user: $(USER_OBJ)
$(CC) $(CFLAGS) $(USER_OBJ) -o $(USER_EXEC)
server: $(SERVER_OBJ)
$(CC) $(CFLAGS) $(SERVER_SRC) -o $(SERVER_EXEC)
clean:
rm -f $(USER_EXEC) $(SERVER_EXEC) src/*.o src/user/*.o src/server/*.o
# Arquitectura
CC := arm-none-eabi-
# Compiladores
GCC :=$(CC)gcc
AS :=$(CC)as
LIBC :=$(CC)ar
# Linker
LINKER :=$(CC)ld
# Flags compilação
FLAGDEBUG :=-g
CFLAGS :=-c -mapcs #-Wall
CDEPEND :=-MM -MF
LIBFLAG := rcs
LDSCRIPT := -T
LDLIBDIR := -L
LDLIBLIBS := -l
# $# -> nome do alvo .. $^/S? lista de dependencias .. $* contêm o valor de % .. $< contêm a primeira dependencia
# Pastas
DEPDIR := Depends/
SOURCEDIR := Source/
SOURCECDIR :=$(SOURCEDIR)C/
SOURCEADIR :=$(SOURCEDIR)Assembly/
LIBDIR := Library/
HEADDIR := Header/
OBJDIR := Object/
# Dependencias
SOURCEC := $(wildcard $(SOURCECDIR)*.c)
SOURCEA := $(wildcard $(SOURCEADIR)*.S)
OBJC :=$(patsubst $(SOURCECDIR)%.c,%.o,$(SOURCEC))
OBJA :=$(patsubst $(SOURCEADIR)%.S,%.o,$(SOURCEA))
HEADER :=$(wildcard $(HEADDIR)*.h)
LIBL = $(wildcard $(LIBDIR)*.a)
#LIBL = $(wildcard $(LIBDIR)lib*.a)
DEPEND :=$(patsubst %.o,$(DEPDIR)%.d,$(OBJC))
SCRIPT := $(wildcard *.ld)
LIB =
# Ficheiros de output
FICHDEBUG := Teste.axf
FICHRELEASE := Release.axf
debug: $(FICHDEBUG)
# Executável para debug
$(FICHDEBUG):$(OBJA) $(OBJC)
#echo A efectuar a linkagem dos módulos para gerar o executável $#
#$(LINKER) $(OBJA) $(OBJC) $(LDSCRIPT) $(SCRIPT) -o $#
# Compilar ficheiros .S e .c
%.o:$(SOURCEADIR)%.S
#echo A compilar $# a partir de $*.S
#$(AS) $(FLAGDEBUG) $< -o $#
%.o:$(SOURCECDIR)%.c
#echo A compilar $# a partir de $*.c
$(GCC) $(CDEPEND) $(patsubst %.o,$(DEPDIR)%.d,$#) $<
$(GCC) $(FLAGDEBUG) $(CFLAGS) $< -o $#
-include $(DEPEND)
release: $(FICHRELEASE)
$(FICHRELEASE): $(OBJA) $(OBJC)
#echo A efectuar a linkagem dos módulos para gerar o executável $#
#$(LINKER) $(OBJA) main.o $(LDSCRIPT) $(SCRIPT) -o $# $(LDLIBDIR) $(LIBDIR) $(LDLIBLIBS)
# Gerar bibliotecas necessárias
gerarLib:$(HEADER)
#echo $(HEADER)
$(HEADDIR)%.h: %.o
#echo $# $*
#$(eval LIB = $(patsubst $(HEADDIR)%.h,$(LIBDIR)lib%.a,$#))
$(LIBC) $(LIBFLAG) $(LIB) $(patsubst $(LIBDIR)lib%.a,%.o,$(LIB))
.PHONY: clean
clean:
# rm -rf $(DEPDIR)*.d $(SOURCEDIR)*/*~ *~ *.o $(LIBDIR)*.a *.axf *.o
So heres the makefile I'm using. As it is it generates the code as its supposed ant it updates correctly when any file changes(.h or .c), the issue is the dependencies generated do not have the proper object path set(I've read its a bug in gcc when it writes to file the dependencies) so I thought I'd make a script that simply adds the path to it and it would work and I'd be able to put my object files where they belong(Object folder) however every time I try to run make after the initial compilation(which works fine btw) it gives me an erro saying one of the header files doesn't exist(which is untrue since the file is there and I can access it).
Anyone have an idea of whats happening?(to change between the "modes" I simply write $(OBJDIR) before every %.o and *.o)
This rule looks suspicious:
$(HEADDIR)%.h: %.o
#echo $# $*
#$(eval LIB = $(patsubst $(HEADDIR)%.h,$(LIBDIR)lib%.a,$#))
$(LIBC) $(LIBFLAG) $(LIB) $(patsubst $(LIBDIR)lib%.a,%.o,$(LIB))
It claims to be creating .h files from .o files, but that seems unlikely, given the rules.