How to write build target for sources from different paths? - makefile

At first, I'm a noobie in makefiles...
I have next targets in my Makefile:
$(BUILD_PATH)/%.o: %.c $(GEN_PATH)/%.c
$(CC) $(FLAGS) $(CFLAGS) $(HEADERS) -c $< -o $#
server: $(BUILD_PATH)/main.o $(BUILD_PATH)/socket.o $(BUILD_PATH)/settings.o $(BUILD_PATH)/options.o
$(CC) -L$(LIB_PATH) -Wl,-rpath=$(LIB_PATH) $(FLAGS) $(CFLAGS) -o $(DIST_PATH)/server $^ $(LDFLAGS)
I specified that object files must be compiled from the current folder and $(GEN_PATH) but it doesn't work and I am getting error:
make: *** No rule to make target '../build/server/options.o', needed by 'server'. Stop.
How can I write this rule right?
P.S. It's not primary question but how can I write my input targets shorter? I tried this variant:
server: $(BUILD_PATH)/%.o
$(CC) -L$(LIB_PATH) -Wl,-rpath=$(LIB_PATH) $(FLAGS) $(CFLAGS) -o $(DIST_PATH)/server $^ $(LDFLAGS)
But it didn't work.

Related

How to write a general pattern in makefile

I have multiple programs which share the same structure of compilation.
test_variance : test_variance.o
$(CPP) -o test_variance.exe $(CFLAGS) test_variance.o $(LIBDIR) $(LIBS)
test_variance_incremental: test_variance_incremental.o
$(CPP) -o test_variance_incremental.exe $(CFLAGS) test_variance_incremental.o $(LIBDIR) $(LIBS)
test_hyper: test_hyper.o
$(CPP) -o test_hyper.exe $(CFLAGS) test_hyper.o $(LIBDIR) $(LIBS)
test_hyper.o: test_hyper.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c test_hyper.cpp
test_variance_incremental.o: test_variance_incremental.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c test_variance_incremental.cpp
test_variance.o : test_variance.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c test_variance.cpp
So for compling .o, I can use the pattern
%.o: %.cpp
$(CPP) $(CFLAGS) $(INCLUDES) -c $<
I wonder if there is a general pattern for compling the executive. I've tried
TARGETS = test_variance test_variance_incremental test_hyper
$(TARGETS): $#.o
$(CPP) -o $#.exe $^ $(CFLAGS) $(LIBDIR) $(LIBS)
But Make tells me there is no input files and I think my usage of $# is wrong. Any advice?
You should use CC and CFLAGS for compiling C code, and CXX and CXXFLAGS for compiling C++ code. CPP (in make) is used for running the C preprocessor (only). The standard variable to hold libraries is LDLIBS.
If you use these variables then you don't even need to define your own rules at all: there are built-in rules in make that already know how to compile and link C++ programs. All you need is this:
TARGETS = test_variance test_variance_incremental test_hyper
all: $(TARGETS)
Anyway, if you want to write it explicitly you can write:
TARGETS = test_variance test_variance_incremental test_hyper
all: $(TARGETS)
% : %.o
$(CXX) -o $# $^ $(CXXFLAGS) $(LDFLAGS) $(LDLIBS)
(you should definitely not name the target test_variance, but then have your link line build test_variance.exe: the target name and the file that the recipe builds must always be the same).

How to make N .o files from N .c files using makefile?

I have 2 .c files that defined in the makefile:
SOURCES = main.c \
memory.c
and I want to build 2 .o files using 1 command "make compile-all" (and don't link them), but can't understand how to do this.
I could create var for objective files and add .PHONY command:
OBJS=$(SOURCES:.c=.o)
.PHONY: compile-all
But what should be written next?
I guess it should be something similar with this:
%.o: %.c $(INCLUDES)
$(CC) -c $< $(CFLAGS) -o $#
But there's no way I can succeed.
Thank you in advance!
BASENAME := main
TARGET := $(BASENAME).out
OBJS=$(SOURCES:.c=.o)
%.i: %.c
$(CC) -E $< $(CFLAGS) -o $#
%.asm: %.c
$(CC) -S $< $(CFLAGS) -o $#
%.o: %.c
$(CC) -c $< $(CFLAGS) -o $#
.PHONY: build
build:$(TARGET)
$(TARGET): $(OBJS)
$(CC) $(OBJS) $(CFLAGS) $(PLATFORM_FLAGS) $(LDFLAGS) -o $#
.PHONY: clean
clean:
rm -f $(OBJS) $(TARGET) *.i *.asm $(BASENAME).map
.PHONY: compile-all
compile-all: $(OBJS)
make compile-all creates .o files from all .c files.

Makefile generic binaries compilations

I have a set of source files that share the same Makefile rule pattern:
bin1: bin1.o libfoo.a
$(LDENV) $(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
bin2: bin2.o libfoo.a
$(LDENV) $(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
bin3: bin3.o libfoo.a
$(LDENV) $(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
...
Now, how may I refactor this to avoid repeating the same rule over and over? This is easy if a file extension is added to the binaries:
%.out: %.o libfoo.a
$(LDENV) $(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
But is it possible to do the same without using one?
You can use Static Pattern Rules:
bin1 bin2 bin3: %: %.o libfoo.a
$(LDENV) $(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
This way this is cleaner and you are sure that the % only match bin1, bin2 and bin3 targets (I think this is want you want).

Makefile : No rule to make target (automatic variables)

I am having trouble with my makefile, i have been reading somme tutoriels on how to make a more re-usable makefile but i am facing this error, and i have been searching for a while now, especially on the GNU make manual and here.
Here is my makefile :
SRC_DIR=./src
BUILD_DIR=./build
OBJS= $(BUILD_DIR)/main.o $(BUILD_DIR)/hamming.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
I am having the error :
make: No rule to make target build/main.o', needed bybuild/main'. Stop.
It seems to me that the objects in the variable OBJS are not associated with the %.o pattern rule, but i don't know why.
In my working directory there is : my makefile and the two directories 'src' and 'build'.
Thank you.
I'll go out on a limb and guess that there is no src/main.h. If that's the case, you could fix things this way:
$(BUILD_DIR)/hamming.o: $(BUILD_DIR)/%.o : $(SRC_DIR)/%.h
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) -c $< $(CFLAGS) -o $#
EDIT:
Now I'm puzzled. Please try this (it is crude, but if it works we can refine it):
SRC_DIR=./src
BUILD_DIR=./build
OBJS= $(BUILD_DIR)/main.o $(BUILD_DIR)/hamming.o
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main.o: $(SRC_DIR)/main.c
$(CC) -c $< $(CFLAGS) -o $#
$(BUILD_DIR)/main: $(OBJS)
$(CC) -o $# $^ $(CFLAGS)
Here is a little documentation I put together for NMake a while back I hope it helps. Are you sure there are only tabs before the commands. You can't have spaces that is the number one error I have seen in the past.

How to make this Makefile more concise?

I know there are ways to remove duplicates $(CC) $(CFLAGS) $# $^ in Makefile. Can you tell me how to make the Makefile below more concise?
CC=gcc
CFLAGS=-pthread -g -o
all: p1 p2
p1: p1.c
$(CC) $(CFLAGS) $# $^
p2: p2.c
$(CC) $(CFLAGS) $# $^
To make your Makefile more concise, you can write it as follows.
CC=gcc
CFLAGS=-pthread -g -o
all: p1 p2
%: %.c
$(CC) $(CFLAGS) $# $^
Then you can add as many p's as you want on the all: line. As long as you provide pN.c, make will compile them into the corresponding pN.
Yes, you can combine commands "by prerequisite". For example:
CC=gcc
CFLAGS=-O3
INCLS=-I$(BASEDIR)/include
LIBS=$(BASEDIR)/lib/thread.a
OBJS = dotprod_mutex.o dotprod_serial.o
EXEC = dotprod
$(EXEC): $(OBJS)
$(CC) -o $(EXEC) $(OBJS) $(LIBS)
$(OBJS): dotprod.h
$(CC) $(CFLAGS) $(INCLS) -c $*.c
or somesuch -- you'll need to go through the details and make sure those libraries and so on actually make sense.
Note that the phrase $(OBJS): dotprod.h means that $(OBJS): depends on the presence of dotprod.h.
You will want to read the manual to get all the gory details, in particular:
Letting Make deduce commands
Combine by prerequisite
As for tools to automate this stuff, you want automake and autoconf: http://sourceware.org/autobook/

Resources