Reputation: 179
Ladies, gentlemen, hello.
I'm trying to create a Makefile in C which will create two libraries
One static,one shared.
So far my Makefile works for the static part.
Projet file structure:
//root
//root/src
An other point to mention, this Makefile also creates *.o in my root project directory and the /src dir.
What to do so it only creates object files inside the /src directory ?
Makefile:
SNAME = libmy_printf_`uname -m`-`uname -s`.a
DNAME = libmy_printf_`uname -m`-`uname -s`.so
SRC = $(wildcard src/*.c)
OBJ = $(SRC:.c=.o)
CC = gcc
RM = rm -f
CFLAGS = -W -Wall -ansi -pedantic -Werror -g3 -fPIC
LDFLAGS = -L. -l$(NAME)
STATIC: $(OBJ)
$(CC) -c $(SRC)
ar r $(SNAME) $(OBJ)
ranlib $(SNAME)
DYNAMIC: $(OBJ)
$(CC) -c $(SRC)
$(CC) -shared -o $(DNAME) $(OBJ)
.PHONY: my_printf_static
my_printf_static: $(STATIC)
.PHONY: my_printf_dynamic
my_printf_dynamic: $(DYNAMIC)
.PHONY: all
all: my_printf_static my_printf_dynamic
.PHONY: clean
clean:
$(RM) $(OBJ)
.PHONY: fclean
fclean: clean
$(RM) $(SNAME) $(DNAME)
.PHONY: re
re: fclean all
Thanks!
Upvotes: 1
Views: 9259
Reputation: 10456
Your makefile can be boiled down to this:
NAME := libmy_printf_$(shell uname -m)-$(shell uname -s)
SNAME := $(NAME).a
DNAME := $(NAME).so
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
CFLAGS := -ansi -pedantic -Wall -W -Werror -g3 -fPIC
LDFLAGS := -L.
LDLIBS := -l$(...)
.PHONY: all clean fclean re
all: $(SNAME) $(DNAME)
$(SNAME): $(OBJ)
$(AR) $(ARFLAGS) $@ $^
$(DNAME): LDFLAGS += -shared
$(DNAME): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(SNAME) $(DNAME)
re: fclean all
There are multiple things that you should know:
Don't use back-quotes commands, use the $(shell)
built-in function in conjunction with the :=
assignment operator to prevent commands being re-run multiple times (unless this is the desired behavior).
Use only one .PHONY
special rule, placed above all rules, and list them there.
Redefining $(CC)
or $(RM)
variables like you did is pointless since they already contain what you wanted here.
You wrote -l$(NAME)
but you didn't define a NAME
variable. I change it to $(...)
since I couldn't guess what you really wanted here, don't forget to handle this.
Use the name of the targets to be created as the name of the related rules. That way Make won't recreate the targets unless you really want it (by calling the clean
, fclean
or re
rules explicitly).
-L
flags and -l
flags should not be mixed in the same variable, unless placed at the right place in the linking command. Actually you didn't even used them. I explicitly separated them in the LDFLAGS
and LDLIBS
built-in variables, as per Make implicit rules.
If you have any questions, go ahead.
As discussed in the comments, if you need to remove the -fPIC
flag from the compilation flags for the static library, you should consider building object files in different directories:
EDIT: I added your my_printf_static
and my_printf_dynamic
rules:
NAME := libmy_printf_$(shell uname -m)-$(shell uname -s)
SNAME := $(NAME).a
DNAME := $(NAME).so
SRC := $(wildcard src/*.c)
SDIR := build-static
SOBJ := $(SRC:src/%.c=$(SDIR)/%.o)
DDIR := build-shared
DOBJ := $(SRC:src/%.c=$(DDIR)/%.o)
CFLAGS := -ansi -pedantic -Wall -Werror -W -g3
LDFLAGS := -L.
LDLIBS := -l$(...)
.PHONY: all clean fclean re my_printf_static my_printf_dynamic
all: my_printf_static my_printf_dynamic
my_printf_static: $(SNAME)
my_printf_dynamic: $(DNAME)
$(SNAME): $(SOBJ)
$(AR) $(ARFLAGS) $@ $^
$(DNAME): CFLAGS += -fPIC
$(DNAME): LDFLAGS += -shared
$(DNAME): $(DOBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(SDIR)/%.o: src/%.c | $(SDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
$(DDIR)/%.o: src/%.c | $(DDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
$(SDIR) $(DDIR):
@mkdir $@
clean:
$(RM) -r $(SDIR) $(DDIR)
fclean: clean
$(RM) $(SNAME) $(DNAME)
re: fclean all
Upvotes: 6
Reputation: 224834
What to do so it only creates object files inside the /src directory ?
Don't run the compiler twice. Your STATIC
and DYNAMIC
rules both depend on $(OBJ)
, which will cause those files to be built by make
's implicit rules. Then, immediately after that you run the compiler again within those rules. Just take those lines out. make
normally prints the commands it's going to run, so you should see why it's happening in your build log.
Upvotes: 0