LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 08-12-2005, 05:02 AM   #1
markhod
Member
 
Registered: Sep 2003
Posts: 103

Rep: Reputation: 15
gmake for c++ insists on recompiling unchanged class


Hi,

I have a structure as follows in some c++ code on a linux box:

class A includes myMacro.C. If I change myMacro.C I would expect class A to be recompiled due to the dependency. This happens.

What is odd is that another class B is recompiled too. This is in the loop because myMacro.C #includes B.h. But B doesnt depend on myMacro.C so why does it recompile all the time? B also does not depend on A and A doesnt depend on B.

The other odd thing is that if do gmake twice it doesnt say nothing to compile (which it shouldnt because it should know I didnt change anything since). It still appears to find the changes in class A (and recompiles B again too!!). Could this be a file system problem of some sort so that gmake is getting incorrect timestamps and thinks it needs to recompile stuff it doesnt? (ls -l shows the timestamps look normal).

I use the identical makefile in other directories and they exhibit no such problem so I am pretty sure the makefile cant be causing this.

Cheers,

Mark
 
Old 08-12-2005, 08:38 AM   #2
orgcandman
Member
 
Registered: May 2002
Location: dracut MA
Distribution: Ubuntu; PNE-LE; LFS (no book)
Posts: 594

Rep: Reputation: 102Reputation: 102
actually, this IS probably a makefile problem. If you're depending on some constantly changing file, or you don't setup your dependancies correctly, make/gmake won't look at the file timestamps correctly. It will just recompile.
 
Old 08-12-2005, 08:46 AM   #3
markhod
Member
 
Registered: Sep 2003
Posts: 103

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by orgcandman
actually, this IS probably a makefile problem. If you're depending on some constantly changing file, or you don't setup your dependancies correctly, make/gmake won't look at the file timestamps correctly. It will just recompile.
the makefile treats all classes the same. It only knows about <name>*.h, not the individual class names. I compiles any class beginning with <name> and treats it the same. I dont understand how one class can therefore be singled out for special treatment. Also the same makefile doesnt cause such a problem in other software packages set up the same way.

The macro.C code does change every time I recompile. This could be every 5 minutes. But I have never had a problem with frequent code changes before.

Why would this matter though - the timestamp is a timestamp regardless of when it was made. Does gmake really treat recently changed files differently? or it knows how many times a file has changed per unit time and cares?

Thanks,

Mark
 
Old 08-12-2005, 11:16 AM   #4
orgcandman
Member
 
Registered: May 2002
Location: dracut MA
Distribution: Ubuntu; PNE-LE; LFS (no book)
Posts: 594

Rep: Reputation: 102Reputation: 102
it would be helpful if you posted the makefile
 
Old 08-12-2005, 11:22 AM   #5
markhod
Member
 
Registered: Sep 2003
Posts: 103

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by orgcandman
it would be helpful if you posted the makefile
I cant make a simple example that shows the problem unfortunatley and the makefile contains a lot of root - http://root.cern.ch - related stuff which may confuse matters (unfortunatly I cant manage to make a simple example to show the problem )...anyway here is all the gore:

# --- External configuration ----------------------------------
CC = g++
CCFLAGS = -O2
LD = g++
#LDFLAGS = -g
LDFLAGS =
MFLAGS = -MM
INCLUDES =
USER_DIR = /home/hodgkinson
WORKDIR = $(USER_DIR)/EFlowAnalysis/tmp
LIBDIR = $(WORKDIR)
# -------------------------------------------------------------


# Internal configuration

PACKAGE =EFlowAnalysis
LD_LIBRARY_PATH :=$(ROOTSYS)/lib: export LD_LIBRARY_PATH
OBJDIR =$(WORKDIR)/objects
INCDIR =$(WORKDIR)/$(PACKAGE)
ROOFITCORE_DIR =$(ROOFITCORE)/$(WORKDIR)/
VPATH =$(INCDIR) $(OBJDIR)

INCLUDES = \
-I$(WORKDIR) \
-I$(ROOTSYS)/include \

ROOTSYS ?= ERROR_RootSysIsNotDefined
RDLLIST = $(filter-out $(PACKAGE)_LinkDef.rdl,$(wildcard *.rdl))
SKIPLIST =
CINTFILE = $(PACKAGE)Cint.cc
CINTOBJ = $(PACKAGE)Cint.o
LIBFILE = $(LIBDIR)/lib$(PACKAGE).a
SHLIBFILE = $(LIBDIR)/lib$(PACKAGE).so
#EXECUTABLE = $(OBJDIR)/$(PACKAGE)App.o

ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)

NGLIBS = $(ROOTGLIBS)
NGLIBS += -lMinuit
NGLIBS += -lEG
NGLIBS += -lHtml
GLIBS = $(filter-out -lNew, $(NGLIBS))

CXXFLAGS := -O -Wall -fPIC
CXXFLAGS += $(ROOTCFLAGS)
CXX := g++

default: shlib

# List of all includes files to copy from rdl
HHLIST=$(patsubst %.rdl,%.hh,$(RDLLIST))

# List of all source files to build
CCLIST=$(filter-out $(SKIPLIST),$(wildcard *.cc))

# List of all object files to build
OLIST=$(patsubst %.cc,%.o,$(CCLIST))

# List of all dependency file to make
DLIST=$(patsubst %.rdl,%.d,$(RDLLIST))

# Implicit rule making all dependency Makefiles included at the end of this makefile
$(INCDIR)/%.d: %.cc $(HHLIST)
@echo "Making $@"
@set -e; $(CC) $(MFLAGS) $(CPPFLAGS) $(INCLUDES) $< \
| sed 's/\($(notdir $*)\)\.o[ :]*/\1.o $(notdir $@) : /g' > $@; \
[ -s $@ ] || rm -f $@

# Implicit rule copying all RDL to INCDIR/HH
%.hh: %.rdl
@mkdir -p $(INCDIR)
@cp $< $(INCDIR)/$@

# Implicit rule to compile all classes
%.o : %.cc
@echo "Compiling $<"
@mkdir -p $(OBJDIR)
@$(CC) $(LDFLAGS) $(CCFLAGS) -c $< -o $(OBJDIR)/$(notdir $@) $(INCLUDES)


# Rule to make ROOTCINT output file
$(OBJDIR)/$(CINTOBJ): $(RDLLIST) $(PACKAGE)_LinkDef.hh $(INCDIR)
@mkdir -p $(INCDIR)
@mkdir -p $(OBJDIR)
# @cp *.hh $(INCDIR)
@echo "Running rootcint"
@ROOTSYS=$(ROOTSYS)
@export ROOTSYS
@cd $(INCDIR) ; $(ROOTSYS)/bin/rootcint -f $(CINTFILE) -c $(INCLUDES) $(HHLIST) $(PACKAGE)_LinkDef.hh
@echo "Compiling $(CINTFILE)"
@$(CC) $(LDFLAGS) $(CCFLAGS) -c $(INCDIR)/$(CINTFILE) -o $(OBJDIR)/$(CINTOBJ) $(INCLUDES)

# Rule to combine objects into a library
$(LIBFILE): $(OLIST) $(INCDIR)/$(CINTFILE)) $(patsubst %.cc,%.o,$(OBJDIR)/$(CINTFILE))
@echo "Making $(LIBFILE)"
@rm -f $(LIBFILE)
@ar q $(LIBFILE) $(addprefix $(OBJDIR)/,$(OLIST) $(patsubst %.cc,%.o,$(CINTFILE)))
@ranlib $(LIBFILE)

# Rule to combine objects into a shared library
$(SHLIBFILE): $(OLIST) $(patsubst %.cc,%.o,$(OBJDIR)/$(CINTFILE))
#$(patsubst %.cc,%.o,/u/br/markhod/RooFitCore/tmp/objects/RooFitCoreCint.o)
@echo "Making $(SHLIBFILE)"
@rm -f $(SHLIBFILE)
@$(CC) $(LDFLAGS) $(addprefix $(OBJDIR)/,$(OLIST) $(patsubst %.cc,%.o,$(CINTFILE))) -shared -o $(SHLIBFILE)
#$(patsubst %.cc,%.o,/u/br/markhod/RooFitCore/tmp/objects/RooFitCoreCint.o) -shared -o $(SHLIBFILE)

# Rule to make executable

.SUFFIXES: .cc

.cc.o:
$(CXX) $(CXXFLAGS) -c $<

$(EXECUTABLE): $(addprefix $(OBJDIR)/,$(OLIST)) $(addprefix $(OBJDIR)/,$(PACKAGE)_Main.o)
#$(filter-out /u/br/markhod/RooFitCore/tmp/objects/RooHtml.o,$(wildcard /u/br/markhod/RooFitCore/tmp/objects/*.o))
@echo "Making $(EXECUTABLE)"
@rm -f $(EXECUTABLE)
@$(LD) $(LDFLAGS) -o $(PACKAGE)App $(addprefix $(OBJDIR)/,$(PACKAGE)_Main.o) $(SHLIBFILE) $(GLIBS)


# Useful build targets

clean:
rm -rf $(OBJDIR)
rm -rf $(INCDIR)
rm -f $(LIBFILE)
rm -f $(SHLIBFILE)
rm -f $(EXECUTABLE)

lib: $(LIBFILE)

shlib: $(SHLIBFILE)

bin: $(EXECUTABLE)

#all: $(SHLIBFILE) $(EXECUTABLE)

.PHONY : clean shlib lib bin default

-include $(addprefix $(INCDIR)/,$(DLIST))
 
Old 08-12-2005, 07:28 PM   #6
leonscape
Senior Member
 
Registered: Aug 2003
Location: UK
Distribution: Debian SID / KDE 3.5
Posts: 2,313

Rep: Reputation: 47
Have you considered where the headers are included? for instance:

file1.h
file2.h --> contains #include file1.h
file3.h
file4.h

file1.cpp --> contains #include file1.h
file2.cpp --> contains #include file2.h
file3.cpp --> contains #include file3.h and file1.h
file4.cpp --> contains #include file4.h and file3.h
file5.cpp --> contains #include file5.h and file2.h

Now if you change file1.h, file1.cpp, file2.cpp, file3.cpp and file5.cpp will be recompiled

file4.cpp will not be recompiled because it does not contain file1.h and neither does file3.h ( which it also includes ) file5.cpp does recompile because file2.h does contain file1.h

These cascading events are eactly why forward declarations are so useful. Since you may need to define a pointer, or a function argument in another header to a class from file1.h you forward declare it and only included the header in the cpp, so anything that also includes that header doesn't have to recompile every time you change that header file. If however you declare an instance you will still need the header.

I know this isn't exactly clear, but run through what each cpp file includes, and then what those headers include.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Mozilla insists on Postscript avenolpey Debian 3 01-27-2009 03:19 PM
dwnloader insists on unpacking tar.gz's on FC1 farpoint Linux - General 2 06-03-2005 03:38 PM
BlackBox.class & VerifierBug.class virus ??? dalek Linux - Security 4 02-29-2004 08:55 AM
lm-sensors unchanged values ndm Linux - Laptop and Netbook 1 02-25-2004 06:44 AM
lm-sensors unchanged values ndm Linux - Newbie 0 02-25-2004 05:21 AM


All times are GMT -5. The time now is 05:28 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration