0

I have the following project directory structure:

Prog
/include
/include/dir1
/include/dir2
/src
/src/dir1
/src/dir2

App1 depends on mod1 and mod2 where as App2 depends only on mod1.

With the makefile denoted below the modules and apps all build correctly - however if I make a change to mod2 and then do a 'make all', App2 gets rebuilt even though it doesn't have a dependency.

The reason for this is because OBJ being passed into the target build recipe is all of the OBJs and not just the specific ones that the current target needs.

I was wondering what change to the makefile can be made to only pass the dependent objects to the current target that's being built.

The makefile:

CC        := g++
LD        := g++

TARGETS   := app1 app2
MODULES   := mod1 mod2
INC_DIR   := $(addprefix include/,$(MODULES))
SRC_DIR   := $(addprefix src/,$(MODULES))
BUILD_DIR := $(addprefix build/,$(MODULES))

SRC       := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp))
OBJ       := $(patsubst src/%.cpp,build/%.o,$(SRC))
INCLUDES  := -Iinclude $(addprefix -I,$(INC_DIR))

vpath %.cpp $(SRC_DIR)

define make-goal
$1/%.o: %.cpp
   $(CC) $(INCLUDES) -c $$< -o $$@
endef

.PHONY: all checkdirs clean

all: checkdirs $(TARGETS)

$(TARGETS) : %: $(OBJ)
   $(CC) $(INCLUDES) -o build/$@ src/$@.cpp $^

checkdirs: $(BUILD_DIR)

$(BUILD_DIR):
   @mkdir -p $@

The makefile has been repurposed from the following answer: https://stackoverflow.com/a/2484343

Sami Kenjat
  • 185
  • 2
  • 12
  • 1
    make can't know which inputs get used by a given output unless you (or something else) tell it. You can list them manually or use something like [Auto-Dependency Generation](http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/) to generate the lists for you. – Etan Reisner May 05 '15 at 02:56
  • 1
    @EtanReisner I've read through that article - my question is how to inject the dependency list mentioned in that article into the targets rule. – Sami Kenjat May 05 '15 at 05:27
  • You don't need to inject it *into* any existing rule. make combines rule definitions. A separate `app1: foobar` line in the above makefile will **add** `foobar` as a prerequisite to `app1` but leaves that `$(TARGETS)` static pattern rule as the recipe for building `app`. See [Multiple Rules for One Target](http://www.gnu.org/software/make/manual/make.html#Multiple-Rules) for example. – Etan Reisner May 05 '15 at 11:48

1 Answers1

1

there are three targets listed in the phony 'all' target.

Each of those should have a separate rule listed, rather than lumping two of the targets 'app1' and 'app2' together.

Note: any common file changes/compiles will result in both targets being re-created.

break the 'SRC' into SRC_APP1 SRC_APP2 then use the appropriate SRC_APPx macro in each of the app1 and app2 targets.

use similar separation for the 'OBJ' macro and the 'INCLUDES' macro

Do not use the 'foreach' rules as that is asking for all the targets to be built

there are several other details that need addressing, but the above should point you in the right direction.

One thing that should greatly help.

Have the object files for app1 and app2 placed in separate directors and have the makefile look in the appropriate directory for each appx

user3629249
  • 16,402
  • 1
  • 16
  • 17
  • 1
    This is a toy example, listing all the dependencies of a typically app1 or app2 is very tedious my question was around how to use makedepend depend etc to make this makefile work – Sami Kenjat May 05 '15 at 05:28
  • @SamiKenjat, strongly suggest, Don't list the dependencies at all. Rather, use something like was linked by Etan Reisner to have 'make' generate all the dependencies for you. – user3629249 May 10 '17 at 22:58