SFrame 3.6
python/PARHelpers.py
Go to the documentation of this file.
00001 # $Id: PARHelpers.py 323 2012-08-17 08:00:10Z krasznaa $
00002 
00003 # Import the needed module(s):
00004 import os.path
00005 import os
00006 import re
00007 import shutil
00008 
00009 ## PAR package creator function
00010 #
00011 # This function creates PAR packages based on a number of parameters.
00012 #
00013 # @param srcdir Base directory from which the PAR package is made
00014 # @param makefile Name of the makefile in the package
00015 # @param include Name of the include directory in the package
00016 # @param src Name of the source file directory in the package
00017 # @param proofdir Name of the directory holding the special PROOF files
00018 # @param output Name of the output file
00019 # @param verbose <code>True</code> if verbose printout is requested
00020 def PARMaker( srcdir, makefile, include, src, proofdir, output, verbose ):
00021 
00022     # Tell the user what we're doing:
00023     if verbose:
00024         print "  >>"
00025         print "  >> Running PARHelpers.PARMaker"
00026         print "  >>"
00027         pass
00028 
00029     # Split the output file name into constituents:
00030     ( outputdir, outputfile ) = os.path.split( output )
00031     ( outputbase, outputext ) = os.path.splitext( outputfile )
00032     if verbose:
00033         print "  >> outputdir  = " + outputdir
00034         print "  >> outputbase = " + outputbase
00035         print "  >> outputext  = " + outputext
00036         pass
00037 
00038     # Check that the output file name has the correct extension:
00039     if( outputext != ".par" ):
00040         print "ERROR: The output file's extension must be \".par\""
00041         return
00042 
00043     # Create an appropriate temporary directory for the package creation:
00044     import tempfile
00045     tempdir = tempfile.mkdtemp()
00046     if verbose:
00047         print "  >> tempdir = " + tempdir
00048         pass
00049 
00050     # Create the temporary directories for the package:
00051     os.system( "rm -rf " + tempdir + "/" + outputbase )
00052     os.mkdir( tempdir + "/" + outputbase )
00053     os.mkdir( tempdir + "/" + outputbase + "/" + include )
00054     os.mkdir( tempdir + "/" + outputbase + "/" + src )
00055     os.mkdir( tempdir + "/" + outputbase + "/PROOF-INF" )
00056 
00057     # Get the list of header files to be included in the package:
00058     headers = os.listdir( srcdir + include )
00059     headers_filt = [ file for file in headers if
00060                     ( re.search( "\.h$", file ) or
00061                       re.search( "\.icc$", file ) ) ]
00062     if verbose:
00063         print "  >> headers = " + ", ".join( headers_filt )
00064         pass
00065 
00066     # Get the list of source files to be included in the package:
00067     sources = os.listdir( srcdir + src )
00068     sources_filt = [ file for file in sources if
00069                     ( ( re.search( "\.cxx$", file ) or re.search( "\.h$", file ) ) and not
00070                       ( re.search( "\_Dict\.cxx$", file ) or re.search( "\_Dict\.h$", file ) ) ) ]
00071     if verbose:
00072         print "  >> sources = " + ", ".join( sources_filt )
00073         pass
00074 
00075     # Copy the header and source files to the correct directories, and
00076     # then transform them in-situ:
00077     for header in headers_filt:
00078         shutil.copy( srcdir + "/" + include + "/" + header,
00079                      tempdir + "/" + outputbase + "/" + include )
00080         SourceTransform( tempdir + "/" + outputbase + "/" + include + "/" + header )
00081         pass
00082     for source in sources_filt:
00083         shutil.copy( srcdir + "/" + src + "/" + source,
00084                      tempdir + "/" + outputbase + "/" + src )
00085         SourceTransform( tempdir + "/" + outputbase + "/" + src + "/" + source )
00086         pass
00087 
00088     # Copy the package makefile to the correct directory:
00089     shutil.copy( srcdir + "/" + makefile,
00090                  tempdir + "/" + outputbase )
00091     ( makefiledir, makefilename ) = os.path.split( makefile )
00092     MakefileTransform( tempdir + "/" + outputbase + "/" + makefilename, verbose )
00093 
00094     # Create the Makefile.proof makefile fragment:
00095     MakefileProof( tempdir + "/" + outputbase + "/Makefile.proof", verbose )
00096 
00097     # Get the list of files in the proof directory:
00098     proof = os.listdir( srcdir + proofdir )
00099     proof_filt = [ file for file in proof if
00100                    ( not re.search( "~$", file ) and
00101                      os.path.isfile( srcdir + "/" + proofdir + "/" + file ) ) ]
00102     if verbose:
00103         print "  >> proof files = " + ", ".join( proof_filt )
00104         pass
00105 
00106     # Copy the proof files:
00107     for pfile in proof_filt:
00108         shutil.copy( srcdir + "/" + proofdir + "/" + pfile,
00109                      tempdir + "/" + outputbase + "/PROOF-INF" )
00110         pass
00111 
00112     # Create the PAR package:
00113     if verbose:
00114         print "  >> Now creating " + output
00115         pass
00116     os.system( "tar -C " + tempdir + " -czf " + output + " " + outputbase + "/" )
00117 
00118     # Remove the temporary directory:
00119     if verbose:
00120         print "  >> Now removing " + tempdir + "/" + outputbase
00121         pass
00122     os.system( "rm -rf " + tempdir + "/" + outputbase )
00123     # The temporary directory itself has to be removed as well:
00124     os.system( "rmdir " + tempdir )
00125 
00126     # Tell the user what we did:
00127     print "  Created PAR package: " + output
00128 
00129     return
00130 
00131 ## Transform the contents of the specified makefile for PROOF usage
00132 #
00133 # @param makefile_path Path to the makefile that should be transformed
00134 # @param verbose <code>True</code> if verbose printout is requested
00135 def MakefileTransform( makefile_path, verbose ):
00136 
00137     if verbose:
00138         print "  >>"
00139         print "  >> Running PARHelpers.MakefileTransform"
00140         print "  >>"
00141 
00142     # Read in the contents of the makefile:
00143     makefile = open( makefile_path, "r" )
00144     contents = makefile.read()
00145     makefile.close()
00146 
00147     # Do the necessary changes:
00148     new_contents = re.sub( "\$\(SFRAME_DIR\)\/Makefile\.common",
00149                            "Makefile.proof", contents )
00150 
00151     # Write out the modified contents in the same file:
00152     makefile = open( makefile_path, "w" )
00153     makefile.write( new_contents )
00154     makefile.close()
00155 
00156     return
00157 
00158 ## Create a makefile fragment with the directives for PROOF usage
00159 #
00160 # @param makefile_path Path to the makefile that should be created
00161 # @param verbose <code>True</code> if verbose printout is requested
00162 def MakefileProof( makefile_path, verbose ):
00163 
00164     if verbose:
00165         print "  >>"
00166         print "  >> Running PARHelpers.MakefileProof"
00167         print "  >>"
00168 
00169     makefile = open( makefile_path, "w" )
00170     makefile.write( MakefileProofContent )
00171     makefile.close()
00172 
00173     return
00174 
00175 ## Transform the contents of the specified source file for PROOF usage
00176 #
00177 # @param file_path Path to the source file that should be transformed
00178 def SourceTransform( file_path ):
00179 
00180     # Read in the contents of the source file:
00181     file = open( file_path, "r" )
00182     contents = file.read()
00183     file.close()
00184 
00185     # Do the necessary changes:
00186     contents = re.sub( "core\/include",
00187                        "SFrameCore/include", contents )
00188     contents = re.sub( "plug\-ins\/include",
00189                        "SFramePlugIns/include", contents )
00190 
00191     # Write out the modified contents in the same file:
00192     file = open( file_path, "w" )
00193     file.write( contents )
00194     file.close()
00195 
00196     return
00197 
00198 ## Contents of the makefile for PROOF compilation
00199 MakefileProofContent = """MAKEFLAGS = --no-print-directory -r -s
00200 
00201 # Include the architecture definitions from the ROOT source:
00202 ARCH_LOC_1 := $(wildcard $(shell root-config --prefix)/test/Makefile.arch)
00203 ARCH_LOC_2 := $(wildcard $(shell root-config --prefix)/share/root/test/Makefile.arch)
00204 ARCH_LOC_3 := $(wildcard $(shell root-config --prefix)/share/doc/root/test/Makefile.arch)
00205 ARCH_LOC_4 := $(wildcard $(shell root-config --prefix)/etc/Makefile.arch)
00206 ARCH_LOC_5 := $(wildcard $(shell root-config --prefix)/etc/root/Makefile.arch)
00207 ifneq ($(strip $(ARCH_LOC_1)),)
00208   $(info Using $(ARCH_LOC_1))
00209   include $(ARCH_LOC_1)
00210 else
00211   ifneq ($(strip $(ARCH_LOC_2)),)
00212     $(info Using $(ARCH_LOC_2))
00213     include $(ARCH_LOC_2)
00214   else
00215     ifneq ($(strip $(ARCH_LOC_3)),)
00216       $(info Using $(ARCH_LOC_3))
00217       include $(ARCH_LOC_3)
00218     else
00219       ifneq ($(strip $(ARCH_LOC_4)),)
00220         $(info Using $(ARCH_LOC_4))
00221         include $(ARCH_LOC_4)
00222       else
00223         ifneq ($(strip $(ARCH_LOC_5)),)
00224           $(info Using $(ARCH_LOC_5))
00225           include $(ARCH_LOC_5)
00226         else
00227           $(error Could not find Makefile.arch!)
00228         endif
00229       endif
00230     endif
00231   endif
00232 endif
00233 
00234 # Some compilation options
00235 VPATH    += $(OBJDIR) $(SRCDIR)
00236 INCLUDES += -I./ -I../
00237 CXXFLAGS += -Wall -Wno-overloaded-virtual -Wno-unused $(USERCXXFLAGS)
00238 
00239 # Set the locations of some files
00240 DICTHEAD  = $(SRCDIR)/$(LIBRARY)_Dict.h
00241 DICTFILE  = $(SRCDIR)/$(LIBRARY)_Dict.$(SrcSuf)
00242 DICTOBJ   = $(OBJDIR)/$(LIBRARY)_Dict.$(ObjSuf)
00243 DICTLDEF  = $(INCDIR)/$(LIBRARY)_LinkDef.h
00244 SKIPCPPLIST = $(DICTFILE)
00245 SKIPHLIST   = $(DICTHEAD) $(DICTLDEF)
00246 SHLIBFILE = lib$(LIBRARY).$(DllSuf)
00247 UNAME = $(shell uname)
00248 
00249 # Set up the default targets
00250 default: shlib
00251 
00252 # List of all header and source files to build
00253 HLIST   = $(filter-out $(SKIPHLIST),$(wildcard $(INCDIR)/*.h))
00254 CPPLIST = $(filter-out $(SKIPCPPLIST),$(wildcard $(SRCDIR)/*.$(SrcSuf)))
00255 
00256 # List of all object files to build
00257 OLIST = $(patsubst %.$(SrcSuf),%.o,$(notdir $(CPPLIST)))
00258 
00259 # Implicit rule to compile all sources
00260 %.o : %.$(SrcSuf)
00261    @echo "Compiling $<"
00262    @mkdir -p $(OBJDIR)
00263    @$(CXX) $(CXXFLAGS) -c $< -o $(OBJDIR)/$(notdir $@) $(INCLUDES)
00264 
00265 # Rule to create the dictionary
00266 $(DICTFILE): $(HLIST) $(DICTLDEF)
00267    @echo "Generating dictionary $@" 
00268    @$(shell root-config --exec-prefix)/bin/rootcint -f $(DICTFILE) -c -p $(INCLUDES) $^
00269 
00270 # Rule to comile the dictionary
00271 $(DICTOBJ): $(DICTFILE)
00272    @echo "Compiling $<"
00273    @mkdir -p $(OBJDIR)
00274    $(CXX) $(CXXFLAGS) -c $(INCLUDES) -o $@ $<
00275 
00276 -include $(foreach var,$(notdir $(CPPLIST:.$(SrcSuf)=.d)),$(DEPDIR)/$(var))
00277 
00278 $(DEPDIR)/%.d: %.$(SrcSuf)
00279    @mkdir -p $(DEPDIR)
00280    if test -f $< ; then \
00281       echo "Making $(@F)"; \
00282       $(SHELL) -ec '$(CPP) -MM $(CXXFLAGS) $(INCLUDES) $< | sed '\''/Cstd\/rw/d'\'' > $@'; \
00283    fi
00284 
00285 # Rule to combine objects into a unix shared library
00286 $(SHLIBFILE): $(OLIST) $(DICTOBJ)
00287    @echo "Making shared library: $(SHLIBFILE)"
00288    @rm -f $(SHLIBFILE)
00289 ifneq (,$(findstring macosx,$(ARCH)))
00290    @$(LD) $(LDFLAGS) $(USERLDFLAGS) -dynamiclib -single_module -undefined dynamic_lookup $(addprefix $(OBJDIR)/,$(OLIST)) $(DICTOBJ) -o $(SHLIBFILE)
00291 else
00292    @$(LD) $(LDFLAGS) $(USERLDFLAGS) $(SOFLAGS) $(addprefix $(OBJDIR)/,$(OLIST)) $(DICTOBJ) -o $(SHLIBFILE)
00293 endif
00294 
00295 # Useful build targets
00296 shlib: $(SHLIBFILE)
00297 
00298 clean:
00299    rm -f $(DICTFILE) $(DICTHEAD)
00300    rm -f $(OBJDIR)/*.o
00301    rm -f $(SHLIBFILE)
00302    rm -f lib$(LIBRARY).so
00303 
00304 distclean:
00305    rm -rf $(OBJDIR)
00306    rm -f *~
00307    rm -f $(INCDIR)/*~
00308    rm -f $(SRCDIR)/*~
00309    rm -f $(DICTFILE) $(DICTHEAD)
00310    rm -f $(DEPDIR)/*.d
00311    rm -f $(SHLIBFILE)
00312    rm -f lib$(LIBRARY).so
00313 
00314 .PHONY : shlib default clean
00315 """