Gee I keep hoping that someone knows this stuff off the top of their heads
but that never seems to be the case.
Well, having spent way too much time on it I figured it out. It required
using a construct that I hadn’t previously used in a makefile called a
Static Pattern Rule.
For anyone who actually cares I’m reposting my makefile, not the simplified
one but the real one that actually works. You can see why I say it writes
itself.
The important thing for me is that it can be located anywhere in pathname
space. It assumes that:
- …/… is a parent directory for the whole project
- …/…/inc is an include directory for the whole project
- …/…/bin is a bin directory for the project
Normally the project parent directory is the root directory but I can copy
the whole project to under my home directory and no path names need to be
changed.
(Don’t forget to convert leading spaces to tab characters)
…SUFFIXES:
these macros may be redefined on the make command line
#DEBUG = -g2d
DEBUG = -Oinertx
MODEL = f
OBJ = /tmp/obj/$(MODEL)/
SHELL = /tmp/bin/ksh
these are all indended to be self defining macros
PWD = $(shell /usr/bin/fullpath -t .)
PRODUCT_PATH = $(shell /usr/bin/fullpath -t …/…)
BIN = $(PRODUCT_PATH)/bin/
INCLUDE_DIRS = $(PRODUCT_PATH)/inc
I_INCLUDE_DIRS = $(foreach DIR, $(INCLUDE_DIRS), -I$(DIR))
HEADER_FILES = $(foreach DIR, $(INCLUDE_DIRS) ., $(wildcard $(DIR)/.h
$(DIR)/.hpp) )
SOURCE_FILES = $(wildcard *.c *.cc *.cpp *.C)
PROGS = $(foreach FILE, $(SOURCE_FILES), $(basename $(FILE) ) )
OBJS = $(foreach FILE, $(SOURCE_FILES), $(OBJ)$(basename $(FILE)).o )
MAPS = $(foreach X, $(PROGS), $(BIN)$(X).map )
XPROGS = $(foreach X, $(PROGS), $(BIN)$(X) )
LIBS = $(OBJ)myLib.lib
L_LIBS = $(foreach X, $(LIBS), -l$(X))
CFLAGS = -Q -5 $(I_INCLUDE_DIRS) -m$(MODEL)
$(DEBUG) -w4 -WC,-we -WC,-xs -WC,-fo=$(OBJ)${@F}
#CFLAGS = -P
$(I_INCLUDE_DIRS) -m$(MODEL) -w4 -WC,-we -WC,-xs -WC,-fo=$(OBJ)${@F
}
LDFLAGS = -Wl,“op map=$@.map” $(L_LIBS) -L/tmp/lib
…PRECIOUS: $(OBJS)
the primary goal
…PHONY: all
all: $(XPROGS) $(OBJS)
$(OBJS) : $(OBJ)%.o : %.cpp $(HEADER_FILES) Makefile
@echo “\033<Compiling $(DEBUG) $<\033>”
@$(CC) $(CFLAGS) $(DEBUG) -c $<
$(XPROGS) : $(BIN)% : $(OBJ)%.o $(LIBS)
@echo “Linking $@”
@$(CC) -Q -m$(MODEL) $(LDFLAGS) $(DEBUG) -o$@ $(OBJ)${@F}.o
@usemsg -c $@ ${@F}.c??
\
phony targets
…PHONY: clean
clean:
@echo Removing .o’s and .lib for $(PWD) modules only
@rm -f *.err $(OBJS) $(MAPS) $(XPROGS)
…PHONY: uncond
uncond: clean all
…PHONY: testMake
testMake:
@echo SHELL=$(SHELL) Command line=$(MAKE) $(MAKEFLAGS)
MAKELEVEL=$(MAKELEVEL)
@echo CC=$(CC) CFLAGS=$(CFLAGS) CCFLAGS=$(CCFLAGS) CPPFLAGS=$(CPPFLAGS)
CXXFLAGS=$(CXXFLAGS) CPP=$(CPP) CXX=$(CXXFLAGS)
@echo LD=$(LD) LDFLAGS=$(LDFLAGS)
@echo SUFFIXES=$(SUFFIXES)
@echo PRODUCT_PATH=$(PRODUCT_PATH) INCLUDE_DIRS=$(INCLUDE_DIRS)
@echo HEADER_FILES=$(HEADER_FILES)
@echo SOURCE_FILES=$(SOURCE_FILES)
@echo BIN=$(BIN) OBJ=$(OBJ) LIBS=$(LIBS) OBJS=$(OBJS)
@echo PROGS=$(PROGS)
@echo MAPS=$(MAPS)
@echo XPROGS=$(XPROGS)
“Bill Caroselli (Q-TPS)” <QTPS@EarthLink.net> wrote in message
news:aetl7p$ol3$1@inn.qnx.com…
I’m trying to write a new generation of makefile that sort of writes
itself.
I’ve had a lot of luck except for implicit targets that aren’t in the
current directory. My example makefile is listed at the end of this post.
It assumes that abc.c & xyz.c are source files.
It assumes that header.h is a header file.
It assumes that lib is a library file.
Basically what I want to accomplish is:
- if a .c or the header files changes I want to recompile the source
file(s)
- if a .o is missing or is newer than the executable or the lib file is
newer than the executable I want to relink the executable.
- BTW, if lib is missing it is OK to just say don’t know how to make lib.
It is outside the scope of this makefile
This is pretty vanilla stuff, no?
For th purpose of testing the make file I’ve changed compiles and links to
‘cp -t’.
As long as all targets are in the current directory the make works as
expected. But if I define the TMP make variable to be '/tmp/ (just delete
the ‘#’ pound sign on line 3) then then it will compile if necessary but
not
link.
To try this make file just create the files as follows:
touch abc.c xyz.c header.h lib
it doesn’t matter what’s in them.
Here is the makefile. If someone can tell me how to get it to put the
targets in the $(TMP) directory I would appreciate it.
NOTE: Make sure that all leading white space is a tab character. I think
my
news reader is substituting spaces.
.SUFFIXES:
TMP = /tmp/
HEADERS would normally be a list of header files
#HEADERS = $(wildcard *.h)
HEADERS = header.h
LIST would normally be a list of source files
#LIST = $(wildcard *.c *.cc *.cpp *.C)
LIST = abc xyz
OBJS = $(foreach x, $(LIST), $(TMP)$(x).o)
XLIST = $(foreach x, $(LIST), $(TMP)$(x))
.PRECIOUS: $(OBJS)
\
the primary goal
.PHONY: all
all: $(XLIST) $(OBJS)
\
I want my .o to be remade if any header files change
$(OBJS): $(HEADERS)
$(TMP)%.o: %.c
@echo COMPILING
cp -t $(notdir $(basename $@)).c $@
I want my executable to remade if my library is remade
$(XLIST) : lib
$(TMP)% : %.o
@echo LINKING
cp -t $(notdir $@).o $@
.PHONY: clean
clean:
rm $(OBJS) $(XLIST)