• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 364
  • Last Modified:

Altering a Makefile to add dependencies on the .hxx files?

Hi,

If I alter the .hxx files, it doesnt recompile the project. How would I add dependencies on the .hxx files?

As an aside, any recommendations on how to make this makefile cleaner?

# makefile on Linux ELF with arm-linux-gcc

# Where the zlib library and include files are located.
ZLIBLIB=./libz/arm/
ZLIBINC=./libz/arm/

ZPNGLIB=./libpng-1.2.5/arm/
ZPNGINC=./libpng-1.2.5/arm/

WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \
      -Wmissing-declarations -Wtraditional -Wcast-align \
      -Wstrict-prototypes -Wmissing-prototypes #-Wconversion

CC = arm-linux-gcc
CXX = arm-linux-g++
CFLAGS = -g -Wall -I$(ZLIBINC) -I$(ZPNGINC) -funroll-loops

LDFLAGS=-Wl,-Map,main.map -L. \
  -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBINC)  \
  -L$(ZPNGLIB) -Wl,-rpath,$(ZPNGINC)  \
      -Wl,-rpath,.  \
  -lpng12 -lz -lm -lpthread
      
RM = /bin/rm

OBJS =  \
  Time.o      \
  Global.o
BIN = main

OBJS += $(BIN:=.o)

.SUFFIXES:
.SUFFIXES: .c .cxx .o

.c.o:
      $(CC) $(CFLAGS) ${DEFINES} -c $< -o $@

.cxx.o:
      $(CXX) $(CFLAGS) ${DEFINES} -c $< -o $@

$(BIN): $(OBJS)
      $(CXX) $(OBJS) -o $@ $(LDFLAGS)

clean:
      $(RM) -f $(BIN) $(OBJS)
      #touch *.cxx
      #touch *.hxx
0
Risky101
Asked:
Risky101
1 Solution
 
brettmjohnsonCommented:
The above makefile contains mostly generic rules.
The only project-specific dependencies are defined in the OBJS and BIN macros.  
The $(BIN): $(OBJS) dependency line states the output executable binary depends
upon the object files defined by $OBJS.  However, only a generic rules are specified
for deriving a .o from a .c or .cxx, and those generic rules do not specify that any
specific .o file depends upon a particular set of header files in addition to the .c or .cxx
file.

You will have to add specific rules to the makefile.  For instance, suppose xyzzy.cxx
depends upon xyzzy.hxx and foobar.hxx, you will need to add dependency line like:

xyzzy.o:      xyzzy.cxx xyzzy.hxx foobar.hxx

0
 
Risky101Author Commented:
Thanks - but I still can't work out how to alter the specific makefile, listed above, to add dependencies on the appropriate .hxx files.
0
 
stefan73Commented:
Hi Risky101,
Have a look at gcc's -M family of switches:

       -M  Instead of outputting the result of preprocessing, output a rule
           suitable for make describing the dependencies of the main source
           file.  The preprocessor outputs one make rule containing the object
           file name for that source file, a colon, and the names of all the
           included files, including those coming from -include or -imacros
           command line options.

           Unless specified explicitly (with -MT or -MQ), the object file name
           consists of the basename of the source file with any suffix
           replaced with object file suffix.  If there are many included files
           then the rule is split into several lines using \-newline.  The
           rule has no commands.

           This option does not suppress the preprocessor's debug output, such
           as -dM.  To avoid mixing such debug output with the dependency
           rules you should explicitly specify the dependency output file with
           -MF, or use an environment variable like DEPENDENCIES_OUTPUT.
           Debug output will still be sent to the regular output stream as
           normal.

           Passing -M to the driver implies -E, and suppresses warnings with
           an implicit -w.

That's probably what you're looking for. You can include the generated dependency rules with the "include" command of GNU make. Use "-include" if you don't want to generate errors in case the files are not there yet.

Check http://www.gnu.org/software/make/make.html for details.

Cheers!

Stefan
0
Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

 
stefan73Commented:
your Makefile additions would look like this:

DEPS = $(OBJS:.o=.dep)

-include $(DEPS)

.c.dep:
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@

.cxx.dep:
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@


Also make sure the rule creating your final binary is your first rule, because that is the default target to build when you just call make without any arguments.
0
 
Risky101Author Commented:
Er, I spent a while on this but couldn't get it to work. I might need a listing of the finished Makefile.
0
 
guynumber5764Commented:
You could try a hack and change "$(BIN): $(OBJS)" to "$(BIN): $(OBJS) $(HDRS)"  where HDRS =  Time.h  Global.h  (or whatever)

or you could explicitly write out your rules:

Global.o: Global.c Global.h
     $(CC) $(CFLAGS) ${DEFINES} -c $< -o $@

Time.o: Time.c Time.h Global.h
     $(CC) $(CFLAGS) ${DEFINES} -c $< -o $@

main: Time.o Global.o
     $(CXX) $(OBJS) -o $@ $(LDFLAGS)

Don't forget to make sure all your [TAB]s are in the right place.  You might even be able to mix and match the general rules (.c.o:) and specific rules but IMO you are better to just use specific rules.
0
 
Risky101Author Commented:
Hi,

I would prefer to use the -M switch, as it automatically works out the dependencies on the .h files.

To make it easier, could you cut'n'paste the Makefile below, and add the correct alterations to it, in the correct place.

# makefile on Linux ELF with arm-linux-gcc

# Where the zlib library and include files are located.
ZLIBLIB=./libz/arm/
ZLIBINC=./libz/arm/

ZPNGLIB=./libpng-1.2.5/arm/
ZPNGINC=./libpng-1.2.5/arm/

WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \
     -Wmissing-declarations -Wtraditional -Wcast-align \
     -Wstrict-prototypes -Wmissing-prototypes #-Wconversion

CC = arm-linux-gcc
CXX = arm-linux-g++
CFLAGS = -g -Wall -I$(ZLIBINC) -I$(ZPNGINC) -funroll-loops

LDFLAGS=-Wl,-Map,main.map -L. \
  -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBINC)  \
  -L$(ZPNGLIB) -Wl,-rpath,$(ZPNGINC)  \
     -Wl,-rpath,.  \
  -lpng12 -lz -lm -lpthread
     
RM = /bin/rm

OBJS =  \
  Time.o      \
  Global.o
BIN = main

OBJS += $(BIN:=.o)

.SUFFIXES:
.SUFFIXES: .c .cxx .o

.c.o:
     $(CC) $(CFLAGS) ${DEFINES} -c $< -o $@

.cxx.o:
     $(CXX) $(CFLAGS) ${DEFINES} -c $< -o $@

$(BIN): $(OBJS)
     $(CXX) $(OBJS) -o $@ $(LDFLAGS)

clean:
     $(RM) -f $(BIN) $(OBJS)
     #touch *.cxx
     #touch *.hxx
0
 
stefan73Commented:
Here's the changes. For the first call, you can type "make depend".

# makefile on Linux ELF with arm-linux-gcc

# Where the zlib library and include files are located.
ZLIBLIB=./libz/arm/
ZLIBINC=./libz/arm/

ZPNGLIB=./libpng-1.2.5/arm/
ZPNGINC=./libpng-1.2.5/arm/

WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \
     -Wmissing-declarations -Wtraditional -Wcast-align \
     -Wstrict-prototypes -Wmissing-prototypes #-Wconversion

CC = arm-linux-gcc
CXX = arm-linux-g++
CFLAGS = -g -Wall -I$(ZLIBINC) -I$(ZPNGINC) -funroll-loops

LDFLAGS=-Wl,-Map,main.map -L. \
  -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBINC)  \
  -L$(ZPNGLIB) -Wl,-rpath,$(ZPNGINC)  \
     -Wl,-rpath,.  \
  -lpng12 -lz -lm -lpthread
     
RM = /bin/rm

OBJS =  \
  Time.o      \
  Global.o
BIN = main

OBJS += $(BIN:=.o)

DEPS = $(OBJS:.o=.dep)


# Change start

all: $(BIN) depend

depend: $(DEPS)

-include $(DEPS)

.c.dep:
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@

.cxx.dep:
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@

# Change end

.SUFFIXES:
.SUFFIXES: .c .cxx .o

.c.o:
     $(CC) $(CFLAGS) ${DEFINES} -c $< -o $@

.cxx.o:
     $(CXX) $(CFLAGS) ${DEFINES} -c $< -o $@

$(BIN): $(OBJS)
     $(CXX) $(OBJS) -o $@ $(LDFLAGS)

clean:
     $(RM) -f $(BIN) $(OBJS)
     #touch *.cxx
     #touch *.hxx
0
 
Risky101Author Commented:
Hi,

This doesnt seem to work.If the .cxx files are changed, it recompiles appropriately, if the .hxx files are changed it does not recompile.

I executed "make depend" before "make". The only way to get it working at the moment is to do a "make clean" then a "make" if any of the .hxx files are changed.

Shane.

I'm increasing the points every time - this script is going to work at some point!
0
 
stefan73Commented:
Did it create the .dep files?
Did you check the content of $(DEPS)?
The .dep files should contain the dependency rules of your .hxx files, too. You can simply look into one of them and check if they're there.

Or do a "make depend" and then replace "-include" by "include" in your make file. In case make complains, something went wrong with file creation.
0
 
stefan73Commented:
Ouch - comment out the ".SUFFIXES" lines. Otherwise .dep files will be ignored.
0
 
Risky101Author Commented:
Hmmmm ... I think this makefile is a long way off from working.

It didn't create the .dep files.

For example:

.c.dep:
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@

Should be:

.c.dep:
    $(CC) $(CFLAGS) -M $(LIST_OF_C_FILES)
0
 
stefan73Commented:
Risky101,
> Should be:

> .c.dep:
>     $(CC) $(CFLAGS) -M $(LIST_OF_C_FILES)

No, unless you want to create a common dependency file for all your .c/.cxx files. That's a possibility, but you'd normally want this only for small projects, since a single .c file modification will result in a dependency rebuild for all your .c files. If you want that, your rule should be:

-include common.dep

common.dep: $(LIST_OF_C_FILES)
     $(CC) $(CFLAGS) -M $(LIST_OF_C_FILES) -o common.dep

Unless the number of your source files is small, you'd usually want to have seperate dependency files.
0
 
stefan73Commented:
Try GNU make's static pattern rules:

DEPS = $(OBJS:.o=.dep)

-include $(DEPS)

$(DEPS): %.dep: %.c
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@

$(DEPS): %.dep: %.cxx
    $(CC) $(CFLAGS) -M ${DEFINES} $< -o $@


$(OBJS): %.o: %.c
     $(CC) $(CFLAGS) ${DEFINES} -c $< -o $@

$(OBJS): %.o: %.cxx
     $(CXX) $(CFLAGS) ${DEFINES} -c $< -o $@

...these work fine for me.
0

Featured Post

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now