# p4/Jamrules # # This Jamrules describes how to build most of Perforce, exclusive of # windows only products. # # This file is organized into sections: # # Section 1. Global variable settings. # Section 2. Library names. # Section 3. Per-build type variable settings. # Section 4. Per-platform variable settings. # Section 5. Perforce-special rules and actions. # Section 6. Perforce-special Windows rules. # Section 7. QT build rules and actions. # Section 8. Per-platform actions. # ################################################# # # Section 1. Global variable settings. # ################################################# if $(JAMBASEDATE) < 2002.05.09 { Exit Jamrules requires Jambase 2002.05.09 ($(JAMBASEDATE)) ; } # Variables you shouldn't set: # # OS - operating system ("FreeBSD") # OSPLAT - OS platform ("sparc") # # Variables you can set: # # OSVER - version of OS ("102" for MACOSX) # TYPE - controls compile flags (see below) # BUILD - subdirectory for special named builds ("nightly") # enable for AS400 port (cheesy) # OS = AS400 ; OSPLAT = ; # This is jam idiomatic, but the result is that # P4BIN is set to ../p4-bin (relative to P4) SubDir AllP4 p4 ; # where we are SubDir AllP4 p4-bin ; # where we want to be SubDir P4BIN ; # name is that SubDir AllP4 p4 ; # back to where we started # Build dir: p4-bin/bin.xxx[/type][/build] EXEC_TOKENS = P4BIN bin.$(OS:L)$(OSVER:EL)$(OSPLAT:EL) $(TYPE) $(BUILD:EL) ; EXEC ?= [ FSubDirPath $(EXEC_TOKENS) ] ; ALL_LOCATE_TARGET = $(EXEC) ; # version file # Ident'ed executables depend on this SEARCH on Version Jamrules = $(P4) ; include Version ; API = p4api.tar ; STRIP = strip ; DEFINES += OS_$(OS) OS_$(OS)$(OSVER) OS_$(OS)$(OSPLAT) OS_$(OS)$(OSVER)$(OSPLAT) ; HDRS += [ FSubDirPath P4 msgs ] [ FSubDirPath P4 support ] [ FSubDirPath P4 sys ] ; ################################################# # # Section 2. Library names. # ################################################# rule SetLibName { $(1) = $(2:S=$(SUFLIB)) ; LOCATE on $($(1)) = $(EXEC) ; } SetLibName CLIENTLIB : libclient ; SetLibName CPPUNIT : libcppunit ; SetLibName DBLIB : libdb ; SetLibName DBOPENLIB : libdbopen ; SetLibName DBSUPPLIB : libdbsupp ; SetLibName DMCLIB : libdmc ; SetLibName DMLIB : libdm ; SetLibName FTPLIB : libp4ftp ; SetLibName LBRLIB : liblbr ; SetLibName P4EXPLIB : libp4exp ; SetLibName P4LIB : libp4 ; SetLibName P4SCCLIB : libp4scc ; SetLibName P4WINLIB : libp4win ; SetLibName P4WINCMNLIB : libp4wcmn ; SetLibName P4WINDIFFLIB : libp4wdf ; SetLibName P4WINMRGLIB : libp4wmrg ; SetLibName PLUGINLIB : libplugin ; SetLibName PROXYLIB : libproxy ; SetLibName QTMERGELIB : libqtmerge ; SetLibName QTUTILLIB : libqtutil ; SetLibName QTREELIB : libqtree ; SetLibName RPCLIB : librpc ; SetLibName SANDSTORM : libstorm ; SetLibName P4ALIB : libp4a ; SetLibName P4V : libp4v ; SetLibName P4VTEST : libp4vtest ; SetLibName SCCDLLLIB : libscc ; SetLibName SERVERLIB : libserver ; SetLibName SUPPORTLIB : libsupp ; SetLibName WEBGIZMOLIB : libp4web ; ################################################# # # Section 3. Per-build type variable settings. # ################################################# TYPE ?= opt ; switch $(TYPE) { # These are official builds # # dyn: windows guis must be dynamic # opt: our standard, optimized built # pic: for special customer requests case dyn : OPTIM = -O2 ; case opt : OPTIM = -O2 ; case pic : OPTIM = -O2 -fPIC ; NO_OPTIM = -fPIC ; # These are for internal testing/playing # # g/dyng/optg: debugging # pg: profiled executable on unix # fast: a fast compile (no optimization) # lower: case insensitive on UNIX # lpg: lower profiled case g : OPTIM = -g ; case dyng : OPTIM = -g ; case fast : OPTIM = ; case lower : OPTIM = -DCASE_INSENSITIVE -O2 ; case lpg : OPTIM = -DCASE_INSENSITIVE -O2 -pg ; LINKFLAGS = -pg ; case optg : OPTIM = -O2 -g ; case pg : OPTIM = -pg -O ; LINKFLAGS = -pg ; case sym : OPTIM = -opt off -sym full ; LINKFLAGS = -sym full ; case * : Echo "Warning -- unknown compilation TYPE" $(TYPE) ; } # TYPE_DEBUG for all debug builds. # TYPE_DYNAMIC for all dynamic builds. switch $(TYPE) { case *g : TYPE_DEBUG = true ; } switch $(TYPE) { case dyn* : TYPE_DYNAMIC = true ; } ################################################# # # Section 4. Per-platform variable settings. # ################################################# # Flags for Perforce # # CASE_INSENSITIVE -- case folding server # ENUM_INT -- force enums to int sized for watcom # USE_CRLF -- ascii opened as binary needs special handling # USE_CR -- special CR <-> LF translation for mac # USE_EBCDIC -- ascii <-> ebcdic translation in rpc GENFLAGS = CCFLAGS C++FLAGS ; switch $(OS)$(OSVER) $(OS) { case AIX32 : # using GNU CC = gcc ; C++ = gcc ; C++FLAGS += -DBSD -Dunix ; LINK = gcc ; case AIX43 : # using GNU C++ = gcc ; CC = gcc ; C++FLAGS += -DBSD -Dunix ; LINK = gcc /usr/local/lib/libsupc++.a ; case AIX5 : C++ = xlc ; CC = xlc ; C++FLAGS += -L/usr/lib/ia64l64 -Dunix ; LINK = xlc -lC ; case AIX51 : C++ = xlc ; CC = xlc ; C++FLAGS += -L/usr/lib/ia64l64 -Dunix ; LINK = xlC_r -lC ; case AMIGA : CC = gcc ; LINK = gcc ; case AS400 : # qifs=32 stdio works right # W1 suppress warnings # O40 optimization # AScp500 set code page # /Xi don't look for INCLUDE_400 by default # (so we can put it in 1st) # and get the right version of errno.h. # switch /O40 to /O- /Ti+ for debugging NT = ; C++ = iccas ; CC = iccas ; C++FLAGS += /DUSE_EBCDIC /Xi /qifs=32 /W1 /AScp500 ; STDHDRS = $(INCLUDE_400) ; NOARSCAN = true ; STRIP = ; OPTIM = /O40 ; case BEOS5 : STRIP = ; LINKLIBS += -lroot ; case CYGWIN : STRIP = ; CC = gcc ; C++ = gcc ; LINK = g++ ; C++FLAGS += -DUSE_CRLF ; case DARWIN : CC = cc ; C++ = cc ; C++FLAGS += -DCASE_INSENSITIVE ; case DARWIN60 : CC = cc ; C++ = cc ; LINK = g++ ; C++FLAGS += -DCASE_INSENSITIVE ; case DARWIN60cs : #case-sensitive CC = cc ; C++ = cc ; LINK = g++ ; case DGUX : CC = ec++ ; C++ = ec++ ; LINK = ec++ ; case FREEBSD : Exit Set OSVER to 22, 3, 4, or 5 for FreeBSD ; case FREEBSD4 : CC = gcc ; $(GENFLAGS) += -pipe ; # to test writeable strings # $(GENFLAGS) += -Wwrite-strings -Dconst_char='const char' ; LINK = gcc ; if $(OSPLAT) != AXP { LINKFLAGS += -static ; } case FREEBSD5 : CC = gcc ; LINK = g++ ; #if $(OSPLAT) != AXP { LINKFLAGS += -static ; } case FREEBSD* : CC = gcc ; LINK = gcc ; if $(OSPLAT) != AXP { LINKFLAGS += -static ; } case HPUX10old : CC = c89 ; C++ = aCC ; OPTIM = -O ; C++FLAGS += -Dunix ; CCFLAGS += -D_INCLUDE_POSIX_SOURCE ; LINK = aCC ; LINKFLAGS += -Wl,-a,archive ; case HPUX10 : CC = gcc ; LINK = gcc -static ; case HPUX11pic : CC = aCC ; C++ = aCC ; C++FLAGS += -D_LARGEFILE64_SOURCE ; LINK = aCC ; OPTIM = +O1 ; $(GENFLAGS) += -Dconst_char='const char' +Z ; case HPUX11 : CC = aCC ; C++ = aCC ; C++FLAGS += -D_LARGEFILE64_SOURCE ; LINK = aCC ; OPTIM = +O1 ; $(GENFLAGS) += -Dconst_char='const char' ; case HPUX9 : CC = gcc ; LINK = gcc ; case INTERIX : # using GNU CC = gcc ; C++ = gcc ; C++FLAGS += -Dunix ; LINK = gcc ; case IRIX62 : CC = cc -Olimit 5000 -o32 ; C++ = CC -Olimit 5000 -o32 ; $(GENFLAGS) += -nostdinc -I /irix62/usr/include ; LINK = CC -o32 -nostdlib -L /irix62/lib ; case IRIX65o32 : CC = cc OPT:Olimit 5000 -o32 ; C++ = CC -OPT:Olimit 5000 -o32 ; LINK = CC -o32 ; case IRIX65 : CC = cc -OPT:Olimit 5000 -64 -mips3 ; C++ = CC -woff 3439,1174,1178,1681,1682 -OPT:Olimit 5000 -64 -mips3 ; LINK = CC -64 ; if $(TYPE) = PIC { C++FLAGS += -KPIC ; CCFLAGS += -KPIC ; } case LINUX80 : CC = gcc ; C++ = g++ ; LINK = g++ ; $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX90 : CC = gcc ; C++ = g++ ; LINK = g++ ; $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX : CC = gcc ; LINK = gcc ; if $(OSPLAT) = X86 { Exit Set OSVER to 42/52 [RedHat M.n], or 22/24 [uname -r M.n] ; } if $(OSPLAT) = IA64 { $(GENFLAGS) += -Dconst_char='const char' ; } if $(OSPLAT) = PPC { LINKFLAGS += -static ; } case LINUX22 : # redhat 6.2 CC = gcc ; C++ = gcc ; LINK = gcc ; if $(OSPLAT) = AXP { LINKFLAGS += -static ; } $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX26 : CC = gcc ; C++ = g++ ; if $(OSPLAT) = AMD64 { LINK = g++ ; $(GENFLAGS) += -Dconst_char='const char' ; } else LINK = g++ ; $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX24 : CC = gcc ; LINK = gcc ; if $(OSPLAT) = AXP { LINKFLAGS += -static ; } $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX72 : # redhat 7.2 (p4v builds) CC = gcc ; LINK = gcc ; $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX90 : # Red Hat 9. Currently only used to build p4v # on a test machine. CC = gcc ; LINK = g++ ; # if $(OSPLAT) = AXP { LINKFLAGS += -static ; } # LINKFLAGS += -static ; LINKFLAGS += -shared ; $(GENFLAGS) += -D_GNU_SOURCE ; case LINUX42 : # redhat 4.2 CC = gcc ; LINK = gcc ; if $(OSPLAT) = AXP { LINKFLAGS += -static ; } case LINUX52 : # redhat 5.2 CC = gcc ; LINK = gcc ; if $(OSPLAT) = AXP { LINKFLAGS += -static ; } if $(OSPLAT) = X86 { $(GENFLAGS) += -D_GNU_SOURCE ; } case LYNX : # using GNU CC = gcc ; C++ = g++ ; C++FLAGS += -Dunix ; LINK = gcc ; LINKLIBS += -lnetinet ; case MAC68K : EXEC = :bin.mac68k ; EXEC = $(EXEC:R=$(P4)) ; CC = mwc68k ; C++ = mwc68k ; $(GENFLAGS) += -model far -w off -D OS_MAC ; LINK = mwlink68k ; LINKFLAGS += -model far ; STRIP = ; case MACHTEN : LINK = gcc ; CC = gcc ; case MPEIX : STRIP = ; LINKLIBS += -lsocket ; case MACOSX : CC = cc ; C++ = cc ; $(GENFLAGS) += -DCASE_INSENSITIVE ; $(GENFLAGS) += -fpascal-strings ; LINKFLAGS += -framework Carbon ; case MACOSX102 : CC = cc ; C++ = cc ; LINK = g++ ; $(GENFLAGS) += -DCASE_INSENSITIVE ; $(GENFLAGS) += -fpascal-strings ; LINKFLAGS += -framework Carbon ; case MACOSX102CW : # Build p4 and the Metrowerks CodeWarrior plugin using # same settings as Mac Classic + Carbon. # Requires CodeWarrior Pro 9 on OS X >= 10.2 CC = mwpefcc ; C++ = mwpefcc ; LINK = mwpefld ; AR = mwpefld -library -o ; RANLIB = ; DEFINES += MAC_MWPEF ; $(GENFLAGS) += -gccinc -DUSE_CARBON -DTARGET_API_MAC_OSX ; if $(TYPE_DEBUG) { $(GENFLAGS) += -sym on,full ; } case MACOSXN : CC = cc ; C++ = cc ; case MVS : CC = cc ; C++ = c++ -+ ; $(GENFLAGS) += -D_OE_SOCKETS -DUSE_EBCDIC -DNO_LONG_LONG ; LINK = c++ ; OPTIM = -O ; case NETBSD : CC = gcc ; C++ = g++ ; $(GENFLAGS) += -pipe -Dunix -I/usr/pkg/include ; LINK = g++ ; # NetBSD gcc choked on -O2 -fPIC if $(TYPE) = pic { OPTIM = -O1 -fPIC ; } case OPENBSD36 : CC = gcc ; $(GENFLAGS) += -pipe -Dunix ; LINK = gcc ; if $(OSPLAT) != AXP { LINKFLAGS += -static ; } case OPENBSD29 : CC = gcc ; $(GENFLAGS) += -pipe -Dunix ; LINK = gcc ; case VMS* : API = p4api.bck ; # use C++ compiler: we're cheap CC = cxx ; C++ = cxx ; DEFINES += NO_MEMCPY ; LINKLIBS += sys$library:libcxxstd.olb/lib ; STRIP = ; OPTIM = ; case OS2 : $(GENFLAGS) += /DUSE_CRLF ; C++FLAGS += /DENUM_INT ; LINKLIBS += $(WATCOM)\\lib386\\so32dll.lib $(WATCOM)\\lib386\\tcp32dll.lib ; OPTIM = ; STRIP = ; case OSFSTATIC : CC = gcc ; C++ = gcc ; LINK = gcc ; $(GENFLAGS) += -mcpu=ev5 ; LINKFLAGS += -static ; case OSF : CC = gcc ; C++ = gcc ; LINK = gcc ; case NEXT : CC = cc ; C++ = cc ; $(GENFLAGS) += -arch m68k -arch i386 -arch hppa -arch sparc ; $(GENFLAGS) += -D_POSIX_SOURCE ; LINKFLAGS += -arch m68k -arch i386 -arch hppa -arch sparc ; LINKLIBS += -lg++ ; LINK = cc ; case NCR : CC = gcc ; CCFLAGS += -D_ATT4 ; C++FLAGS += -D_ATT4 ; LINK = gcc ; LINKLIBS += /usr/ucblib/libucb.a -lsocket -lnsl ; case NT* : # Use setargv.obj to get wildcard expansion. # The "rc" tool needs MS headers: BINDIR = e:\\perforce ; JAMSHELL ?= $(P4)\\Jamsh.bat % ; if $(OSPLAT) != IA64 { JAMSHELL ?= $(P4)\\Jamsh.bat % ; } C++FLAGS += /DCASE_INSENSITIVE /DUSE_CRLF ; LINKLIBS = setargv.obj advapi32.lib oldnames.lib kernel32.lib wsock32.lib ; STDHDRS = $(MSVCNT)\\include $(MSVCNT)\\atlmfc\\include ; STRIP = ; # Now, unset STDHDRS so Jam doesn't scan system headers (takes # too long when using compiler on networked machine): STDHDRS = ; if $(BCCROOT) { # Jeff Anton compiles with borland. OPTIM = -O2 ; RCFLAGS = /d NDEBUG /r ; AR = tlib /C /P128 ; LINKLIBS = $(BCCROOT)/lib/wildargs.obj ; } else if $(TYPE) = g { # Debugging build OPTIM = /Zi /Gm ; RCFLAGS = /d DEBUG /r ; LINKFLAGS = /DEBUG ; CCFLAGS += /MTd ; C++FLAGS += /MTd ; } else if $(TYPE) = dyn { # Dynamic link version, for qt products OPTIM = /O2 /Zi ; RCFLAGS = /d NDEBUG /r ; CCFLAGS += /MD ; C++FLAGS += /MD ; LINKFLAGS = /MAP /DEBUG /OPT:REF /OPT:ICF ; } else if $(TYPE) = dyng { # Dynamic Debugging build OPTIM = /Zi /Gm ; RCFLAGS = /d DEBUG /r ; LINKFLAGS = /DEBUG /NODEFAULTLIB:msvcrt.lib /fixed:no ; CCFLAGS += /MDd ; C++FLAGS += /MDd ; } else if $(OSVER) = 98 { # Dynamic link version for win98 version of p4win # Goes into bin.win98 -- oddity. EXEC = [ FSubDirPath P4BIN bin.win98 ] ; ALL_LOCATE_TARGET = $(EXEC) ; OPTIM = /O2 /Zi ; RCFLAGS = /d NDEBUG /r ; CCFLAGS += /MD ; C++FLAGS += /MD ; LINKFLAGS = /MAP ; } else { # Static link version, for command line products OPTIM = /O2 ; RCFLAGS = /d NDEBUG /r ; CCFLAGS += /MT ; C++FLAGS += /MT ; LINKFLAGS = /DEBUG /MAP ; } case PTX : C++ = CC ; LINK = CC ; LINKLIBS += -lsocket -lnsl ; case QNX : C++FLAGS += -DENUM_INT -Dbool=int -Dtrue=1 -Dfalse=0 ; STRIP = ; case QNXNTO : CC = cc ; C++ = cc ; LINKLIBS += -lsocket ; case RHAPSODY : CC = cc ; C++ = cc ; case SCO : C++ = gcc ; CC = gcc ; LINK = gcc ; LINKLIBS += -lsocket ; case SINIX : C++ = CC ; LINK = CC ; LINKLIBS += -lsocket -lnsl ; case SOLARIS25 : CC = gcc ; $(GENFLAGS) += -Dsolaris ; LINK = gcc ; LINKLIBS += /usr/ucblib/libucb.a -lsocket -lnsl ; AR = /usr/ccs/bin/ar ru ; STRIP = /usr/ccs/bin/strip ; case SOLARIS26 : CC = gcc ; C++ = gcc ; $(GENFLAGS) += -Dsolaris -D_LARGEFILE64_SOURCE -D__STDC__=0 ; LINK = gcc ; LINKLIBS += -lsocket -lnsl ; AR = /usr/ccs/bin/ar ru ; STRIP = /usr/ccs/bin/strip ; case SOLARIS27 : CC = cc ; C++ = CC ; $(GENFLAGS) += -Dsolaris -D_LARGEFILE64_SOURCE -D_STDC_=0 -Dconst_char='const char' ; LINK = CC ; LINKLIBS += -lsocket -lnsl ; AR = /usr/ccs/bin/ar ru ; STRIP = /usr/ccs/bin/strip ; OPTIM = -0 ; case SOLARIS8 : CC = gcc ; C++ = gcc ; $(GENFLAGS) += -Dsolaris -D_LARGEFILE64_SOURCE -Dconst_char='const char' ; LINK = gcc ; LINKLIBS += /usr/local/lib/libstdc++.a -lsocket -lnsl ; AR = /usr/ccs/bin/ar ru ; STRIP = /usr/ccs/bin/strip ; OPTIM = -O ; case SUNOS : CC = gcc ; LINK = gcc ; LINKFLAGS += -static ; case UNICOS : C++ = CC ; LINK = CC ; case UNIXWARE2 : C++ = CC ; LINK = CC ; LINKLIBS += -lsocket /usr/ccs/lib/libgen.a ; case UNIXWARE7 : CC = gcc ; C++ = gcc ; LINK = gcc ; $(GENFLAGS) += -D_LARGEFILE64_SOURCE ; LINKLIBS += -lsocket ; case ZETA : LINKLIBS += -lsocket -lroot -lbind ; case * : Exit Don't know "$(OS)$(OSVER) or " $(OS) ; } ################################################# # # Section 5. Perforce-special rules and actions. # ################################################# # # Special Rules # # DefineVar src : var ; # define a var for src compilation # Ident exe ; -- define bits for program ident string # LinkP4WebMacOptions exe ; - adjusting LINKLIBS/LINKFLAGS # ListAC ??? ; # P4ClientHdrs ; - add all p4 client headers for building Web, ftp # Strip exe ; strip executable of symbols after building # TarBall x.tar : sources ; - tar up sources into archive # rule DefineVar { # Usage: DefineVar foo.cc : VARNAME # Defines it if set if $($(>)) { ObjectDefines $(<) : [ Fconcat $(>)= [ FQuote \"$($(>))\" ] ] ; } } rule Ident { # Set up special defines local osid = $(OS)$(OSVER:E)$(OSPLAT:E) ; rule Fconcat { return $(<:J) ; } ObjectDefines $(<) : [ Fconcat ID_OS= [ FQuote $(osid[1]:U) ] ] [ Fconcat ID_REL= [ FQuote $(RELEASE) ] ] [ Fconcat ID_PATCH= [ FQuote $(PATCHLEVEL)$(SPECIAL:E) ] ] [ Fconcat ID_Y= [ FQuote $(SUPPDATE[1]) ] ] [ Fconcat ID_M= [ FQuote $(SUPPDATE[2]) ] ] [ Fconcat ID_D= [ FQuote $(SUPPDATE[3]) ] ] ; # Source file includes Version Includes [ FGristSourceFiles $(<) ] : Version ; } rule LinkP4WebMacOptions { # LinkP4WebMacOptions exe ; - adjusting LINKLIBS/LINKFLAGS local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; # sizemax 2560: because the 384K default is too small # sizeflags canbackground: app gets null events to keep it # alive when other apps (like netscape!) are running if $(OSPLAT) = CARBON { LINKFLAGS on $(_t) = -warn -application -sizemax 2560 -sizemin 1536 -@export :Mac:p4-web.exp -term OTCFMExit ; LINKLIBS on $(_t) = "$(UI):Universal:Libraries:StubLibraries:CarbonLib" "$(MF):MoreFilesCarbon.lib" "$(CW):MacOS Support:Libraries:Runtime:Libs:MSL_Runtime_PPC.Lib" "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_SIOUX_Carbon.Lib" "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_C_Carbon.Lib" "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_Extras_Carbon.Lib" ; } else { LINKFLAGS on $(_t) = -warn -application -sizemax 2560 -sizemin 1536 -@export :Mac:p4-web.exp -term OTCFMExit "-weakimport \"$(UI):Universal:Libraries:StubLibraries:Interfacelib\"" ; LINKLIBS on $(_t) = "$(UI):Universal:Libraries:StubLibraries:Mathlib" "$(UI):Universal:Libraries:StubLibraries:TextEncodingConverter" "$(UI):Universal:Libraries:StubLibraries:UnicodeConverter" "$(UI):Universal:Libraries:StubLibraries:TextCommon" "$(UI):Universal:Libraries:StubLibraries:OpenTransportLib" "$(UI):Universal:Libraries:StubLibraries:OpenTptInternetLib" "$(UI):Universal:Libraries:PPCLibraries:OpenTptInetPPC.o" "$(UI):Universal:Libraries:PPCLibraries:OpenTransportExtnPPC.o" "$(UI):Universal:Libraries:StubLibraries:InternetConfigLib" "$(UI):Universal:Libraries:StubLibraries:ThreadsLib" "$(UI):Universal:Libraries:StubLibraries:UTCUtils" "$(MF):MoreFilesPPC.lib" $(SIOUXLIBS) "$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL_Extras_PPC.Lib" ; } } rule ListAC { # Special jam trickery to display AC numbers with "jam AC" NOTFILE $(<) ; ALWAYS $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; Depends $(<) : $(>) ; } actions ListAC { $(AWK) 'BEGIN {L=0; FS=","} /AC_/ {print L, $1; L++}' $(>) } rule MacRes { local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; Depends $(_t) : $(>) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; if $(OS) = MAC { MacRes1 $(_t) : $(>) ; } } actions MacRes1 { rez -a -o $(<) $(>) } rule MacCreatorCode { switch $(<) { case p4v : return P4VC ; case p4merge : return P4MG ; case * : return ttxt ; } } rule P4ClientHdrs { # P4ClientHdrs ; - add p4 client headers for building Web, ftp SubDirHdrs $(P4) client ; SubDirHdrs $(P4) diff ; SubDirHdrs $(P4) i18n ; SubDirHdrs $(P4) middle ; SubDirHdrs $(P4) net ; SubDirHdrs $(P4) web ; } rule LinkLibraries { # make library dependencies of target # set NEEDLIBS variable used by 'actions Main' local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; local _s = [ FAppendSuffix $(>) : $(SUFLIB) ] ; Depends $(_t) : $(_s) ; NEEDLIBS on $(_t) += $(_s) ; } rule Strip { if $(STRIP) && $(TYPE:E=opt) = opt { Strip1 $(<:S=$(SUFEXE)) ; } } actions Strip1 { $(STRIP) $(<) } rule TarBall { NotFile api ; Depends api : $(<) ; Depends $(<) : $(>) ; LOCATE on $(<) = $(EXEC) ; SEARCH on $(>) += $(HDRS) $(SUBDIRHDRS) $(SUBDIR) ; TarBallPre $(<) : $(>) ; TarBallCopy $(<) : $(>) ; TarBallPost $(<) : $(>) ; } rule TarBallPre { } rule TarBallPost { } actions TarBallCopy { t=/tmp/td.$$ trap 'rm -rf $t' 0 mkdir $t cp $(>) $t ( cd $t; tar cvf - * ) > $(<) } ################################################# # # Section 5. Perforce-special Windows rules. # ################################################# # # Special p4-win/scc/p4-exp rules: # # P4EXPCompileActions - quotes STDHDRS # P4EXPIncludes - set up headers fpr WTL and platform SDK # P4EXPDefines - set C++ flags for P4-EXP # P4EXPDOTH file : file ; - wrapper for p4exp.h dependencies # P4EXPDOTHDEPENDS files : file ; - wrapper for files dependant on p4exp.h # P4EXPMIDL file : file ; - set up files for MIDL compiling # EXPMIDL file : file ; - compile .idl file # P4EXPLinkage exe : libs ; - set up link flags windows exe # # P4SccDefines - set C++ flags for (old) p4scc.dll # # P4WinDefines - set C++ flags for p4-win/gui # P4WinDiffDefines - set C++ flags for p4-win/diff, merge # # WinDefines opts : defines ; - set C++ flags for p4-win # WinDllDeffile exe : file ; - set /def: file for link # WinDllLinkage exe : libs ; - set up link flags windows DLL # WinDllNoMain exe ; - setup exe with no main # WinLinkage exe : libs ; - set up link flags windows exe # WinRes exe : *.rc : flags ; - compile .rc->.res, link against exe # #Hacking in P4GT rules for instant gratification rule P4GTLinkage { local _lf = /subsystem:windows ; switch $(TYPE_DEBUG) { case true : _lf += /DEBUG ; case * : _lf += /MAP ; } _lf += /DLL ; _lf += /INCREMENTAL:NO ; _lf += /NODEFAULTLIB:"libcmt" ; _lf += /NODEFAULTLIB:"libc" ; switch $(OSPLAT) { case x86 : _lf += /MACHINE:x86 ; } LINKFLAGS on $(<) = $(LINKFLAGS) $(_lf) ; LINKLIBS on $(<) = $(P4GT)/htmlhelp/htmlhelp.lib gdi32.lib comctl32.lib shlwapi.lib user32.lib version.lib shell32.lib advapi32.lib oldnames.lib kernel32.lib wsock32.lib winmm.lib odbc32.lib odbccp32.lib $(2) ; } rule P4GTDefines { WinDefines /GX : _USRDLL _WINDLL NT_PLUGIN ; } rule LinkSmartHeap { if $(OS) = NT { local e = [ FAppendSuffix $(<) : $(SUFEXE) ] ; LINKLIBS on $(e) = setargv.obj c:\\perforce\\import\\smartheap\\lib\\msvc\\shlSMPMt.lib advapi32.lib oldnames.lib kernel32.lib wsock32.lib ; } } rule P4EXPCompileActions { actions C++ { $(C++) /c /Fo$(<) $(C++FLAGS) $(CCDEFS) $(CCHDRS) "/I$(STDHDRS)" /Tp$(>) } actions Cc { $(CC) /c /Fo$(<) $(CCFLAGS) $(CCDEFS) $(CCHDRS) "/I$(STDHDRS)" $(>) } } rule P4EXPIncludes { P4ClientHdrs ; STDHDRS += $(MSVCNT)\\wtl71\\include ; STDHDRS += "C:\\Program Files\\Microsoft SDK\\include" ; } rule P4EXPDefines { WinDefines /Ob1 /EHsc : _ATL_STATIC_REGISTRY _USRDLL _WINDLL ; } rule P4EXPDOTH { DEPENDS $(<) : $(>) ; } rule P4EXPDOTHDEPENDS { DEPENDS $(<) : $(>) ; } rule P4EXPMIDL { DEPENDS $(<) : $(>) ; EXPMIDL $(<) : $(>) ; } actions EXPMIDL { $(MSVCNT)\..\Common7\tools\bin\midl /env win32 /Oicf /tlb ".\p4exp.tlb" /h "p4exp.h" /iid $(<) $(>) } rule P4EXPLinkage { # P4EXPLinkage exe : libs ; - set up link flags windows exe local _lf = /subsystem:windows ; switch $(TYPE_DEBUG) { case true : _lf += /DEBUG ; case * : _lf += /MAP ; } _lf += /DLL ; _lf += /def:p4exp.def ; switch $(OSPLAT) { case X86 : _lf += /MACHINE:X86 ; } LINKFLAGS on $(<) = $(LINKFLAGS) $(_lf) ; LINKLIBS on $(<) = gdi32.lib comctl32.lib shlwapi.lib user32.lib version.lib shell32.lib advapi32.lib oldnames.lib kernel32.lib wsock32.lib winmm.lib $(2) ; } rule P4SccDefines { WinDefines /GX : _USRDLL _WINDLL ; } rule P4WinDefines { local u = ; # Unicode builds except on Win98. if $(OSVER) != 98 && ! $(NOUNICODE) { u += [ FDefines UNICODE _UNICODE ] ; } else { u += [ FDefines _MBCS ] ; } u += /GR /EHsc /GS /Zi ; WinDefines $(u) : STRICT ; } rule P4WinDiffDefines { WinDefines /GR /GX : P4DIFF ; } rule WinDefines { SubDirC++Flags /W3 $(1) [ FDefines NDEBUG WIN32 _WINDOWS $(2) ] ; if $(TYPE_DYNAMIC) { SubDirC++Flags [ FDefines _AFXDLL ] ; } } rule WinDllDeffile { # WinDllDeffile exe : file ; - set /def: file for link SEARCH on $(>) = $(SEARCH_SOURCE) ; DEFFILE on $(<) = $(>) ; DEPENDS $(<) : $(>) ; # Have to redefine actions for the DEFFILE # Should move to jambase actions Link bind NEEDLIBS DEFFILE { $(LINK) $(LINKFLAGS) /out:$(<) /def:$(DEFFILE) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) } } rule WinDllLinkage { # WinDllLinkage exe : libs ; - set up link flags windows DLL WinLinkage $(<) : $(>) ; LINKFLAGS on $(<) += /dll ; } rule WinDllNoMainLinkage { # WinDllNoMain exe ; LINKFLAGS on $(<) += /NOENTRY /MACHINE:I386 /SUBSYSTEM:WINDOWS /DLL ; LINKLIBS on $(<) = $(2) ; } rule WinLinkage { # WinLinkage exe : libs ; - set up link flags windows exe local _lf = /subsystem:windows ; switch $(TYPE_DEBUG) { case true : _lf += /DEBUG ; case * : _lf += /MAP /DEBUG ; } if $(OSVER) != 98 && ! $(NOUNICODE) { _lf += /ENTRY:"wWinMainCRTStartup" ; } switch $(OSPLAT) { case X86 : _lf += /MACHINE:X86 ; } LINKFLAGS on $(<) = $(LINKFLAGS) $(_lf) ; LINKLIBS on $(<) = $(2) ; } rule WinRes { # WinRes exe : *.rc : flags ; - compile .rc->.res, link # Compile .rc into .res for linking into executable. # (Strictly MSVCNT, I presume.) local s r e ; e = [ FAppendSuffix $(<) : $(SUFEXE) ] ; s = [ FGristSourceFiles $(>) ] ; r = $(s:S=.res:G=) ; DEPENDS $(e) : $(r) ; DEPENDS $(r) : $(s) ; LinkLibraries $(e) : $(r) ; LOCATE on $(r) = $(LOCATE_TARGET) ; SEARCH on $(s) = $(SEARCH_SOURCE) ; # .rc files have #includes, but we're pretty sure # they include only files local to the .rc's directory HDRRULE on $(>) = HdrRule ; HDRSCAN on $(>) = $(HDRPATTERN) ; HRDSEARCH on $(>) = $(SEARCH_SOURCE) ; HDRGRIST on $(>) = $(HDRGRIST) ; # Bind headers RCFLAGS on $(r) = $(RCFLAGS) $(3) ; RCHDRS on $(r) = [ on $(r) FIncludes $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ] ; WinRc $(r) : $(s) ; Clean clean : $(r) ; } actions WinRc { rc /fo $(<) $(RCFLAGS) "$(RCHDRS)" $(>) } ################################################# # # Section 7. QT build rules and actions. # ################################################# # # QtDefines ; - Add defines/headers for building with QT # QtLinkage exe ; - Add linkflags/libs to exe for building with QT # QtFormLibrary lib : *.ui ; make .h's and archive .obj's # QtMocLibrary lib : *.h ; - moc, compile, & archive # QtImages x.h : files ; - make a .h from image files # QtEmbed x.h : files : flags ; - preprocess with qembed # QtMoc x.cpp : x.h ; - preprocess with moc # QtUicCpp x.cpp : x.ui x.h ; - preprocess with uic to make .cpp # QtUicHdr x.h : x.ui ; - preprocess with uic to make .h # rule QtDefines { # QtDefines ; - Add defines/headers for building with QT if ! $(QTDIR) { Exit Can't build in QT directories without QTDIR set. ; } if $(JAMVERSION) < 2.4.1 { Exit QT builds require 2.4.1 ; } QTMOC = [ FDirName $(QTDIR) bin moc ] ; QTUIC = [ FDirName $(QTDIR) bin uic ] ; QEMBED = [ FDirName $(QTDIR) bin qembed ] ; local _d _f ; _d += QT_NO_STL ; _d += QT_THREAD_SUPPORT ; if $(TEST) { _d += TEST ; } # Source code debugging # DEBUG is in our code -- conditional compilations # QT_NO_* is in QT code switch $(TYPE_DEBUG) { case true : _d += DEBUG ; case * : _d += QT_NO_DEBUG QT_NO_CHECK ; } switch $(OS) { case NT : _f += /GX /GR ; # from Qt's Makefile _f += /Zm200 /W3 ; case MACOSX : if ! $(TYPE_DEBUG) { OPTIM = -O4 ; } case FREEBSD : SubDirHdrs /usr/X11R6/include ; } SubDirC++Flags [ FDefines $(_d) ] $(_f) ; SubDirHdrs [ FDirName $(QTDIR) include ] ; SubDirHdrs $(LOCATE_SOURCE[1]) ; } rule QtLinkage { # QtLinkage exe ; - linkflags/libs for building with QT local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; switch $(OS) { case FREEBSD : LINKFLAGS on $(_t) += -Wl,-rpath,$(QTDIR)/lib -L$(QTDIR)/lib -L/usr/X11R6/lib ; LINKLIBS on $(_t) += -lqt-mt -lSM -lICE -lXext -lX11 -lXmu -lm -pthread ; case SOLARIS : LINKFLAGS on $(_t) += -Wl,-R,$(QTDIR)/lib -L$(QTDIR)/lib -L/usr/X11R6/lib ; LINKLIBS on $(_t) += -lqt-mt -lqui -lSM -lICE -lXext -lX11 -lxnet -ldl -lpthread -lposix4 -lrt -lm /usr/local/lib/libstdc++.a -lsocket -lnsl ; case NETBSD : LINKFLAGS on $(_t) += -Wl,-rpath,$(QTDIR)/lib -Wl,-rpath,/usr/X11R6/lib -Wl,-rpath,/usr/pkg/lib -L$(QTDIR)/lib -L/usr/X11R6/lib -L/usr/pkg/lib ; LINKLIBS on $(_t) += -lqt-mt -lSM -lICE -lXext -lX11 -lGL # for revision graph -lm -lpthread -lXmu -lX11 -lXm ; if ! $(TYPE_DYNAMIC) { LINKFLAGS on $(_t) += -static ; } case LINUX : LINKFLAGS on $(_t) += -Wl,-rpath,$(QTDIR)/lib -L$(QTDIR)/lib -L/usr/X11R6/lib ; LINKLIBS on $(_t) += -lqt-mt -lSM -lICE -lXext -lX11 -lm -pthread -ldl ; case MACOSX : LINKFLAGS on $(_t) += -prebind -L$(QTDIR)/lib -framework Carbon -framework QuickTime -framework OpenGL -framework AGL ; LINKLIBS on $(_t) += -lqt-mt -lz ; #LINKLIBS on $(_t) += -lqt ; if ! $(TYPE_DYNAMIC) { LINKLIBS on $(_t) += -lz ; } QtMacPackage $(<) ; case NT : # warn about non-dynamic builds on NT if ! $(TYPE_DYNAMIC) && ! $(QTWARNED) { echo Warning: you really want jam -sTYPE=dyn for QT on NT. ; QTWARNED = 1 ; } # no dos box unless debug if ! $(TYPE_DEBUG) { LINKFLAGS on $(_t) += $(LINKFLAGS) /subsystem:windows ; } LINKLIBS on $(_t) = [ Glob [ FDirName $(QTDIR) lib ] : qt-mt*.lib ] [ FDirName $(QTDIR) lib qtmain.lib ] advapi32.lib # for qtree user32.lib gdi32.lib comdlg32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib uuid.lib imm32.lib winmm.lib wsock32.lib winspool.lib ; case * : Exit Don't know how to link QT executables on $(OS). ; } } rule QtDllLinkage { # QtLinkage exe ; - linkflags/libs for building with QT switch $(OS) { case NT : # warn about non-dynamic builds on NT if ! $(TYPE_DYNAMIC) && ! $(QTWARNED) { echo Warning: you really want jam -sTYPE=dyn for QT on NT. ; QTWARNED = 1 ; } LINKFLAGS on $(<) += $(LINKFLAGS) /DLL ; echo Warning: you are building a dll $(LINKFLAGS) ; # no dos box unless debug if ! $(TYPE_DEBUG) { LINKFLAGS on $(<) += $(LINKFLAGS) /subsystem:windows ; } LINKLIBS on $(<) = [ Glob [ FDirName $(QTDIR) lib ] : qt-mt*.lib ] [ FDirName $(QTDIR) lib qtmain.lib ] advapi32.lib # for qtree user32.lib gdi32.lib comdlg32.lib ole32.lib oleaut32.lib opengl32.lib shell32.lib uuid.lib imm32.lib winmm.lib wsock32.lib winspool.lib shlwapi.lib ; case * : Exit Don't know how to link QT executables on $(OS). ; } } # Mac special package - make a raw executable into a .app folder # This does x things: # 1. locates the actual exe in exe.app/Contents/MacOS/exe # 2. Creates exe.app/Contents/PkgInfo # 3. Creates exe.app/Contents/Info.plist # 4. Creates exe.app/Contents/Resources/application.icns rule QtMacPackage { # QtMacPackage exe ; Depends $(<) : <$(<)>PkgInfo ; Depends $(<) : <$(<)>Info.plist ; Depends $(<) : <$(<)>application.icns ; MakeLocate $(<) : [ FSubDirPath $(EXEC_TOKENS) $(<:S=.app) Contents MacOS ] ; MakeLocate <$(<)>PkgInfo : [ FSubDirPath $(EXEC_TOKENS) $(<:S=.app) Contents ] ; MakeLocate <$(<)>Info.plist : [ FSubDirPath $(EXEC_TOKENS) $(<:S=.app) Contents ] ; MakeLocate <$(<)>application.icns : [ FSubDirPath $(EXEC_TOKENS) $(<:S=.app) Contents Resources ] ; QtMacPlist <$(<)>Info.plist : Info.plist.app : application.icns p4v ; SEARCH on Info.plist.app = [ FDirName $(QTDIR) mkspecs default ] ; QtMacPackageInfo <$(<)>PkgInfo ; QMS on <$(<)>PkgInfo = [ MacCreatorCode $(<) ] ; } actions QtMacPackageInfo { echo "APPL$(QMS)" > $(<) } rule QtMacIcons { File <$(<)>application.icns : $(>) ; } rule QtMacPlist { Depends files : $(<) ; Depends $(<) : $(>) ; QMI on $(<) = $(3[1]) ; QME on $(<) = $(3[2]) ; QMS on $(<) = [ MacCreatorCode $(3[2]) ] ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MODE on $(<) = $(FILEMODE) ; Chmod $(<) ; } actions QtMacPlist { sed 's/@ICON@/$(QMI)/;s/@EXECUTABLE@/$(QME)/;s/ttxt/$(QMS)/' $(>) > $(<) } # Library rules rule QtHdrRule { # Our own HdrRule that knows a .ui doesn't itself include # a .h, but instead causes the resulting .cpp to do so. # What .cpp? TCPP is set on the .ui by QtFormLibrary, # and that's how we know it's this rigged dependency. HdrRule $(TCPP:E=$(<)) : $(>) ; } rule QtFormLibrary { # QtFormLibrary lib : *.ui ; make .h's and archive .obj's # For each x.ui file we generate _3_ files: # # x.h (uic x.ui) # tx.cpp (uic x.ui x.h) (temp) # mx.cpp (moc x.h) (temp) # # The tx.cpp and mx.cpp get compiled into tx.o and mx.o # and archived into the library. Library $(<) : m$(>:S=.cpp) ; Library $(<) : t$(>:S=.cpp) ; local i ; for i in $(>) { local h = $(i:S=.h) ; local ui = [ FGristSourceFiles $(i) ] ; local mcpp = [ FGristSourceFiles m$(i:S=.cpp) ] ; local tcpp = [ FGristSourceFiles t$(i:S=.cpp) ] ; local mobj = $(mcpp:S=$(SUFOBJ)) ; local tobj = $(tcpp:S=$(SUFOBJ)) ; # .ui's can include .h files, though what it actually # means is that the generated tx.cpp includes the .h's, # so we pass the tx.cpp name down to our own QtHdrRule. TCPP on $(ui) = $(tcpp) ; HDRRULE on $(ui) = QtHdrRule ; HDRSCAN on $(ui) = "(.*)" ; HDRSEARCH on $(ui) = $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ; QtUicHdr $(h) : $(ui) ; QtUicCpp $(tcpp) : $(ui) $(h) ; QtMoc $(mcpp) : $(h) ; if ! $(TYPE_DEBUG) { RmTemps $(mobj) : $(mcpp) ; } if ! $(TYPE_DEBUG) { RmTemps $(tobj) : $(tcpp) ; } Includes $(mcpp) : $(h) ; Includes $(tcpp) : $(h) ; } } rule QtMocLibrary { # QtMocLibrary lib : *.h ; - moc, compile, & archive # X.h -> temp mX.cpp -> temp mX.obj -> lib # Normal library rule on the generated m*.cpp files Library $(<) : m$(>:S=.cpp) ; # Make mX.cpp from X.h using moc # mX.cpp is a temp local h ; for h in $(>) { local cpp = [ FGristSourceFiles m$(h:S=.cpp) ] ; local obj = $(cpp:S=$(SUFOBJ)) ; QtMoc $(cpp) : $(h) ; if ! $(TYPE_DEBUG) { RmTemps $(obj) : $(cpp) ; } } } # Source file rules rule QtImages { # QtImages x.h : files ; - make a .h from image files # Delete and do piecemeal append for line-length limited NT. QtEmpty $(<) ; QEMBED on $(<) = $(QTUIC) ; QtEmbed $(<) : $(>) : -embed $(<:B) ; } actions QtEmpty { $(RM) $(<) } rule QtEmbed { # QtEmbed x.h : files : flags ; - preprocess with qembed NotFile src ; Depends src : $(<) ; Depends all : $(<) ; Depends $(<) : $(>) ; Clean clean : $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; QEMBEDFLAGS on $(<) = $(3) ; } actions piecemeal QtEmbed { $(QEMBED) $(QEMBEDFLAGS) $(>) >> $(<) } rule QtMoc { # QtMoc x.cpp : x.h ; - preprocess with moc # Derive a .cpp from .h using Qt's moc NotFile src ; Depends src : $(<) ; Depends all : $(<) ; Depends $(<) : $(>) ; Clean clean : $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; } actions QtMoc { $(QTMOC) $(>) -o $(<) } rule QtUicCpp { # QtUicCpp x.cpp : x.ui x.h ; - preprocess with uic to make .cpp NotFile src ; Depends src : $(<) ; Depends all : $(<) ; Depends $(<) : $(>) ; Clean clean : $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; } # don't include dir name in x.h actions QtUicCpp { $(QTUIC) $(>[1]) -i $(>[2]:D=) -o $(<) } rule QtUicHdr { # QtUicHdr x.h : x.ui ; - preprocess with uic to make .h NotFile src ; Depends src : $(<) ; Depends all : $(<) ; Depends $(<) : $(>) ; Clean clean : $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; } actions QtUicHdr { $(QTUIC) $(>) -o $(<) } ################################################# # # Section 8. Per-platform actions. # ################################################# if $(OS) = AS400 { actions Archive { echo > $(<) } actions Link { echo > $(<) } actions Cc { $(CC) /Q+ /C $(CCFLAGS) $(CCDEFS) /I$(HDRS) /I$(STDHDRS) $(>) if not errorlevel 1 echo > $(<) } actions C++ { $(C++) /Q+ /C $(C++FLAGS) $(CCDEFS) /I$(HDRS) /I$(STDHDRS) $(>) if not errorlevel 1 echo > $(<) } } if $(MSVCNT) { actions updated together piecemeal Archive { pushd $(<:D) if exist $(<:BS) set _$(<:B)_=$(<:BS) $(AR) /nologo /out:$(<:BS) %_$(<:B)_% $(>:BS) popd } actions QtEmpty { if exist $(<) $(RM) $(<) } } if $(OS) = VMS { actions TarBallCopy { $(MKDIR) [.p4api] $(CP) $(>[1]) ,$(>[2-]) [.p4api] backup [.p4api]*.* $(<)/save delete [.p4api]*.*;* set file/prot=(o:d) p4api.dir delete p4api.dir; } } if $(OS) = NT { actions TarBallPre { $(MKDIR) p4api.dir } actions piecemeal TarBallCopy { cp $(>) p4api.dir } actions TarBallPost { cd p4api.dir tar cvf ../p4api.tmp * cd .. mv p4api.tmp $(<) rm -rf p4api.dir } }