Makefile: how to include obj file from another directory and how to recompile it if the sources change.

Hi,

Here is the structure of my directories:
../Projects/Common
../Projects/SES

The common project has its own Makefile which builds an object file common.o.
The ses project uses classes from common and builds an executable, its Makefile below.

I have two questions:
1) Is it the right way to include common.o?
2) If I change common.*, how can I re-compile common.o from ses Makefile? Right now I have to go to ../Common directory and run its Makefile.

THX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Variables
TARGET = ses
HDRS = ses.h
SRCS = ses.cpp
OBJS = $(SRCS:.cpp=.o)
CDFLAGS = -g -std=c++11
CRFLAGS = -O3 -Ofast -std=c++11 -pedantic -Wall -Wextra
LFLAGS = -static -pthread ../Common/common.o
CC = g++

# all
all: debug

# Rule to build debug
debug: $(OBJS)
	$(CC) $(LFLAGS) $(OBJS) -o $(TARGET) -lrt

# Rule to build object files
$(OBJS): $(SRCS) $(HDRS)
	$(CC) $(CDFLAGS) -c $(SRCS) -I../Common

# Rule to re-build release
release: $(SRCS) $(HDRS)
	$(CC) $(CRFLAGS) $(LFLAGS) $(SRCS) -o $(TARGET) -I ../Common

# Clean
.PHONY:clean
clean:
	rm -f $(TARGET) $(OBJS)


Edit: I use gnu.
Last edited on
It may be easier to make Common a static library. That way it can be treated as a self contained unit with little overhead. Remember, a Unix static library is just a buch of object files that are compiled in exactly the same way a program's object files are compiled.

The the makefile in Common might look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
NAME = myproject-common
VERSION = 0.1
BOOST_ROOT = /home/kbw/Code/src/boost_1_54_0

PROG = lib$(NAME)-$(VERSION).a

SRCS = common_file1.cpp common_file2.cpp common_file3.cpp

CXXFLAGS += -I./ -I$(BOOST_ROOT) -std=c++11
ifeq ($(strip $(DEBUG)), true)
	CXXFLAGS += -g
else
	CXXFLAGS += -O2
endif

all: $(PROG)

clean:
	- rm $(SRCS:.cpp=.o)

clean-all:
	- rm $(SRCS:.cpp=.o)
	- rm $(PROG)

$(PROG): $(SRCS:.cpp=.o)
	ar rcs $@ $^


Your project makefile would look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
NAME = ses
VERSION = 0.1
BOOST_ROOT = /home/kbw/Code/src/boost_1_54_0

PROG = $(NAME)

SRCS = ses_file1.cpp ses_file2.cpp ses_file3.cpp

LDFLAGS += -Wl,-Bstatic -L../Common/ -lmyproject-common-$(VERSION)
CXXFLAGS += -I./ -I$(BOOST_ROOT) -std=c++11
ifeq ($(strip $(DEBUG)), true)
	CXXFLAGS += -g
else
	CXXFLAGS += -O2
endif

all: $(PROG)

clean:
	- rm $(SRCS:.cpp=.o)

clean-all:
	- rm $(SRCS:.cpp=.o)
	- rm $(PROG)

$(PROG): $(SRCS:.cpp=.o)
	$(LINK.cc) $^ -o $@


Then you have a makefile in the parent directory that looks like:
1
2
3
4
5
6
PROJECTS = Common ses

all: $(PROJECTS)

$(PROJECTS):
	$(MAKE) -C $@
Last edited on
@kbw, thank you for replying. I am using static lib for my other shared library I can as well do it for common. I used to have all the files of respective projects in the same directory but as the number of projects grow that came the time to put them into their own directories. I have to say besides ses I have multiple other projects using classes from common.

That means I have to call a third makefile from the parent directory to make sure common is built before ses. I usually work from the ses directory, can I call Common Makefile from the ses Makefile?
I think I just call Common makefile from ses Makefile and from other projects' Makefiles:

 
$(MAKE) -C ../Common
Last edited on
can I call Common Makefile from the ses Makefile?
You can. You could set up a rule to say that libcommon.a is built by running (cd ../Common/; make) or even better, your line above.

Or you could run (cd ../; make) from ses.

I find it's best to keep the makefiles as simple as reasonably possible.
Last edited on
I see, thank you.
Quick question, I noticed that even when I haven't changed the source files and run the make file the date on object files and executable files is updated. So it's not really doing re-compiling and re-building but just updating the date, right?

Edit: also in your code, how do you set DEBUG variable?
Edit: so DEBUG is a env. var. If I do not want to read env. var. how can I do such conditional?
Last edited on
I noticed that even when I haven't changed the source files and run the make file the date on object files and executable files is updated.
I'm not sure what's going on there. That shouldn't be the case.

You can look in details what make is doing by running:
 
make -B -n -d | less

-B rebuild everything
-n do nothing
-d show debug

It's verbose.

how do you set DEBUG variable?
make DEBUG=true
I have to investigate this, I might post another thread.

Thank you for your help.
Topic archived. No new replies allowed.