# p4/Jamrules # # This Jamrules describes how to build most of Perforce, exclusive of # windows only products. # # This file is organized into sections: # # Section 0. Generic helper rules # 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. Lua build rules and actions. # Section 9. Boost provides free peer-reviewed portable C++ source libraries. # Section 10. Google protocol buffers build rules and actions. # Section 11. Unit test rules # Section 12. Per-platform actions. # Section 13. Useful miscellanea # ################################################# # # Section 0. Generic helper rules # ################################################# # # Special Rules # # FRemoveAny x : y ; - return new array of x minus any values in y # FSplit s : delim ; - split string at delim (default /) # FStringToList s ; - return a list of chars from string # FLengthCmp s1 : s2 ; - compare length of strings # FVersionCmp x : y ; - compare version numbers (e.g. 3.4 vs. 4.5) # OnTargetVarPrepend TARGET : VARIABLE : VALUES ; # OnTargetVarAppend TARGET : VARIABLE : VALUES ; # OnTargetVarDelete TARGET : VARIABLE : VALUES ; # LinkDir app : dir ; - adds directory dir to the list of directories to be # - scanned for libraries # LinkLib app : lib ; - adds library for an app # ExLibrary cpp ; - same as Library, but with exception support # Deploy source : target ; - copies the source into the target # - unlike InstallXYZ rules it ensures that directory will be created # - and the target will be forced to be created before the install # - operation is called # MakeLocateWithSubDirectory - same as MakeLocate but the targets may have sub directory # say object/depot.cpp # rule FRemoveAny { # Usage: y = [ FRemoveAny $(x) : v1 v2 ... ] ; # returns new array with any occurence of v1, v2, etc from $(x) elided local _new ; local _elt ; for _elt in $(1) { if ! ( $(_elt) in $(2) ) { _new += $(_elt) ; } } return $(_new) ; } rule FSplit { # string : delim (default /) local s = $(>:E=/) ; local x = [ MATCH ([^$(s)]*)$(s)(.*) : $(<) ] ; if ! $(x) { return $(<) ; } return $(x[1]) [ FSplit $(x[2]) : $(>) ] ; } rule FStringToList { # Expand string into a list of characters. if ! $(<) { return ; } local x = [ MATCH ^(.)(.*) : $(<) ] ; return $(x[1]) [ FStringToList $(x[2-]) ] ; } rule FLengthCmp { # x = [ FLengthCmp STRING1 : STRING2 ] ; # # Return [-1, 0, 1] if string1 is shorter than, same length as, or longer # than, string2. local i ; local a ; local b ; # Jam doesn't understand numbers, so we can only count in unary. for i in [ FStringToList $(<) ] { a += . ; } for i in [ FStringToList $(>) ] { b += . ; } if $(a) < $(b) { return -1 ; } if $(a) > $(b) { return 1 ; } return 0 ; } rule FVersionCmp { # x = [ FVersionCmp X1.Y1.Z1 : X2.Y2.Z2 ] ; # # Return [-1, 0, 1] if the version number X1.Y1.Z1 is less than, equivalent # to, or greater than, X2.Y2.Z2. Version strings can be any alphanumeric # dotted strings. # # This function is necessary because Jam doesn't understand numbers; the # inequality operators use character collating order, so for example the # naive comparison "10 > 8" is actually false. # # Leading zeroes in each field are ignored, so for example this function # considers "3.4" and "3.4.0" to be equivalent. local a = [ FSplit $(<:J=.) : \\. ] ; # normalize a.b c => a.b.c => a b c local b = [ FSplit $(>:J=.) : \\. ] ; local r ; while $(a) || $(b) { local a1 = [ MATCH ^0*(.*) : $(a[1]) ] ; # strip leading zeroes local b1 = [ MATCH ^0*(.*) : $(b[1]) ] ; if $(a1) != $(b1) { r = [ FLengthCmp $(a1) : $(b1) ] ; if $(r) = 0 { if $(a1) < $(b1) { return -1 ; } if $(a1) > $(b1) { return 1 ; } } return $(r) ; } a = $(a[2-]) ; b = $(b[2-]) ; } return 0 ; } # Rules for modifying target-specific variables. # If a variable does not already have a target-specific binding, one is # created with a copy of the global value prior to altering the # target-specific value. # # These use no local variables, to avoid shadowing anything in caller. rule OnTargetVarPrepend { # OnTargetVarPrepend TARGET : VARIABLE : VALUES ; $(2[1]) on $(1[1]) = $(3) [ on $(1[1]) return $($(2[1])) ] ; } rule OnTargetVarAppend { # OnTargetVarAppend TARGET : VARIABLE : VALUES ; $(2[1]) on $(1[1]) = [ on $(1[1]) return $($(2[1])) ] $(3) ; } rule OnTargetVarDelete { # OnTargetVarDelete TARGET : VARIABLE : VALUES ; $(2[1]) on $(1[1]) = [ on $(1[1]) FRemoveAny $($(2[1])) : $(3) ] ; } rule SetDefaultDirName { # Usage: SetDefaultDirName VARIABLE : DEFAULT ; # Initialize VARIABLE with DEFAULT if it is not already set. # # If the variable's value after initialization is a multi-element # list, it is assumed that the variable was inherited from the # environment with spaces in the value and these are joined # together to create a single string with spaces in it. # # HOWEVER, if the first string in the list matches a subdir token # as defined by SubDir, resolve that and prepend it to the rest of # the path separated by a / or \ (as appropriate per OS). # # This allows one e.g. to set SSLPREFIX to "AllP4 ../../3rd_party/whatever" # and it will always point to the correct relative location regardless # of where you invoke jam, and regardless of your workspace root. $(1) ?= $(2) ; if $($(1)[2]) && [ FSubDirPath $($(1)[1]) ] { $(1) = [ FSubDirPath $($(1)[1]) $($(1)[2-]:J=" ") ] ; } else { $(1) = $($(1):J=" ") ; } return $($(1)) ; } rule LinkDir { # Usage: LinkDir app : dir1 dir2 ... ] ; local app = [ FAppendSuffix $(<) : $(SUFEXE) ] ; # On macs, search both normal libs and frameworks if $(OS) = MACOSX { OnTargetVarAppend $(app) : LINKLIBS : -L$(>) -F$(>) ; } else if $(UNIX) { OnTargetVarAppend $(app) : LINKLIBS : -L$(>) ; } else if $(NT) { OnTargetVarAppend $(app) : LINKLIBS : /LIBPATH:"$(>)" ; } else { Exit Don't know how to add additional library dir on $(OS). ; } } rule LinkLib { # Usage: LinkLib app : lib1 lib2 ... ] ; local app = [ FAppendSuffix $(<) : $(SUFEXE) ] ; if $(UNIX) { OnTargetVarAppend $(app) : LINKLIBS : -l$(>) ; } else if $(NT) { OnTargetVarAppend $(app) : LINKLIBS : $(>)$(SUFLIB) ; } else { Exit Don't know how to link library on $(OS). ; } } rule ExLibrary { if $(OS) = NT { ObjectC++Flags $(>) : /EHsc ; } Library $(<) : $(>) ; } rule Deploy { # Deploy source : target ; - copies the source into the target local _d = [ FDirName $(LOCATE_SOURCE[1]) $(<:D) ] ; MkDir $(_d:G=dir) ; Depends $(<) : $(_d:G=dir) ; NotFile deploy ; Depends deploy : $(<) ; Depends all : deploy ; Depends $(<) : $(>) ; Clean clean : $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; } actions Deploy { $(CP) $(>) $(<) } rule MakeLocateWithSubDirectory { # MakeLocateWithSubDirectory targets : directory ; # Sets special variable LOCATE on targets, and arranges # with MkDir to create target directory. # Note we grist the directory name with 'dir', # so that directory path components and other # targets don't conflict. for target in $(<) { local directory = [ FDirName $(>[1]) $(target:D) ] ; if $(>) { LOCATE on $(target) = $(>) ; Depends $(target) : $(directory:G=dir) ; MkDir $(directory:G=dir) ; } } } rule SetCommonCompiler { # Basic setup for common cross-platform compilers (gcc, llvm/clang, etc). # This doesn't include OS-specific compiler tweaking. # If cross compiling on one platform for another, set # CROSS_COMPILE to the prefix of the cross tools. For # example, to build for ARM using an X86 host, set # CROSS_COMPILE="arm-none-linux-gnueabi-" and OSPLAT="ARM". # COMPILER_PREFIX can be e.g. "llvm-". This variable differs from # CROSS_COMPILE in that it only affects the compiler tools, # not other cross-compile-sensitive programs such as ranlib, ar, # and so on. # COMPILER_SUFFIX is used to specify special versions of the # compiler, e.g. when needing to use "gcc34" or "g++34" to make a # portable legacy build. local linker = $(2:E=C++) ; local prefix = $(3:E=$(COMPILER_PREFIX:E)$(CROSS_COMPILE:E)) ; local suffix = $(4:E=$(COMPILER_SUFFIX:E)) ; switch $(1:U) { case *CLANG* : CC = $(prefix)clang$(suffix) ; C++ = $(prefix)clang++$(suffix) ; # make no return value from non-void func an error, and quiet # some of the noisier clang warnings until we clean up the code C++FLAGS += -Wno-parentheses -Wno-switch -Wreturn-type -Werror=return-type ; LINK = $(OSLINK:E=$($(linker))) ; case *GCC* : CC = $(prefix)gcc$(suffix) ; C++ = $(prefix)g++$(suffix) ; # no return value from non-void func is an error in Visual Studio # so make it a warning in gcc; unfortunately gcc 3.4.5 does not # support making it an error, so we can't use -Werror=return-type C++FLAGS += -Wreturn-type ; LINK = $(OSLINK:E=$($(linker))) ; } STRIP = $(CROSS_COMPILE:E)strip ; RANLIB = $(CROSS_COMPILE:E)ranlib ; AR = $(CROSS_COMPILE:E)ar cru ; } rule SetOSXSdk { # Common setup for darwin/macosx platform. # Determine correct version and location of SDK to use, and arch flags. local _xcode = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform ; local _sdkver = $(1:J=.) ; # Override computed sdk version local _xflags = $(2) ; # additional flags to compiler+linker local _uplats = $(3:E=i386 x86_64) ; # platforms for "universal" builds switch $(OS:U) { case DARWIN : # For Darwin 11 (OSX 10.7) and later, sdk lives deep under xcode.app if [ FVersionCmp $(OSVER) : 110 ] >= 0 { XCODE_PREFIX ?= $(_xcode) ; } local _v = [ MATCH ([0-9]+)[0-9]$ : $(OSVER) ] ; # darwin: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 local _sdkmap = 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12 ; _sdkver ?= 10.$(_sdkmap[$(_v)]) ; case MACOSX : # For OSX 10.7 and later, sdk lives deep under xcode.app if [ FVersionCmp $(OSVER) : 107 ] >= 0 { XCODE_PREFIX ?= $(_xcode) ; } local _v = [ MATCH ([0-9]+)([0-9])$ : $(OSVER) ] ; _sdkver ?= $(_v:J=.) ; } if $(_sdkver) = 10.4 { _sdkver = $(_sdkver)u ; } # "10.4u.sdk" MACOSX_SDK ?= $(XCODE_PREFIX:E)/Developer/SDKs/MacOSX$(_sdkver).sdk ; MACOSX_SDK_FLAGS ?= -isysroot $(MACOSX_SDK) ; # OSPLAT=U : universal binary local _arch _elt ; switch $(OSPLAT:U) { case PPC : _arch = -arch ppc ; case X86 : _arch = -arch i386 ; case X86_64 : _arch = -arch x86_64 ; case U : for _elt in $(_uplats) { _arch += -arch $(_elt) ; } NOARSCAN = true ; # can't scan "fat" archives } # n.b. we used to have a "CS" OSVER suffix so you could produce a # case-sensitive server on mac, but that's no longer necessary # since you can specify a different default at runtime on any platform. $(GENFLAGS) += $(MACOSX_SDK_FLAGS) $(_arch) -DCASE_INSENSITIVE $(_xflags) ; LINKFLAGS += $(MACOSX_SDK_FLAGS) $(_arch) $(_xflags) ; } ################################################# # # 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") # Variables that activate certain build features # DEV_VERSION - replaces the default version with a bogus one # WARN_FOR_DEPRECATED - enables deprecated warnings # FULL_PATH_DIAGNOSTICS - full path Source Code File in Diagnostics (visual studio only) # INCREMENTAL_BUILD - disable removing of temporary artifacts # BUILD_WITH_SUB_DIRECTORIES - locates the object files in a subtree BUILD_WITH_SUB_DIRECTORIES ?= true ; # Variables that activate certain build features per group # P4DEVELOPER - enables set of features appropriate for p4 dev environment # P4VDEVELOPER - enables set of features appropriate for p4v dev environment if $(P4DEVELOPER) = true { FULL_PATH_DIAGNOSTICS = true ; INCREMENTAL_BUILD = true ; } if $(P4VDEVELOPER) = true { WARN_FOR_DEPRECATED = true ; DEV_VERSION = true ; FULL_PATH_DIAGNOSTICS = true ; INCREMENTAL_BUILD = true ; } # Variables that shouldn't be set in PRODUCTION build environment if $(PRODUCTION) { if $(P4DEVELOPER) = true { exit ERROR - P4DEVELOPER and PRODUCTION defined at the same time ; } if $(P4VDEVELOPER) = true { exit ERROR - P4VDEVELOPER and PRODUCTION defined at the same time ; } if $(DEV_VERSION) = true { exit ERROR - DEV_VERSION and PRODUCTION defined at the same time ; } } # For convenience of historical compatibility, the OSPLAT value # "AMD64" will be changed to "X86_64", which is the canonical name # we are now using for that platform. Please get into the habit of # using it directly, as this may go away someday. if $(OSPLAT:U) = AMD64 { OSPLAT = X86_64 ; } # 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 EXEC_SUB_TOKENS = $(OS:L)$(OSVER:EL)$(OSPLAT:EL) $(BUILD) $(TYPE:L) ; EXEC_LIB ?= [ FSubDirPath P4BIN lib.$(EXEC_SUB_TOKENS[1]) ] ; EXEC_INC ?= [ FSubDirPath P4BIN inc.$(EXEC_SUB_TOKENS[1]) ] ; EXEC_LIBEXEC ?= [ FSubDirPath P4BIN libexec.$(EXEC_SUB_TOKENS[1]) ] ; # Build dir: p4-bin/bin.xxx[/build][/type] EXEC_TOKENS = P4BIN bin.$(EXEC_SUB_TOKENS[1]) $(EXEC_SUB_TOKENS[2]) $(EXEC_SUB_TOKENS[3]) ; EXEC ?= [ FSubDirPath $(EXEC_TOKENS) ] ; ALL_LOCATE_TARGET = $(EXEC) ; if $(BUILD_WITH_SUB_DIRECTORIES) = true { # Override the default Objects rule Objects { local _i ; for _i in [ FGristFiles $(<) ] { Object $(_i:S=$(SUFOBJ)) : $(_i) ; Depends obj : $(_i:S=$(SUFOBJ)) ; if $(INCREMENTAL_BUILD) != true { NotFile protobuf ; Depends $(_i:S=$(SUFOBJ)) : protobuf ; } MakeLocateWithSubDirectory $(_i:S=$(SUFOBJ)) : [ FDirName $(LOCATE_SOURCE[1]) objects $(SUBDIR_TOKENS) ] ; } } } # version file # Ident'ed executables depend on this SEARCH on Version = $(P4) ; include Version ; if $(DEV_VERSION) = true { # Add local-dev-build marker to the revision RELEASE = $(RELEASE[1]) $(RELEASE[2]) $(RELEASE[3])-local-dev-build ; # Change the version to bogus one # TODO: This could be improved to grab the version from perforce # but is it going to be better. Developers may have # old revision, cherry picking, un-submitted changes, etc. PATCHLEVEL = 9999999 ; SUPPDATE = 2100 01 01 ; } STRIP = strip ; COMPRESS = gzip -9 ; ZIP = zip -9 -r -q ; # symbolic flags with no user/group/other specifier will default to # ANDing with the user's umask. # Thus, if the user's umask is 022, # files will be -rw-r--r-- and executables will be -rwxr-xr-x # If a user's umask is 002, # files will be -rw-rw-r-- and executables will be -rwxrwxr-x # and so on. if $(UNIX) { FILEMODE = "+r,go-w" ; EXEMODE = "+rx,go-w" ; } DEFINES += OS_$(OS) OS_$(OS)$(OSVER) OS_$(OS)$(OSPLAT:U) OS_$(OS)$(OSVER)$(OSPLAT:U) ; HDRS += [ FSubDirPath P4 msgs ] [ FSubDirPath P4 support ] [ FSubDirPath P4 sys ] ; # For production builds we customize the names of our Qt shared # libaries on some platforms to avoid naming/version conflicts with # system libraries on numerous platforms. The main exception is # OSX, where it isn't needed. # # Developers don't necessarily bother to add this infix to their # builds, but these variables allow one to use them if desired even # for non-production builds. if $(PRODUCTION) && $(OS) != MACOSX { QT_LIBINFIX ?= P4 ; } # The default, if linking with stdc++, is to dynamically link unless a specific platform overrides as static. STATIC_LIBSTDC++ = no ; # This really ought to be renamed LINK_WITH_STL since some operating systems use a different name. LINK_WITH_STDC++ = p4d p4p p4broker p4zk p4sandbox p4sandbox_ja p4vc ; # SSL configuration: # Define SSL to include netssl* source code into the libraries and executables # Define SSLSTUB to link in a stubbed version of the SSL libraries rather than linking # to the OpenSSL libraries. # Expected build configurations: # 1. All in-house executables compiled with SSL = yes and SSLSTUB = no # (i.e., link with OpenSSL libraries) # 2. C/C++ Client API built with SSL = yes and SSLSTUB = yes # SSL is defined but libraries not released with code. SSL ?= no ; SSLSTUB ?= no ; SetDefaultDirName SSLPREFIX : [ FSubDirPath P4BIN ] ; # 2014-10-23 temporary backward compatibility for transition. # Don't use SSLINCLUDE anymore. if $(SSLINCLUDE) { SSLINCDIR ?= $(SSLINCLUDE) ; } if $(SSLSTUB) = yes { SSL = yes ; SSLINCDIR ?= [ FSubDirPath AllP4 p4 sslstub ] [ FDirName $(SSLPREFIX) inc.$(EXEC_SUB_TOKENS[1]) ] ; SetDefaultDirName SSLINCDIR ; } else { SetDefaultDirName SSLINCDIR : [ FDirName $(SSLPREFIX) inc.$(EXEC_SUB_TOKENS[1]) ] ; } # Zookeeper configuration # Define ZK to include zkservice client network code into the server process. # The ZKS client network code should be used only with the Perforce Clustered Servers. # The Clustered Servers are only being released on Linux varients. # Expected build configurations: # 1. Only the p4d and p4broker executables on Linux 32 and 64 bit platforms. Non-clustered # servers and brokers on Linux will have support for Zookeeper built in but will not use # the service. # 2. All non-linux OS p4d and p4brokers will not compile in support for Zookeeper. # 3. The proxy and perforce client will not compile in support for Zookeeper ZK ?= no ; # LDAP configuration: # Define LDAPSTUB to link in a stubbed version of the LDAP libraries # rather than linking to either the OpenLDAP or WinLDAP libraries. # Expected build configurations: # 1. NT P4D binaries built with LDAPSTUB = no and linked against WinLDAP # in the Windows SDK. # 2. Linux P4D binaries built with LDAPSTUB = no and linked against the # OpenLDAP and CyrusSASL libraries # 3. All other P4D binaries built with LDAPSTUB = yes LDAPSTUB ?= yes ; SetDefaultDirName OPENLDAPINCDIR : $(EXEC_INC) ; SetDefaultDirName OPENLDAPLIBDIR : $(EXEC_LIB) ; SetDefaultDirName CYRUSSASLPINCDIR : $(EXEC_INC) ; SetDefaultDirName CYRUSSASLPLIBDIR : $(EXEC_LIB) ; ################################################# # # Section 2. Library names. # ################################################# rule SetLibName { $(1) = $(2:S=$(SUFLIB)) ; LOCATE on $($(1)) = $(EXEC) ; } SetLibName CLIENTLIB : libclient ; SetLibName DMLIB : libdm ; SetLibName FTPLIB : libp4ftp ; SetLibName LBRLIB : liblbr ; SetLibName P4EXPLIB : libp4exp ; SetLibName P4TD : libp4thumb ; SetLibName P4LIB : libp4 ; SetLibName P4SCCLIB : libp4scc ; SetLibName P4SSLLIB : libp4sslstub ; SetLibName P4WINLIB : libp4win ; SetLibName P4WINCMNLIB : libp4wcmn ; SetLibName P4WINDIFFLIB : libp4wdf ; SetLibName P4WINMRGLIB : libp4wmrg ; SetLibName PLUGINLIB : libplugin ; SetLibName PROXYLIB : libproxy ; SetLibName QTADMINAPPLIB : libqtadminapp ; SetLibName QTADMINLIB : libqtadmin ; SetLibName QTCMDLIB : libqtcmd ; SetLibName QTCORELIB : libqtcore ; SetLibName QTP4APILIB : libqtp4api ; SetLibName QTIMGMAXLIB : libqtmaxfmt ; SetLibName QTIMGMAYALIB : libqtmayafmt ; SetLibName QTIMGPHOTOLIB : libqtphotofmt ; SetLibName QTIMGTGALIB : libqttgafmt ; SetLibName QTMERGELIB : libqtmerge ; SetLibName QTMERGEAPPLIB : libqtmergeapp ; SetLibName QTPLATLIB : libqtplat ; SetLibName QTPREFLIB : libqtpref ; SetLibName QTUTILLIB : libqtutil ; SetLibName QTREELIB : libqtree ; SetLibName RPCLIB : librpc ; SetLibName SANDSTORM : libstorm ; SetLibName P4VSHELL : libp4vshell ; SetLibName P4ALIB : libp4a ; SetLibName P4V : libp4v ; SetLibName P4VPRIMITIVES : libp4vprimitives ; SetLibName P4VC : libp4vc ; SetLibName P4VTEST : libp4vtest ; SetLibName SCCDLLLIB : p4scc2 ; SetLibName SERVERLIB : libserver ; SetLibName SUPPORTLIB : libsupp ; SetLibName SHSTUBLIB : libshstub ; SetLibName WEBGIZMOLIB : libp4web ; SetLibName P4SANDBOXLIB : libp4sandbox_$(P4SBLANG:E=en) ; SetLibName ZKSLIB : libzks ; SetLibName P4SHAREDLIB : libp4shared ; SetLibName ZKUILIB : libzkui ; ################################################# # # 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 build # pic: for API and some client applications case dyn : OPTIM = -O2 ; case opt : OPTIM = -O2 ; case pic : OPTIM = -O2 -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 picg : OPTIM = -g -fPIC ; case picog : OPTIM = -g -fPIC -O2 ; case gpic : OPTIM = -g -fPIC ; # mistake in convention; avoid using 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 ; # _FORTIFY_SOURCE: http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html case FSgSSP : OPTIM = -g -D_FORTIFY_SOURCE=2 -fstack-protector-all ; # asan: https://code.google.com/p/address-sanitizer/wiki/AddressSanitizer case asan : OPTIM = -g -fsanitize=address -fno-omit-frame-pointer -O1 ; LINKLIBS = -lasan ; case gcov : OPTIM = -fprofile-arcs -ftest-coverage -g -O ; LINKFLAGS = -fprofile-arcs -ftest-coverage -g ; case *vsdebug* : # special-target builds; see NT section case * : Echo "Warning -- unknown compilation TYPE" $(TYPE) ; } # TYPE_DEBUG for all debug builds. # TYPE_DYNAMIC for all dynamic builds. # TYPE_PIC for all position-independent code gen switch $(TYPE) { case *dyn* : TYPE_DYNAMIC ?= true ; } switch $(TYPE) { case *g* : TYPE_DEBUG ?= true ; } switch $(TYPE) { case *pic* : TYPE_PIC ?= true ; } if $(TYPE_DEBUG) = true { C++FLAGS += -D_DEBUG ; INCREMENTAL_BUILD = true ; } else { C++FLAGS += -DNDEBUG ; } # Some things don't get built dynamically/statically. if ! $(TYPE_DYNAMIC) || $(OS) != NT { BUILD_P4D ?= true ; } if [ FVersionCmp $(GCCVER) : 4.2 ] >= 0 { OPTIM += -fwrapv ; } # see job047026 ################################################# # # 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:E) { case AIX53 : SetCommonCompiler $(OSCOMP:E=gcc) : CC ; # NO_VIZ disables the use of the `hidden' symbol # visibility attribute used by gcc in zlib/zutil.h. CCFLAGS += -DNO_VIZ ; C++FLAGS += -DBSD -Dunix -D_LARGE_FILES=1 ; LINKLIBS += -lsupc++ ; if $(CROSS_COMPILE) { # For some reason our binutils cross-compiled `strip' doesn't # actually remove debug symbols unless you explicitly tell it # to remove that section. STRIP += -R .debug ; } switch $(OSPLAT:U) { case PPC64 : $(GENFLAGS) += -maix64 ; LINKFLAGS += -maix64 ; AR = $(CROSS_COMPILE:E)ar -X64 -ru ; if ! $(CROSS_COMPILE) { # The native aix strip command requires this flag on 64-bit # objects, but the gnu binutils strip command (used when # cross compiling) does not recognize it. STRIP += -X64 ; } } case AS400 : CC = icc ; C++ = icc ; LINK = icc ; OPTIM = -O4 ; $(GENFLAGS) += -DUSE_EBCDIC ; LINKFLAGS += -qDUPPROC ; AR = qar -cru ; STRIP = ; # This QSYS library must be pre-created before building QSYSLIB = p4 ; case CYGWIN* : CC = gcc ; C++ = gcc ; LINK = g++ ; C++FLAGS += -DUSE_CRLF ; case DARWIN : CC = cc ; C++ = cc ; C++FLAGS += -DCASE_INSENSITIVE ; case DARWIN60cs : #case-sensitive CC = cc ; C++ = cc ; LINK = g++ ; case DARWIN8* : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.4 : ppc i386 ; LIBRARY_DEPOLYMENT_SDK = sdk10.4 ; case DARWIN9* : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv : ppc i386 x86_64 ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; # Unspeakably horrible kludge: # The *actual* 10.5 linker doesn't understand this option (and it's # not needed), but it's needed if we want to build 10.5-compatible # executables on a 10.6 system. if $(MACOSX105ON106) { LINKFLAGS += -Wl,-no_compact_linkedit ; } case DARWIN10* : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; # Don't insert LC_* loader commands in executables. Even though OS # X 10.5 can load these executables, none of the older editing # tools like `strip', `otool', etc. from earlier SDKs can interpret # them. So if we really want to reuse artifacts portably, we can't # use these newer features. LINKFLAGS += -Wl,-no_compact_linkedit ; case DARWIN1[12]* : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; case DARWIN13* : SetCommonCompiler $(OSCOMP:E=clang) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; LINKFLAGS += -Wl ; case FREEBSD : Exit Set OSVER to 4, 54, 60, 70, 80, etc for FreeBSD ; case FREEBSD4 : SetCommonCompiler $(OSCOMP:E=gcc) ; if $(OSPLAT:U) != AXP { LINKFLAGS += -static ; } $(GENFLAGS) += -pipe ; case FREEBSD[56789]* : # Freebsd 5.0 to 9.0 SetCommonCompiler $(OSCOMP:E=gcc) ; if [ FVersionCmp $(OSVER) : 70 ] >= 0 { OPTIM += -fwrapv ; } # see job047026 _mflags = ; switch $(OSPLAT:U) { case X86 : _mflags = -m32 ; case X86_64 : _mflags = -m64 ; case SPARC64 : _mflags = -m64 ; } $(GENFLAGS) += $(_mflags) -pipe ; LINKFLAGS += $(_mflags) ; case FREEBSD1* : # FreeBSD 10.0 and later SetCommonCompiler $(OSCOMP:E=clang) ; OPTIM += -Wno-parentheses -Wno-switch -fwrapv ; _mflags = ; switch $(OSPLAT:U) { case X86 : _mflags = -m32 ; case X86_64 : _mflags = -m64 ; } $(GENFLAGS) += $(_mflags) -pipe ; LINKFLAGS += $(_mflags) ; case HPUX11 : switch $(OSPLAT:EU)-$(OSCOMP:E) { # On IA64, hpux supports both 64-bit and 32-bit executables. # We build 64-bit for the benefit of p4d, and client apps are built # the same way for the sake of simplicity. case IA64-GCC : CC = gcc ; C++ = gcc ; $(GENFLAGS) += -mlp64 ; LINK = gcc ; LINKFLAGS += -mlp64 ; LINKLIBS += -lsupc++ -lunwind ; case IA64-* : # unbundled vendor compiler CC = aCC ; C++ = aCC ; OPTIM = +O1 ; if $(TYPE_PIC) { OPTIM += +Z ; } CCFLAGS += -Ae ; # treat .c files as C89, not C++ C++FLAGS += -Wc,-ansi_for_scope,on ; $(GENFLAGS) += +DD64 -z ; # Suppress compiler warnings: # 2611: overloaded virtual function "x" is only partially overridden in class "y" # 2997: function "x::fn is hidden by y::fn" -- virtual function override intended? # 2177: label "x" was declared but never referenced # 2815: type qualifier on return type is meaningless # 4232: conversion from "indx_t *" to a more strictly aligned type "pgno_t *" may cause misaligned access $(GENFLAGS) += +W2611,2997,2177,2815,4232 ; LINK = aCC ; # The +hideallsymbols linker option will generate a # lot of harmless warnings about being unable to hide # symbols that are undefined and need resolving # from the (dynamically linked) system libraries, # but see //depot/main/p4-doc/code/PORTING for rationale. LINKFLAGS += +DD64 +Oprocelim -z -Wl,+hideallsymbols,+stripunwind ; case PA11-* : # unbundled vendor compiler CC = aCC ; C++ = aCC ; LINK = aCC ; OPTIM = +O1 ; CCFLAGS += -Ae ; # treat .c files as C89, not C++ $(GENFLAGS) += -D_LARGEFILE64_SOURCE +DA1.1 ; case *-* : # assumed PA20 (32-bit) with unbundled vendor compiler CC = aCC ; C++ = aCC ; LINK = aCC ; OPTIM = +O1 ; CCFLAGS += -Ae ; # treat .c files as C89, not C++ $(GENFLAGS) += -D_LARGEFILE64_SOURCE ; } case IPHONE30 : # This is distinct from the MACOSX or DARWIN platforms # because the SDKs used are not compatible, and because # someday the iPhone may target both armv6 and i386. PLATFORM_ROOT ?= /Developer/Platforms/iPhoneOS.platform ; COMPILER_DIR ?= $(PLATFORM_ROOT)/Developer/usr/bin ; SDK_VERSION ?= iPhoneOS3.0.sdk ; IPHONE_SDK ?= $(PLATFORM_ROOT)/Developer/SDKs/$(SDK_VERSION) ; CC = $(COMPILER_DIR)/gcc ; C++ = $(COMPILER_DIR)/g++ ; LINK = $(COMPILER_DIR)/g++ ; RANLIB = $(COMPILER_DIR)/ranlib ; $(GENFLAGS) += -DCASE_INSENSITIVE -DOS_DARWIN -fpascal-strings -isysroot$(IPHONE_SDK) ; LINKFLAGS += -Wl,-syslibroot,$(IPHONE_SDK) ; # OSPLAT=U : universal binary (don't use this right now) switch $(OSPLAT:U) { case ARMV6 : _arch = -arch armv6 ; case ARMV7 : _arch = -arch armv7 ; case U : _arch = -arch armv6 -arch armv7 ; NOARSCAN = true ; # can't scan "fat" archives } $(GENFLAGS) += $(_arch) -DCASE_INSENSITIVE ; LINKFLAGS += $(_arch) ; 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) { OPTIM = -O2 -KPIC ; } case LINUX : Exit Set OSVER to 24 or 26 ; case LINUX2[46] : SetCommonCompiler $(OSCOMP:E=gcc) : CC ; LINKLIBS += -lsupc++ # Assumes gcc 3.x or later -lrt # for clock_gettime -ldl # for OpenSSL -lm ; # for floor & misc STATIC_LIBSTDC++ = yes ; LIBRARY_DEPOLYMENT_OS_VERSION = $(OSVER) ; # be explicit about submodel since we may be compiling x86 code on # an x86/x86_64 biarch system, and the default may be uncertain. _mflags = ; switch $(OSPLAT:U) { case X86 : _mflags = -m32 ; SMARTHEAP ?= yes ; SMARTHEAP_CHECKS ?= 0 ; case X86_64 : _mflags = -m64 ; SMARTHEAP ?= yes ; SMARTHEAP_CHECKS ?= 0 ; case PPC : _mflags = -m32 ; case PPC64 : _mflags = -m64 ; case ARMEL : _mflags = -march=armv4t -mfloat-abi=soft ; # Use arch=armv6 for compatibility with Raspberry Pi Raspian. # # It should be noted that vfpv3-d16 is the agreed upon linux # floating point ABI for armv7 and above. This won't actually work # on the raspi because it doesn't have these registers, but we # don't use any floating point in our own programs at present. # This flag is just present to make sure our cross compiler # generates the right code if this situation changes. case ARMHF : _mflags = -march=armv6 -mfloat-abi=hard -mfpu=vfpv3-d16 ; } $(GENFLAGS) += $(_mflags) -D_GNU_SOURCE ; LINKFLAGS += $(_mflags) ; QTOPENGL ?= no ; case MACOSX : Exit Set OSVER to 104, 105, 106, ... for MACOSX ; case MACOSX104 : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.4 : ppc i386 ; LIBRARY_DEPOLYMENT_SDK = sdk10.4 ; # The -fvisibility-inlines-hidden option is a C++-only # option, needed because Qt4 is built with it and all # statically-compiled objects need to use it consistently. C++FLAGS += -fvisibility-inlines-hidden ; $(GENFLAGS) += -fpascal-strings -F$(QTDIR)/lib ; LINKLIBS += -framework ApplicationServices -framework Foundation ; case MACOSX105 : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv : ppc i386 ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; # The -fvisibility-inlines-hidden option is a C++-only # option, needed because Qt4 is built with it and all # statically-compiled objects need to use it consistently. C++FLAGS += -fvisibility-inlines-hidden ; $(GENFLAGS) += -fpascal-strings -F$(QTDIR)/lib ; # Unspeakably horrible kludge: # The *actual* 10.5 linker doesn't understand this option (and it's # not needed), but it's needed if we want to build 10.5-compatible # executables on a 10.6 system. if $(MACOSX105ON106) { LINKFLAGS += -Wl,-no_compact_linkedit ; } LINKLIBS += -framework ApplicationServices -framework Foundation ; case MACOSX106 : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv : i386 ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; # The -fvisibility-inlines-hidden option is a C++-only # option, needed because Qt4 is built with it and all # statically-compiled objects need to use it consistently. C++FLAGS += -fvisibility-inlines-hidden ; $(GENFLAGS) += -fpascal-strings -F$(QTDIR)/lib ; # Don't insert LC_* loader commands in executables. Even though OS # X 10.5 can load these executables, none of the older editing # tools like `strip', `otool', etc. from earlier SDKs can interpret # them. So if we really want to reuse artifacts portably, we can't # use these newer features. LINKFLAGS += $(MACOSX_SDK_FLAGS) -Wl,-no_compact_linkedit ; LINKLIBS += -framework ApplicationServices -framework Foundation ; case MACOSX10[78] : SetCommonCompiler $(OSCOMP:E=gcc) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; # The -fvisibility-inlines-hidden option is a C++-only # option, needed because Qt4 is built with it and all # statically-compiled objects need to use it consistently. C++FLAGS += -fvisibility-inlines-hidden ; $(GENFLAGS) += -fpascal-strings -F$(QTDIR)/lib ; LINKLIBS += -framework ApplicationServices -framework Foundation ; case MACOSX1[01]* : # 10.9 and later SetCommonCompiler $(OSCOMP:E=clang) ; SetOSXSdk : -mmacosx-version-min=10.5 -fwrapv ; LIBRARY_DEPOLYMENT_SDK = sdk10.5 ; # The -fvisibility-inlines-hidden option is a C++-only # option, needed because Qt4 is built with it and all # statically-compiled objects need to use it consistently. C++FLAGS += -fvisibility-inlines-hidden ; $(GENFLAGS) += -fpascal-strings -F$(QTDIR)/lib ; LINKLIBS += -framework ApplicationServices -framework Foundation ; case MINGW* : # MinGW is a special case of NT : instead of using msft's compiler, # it uses gcc. But unlike cygwin it is not an emulation layer. # # Most of the win32 API is accessible but not all MSVC extensions # are; there might be difficulty using routines that are part of # the MSVCR dynamic runtime. # Use 7z on the MinGW-w64 port if $(RI_DEVKIT) { ZIP = 7z a -r ; } # If cross compiling (e.g. on linux), set CROSS_COMPILE to the # prefix of the cross tools. if ! $(NT) && ! $(MINGW) && ! $(MINGW64) { CROSS_COMPILE ?= i686-pc-mingw32- ; } SetCommonCompiler $(OSCOMP:E=gcc) ; SUFLIB = .a ; SUFOBJ = .o ; SUFEXE = .exe ; DEFINES += OS_NT CASE_INSENSITIVE USE_CRLF ; # Set minimum API compatibility to WindowsXP (see w32api.h) # # Make sure exceptions are disabled; the API doesn't use any and # some builds of MinGW don't even support them. $(GENFLAGS) += -D_WIN32_WINNT=0x0501 -DWINVER=0x0501 -fno-exceptions ; # For MinGW-w64 set the old MinGW macro as well. # This avoids having the redo all the ifdefs. if $(RI_DEVKIT) { $(GENFLAGS) += -DOS_MINGW ; } # LINKLIBS comes from jambase wrongly initialized # do not use += here LINKLIBS = -lws2_32 -lsupc++ ; # MinGW-w64 also uses the Visual Studio libs. if $(RI_DEVKIT) { LINKLIBS += -ladvapi32 -lkernel32 ; if $(SSL) = yes { LINKLIBS += -lUser32 -lOle32 -lOleaut32 -lGdi32 ; } } case MVS : # Set the following variables in your shell before # invoking jam # # _C89_CLIB_PREFIX="SYS1.CBC" # _C89_PLIB_PREFIX="SYS1.CEE" # _C89_SLIB_PREFIX="SYS1" # # _CC_CLIB_PREFIX="SYS1.CBC" # _CC_PLIB_PREFIX="SYS1.CEE" # _CC_SLIB_PREFIX="SYS1" # # _CXX_CLIB_PREFIX="SYS1.CBC" # _CXX_PLIB_PREFIX="SYS1.CEE" # _CXX_SLIB_PREFIX="SYS1" # # Note: some might not be required if all the aliases have # been set correctly # EBCDIC ?= yes ; CC = cc ; C++ = c++ -+ ; $(GENFLAGS) += -D_OE_SOCKETS -DNO_LONG_LONG ; if $(EBCDIC) != no { $(GENFLAGS) += -DUSE_EBCDIC ; } if $(ASCII) = yes { $(GENFLAGS) += -DNO_EBCDIC_FILES ; } LINK = c++ ; OPTIM = -O ; case NETBSD3* : OSCOMPDIR ?= /usr/pkg/gcc34/bin/ ; CC = $(OSCOMPDIR:E)gcc ; C++ = $(OSCOMPDIR:E)g++ ; LINK = $(OSCOMPDIR:E)gcc ; LINKLIBS += -lsupc++ -lm ; $(GENFLAGS) += -pipe -Dunix ; # NetBSD gcc choked on -O2 -fPIC if $(TYPE_PIC) { OPTIM = -O1 -fPIC ; } case NETBSD* : CC = $(OSCOMPDIR:E)gcc ; C++ = $(OSCOMPDIR:E)g++ ; LINK = $(OSCOMPDIR:E)gcc ; LINKLIBS += -lsupc++ -lm ; $(GENFLAGS) += -pipe -Dunix ; case VMS* : # use C++ compiler: we're cheap CC = cxx ; C++ = cxx ; DEFINES += NO_MEMCPY ; STRIP = ; OPTIM = ; case NT* : LIBRARY_DEPOLYMENT_SDK = vs$(MSVSVER) ; # Jambase adds /MT to C++FLAGS, even when we don't want it. # We'll set the right flags below. C++FLAGS = [ FRemoveAny $(C++FLAGS) : /MT ] ; CCFLAGS = [ FRemoveAny $(CCFLAGS) : /MT ] ; # Define min windows version supported C++FLAGS += -D_WIN32_WINNT=0x0501 ; if $(FULL_PATH_DIAGNOSTICS) = true { C++FLAGS += /FC ; } local _Z = /Zi ; # flag to put debug syms in .pdb file # Visual Studio 8 and earlier choke when writing .pdb files # to a networked drive; this variable provides a way to # override the pdb filename. Visual Studio 9 # (VS2008) and later apparently are ok. PDBFILENAME ?= $(EXEC)\\ ; if [ FVersionCmp $(MSVSVER) : 12 ] >= 0 { # If using parallel builds, VS12 will abort due to multiple # simultaneous accesses to the pdb file unless you serialize # accesses with this flag. $(GENFLAGS) += /FS ; } if $(JAMFAST) { if $(PRODUCTION) { Exit Do not use JAMFAST with PRODUCTION, since JAMFAST embeds debug symbols directly in object files. ; } # Put debug syms directly in object files. # If running jam with -j2 or greater, using a .pdb database # for the debug symbols may cause locking failures from # parallel compilation processes trying to access it. _Z = /Z7 ; } switch $(BUILD) { # When we do API builds, we set BUILD=vs2003, vs2005, etc. # These builds should have neither /Zi nor /Z7 symbol # instrumentation, because we don't want to ship debug # symbols to our customers, either embedded in the # .obj/.lib files or in the .pdb database which the linker # would want provided. case vs2* : _Z = ; } C++FLAGS += /DCASE_INSENSITIVE /DUSE_CRLF ; if $(WARN_FOR_DEPRECATED) = true { # removes /wd4996 that cames from jam - jambase file C++FLAGS = [ FRemoveAny $(C++FLAGS) : /wd4996 ] ; } # Use setargv.obj to get wildcard expansion. # This is coupled with our own modified wildcard expander used by # setargv.obj in VS8 or later, per job030753. # LINKLIBS comes from jambase wrongly initialized # do not use += here LINKLIBS = setargv.obj advapi32.lib oldnames.lib kernel32.lib ws2_32.lib ; if $(SSL) = yes { LINKLIBS += User32.lib Ole32.lib Oleaut32.lib Gdi32.lib ; } # 2008-10-17: static only for now if ! $(TYPE_DYNAMIC) && [ FVersionCmp $(MSVSVER) : 8 ] >= 0 { local _dyn ; if $(TYPE_DYNAMIC) = true { _dyn = -dyn ; } LINKLIBS += $(EXEC_LIB)/wild-vs$(MSVSVER)$(_dyn:E).obj ; } if $(OSPLAT:U) = IA64 && ! $(MSVSVER) { # When using the windows 2003 SDK on IA64, the /GS flag is # enabled by default but even if you disable it for our own # builds, the libraries provided with the SDK itself were build # with /GS, so there's no way to avoid having to link against # this library. # # See http://support.microsoft.com/?id=894573 LINKLIBS += bufferoverflowU.lib ; } # The "rc" tool needs MS headers: RCSTDHDRS = $(MSVCNT:J=" ")\\include $(MSVCNT:J=" ")\\atlmfc\\include ; STRIP = ; switch $(OSPLAT:U) { case X86 : SMARTHEAP ?= yes ; SMARTHEAP_CHECKS ?= 0 ; case X64 : SMARTHEAP ?= yes ; SMARTHEAP_CHECKS ?= 0 ; } # 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 switch $(TYPE) { case g : # Debugging build OPTIM = $(_Z) /Gm ; RCFLAGS = /d DEBUG /r ; LINKFLAGS += /DEBUG ; if $(SMARTHEAP) = yes { LINKFLAGS += /FORCE ; } if $(CRT) = dyn { $(GENFLAGS) += /MDd ; } else { $(GENFLAGS) += /MTd ; } case dyn : # Dynamic link version, for qt products OPTIM = $(_Z) /O2 ; RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MD ; LINKFLAGS += /MAP /DEBUG /OPT:REF /OPT:ICF ; case dyng : # Dynamic Debugging build if $(JAMFAST) { OPTIM = $(_Z) ; } else { OPTIM = $(_Z) /Gm ; } RCFLAGS = /d DEBUG /r ; $(GENFLAGS) += /MDd ; LINKFLAGS += /DEBUG /NODEFAULTLIB:msvcrt.lib /fixed:no ; case vsdebug : # Static link with Visual Studio debug libraries. # This does not enable debugging our own code, just sets # linker dependencies for VS libraries. # This is intended for customer use. OPTIM = /O2 ; RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MTd ; case vsdebug_idl0 : # Static link with Visual Studio debug libraries. # This does not enable debugging our own code, just sets # linker dependencies for VS libraries. # This is intended for customer use. OPTIM = /O2 ; RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MTd -DITERATOR_DEBUG_LEVEL=0 ; case vsdebug_idl1 : # Static link with Visual Studio debug libraries. # This does not enable debugging our own code, just sets # linker dependencies for VS libraries. # This is intended for customer use. OPTIM = /O2 ; RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MTd -DITERATOR_DEBUG_LEVEL=1 ; case dyn_vsdebug : # Dynamic link with Visual Studio debug libraries. # This does not enable debugging our own code, just sets # linker dependencies for VS libraries. # This is intended for customer use. OPTIM = /O2 ; RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MDd ; case dyn_vsdebug_idl0 : # Dynamic link with Visual Studio debug libraries. # This does not enable debugging our own code, just sets # linker dependencies for VS libraries. # This is intended for customer use. RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MDd -DITERATOR_DEBUG_LEVEL=0 ; case dyn_vsdebug_idl1 : # Dynamic link with Visual Studio debug libraries. # This does not enable debugging our own code, just sets # linker dependencies for VS libraries. # This is intended for customer use. RCFLAGS = /d NDEBUG /r ; $(GENFLAGS) += /MDd -DITERATOR_DEBUG_LEVEL=1 ; case * : # Static link version, for command line products OPTIM = /O2 $(_Z) ; RCFLAGS = /d NDEBUG /r ; if $(CRT) = dyn { $(GENFLAGS) += /MD ; } else { $(GENFLAGS) += /MT ; } LINKFLAGS += /MAP /DEBUG /OPT:REF /OPT:ICF ; } if $(OSPLAT:U) = X64 { # 64 bit windows needs increased stack size, so # we're doubling the stack from 2mb to 4mb. # See job31737. LINKFLAGS on p4d.exe = $(LINKFLAGS) /STACK:4194304 ; } case QNXNTO* : CC = cc ; C++ = cc ; LINKLIBS += -lsocket ; case SCO* : C++ = gcc ; CC = gcc ; LINK = gcc ; LINKLIBS += -lsocket ; case SOLARIS* : switch $(OSCOMP) { case SUNC11 : # Sun Studio 11 # Recommended jam flags: -sOSCOMP=SUNC11 -sBUILD=suncc # Add -sTYPE=pic for api. CC = c99 ; C++ = CC ; LINK = CC ; OPTIM = -xO3 ; if $(TYPE_PIC) { OPTIM += -KPIC ; } switch $(OSPLAT:U) { case *64 : $(GENFLAGS) += -xarch=generic64 ; LINKFLAGS += -xarch=generic64 ; } case SUNC12 : # Sun Studio 12 # Recommended jam flags: -sOSCOMP=SUNC12 -sBUILD=suncc # Add -sTYPE=pic for api. CC = c99 ; C++ = CC ; LINK = CC ; OPTIM = -xO3 ; if $(TYPE_PIC) { OPTIM += -KPIC ; } switch $(OSPLAT:U) { case *64 : $(GENFLAGS) += -m64 ; LINKFLAGS += -m64 ; } case * : # GCC SetCommonCompiler $(OSCOMP:E=gcc) ; switch $(OSPLAT:U) { case *64 : # X86_64 or SPARC64 LINKFLAGS += -m64 ; $(GENFLAGS) += -m64 ; } # supc++ needed for all apps since we use gcc >= 3.2. LINKLIBS += -lsupc++ ; STATIC_LIBSTDC++ = yes ; } $(GENFLAGS) += -I/opt/lude/include -Dsolaris -D_LARGEFILE64_SOURCE # NO_VIZ disables the use of the `hidden' symbol # visibility attribute used by gcc in zlib/zutil.h. # Solaris 10 x86 still uses a gcc 3.x compiler which # does not properly support this attribute. -DNO_VIZ ; LINKLIBS += -lsocket -lnsl ; STRIP = $(CROSS_COMPILE:E=/usr/ccs/bin/)strip ; RANLIB = $(CROSS_COMPILE:E=/usr/ccs/bin/)ranlib ; AR = $(CROSS_COMPILE:E=/usr/ccs/bin/)ar ru ; if $(CROSS_COMPILE:E=no) != no { LINKFLAGS += -Wl,--allow-shlib-undefined ; } QTOPENGL ?= no ; case * : Exit Don't know "$(OS)$(OSVER) or " $(OS) ; } if $(SMARTHEAP) = yes { DEFINES += USE_SMARTHEAP ; if $(MEM_DEBUG) = yes { DEFINES += MEM_DEBUG=1 DEFINE_NEW_MACRO=1 ; } if $(SMARTHEAP_CHECKS) != 0 { DEFINES += SMARTHEAP_CHECKS=$(SMARTHEAP_CHECKS) ; DEFINES += MEM_DEBUG=1 DEFINE_NEW_MACRO=1 ; } } if $(SSL) = yes { DEFINES += USE_SSL ; } if $(ZK) = yes { DEFINES += USE_ZK ; } if $(JSP) = yes { DEFINES += USE_JSP ; } if $(ZMQ) = yes { DEFINES += USE_ZMQ ; } if $(UNIX) { # Don't fail if directory already exists. MKDIR = mkdir -p ; } if $(UNIX) && $(PRODUCTION) && ! ( $(TYPE_DEBUG) || $(PRODUCTION_NO_DEBUG) ) { # Compile with both -O2 and -g, even for opt builds. # The resulting build will produce foo.debug and foo, where foo has # local symbols and foo is stripped as per usual. # The PRODUCTION_NO_DEBUG override is for building p4api.tgz, where # we do not want give our customers local symbols. OPTIM += -g ; # Work around an internal compiler fault in gcc 3.4.x that occurs # on this file when you use -O2 and -g at the same time. # This can go away if/when we start using gcc 4.x on these # platforms. if $(OS) = LINUX || $(OS) = SOLARIS { local _f = <p4-qt!windows!integrate>IntegratePreviewView.o ; C++FLAGS on $(_f) += $(C++FLAGS) -fno-unit-at-a-time ; } # On AIX, don't perform the intermediate strip. The use of "-x" # generates an "0654-407 Internal error", and trying to fully strip # an executable twice will result in a gratuitous failure message # the second time. switch $(OS) { case AIX : STRIP_LOCAL = ":" ; case * : STRIP_LOCAL = $(STRIP) -x ; } # Copy, then strip; "strip -o" is not portable, e.g. doesn't work on AIX. # This strips local symbols only. Some programs will get strippped # more thoroughly later via the Strip rule (e.g. p4d) but in general # global symbols assist with backtraces from customers. And plugins # can *not* be stripped of global symbols or dlsym lookups will fail. actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) -o $(<).debug $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) && $(CP) -p $(<).debug $(<) && $(STRIP_LOCAL) $(<) } } ################################################# # # Section 4.2. Library deployment # ################################################# LIBRARY_DEPOLYMENT_PACKAGE = $(OS:L)$(LIBRARY_DEPOLYMENT_OS_VERSION:E)$(OSPLAT:EL) ; #LIBRARY_DEPOLYMENT_SDK must be specified in the previous section LIBRARY_DEPOLYMENT_CONFIGURATION = $(BUILD) $(TYPE:L) ; LIBRARY_DEPOLYMENT_DIRECTORY = $(LIBRARY_DEPOLYMENT_PACKAGE) $(LIBRARY_DEPOLYMENT_SDK) $(LIBRARY_DEPOLYMENT_CONFIGURATION) ; ################################################# # # Section 5. Perforce-special rules and actions. # ################################################# # # Special Rules # # FRegexpQuote list ; - quote regexp metacharacters into literals # FDirEntries path : pat ; - return a list of files matching pat in path # DefineVar src : var ; - define a var for src compilation # Ident exe ; - define bits for program ident string # ListAC ??? ; # P4ClientHdrs ; - add all p4 client headers for building Web, ftp # P4Library lib : src ; - Library of P4 client libs # P4DLibrary lib : src ; - Library of P4D server libs # Strip exe ; - strip executable of symbols after building # CopyRec target : dstdir : srcdir : excludes ; - recursively copy srcdir into dstdir # # And build packaging rules # # P4APIMakeDir apiname : files ; build api dist structure # P4Api apiname : files ; make archive files of api dist structure # MkDistArchive file : directory ; calls appropriate action based on file extension # MakeP4ObjCdist file ; Create Objective C API package # MakeP4DTGdist file ; Create p4dtg package rule FRegexpQuote { # FRegexpQuote list ; # Quote any egrep(1) regexp metacharacters in elements of # list such that they will only match a literal expression. # Returns the quoted list. local result ; local p ; for p in $(<) { local q ; while (1) { local r = [ Match ^([^][()*+.?\\]*)([][()*+.?\\])(.*) : $(p) ] ; q += $(r[1]) ; if $(r[2]) = "" { q += $(p) ; break ; } q += \\$(r[2]) ; p = $(r[3]) ; } result += $(q:J=) ; } return $(result) ; } rule FDirEntries { # Usage: files = [ FDirEntries path to directory : pat ] ; # Returns list of entries in directory which match pat (default '*') local dir = [ FDirName $(<) ] ; local pat = $(>) ; if ! $(pat) { pat = "*" ; } local ents = [ Glob $(dir) : $(pat) ] ; # => d/. d/.. d/a d/b # We need to quote windows directories because they use # backslashes, and those are regexp metacharacters. # Safer on unix too. local re = [ FRegexpQuote $(dir)$(SLASH) ] ; ents = [ Match $(re)(.*) : $(ents) ] ; # => . .. a b return [ FRemoveAny $(ents) : $(DOT) $(DOTDOT) ] ; # return minus . and .. } rule FileIsDir { # Returns a list of just those elements that are names of existing directories local result ; local f ; for f in $(1) { if [ Glob $(f) : $(DOT) ] { result += $(f) ; } } return $(result) ; } rule DefineVar { # Usage: DefineVar foo.cc : VARNAME # Defines it if set if $($(>)) { ObjectDefines $(<) : [ Fconcat $(>)= [ FQuote \"$($(>):J=" ")\" ] ] ; } } rule DefineVarNQ { # Usage: DefineVarNQ foo.cc : VARNAME # Defines it if set, but do not surround with quotes. # Useful for numbers and other atoms. if $($(>)) { ObjectDefines $(<) : [ Fconcat $(>)= $($(>)) ] ; } } 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:J=.) ] ] [ 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 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) ; } 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 P4Library { Library $(<) : $(>) ; } rule P4DLibrary { if $(BUILD_P4D) = true { Library $(<) : $(>) ; } } rule P4Main { Main $(<) : $(>) ; LinkSSL $(<) ; Strip $(<) ; # Things get a little messy with supc++/stdc++ depending on the # compiler front end used for linking. if $(<) in $(LINK_WITH_STDC++) { if $(STATIC_LIBSTDC++) = yes { local _lib = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic ; OnTargetVarDelete $(<)$(SUFEXE) : LINKLIBS : -lsupc++ ; OnTargetVarAppend $(<)$(SUFEXE) : LINKLIBS : $(_lib) ; } else { OnTargetVarDelete $(<)$(SUFEXE) : LINKLIBS : -lsupc++ ; if [ on $(<) return $(LINK) ] = [ on $(<) return $(CC) ] { # If using the CC front end to link by default, but we need # STL (not necessarily stdc++, e.g. when using clang on # freebsd, which has a different C++ runtime), use the C++ # front end for this target instead. LINK on $(<) = [ on $(<) return $(C++) ] ; } } } } rule ExP4Main { if $(OS) = NT { ObjectC++Flags $(>) : /EHsc ; } P4Main $(<) : $(>) ; } rule P4DMain { if $(BUILD_P4D) = true { P4Main $(<) : $(>) ; } else { P4NoBuild $(<) : BUILD_P4D ; } } rule P4NoBuild { NotFile $(>) ; } actions quietly P4NoBuild { echo Set $(>) to force build of $(<). } rule Lex { # Some places don't have lex or flex on $(<) if $(LEX) { # In most cases we generate and check in a copy of the # generated file, because most operating systems lack a working # lexer. Here we check to see if that source is fact present, # and if it is, force the lexer to overwrite it directly. This # has the advantage that parallel builds will not stomp on each # others' temporary output files (usually "lex.yy.c" the # current working directory). local _exist = [ FDirEntries $(SEARCH_SOURCE) : $(<:G=) ] ; if $(_exist) = $(<:G=) { SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(<) : $(SEARCH_SOURCE) ; local output = $(SEARCH_SOURCE) $(<:G=) ; # flex does not permit a space between -o and filename OnTargetVarAppend $(<) : LEX : -o$(output:J=/) ; Depends $(<) : $(>) ; } else { # Traditional Jambase behavior LexMv $(<) : $(>) ; Depends $(<) : $(>) ; MakeLocate $(<) : $(LOCATE_SOURCE) ; Clean clean : $(<) ; } } } rule Yacc { local _h = $(<:BS=.h) ; local _dst = $(<) $(_h) ; # Some places don't have a yacc. on $(<) if $(YACC) { # In most cases we generate and check in a copy of the # generated files, because most operating systems lack a # working parser generator. Here we check to see if those # sources are in fact present, and if they are, force the # parser generator to overwrite them directly. This has the # advantage that parallel builds will not stomp on each others' # temporary output files (usually "y.tab.c" and "y.tab.h" in # the current working directory). local _exist = [ FDirEntries $(SEARCH_SOURCE) : $(_dst:G=) ] ; if $(_exist) = $(_dst:G=) { SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocate $(_dst) : $(SEARCH_SOURCE) ; local output = $(SEARCH_SOURCE) $(<:G=) ; OnTargetVarAppend $(<) : YACCFLAGS : -o $(output:J=/) ; Depends $(_dst) : $(>) ; Yacc1 $(_dst) : $(>) ; } else { # Traditional Jambase behavior MakeLocate $(_dst) : $(LOCATE_SOURCE) ; Depends $(_dst) : $(>) ; Yacc1 $(_dst) : $(>) ; YaccMv $(_dst) : $(>) ; Clean clean : $(_dst) ; } } # make sure someone includes $(_h) else it will be # a deadly independent target Includes $(<) : $(_h) ; # Handle #includes in .y file HDRRULE on $(>) = YaccHdr ; } rule LinkLibraries { # NB this is superfluous in jam 2.6 # 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 { on $(<) if $(STRIP) && ! $(TYPE_DEBUG) { Strip1 $(<:S=$(SUFEXE)) ; } } actions Strip1 { $(STRIP) $(<) } # CopyRec target : dstdir : srcdir : excludes ; # Recursively copies the contents of srcdir into dstdir # target is a non-file token to use for dependency generation # excludes are directory or file names not to copy. rule CopyRec { local target = $(1) ; local dst = [ FDirName $(2) ] ; local src = [ FDirName $(3) ] ; local excludes = $(4) ; local filepat = $(5) ; # Avoid duplicate recursion/dependencies if we've seen this # target already. if $($(dst)-CopyRec-seen) { return ; } $(dst)-CopyRec-seen = 1 ; NotFile $(target) ; # ents will be empty if src is not a directory local ents = [ Glob $(src) : * ] ; # => src/. src/.. src/a src/b if $(ents) { Depends $(target) : $(dst:G=dir) ; MkDir $(dst:G=dir) ; ents = [ FDirEntries $(src) ] ; local sub ; for sub in $(ents) { if $(sub) in $(excludes) { continue ; } CopyRec $(target) : $(dst) $(sub) : $(src) $(sub) : $(excludes) : $(filepat) ; } } else { if $(filepat) { local dir = $(src:P) ; local matches = [ Glob $(dir) : $(filepat) ] ; if ! $(src) in $(matches) { return ; } } local pdst = $(dst:PG=dir) ; Depends $(target) : $(dst) ; Depends $(dst) : $(pdst) ; MkDir $(pdst) ; if $(UNIX) { # For a recursive copy on unix we want to try to preserve # file timestamps and permissions (e.g. they might be # executables plain files). local CHMOD = ; CP on $(dst) = $(CP) -p ; File $(dst) : $(src) ; } else { File $(dst) : $(src) ; } } } rule P4APIDirName { # P4APIDirName apiname ; # # The API should be copied into a temp subdirectory by P4APIMakeDir # and the API files copied into it. # # This rule computes the name of that directory, and the name of # the tar/zip file that it should be packed into, and returns a # list of those two names. # # This is a subroutine for clarity purposes, and is use both by # P4APIMakeDir and the DTG sdk builds to compute P4DIR. local _sep = "." ; # directory name field separator if $(VMS) { _sep = "_" ; } # _dirname - apiname-releaseinfo # on nt: apiname-releaseinfo-build_type local _dirname = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ; _dirname = $(<)-$(_dirname:J=$(_sep)) ; local _arcname = $(<) ; if $(NT) { local _ntsuffix ; switch $(TYPE) { case dyn* : _ntsuffix = $(BUILD) $(TYPE) ; case opt : _ntsuffix = $(BUILD) static ; case * : _ntsuffix = $(BUILD) static $(TYPE) ; } _dirname = $(_dirname)-$(_ntsuffix:J=_) ; _arcname = $(<)_$(_ntsuffix:J=_) ; } return $(_dirname) $(_arcname) ; } rule P4APIMakeDir { # P4APIMakeDir apiname : files ; # # Builds a temp subdirectory $(EXEC)/apiname-releaseinfo # and copies the API files into it. # # Returns a list consisting of the api directory name # (usually api-releaseinfo, but possibly # api-releasinfo_build_type on NT), and the archive file # name (minus final suffix) into which the directory should # be stored. # # This is a subroutine for clarity purposes and probably # shouldn't be used directly except by the P4API rule. local _dirname_data = [ P4APIDirName $(<) ] ; local _dirname = $(_dirname_data[1]) ; local _arcname = $(_dirname_data[2]) ; local _cpflags ; if $(UNIX) { _cpflags = -p ; # to preserve times with cp -p } NotFile api ; Depends all : api ; MakeLocate $(_dirname) : $(EXEC) ; Depends api : $(_dirname) ; # SEARCH_SOURCE -- where api files are found (all over) local SEARCH_SOURCE = $(HDRS) $(SUBDIRHDRS) $(SUBDIR) $(P4) ; # for each target file, copy to named temp directory # create mini structure (include/p4, lib, sample directories) local _f ; for _f in $(>) { local _d _t ; # Note that for .h and .cc files we use different # grist $(x:G=alt), to distinguish these targets from # the ones used in compiles. We don't want #include # processing on these. switch $(_f) { case *.h : _d = include p4 ; _f = $(_f:G=alt) ; case *.a : _d = lib ; case *.lib : _d = lib ; case *.olb : _d = lib ; # VMS library archive case *.cc : _d = sample ; _f = $(_f:G=alt) ; case * : _d = sample ; } _t = $(_f:G=$(<)) ; # target switch $(_t:G=) { case Jamfile.api : _t = $(_t:S=) ; # remove .api suffix in target } _d = [ FDirName $(EXEC) $(_dirname) $(_d) ] ; # directory CP on $(_t) = $(CP) $(_cpflags) ; MakeLocate $(_t) : $(_d) ; File $(_t) : $(_f) ; Depends api : $(_t) ; Clean clean : $(_t) ; } return $(_dirname) $(_arcname) ; } rule P4Api { # P4Api apiname : files ; # # Builds a temporary subdirectory $(EXEC)/apiname-releaseinfo # and makes a tarball apiname.tar of that stuff. # _dirname - apiname-releaseinfo # on nt: apiname-releaseinfo-build_type local _apidata = [ P4APIMakeDir $(<) : $(>) ] ; local _dirname = $(_apidata[1]) ; local _arcname = $(_apidata[2]) ; local _tar = $(_arcname:S=.tar) ; local _tgz = $(_arcname:S=.tgz) ; local _zip = $(_arcname:S=.zip) ; local _bck = $(_arcname:S=.bck) ; local _targets = $(_tar) $(_tgz) $(_zip) ; if $(NT) { # This allows one to still be able to run the # command "jam p4api.tar" and have it work, even # though the actual file name will vary. Depends $(<:S=.tar) : $(_tar) ; Depends $(<:S=.tgz) : $(_tgz) ; Depends $(<:S=.zip) : $(_zip) ; } else if $(VMS) { _targets += $(_bck) ; } LOCATE on $(_targets) = $(EXEC) ; Depends $(_targets) : api ; MkTarArchive $(_tar) : $(_dirname) ; MkComressedTarArchive $(_tgz) : $(_dirname) ; MkZipArchive $(_zip) : $(_dirname) ; if $(VMS) { MkBckArchive $(_bck) : $(_dirname) ; } } rule MkDistArchive { local _trg ; for _trg in $(<) { switch $(_trg:S) { case .tar : MkTarArchive $(_trg) : $(>) ; case .tgz : MkComressedTarArchive $(_trg) : $(>) ; case .tar.gz : MkComressedTarArchive $(_trg) : $(>) ; case .zip : MkZipArchive $(_trg) : $(>) ; case .bck : MkBckArchive $(_trg) : $(>) ; case * : exit "Don't know how to make $(_trg)" ; } } } # Args: [bin.dir] name : files ... ; # # Will create targets name.tgz and name.zip # which unpack into a single directory named "name-<version>" # containing all of the remaining files. # # The tar files will go in the normal bin.<os><osver><osplat>/$BUILD # directory unless the first parameter lists the target directory # (relative to p4-bin). A common use case would be bin.tools. # # Will not preserve directory hierarchy of files listed in 2nd # parameter, so avoid duplicate names. rule MakeFlatFilesDist { local bindir = bin.$(EXEC_SUB_TOKENS[1]) ; local pkg = $(1[1]) ; if $(1[2]) { bindir = $(1[1]) ; pkg = $(1[2]) ; } local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ; local dirname = $(pkg)-$(release_info:J=.) ; local exec_dir = [ FSubDirPath P4BIN $(bindir) $(BUILD) ] ; local dest_dir = [ FDirName $(exec_dir) $(dirname) ] ; local dist = $(pkg)-dist ; local _cpflags ; if $(UNIX) { _cpflags = -p ; # to preserve times with cp -p } Depends $(dist) : $(dest_dir) ; MkDir $(dest_dir) ; local _src ; for _src in $(2) { local _dst = $(_src:D=$(dest_dir):G=) ; SEARCH_SOURCE on $(_src) = $(exec_dir) $(SUBDIR) $(AllP4) ; CP on $(_dst) = $(CP) $(_cpflags) ; Depends $(dist) : $(_dst) ; Depends $(_dst) : $(dest_dir) ; File $(_dst) : $(_src) ; } local _ext ; for _ext in tgz zip { local archive = $(pkg).$(_ext) ; LOCATE on $(archive) = $(exec_dir) ; Depends all : $(archive) ; Depends $(archive) : $(dist) ; MkDistArchive $(archive) : $(dest_dir) ; } } rule MakeBrowseDist { local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ; local dirname = browse-$(release_info:J=.) ; local exec_dir = [ FSubDirPath P4BIN bin.tools $(BUILD) ] ; local _f ; if ! $(browse-dist-dir-DONE) { browse-dist-dir-DONE = true ; MakeLocate $(dirname) : $(exec_dir) ; Depends browse-dist : $(dirname) ; local topdir = $(exec_dir) $(dirname) ; # Copy browse benchmarks scripts, documentation, etc., # excluding all Jamfile and Jamrules files. CopyRec browse-dist : $(topdir) : $(AllP4) p4-tools benchmarks browse : Jamfile Jamrules ; # Change permissions on the browse private key so that # it can be successfully used with the user's SSH daemon. _f = [ FDirName $(topdir) browse ] ; MODE on $(_f) = 400 ; Chmod $(_f) ; # Change permissions on the browse JavaScript so that the configuration # defined within can be edited by the user, and change the line-endings # so that it can be easily edited using most Windows utilities. _f = [ FDirName $(topdir) browse.js ] ; MODE on $(_f) = 644 ; Chmod $(_f) ; Unix2Dos $(_f) ; # Change permissions on the browse Bourne shell script so that # the configuration defined within can be edited by the user. _f = [ FDirName $(topdir) browse.sh ] ; MODE on $(_f) = 755 ; Chmod $(_f) ; # Copy browsechild binaries for all platforms on which it was built. for _f in [ FDirEntries $(P4BIN) : bin.* ] { local bindir = [ FDirName $(P4BIN) $(_f) ] ; local prog = [ FDirEntries $(bindir) : browsechild browsechild.exe ] ; local _g ; for _g in $(prog) { CopyRec browse-dist : $(topdir) $(_f) $(_g) : $(bindir) $(_g) ; } } } LOCATE on $(<) = $(exec_dir) ; Depends $(<) : browse-dist ; Depends all : $(<) ; MkDistArchive $(<) : $(dirname) ; } rule MakeP4ObjCdist { local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ; local dirname = p4objc-$(release_info:J=.) ; local exec_dir = [ FSubDirPath P4BIN bin.tools $(BUILD) ] ; MakeLocate $(dirname) : $(exec_dir) ; Depends p4objc-dist : $(dirname) ; local topdir = $(exec_dir) $(dirname) ; CopyRec p4objc-dist : $(topdir) LICENSE.txt : $(AllP4) p4-objc LICENSE.txt ; CopyRec p4objc-dist : $(topdir) api : $(AllP4) p4-objc api ; CopyRec p4objc-dist : $(topdir) doc : $(AllP4) p4-objc doc ; # When we copy images from the sample, we want to exclude # the ones that we override from the watermarked images # directory. So exclude those (and the watermark images # directory itself), then copy the watermarked ones in. local watermark_dir = $(AllP4) p4-objc sample resources images_watermarked ; local watermark_excludes = [ FDirEntries $(watermark_dir) ] ; local all_excludes = build ._build images_watermarked $(watermark_excludes) ; CopyRec p4objc-dist : $(topdir) sample : $(AllP4) p4-objc sample : $(all_excludes) ; # Now copy in the watermarked images local _ent ; for _ent in $(watermark_excludes) { CopyRec p4objc-dist : $(topdir) sample resources images $(_ent) : $(watermark_dir) $(_ent) ; } LOCATE on $(<) = $(exec_dir) ; Depends $(<) : p4objc-dist ; Depends all : $(<) ; MkDistArchive $(<) : $(dirname) ; } rule MakeP4ScoutDist { local kind = $(<) ; local appdir = <$(kind)>P4Scout.app ; local zipfiles = $(kind)-$(appdir:G=).zip $(kind)-$(appdir:G=).dSYM.zip ; local srcdir = $(AllP4) p4-objc sample ; SCOUTSRCDIR on $(appdir) = [ FDirName $(srcdir) ] ; Depends p4scout-dist : p4scout-dist-$(kind) ; Depends p4scout-dist-$(kind) : $(appdir) ; Depends $(appdir) : p4api.tgz ; LOCATE on $(zipfiles) = $(EXEC) ; Depends $(zipfiles) : $(appdir) ; on $(appdir) NOTFILE $(kind) ; P4Scout_xcodebuild $(appdir) : $(kind) ; } rule MakeP4PHPdist { local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ; local dirname = p4php-$(release_info:J=.) ; local exec_dir = [ FSubDirPath P4BIN bin.tools $(BUILD) ] ; local topdir = $(exec_dir) $(dirname) ; MakeLocate $(dirname) : $(exec_dir) ; Depends p4php-dist : $(dirname) ; local excludes = docs [ FDirEntries $(AllP4) p4-php : Jam* *~ ] ; CopyRec p4php-dist : $(topdir) : $(AllP4) p4-php : $(excludes) ; CopyRec p4php-dist : $(topdir) RELNOTES.txt : $(AllP4) p4-doc user p4phpnotes.txt ; CopyRec p4php-dist : $(topdir) Version : $(AllP4) p4 Version ; LOCATE on $(<) = $(exec_dir) ; Depends $(<) : p4php-dist ; Depends all : $(<) ; MkDistArchive $(<) : $(dirname) ; } rule MakeP4DTGdist { local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ; local dirname = p4dtg-$(release_info:J=.) ; local topdir = $(EXEC) $(dirname) ; local bugz_docdir = $(EXEC) $(dirname) doc bugz3mysql5 ; local mysql_docdir = $(EXEC) $(dirname) doc mysql5 ; local redmine_docdir = $(EXEC) $(dirname) doc redminesql5 ; local jira_docdir = $(EXEC) $(dirname) doc jira ; local jira_jardir = $(EXEC) $(dirname) jira ; local dtg_configdir = $(EXEC) $(dirname) config ; MakeLocate $(dirname) : $(EXEC) ; Depends p4dtg-dist : $(dirname) ; CopyRec p4dtg-dist : $(topdir) p4dtg-config : p4dtg-config ; CopyRec p4dtg-dist : $(topdir) p4dtg-test : p4dtg-test ; CopyRec p4dtg-dist : $(topdir) p4dtg-repl : p4dtg-repl ; CopyRec p4dtg-dist : $(topdir) plugins p4jobdt.so : p4jobdt.so ; CopyRec p4dtg-dist : $(topdir) plugins mysql5.so : mysql5.so ; CopyRec p4dtg-dist : $(topdir) plugins bugz3mysql5.so : bugz3mysql5.so ; CopyRec p4dtg-dist : $(topdir) plugins redminemysql5.so : redminemysql5.so ; CopyRec p4dtg-dist : $(topdir) plugins jiradtg.so : jiradtg.so ; CopyRec p4dtg-dist : $(topdir) plugins jirarest.so : jirarest.so ; CopyRec p4dtg-dist : $(topdir) p4dtg-config.png : $(P4DTG) src p4dtg-config p4dtg-config.png ; CopyRec p4dtg-dist : $(topdir) p4dtgnotes.txt : $(AllP4) p4-doc user p4dtgnotes.txt ; CopyRec p4dtg-dist : $(topdir) p4dtg.pdf : $(AllP4) p4-doc manuals p4dtg p4dtg.pdf ; CopyRec p4dtg-dist : $(topdir) help : $(AllP4) p4-doc help p4dtg ; CopyRec p4dtg-dist : $(bugz_docdir) patch.bugzilla-3 : $(P4DTG) sdk bugz patch.bugzilla-3 ; CopyRec p4dtg-dist : $(bugz_docdir) patch.bugzilla-3.4 : $(P4DTG) sdk bugz patch.bugzilla-3.4 ; CopyRec p4dtg-dist : $(bugz_docdir) patch.bugzilla-3.6.2 : $(P4DTG) sdk bugz patch.bugzilla-3.6.2 ; CopyRec p4dtg-dist : $(bugz_docdir) patch.bugzilla-4.0 : $(P4DTG) sdk bugz patch.bugzilla-4.0 ; CopyRec p4dtg-dist : $(bugz_docdir) patch.bugzilla-4.4 : $(P4DTG) sdk bugz patch.bugzilla-4.4 ; CopyRec p4dtg-dist : $(bugz_docdir) README.txt : $(P4DTG) sdk bugz README.txt ; CopyRec p4dtg-dist : $(bugz_docdir) README.p4dti.txt : $(P4DTG) sdk bugz README.p4dti.txt ; CopyRec p4dtg-dist : $(bugz_docdir) mk_dtgdtissue.pl : $(P4DTG) sdk bugz mk_dtgdtissue.pl ; CopyRec p4dtg-dist : $(bugz_docdir) dti_to_dtg.pl : $(P4DTG) sdk bugz dti_to_dtg.pl ; CopyRec p4dtg-dist : $(bugz_docdir) changeid.pl : $(P4DTG) sdk bugz changeid.pl ; CopyRec p4dtg-dist : $(bugz_docdir) jobspec.txt : $(P4DTG) sdk bugz jobspec.txt ; CopyRec p4dtg-dist : $(mysql_docdir) README.txt : $(P4DTG) sdk mysql README.txt ; CopyRec p4dtg-dist : $(mysql_docdir) import.pl : $(P4DTG) sdk mysql import.pl ; CopyRec p4dtg-dist : $(redmine_docdir) README.txt : $(P4DTG) sdk redmine README.txt ; CopyRec p4dtg-dist : $(redmine_docdir) jobspec.txt : $(P4DTG) sdk redmine jobspec.txt ; CopyRec p4dtg-dist : $(jira_docdir) README.txt : $(P4DTG) sdk jira README.txt ; CopyRec p4dtg-dist : $(jira_docdir) README.rest.txt : $(P4DTG) sdk jira-rest README.rest.txt ; CopyRec p4dtg-dist : $(jira_docdir) jobspec.txt : $(P4DTG) sdk jira jobspec.txt ; CopyRec p4dtg-dist : $(jira_jardir) jira-dts.jar : $(P4BIN) bin.java $(BUILD) jira-dts.jar ; CopyRec p4dtg-dist : $(jira_jardir) jira-soapclient-4.1.1-1.jar : $(P4BIN) bin.java $(BUILD) jira-soapclient-4.1.1-1.jar ; CopyRec p4dtg-dist : $(jira_jardir) logging.properties : $(P4DTG) sdk jira jiradts resources logging.properties ; CopyRec p4dtg-dist : $(dtg_configdir) jira-config.xml : $(P4DTG) sdk jira jiradts resources jira-config.xml ; CopyRec p4dtg-dist : $(jira_jardir) jira-rest.jar : $(P4BIN) bin.java $(BUILD) jira-rest.jar ; CopyRec p4dtg-dist : $(jira_jardir) jira-rest-all-dependencies.jar : $(P4DTG) sdk jira-rest java lib jira-rest-all-dependencies.jar ; CopyRec p4dtg-dist : $(jira_jardir) license : $(P4DTG) sdk jira-rest java license ; CopyRec p4dtg-dist : $(jira_jardir) logging-rest.properties : $(P4DTG) sdk jira-rest java resources logging-rest.properties ; CopyRec p4dtg-dist : $(dtg_configdir) jira-rest-config.xml : $(P4DTG) sdk jira-rest java resources jira-rest-config.xml ; local axis_files = axis.jar axis.LICENSE commons-discovery-0.2.jar commons-discovery-0.2.LICENSE commons-logging-1.0.4.jar commons-logging-1.0.4.LICENSE jaxrpc.jar saaj.jar wsdl4j-1.5.1.jar wsdl4j-1.5.1-sources.jar wsdl4j-1.5.1.LICENSE ; local _a ; for _a in $(axis_files) { CopyRec p4dtg-dist : $(jira_jardir) $(_a) : $(AllP4) .. import axis axis-1_4 lib $(_a) ; } local empty_dirs = config repl ; local _d ; for _d in $(empty_dirs) { _d = [ FDirName $(topdir) $(_d) ] ; MkDir $(_d:G=dir) ; Depends p4dtg-dist : $(_d:G=dir) ; } local _strip_bin = p4dtg-config p4dtg-repl p4dtg-test ; local _strip_lib = bugz3mysql5.so p4jobdt.so mysql5.so redminemysql5.so jiradtg.so jirarest.so ; local _f ; for _f in $(_strip_bin) { _f = [ FDirName $(topdir) $(_f) ] ; Strip $(_f) ; } for _f in $(_strip_lib) { _f = [ FDirName $(topdir) plugins $(_f) ] ; STRIP on $(_f) = $(STRIP) -x ; Strip1 $(_f) ; } LOCATE on $(<) = $(EXEC) ; Depends $(<) : p4dtg-dist ; Depends all : $(<) ; MkDistArchive $(<) : $(dirname) ; } actions MkTarArchive { tar -cf $(<) -C $(>:P) $(>:BE)$(>:SE) } actions MkZipArchive { cd $(<:P) $(ZIP) $(<:BE)$(<:SE) $(>:BE)$(>:SE) } actions MkComressedTarArchive { tar -cf - -C $(>:P) $(>:BE)$(>:SE) | $(COMPRESS) > $(<) } actions Unix2Dos { unix2dos -q $(<) ; } rule LinkSmartHeap { if $(SMARTHEAP) != yes { return ; } # short circuit all this switch $(OS)-$(OSVER:E)-$(OSPLAT:E)-$(OSCOMP:E) { case NT-*-X*-* : local _64 = "32" ; local d = "" ; if $(OSPLAT) = X64 { _64 = 64 ; } if $(TYPE_DEBUG) { d = d ; } if $(SMARTHEAP_CHECKS) != 0 || $(MEM_DEBUG) = yes { SMARTHPLIB ?= $(EXEC_LIB)\\shdw$(_64)Mtd.lib ; } else { SMARTHPLIB ?= $(EXEC_LIB)\\shlSMP$(_64)Mt$(d).lib ; } local e = [ FAppendSuffix $(<) : $(SUFEXE) ] ; OnTargetVarPrepend $(e) : LINKLIBS : $(SMARTHPLIB) ; case LINUX-*-X86*-* : local _64 = "" ; if $(OSPLAT) = X86_64 { _64 = 64 ; } SMARTHPLIB ?= $(EXEC_LIB)/libsmartheapC$(_64).a $(EXEC_LIB)/libsmartheap$(_64).a ; OnTargetVarPrepend $(<) : LINKLIBS : $(SMARTHPLIB) ; # Ignore a couple of duplicate symbol definitions in # exception handler code between some of the smartheap 9.01 # objects and libsupc++ (or static libstdc++). # # We aren't using exception handlers anyway, but there is # no other way to work around this problem at link time # without upgrading to gcc 4.1 for our builds; we're still # using gcc 3.4.5. if [ FVersionCmp $(GCCVER) : 4.1 ] < 0 { OnTargetVarAppend $(<) : LINKFLAGS : -Wl,-z,muldefs ; } } } rule LinkSSL { if $(SSL) != yes { return ; } # short circuit all this if $(SSLSTUB) = yes { LinkLibraries $(<) : $(P4SSLLIB) ; return ; } switch $(OS)-$(OSVER:E)-$(OSPLAT:E)-$(OSCOMP:E) { case NT-*-*-* : local _64 dyn d ; switch $(OSPLAT) { case X86_64 : _64 = 64 ; case X64 : _64 = 64 ; case IA64 : _64 = 64 ; } if $(TYPE_DYNAMIC) { dyn = dyn ; } if $(TYPE_DEBUG) { d = d ; } local suflib = $(_64:E=32)$(d:E).lib ; SetDefaultDirName SSLLIBDIR : [ FDirName $(SSLPREFIX) lib.$(EXEC_SUB_TOKENS[1]) vs$(MSVSVER) $(dyn) ] ; SSLLIB ?= [ FDirName $(SSLLIBDIR) libeay$(_64:E=32)$(d:E).lib ] ; CRYPTOLIB ?= [ FDirName $(SSLLIBDIR) ssleay$(_64:E=32)$(d:E).lib ] ; case *-*-*-* : SetDefaultDirName SSLLIBDIR : [ FDirName $(SSLPREFIX) lib.$(EXEC_SUB_TOKENS[1]) ] ; SSLLIB ?= [ FDirName $(SSLLIBDIR) libssl.a ] ; CRYPTOLIB ?= [ FDirName $(SSLLIBDIR) libcrypto.a ] ; } local e = [ FAppendSuffix $(<) : $(SUFEXE) ] ; OnTargetVarPrepend $(e) : LINKLIBS : $(CRYPTOLIB) ; OnTargetVarPrepend $(e) : LINKLIBS : $(SSLLIB) ; } rule LinkLDAP { if $(LDAPSTUB) != no { return ; } # short circuit all this switch $(OS)-$(OSVER:E)-$(OSPLAT:E)-$(OSCOMP:E) { case NT-*-*-* : # We use the Windows SDK on NT. LDAPLIB ?= Wldap32.lib Crypt32.lib ; case *-*-*-* : # Everywhere else we use OpenLDAP. # OpenLDAP is linked against CyrusSASL and OpenSSL if $(SSL) = yes && $(SSLSTUB) != yes { # If we don't have OpenSSL, this will fail! LDAPLIB ?= $(OPENLDAPLIBDIR)/libldap.a $(OPENLDAPLIBDIR)/liblber.a $(CYRUSSASLPLIBDIR)/libsasl2.a ; } } local e = [ FAppendSuffix $(<) : $(SUFEXE) ] ; OnTargetVarPrepend $(e) : LINKLIBS : $(LDAPLIB) ; } ################################################# # # Section 6. Perforce-special Windows rules. # ################################################# # # Special p4-win/scc/p4-exp rules: # # 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 # EXP64MIDL file : file ; - compile .idl file for 64 bit Windows # 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 # WinResIdent *.rc ; - set special defines for build identification # rule P4RPTCLILinkage { local _lf = /subsystem:console ; switch $(TYPE_DEBUG) { case true : _lf += /DEBUG ; case * : _lf += /MAP ; } _lf += /INCREMENTAL:NO ; _lf += /NODEFAULTLIB:"libcmt" ; _lf += /NODEFAULTLIB:"libc" ; 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 ws2_32.lib winmm.lib odbc32.lib odbccp32.lib $(2) ; } rule P4GTLinkage { local _lf = /subsystem:windows /DLL /INCREMENTAL:NO /MACHINE:$(OSPLAT:L) ; if $(TYPE_DEBUG) { _lf += /DEBUG ; } else { _lf += /MAP ; } if $(TYPE_DYNAMIC) { _lf += /NODEFAULTLIB:"libcmt" /NODEFAULTLIB:"libc" ; } OnTargetVarAppend $(<) : LINKFLAGS : $(_lf) ; local _x64 ; if $(OSPLAT) = X64 { _x64 = _x64 ; } OnTargetVarAppend $(<) : LINKLIBS : $(P4GT)/htmlhelp/htmlhelp$(_x64:E).lib gdi32.lib comctl32.lib shlwapi.lib user32.lib version.lib shell32.lib advapi32.lib oldnames.lib kernel32.lib ws2_32.lib winmm.lib odbc32.lib odbccp32.lib $(>) ; LinkSSL $(<) ; } rule P4GTDefines { if [ FVersionCmp $(MSVSVER) : 8 ] >= 0 { SubDirC++Flags /Zc:wchar_t- ; WinDefines /GR : _USRDLL _WINDLL NT_PLUGIN ; } else { WinDefines /GR /GX : _USRDLL _WINDLL NT_PLUGIN ; } if ! $(TYPE_DYNAMIC) { SubDirC++Flags /D_STATIC_CPPLIB ; } # # Setting environment variable "LANG=ja" triggers Japanese # localized P4GT builds only. # if $(LANG) { SubDirC++Flags /DLANG_$(LANG) ; } } rule P4EXPDefines { local u = ; if $(OSVER) != 98 && ! $(NOUNICODE) { u += [ FDefines UNICODE _UNICODE ] ; } WinDefines /Ob1 /EHa $(u) : _UNICODE _ATL_STATIC_REGISTRY _USRDLL _WINDLL ; } rule P4EXPDOTH { DEPENDS $(<) : $(>) ; Clean clean : $(<) ; } rule P4EXPDOTHDEPENDS { DEPENDS $(<) : $(>) ; } rule P4EXPMIDL { DEPENDS $(<) : $(>) ; switch $(OSPLAT) { case X64 : EXP64MIDL $(<) : $(>) ; case * : EXPMIDL $(<) : $(>) ; } Clean clean : $(<) p4exp.tlb dlldata.c p4exp_p.c ; } actions EXPMIDL { midl /env win32 /Oicf /tlb ".\p4exp.tlb" /h "p4exp.h" /iid $(<) $(>) } actions EXP64MIDL { midl /env x64 /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 ; case X64 : _lf += /MACHINE:X64 ; } LINKFLAGS on $(<) = $(LINKFLAGS) $(_lf) ; LINKLIBS on $(<) = gdi32.lib comctl32.lib shlwapi.lib user32.lib version.lib shell32.lib advapi32.lib oldnames.lib kernel32.lib ws2_32.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 ; if $(TYPE_DEBUG) = true { u += /Zi ; } WinDefines $(u) : STRICT ; } rule P4WinDiffDefines { WinDefines /GR /GX : P4DIFF ; } rule WinDefines { SubDirC++Flags /W3 $(1) [ FDefines NDEBUG _WINDOWS $(2) ] ; switch $(OSPLAT) { case X64 : SubDirC++Flags [ FDefines WIN64 ] ; case * : SubDirC++Flags [ FDefines WIN32 ] ; } if $(TYPE_DYNAMIC) { SubDirC++Flags [ FDefines _AFXDLL ] ; } } rule WinDllDeffile { # WinDllDeffile exe : file ; - set /def: file for link SEARCH on $(>) = $(SEARCH_SOURCE) ; DEFFILE on $(<) = $(>) ; DEPENDS $(<) : $(>) ; } rule WinDllLinkage { # WinDllLinkage exe : libs ; - set up link flags windows DLL WinLinkage $(<) : $(>) ; LINKFLAGS on $(<) += /dll ; } rule WinDllNoMainLinkage { # WinDllNoMain exe ; LINKFLAGS on $(<) += /NOENTRY /SUBSYSTEM:WINDOWS /DLL ; switch $(OSPLAT) { case X64 : LINKFLAGS on $(<) += /MACHINE:X64 ; case * : LINKFLAGS on $(<) += /MACHINE:I386 ; } 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) $(RCSTDHDRS) ] ; switch $(OSPLAT) { case X86 : RCFLAGS on $(r) += /d _WIN32 ; case X64 : RCFLAGS on $(r) += /d _WIN64 ; } WinRc $(r) : $(s) ; MakeLocate $(r) : $(LOCATE_SOURCE) ; Clean clean : $(r) ; } rule WinResIdent { # WinResIdent *.rc ; local s r p v ; s = [ FGristSourceFiles $(<) ] ; r = $(s:S=.res:G=) ; # If RELEASE=2005.1 and PATCHLEVEL=69929 then # P4_FILE_VERSION = 2005.1.6.9929 # P4_PRODUCT_VERSION = 2005.1 p = [ Match (.*)(....) : $(PATCHLEVEL) ] ; v = $(RELEASE[1]).$(RELEASE[2]).$(p:J=.) $(RELEASE[3]) ; rule Fconcat { return $(<:J) ; } RCFLAGS on $(r) += [ FDefines [ Fconcat P4_INT_MAJOR= $(RELEASE[1]) ] [ Fconcat P4_INT_MINOR= $(RELEASE[2]) ] [ Fconcat P4_INT_HBUILD= $(p[1]) ] [ Fconcat P4_INT_LBUILD= $(p[2]) ] [ Fconcat P4_FILE_VERSION= [ FQuote $(v[1]) ] ] [ Fconcat P4_PRODUCT_VERSION= [ FQuote $(v:J=.) ] ] [ Fconcat P4_COPYRIGHT= [ FQuote $(RELEASE[1]) ] ] ] ; # Source file includes Version Includes $(s) : Version ; } actions WinRc { rc /fo $(<) $(RCFLAGS) "$(RCHDRS)" $(>) } ################################################# # # Section 7. QT build rules and actions. # ################################################# # # QtDefines ; - Add defines/headers for building with QT # QtFormLibrary lib : *.ui ; make .h's and archive .obj's # QtHeaders ts : headers ; - list headers for i18n xlation # QtLibrary lib : ts : files ; - Library call with lupdate # QtLinkage exe : opt ; - linkflags/libs for building with QT # QtConsoleLinkage exe ; - QtLinkage for a console app on NT # QtLrelease qm : ts ; - build qm from ts files with lrelease # QtMoc x.cpp : x.h ; - preprocess with moc # QtMocLibrary lib : *.h ; - moc, compile, & archive # QtResource qrc : mod : pngs ; - name pngs to make resource # QtResourceCpp cpp : qrc ; - build .cpp from resource file # QtUicCpp x.cpp : x.ui x.h ; - preprocess with uic to make .cpp # QtUicHdr x.h : x.ui ; - preprocess with uic to make .h # QtLanguages = ja en ; rule QtHeaders { # QtHeaders ts : headers ; - list headers for lupdate # This just stashes the named headers in the QTLUPHDRS # variable, used by QtLupdate1 to generate the translation # files. # We give the headers a separate grist, so that we don't # confuse their other uses (just in case we mess up here). QtLupdate $(<) : h : $(>:G=QTLHDR) ; } rule QtLibrary { # QtLibrary lib : ts : files ; - Library call with lupdate Library $(1) : $(3) ; QtLupdate $(2) : s : [ FGristSourceFiles $(3) ] ; } rule QtLrelease { # QtLrelease qm : ts ; for _i in $(QtLanguages) { QtLreleaseRun $(1)_$(_i).qm : $(2)_$(_i).ts ; } LOCATE on $(_qm) = $(LOCATE_TARGET) ; } rule QtLreleaseRun { # QtLreleaseRun qm : ts ; NotFile lrelease ; Depends lrelease : $(1) ; Depends $(1) : $(2) ; Clean clean : $(1) ; LOCATE on $(1) = $(LOCATE_TARGET) ; } actions QtLreleaseRun { $(QTLREL) $(>) -qm $(<) } rule QtLupdate { # QtLupdate ts : h/s : files ; - Add sources/hdrs to lupdate # This rule is complicated, and here's why. # # TrollTech's lupdate command uses a .pro file to declare the name # and location of the .ts, source, and header files to be # processed. Unfortunately, rather than computing the location of # these files relative to the current working directory, they are # determined relative to the location of the .pro file! # # The naive solution would be to write the .pro files out to the # current working directory, but that means parallel builds on # different platforms using a shared workspace can clobber each other. # # Writing the .pro files out to the build output directory is # pretty much impossible to do right, because Jam offers no way to # compute the relative path to a source file from any other # arbitrary location; you can only compute it from the current # working directory. Thus, you might be able to finagle "jam # lupdate" to work from p4-bin, but then it would blow up if you # tried to run it from p4-qt. # # To avoid the platform-clobbering race, we create a temporary # directory in the current working directory, wherever that is, # write the .pro files there, and fix up the file paths using a # now-known relative prefix ("..") from cwd. The .pro files are # then deleted and you wind up with an empty temporary directory. # There might be some clever way to remove that that I don't know # about, but it's a harmless artifact. # # If LUPDATE_MERGE is set, the .ts files are written to the # merged_lupdate.<platform> directory instead of the bin.<platform> # directory, and obsolete entries are retained. These are the # versions of the files that should be checked back into # p4-qt/translations when they are to be permanently updated. local tmpdir = tmp_lupdate.$(EXEC_SUB_TOKENS[1]) ; if $(LUPDATE_MERGE) { tmpdir = merged_lupdate.$(EXEC_SUB_TOKENS[1]) ; } local cwdrel = ..$(SLASH) ; NotFile $(cwdrel) ; for lang in $(QtLanguages) { # add grist to distinguish source .ts file from the copy of it # in target dir local _ts = $(1)_$(lang).ts ; local _tss = $(_ts:G=SRC) ; SEARCH on $(_tss) = [ FSubDirPath P4QT translations ] [ FSubDirPath P4SCC translations ] ; local _pro = $(1)_$(lang).pro ; local _proh = $(1)_h_$(lang).pro ; local _pros = $(1)_s_$(lang).pro ; local _prox = $(1)_$(2)_$(lang).pro ; on $(_ts) if ! $(Done) { Done on $(_ts) = true ; # .ts -> .pro -> s.pro (QtLupTmp)-> sources # -> h.pro (QtLupTmp)-> headers # -> .ts from source tree, aka _tss NotFile lupdate ; Depends lupdate : $(_ts) ; Depends $(_ts) : $(_pro) ; Depends $(_pro) : $(_proh) $(_pros) ; Depends $(_proh) $(_pros) : $(_tss) ; Clean clean : $(_ts) ; if $(LUPDATE_MERGE) { LOCATE on $(_ts) = $(tmpdir) ; } else { LOCATE on $(_ts) = $(LOCATE_TARGET) ; } MakeLocate $(_proh) $(_pros) $(_pro) : $(tmpdir) ; QTLTRANS on $(_pro) = $(_ts) ; # Copy translated ts files from source tree # Update ts files using pro file, headers/sources # Build pro file from list of headers/sources # lupdate reads and writes the same .ts file # we keep any translations in .ts files in the source tree # but need to copy them into the target dir for lupdate to # be able to update them # it is a manual step not involving jam to copy them back # to the source tree # source .ts file may not be present; that's ok because # lupdate will create one NOCARE $(_tss) ; # Zero h.pro/s.pro files to begin with QtLupTmp0 $(_proh) ; QtLupTmp0 $(_pros) ; QtLupdatePro $(_pro) $(cwdrel) : $(_proh) $(_pros) ; QtLupdateRun $(_ts) : $(_tss) $(_pro) ; # Zonk pro files when done RmTemps $(_ts) : $(_pro) ; RmTemps $(_pro) : $(_proh) $(_pros) ; } SEARCH on $(3) = $(SEARCH_SOURCE) ; Depends $(_prox) : $(3) ; QtLupTmp1 $(_prox) $(cwdrel) : $(3) ; } } # QtLupdatePro pro cwdrel : hpro spro ; # If set, cwdrel is extra path from cwd needed to instruct lupdate # where the sources really are relative to the pro file, because # lupdate searches for files relative to the location of the pro file, # not cwd. if $(NT) { actions quietly together piecemeal QtLupTmp1 { echo $(<[2]:E)$(>) \ >> $(<[1]) } actions quietly QtLupTmp0 { copy nul: $(<) } actions quietly QtLupdatePro bind QTLTRANS { echo TRANSLATIONS = $(<[2]:E)$(QTLTRANS) > $(<[1]) echo HEADERS = \ >> $(<[1]) type $(>[1]) >> $(<[1]) echo. >> $(<[1]) echo SOURCES = \ >> $(<[1]) type $(>[2]) >> $(<[1]) echo. >> $(<[1]) } } else { actions quietly together piecemeal QtLupTmp1 { echo $(<[2]:E)$(>) \\ >> $(<[1]) } # Zero out the file if it already exists, or create it. This way # the commands in QtLupdatePro will not print errors for files that # don't exist because there are e.g. no h files to write to it. actions quietly QtLupTmp0 { : > $(<) } actions quietly QtLupdatePro bind QTLTRANS { echo TRANSLATIONS = $(<[2]:E)$(QTLTRANS) > $(<[1]) echo HEADERS = \\ >> $(<[1]) cat $(>[1]) >> $(<[1]) echo "" >> $(<[1]) echo SOURCES = \\ >> $(<[1]) cat $(>[2]) >> $(<[1]) echo "" >> $(<[1]) } } # QtLupdateRun ts : tss pro ; # copy the source .ts file (tss) into the output directory (ts) # and make sure it's writable, then run lupdate on the pro file (pro) # to extracted strings from the .cpp/.h files and update the ts # file (ts) with newly found strings if $(CHMOD) { actions QtLupdateRun { $(CP) $(>[1]) $(<[1]) $(CHMOD) +w $(<[1]) $(QTLUP) $(>[2]) } } else { actions QtLupdateRun { $(CP) $(>[1]) $(<[1]) $(QTLUP) $(>[2]) } } rule QtBaseDefines { # QtDefines ; - Add defines/headers for building with QT BoostDefines p4-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 ; } if $(JAMBASEDATE) < 2005.05.05 && ! $(QT25WARN) { Echo QT builds work poorly without Jambase 2005.05.05 ; QT25WARN = true ; } QTLUP = [ FDirName $(QTDIR) bin lupdate ] ; QTLREL = [ FDirName $(QTDIR) bin lrelease ] ; QTMOC = [ FDirName $(QTDIR) bin moc ] ; QTUIC = [ FDirName $(QTDIR) bin uic ] ; QEMBED = [ FDirName $(QTDIR) bin qembed ] ; if ! $(LUPDATE_MERGE) && ( $(LUPDATE_NO_OBSOLETE) || $(PRODUCTION) ) { # lrelease has a "bug" whereby if entries in one ts file are # marked obsolete but are active in another ts file (because # keys were moved, say) then lrelease may drop duplicates # *favoring the obsolete entries*, which it then doesn't # include in the .qm file. (The order of preference depends on # the order of files on the command line.) So for production # builds, we strip the obsolete entries for the tmp ts files. # # The default is to keep the obsolete entries because we don't # always want to throw them away; they are useful for the # linquist tool and when we check in merged ts files we should # usually save them. QTLUP += -no-obsolete ; } local _d _f ; _d += QT_NO_STL ; _d += QT_THREAD_SUPPORT ; _d += QT_NO_CAST_TO_ASCII ; _d += QT_NO_CAST_FROM_ASCII ; _d += QT_STATICPLUGIN ; if $(QTOPENGL) = no { _d += NO_OPENGL ; } 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 += /EHsc /GR /W4 ; _f += /wd4127 ; # conditional expression is constant _f += /wd4512 ; # assignment operator could not be generated # from Qt's Makefile # but we want stricter warnings and don't use precompiled headers # _f += /Zm200 /W3 ; if [ FVersionCmp $(MSVSVER) : 8 ] >= 0 { # VS8 treats wchar_t as a builtin type by default # while prior version use a typedef _f += /Zc:wchar_t- ; } if $(TYPE_DEBUG) { # enable runtime checks for debug builds only # this isn't compatible with optimizations _f += /RTCcsu ; if $(VLD) { _d += VLD ; } } case MACOSX : if $(TYPE_DEBUG) && ! $(TEST) { # Crank up the warnings. _f += -Wall -Wextra -Wformat -Woverloaded-virtual -Wno-shadow -Wno-system-headers -Wunknown-pragmas -Wno-unreachable-code -Wnon-virtual-dtor -Wextra-tokens ; } } SubDirC++Flags [ FDefines $(_d) ] $(_f) ; } rule QtCoreHeaders { QtAllHeaders : QtCore ; } # If a list of ": modules ..." is specified, just add those directories # into the search list. Otherwise, a default list is generated. rule QtAllHeaders { local QtModules = $(2) ; if ! $(QtModules) { QtModules = QtCore QtGui QtAssistant QtNetwork QtWebKit QtXml QtXmlPatterns ; } if $(OS) = NT || ( $(OS) = MACOSX && $(OSPLAT:U) = X86 ) { QtModules += phonon ; } if $(QTOPENGL) != no { QtModules += QtOpenGL ; } for module in $(QtModules) { local includeModule = [ FDirName $(QTDIR) include $(module) ] ; SubDirC++Flags -I$(includeModule) ; #SubDirHdrs [ FDirName $(QTDIR) include $(module) ] ; # Also search the framework directories so that # non-module-qualified #include <QFoo> directives # work even when headers are not installed in # QTDIR/include/qtmodule. if $(OS) = MACOSX && ! $(QT_NO_FRAMEWORK_INCLUDES) { local includeModule = [ FDirName $(QTDIR) lib $(module).framework Headers ] ; SubDirC++Flags -I$(includeModule) ; #SubDirHdrs [ FDirName $(QTDIR) lib $(module).framework Headers ] ; } } local include = [ FDirName $(QTDIR) include ] ; SubDirC++Flags -I$(include) ; #SubDirHdrs [ FDirName $(QTDIR) include ] ; SubDirHdrs [ FDirName $(LOCATE_SOURCE[1]) qt-ui ] ; if $(OS) = FREEBSD { SubDirHdrs /usr/X11R6/include ; } if $(OS) = NT && $(TYPE_DEBUG) && $(VLD) { SubDirHdrs $(VLD)/include ; } } rule QtDefines { # QtDefines ; - Add defines/headers for building with QT # Adds headers for all Qt modules if $(MSVSVER) = 8 && $(WindowsSdkDir) { # Include vista SDK directory for vs2005 # This should only be done for Qt products. # Prior to adding the SDK dir, make sure the API # includes defined at the top of this Jamrules are # inserted. Otherwise we may pick up the wrong # error.h. local _h ; for _h in $(HDRS) { SubDirHdrs $(_h) ; } SubDirHdrs $(WindowsSdkDir:J=" ")/include ; } QtBaseDefines $(1) ; QtAllHeaders $(1) ; } rule QtCoreDefines { # QtCoreDefines ; - Add defines/headers for building with QT # Adds headers for QtCore only; no QtGui or other rot if $(MSVSVER) = 8 && $(WindowsSdkDir) { # Include vista SDK directory for vs2005 # This should only be done for Qt products. # Prior to adding the SDK dir, make sure the API # includes defined at the top of this Jamrules are # inserted. Otherwise we may pick up the wrong # error.h. local _h ; for _h in $(HDRS) { SubDirHdrs $(_h) ; } SubDirHdrs $(WindowsSdkDir:J=" ")/include ; } QtBaseDefines ; QtCoreHeaders ; } rule QtLinkage { # QtLinkage exe : opt : qtlibs : rpath ; - linkflags/libs for building with QT local _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; local _opt = $(2) ; # Executable-local rpaths are only supported by the dynamic # linker/loader on solaris and linux so far. MacOSX also supports # them but the syntax and mechanism is different; see MacP4VdyldFixup. # # Please don't use this parameter for absolute paths; it should be # for paths relative to the executable, wherever it is run, a la # the linux/solaris $ORIGIN token. # # Use the literal token "NULL" for rpath arg if you want to supress # any dynamic rpath. local _rpath = $(4) ; if $(_rpath) = "" { _rpath = $ORIGIN/../lib/p4v/qt4/lib ; } # The order here is significant when linking statically. # # The STATIC variable is a list of additional library dependencies # which the static Qt libraries have. They don't need to be # enumerated when doing shared builds because the shared libraries # already have their library dependencies enumerated in the shared # object files and the linker picks these up automatically. For # static libraries there is no such facility. local QT4LIBLIST ; local QT4LIBLIST_STATIC ; if $(3) { # If a Qt library list is specified in the 3rd # parameter to this rule, we use those and only # those libraries. QT4LIBLIST = $(3) ; } else { # otherwise, we use a library list customized for p4v. if $(TEST) # unit testing { QT4LIBLIST += QtTest ; } if $(QTOPENGL) != no { QT4LIBLIST += QtOpenGL ; # $(UNIX) is set even for osx, but we must exclude macs here. if $(UNIX) && $(OS) != MACOSX && ! $(TYPE_DYNAMIC) { QT4LIBLIST_STATIC += GL ; } } QT4LIBLIST += QtXml QtXmlPatterns QtNetwork QtGui QtWebKit QtCore ; } switch $(OS) { # We don't want to embed rpath entries for QTDIR/lib in # production builds because they are not located in a # standard system directory (unlike e.g. /usr/X11R6/lib). # Doing so results in unnecessary stat calls on customer # filesystems that may even cause network timeouts. We # link Qt statically in unix production builds. # # Please don't add X libraries here in order to satisfy # dependencies in development builds of Qt. The libraries # listed here are the dependencies required for production # builds; adding more dynamic linker dependencies # decreases portability. # # If you are working with QT shared libraries in a # development environment, there are 3 alternatives: # 1. set LD_LIBRARY_PATH # 2. edit your system ld.so.conf # 3. use the dev_LINKFLAGS and dev_LINKLIBS hooks: # jam -sdev_LINKFLAGS="..." -sdev_LINKLIBS="..." case FREEBSD : if ! $(TYPE_DYNAMIC) { QT4LIBLIST_STATIC += Xrender Xrandr Xcursor fontconfig SM Xfixes X11 m ; } OnTargetVarPrepend $(_t) : LINKFLAGS : # -Wl,-rpath,$(QTDIR)/lib -L$(QTDIR)/lib -L/usr/X11R6/lib ; OnTargetVarPrepend $(_t) : LINKLIBS : -l$(QT4LIBLIST)$(QT_LIBINFIX:E) -l$(QT4LIBLIST_STATIC) -pthread /usr/local/lib/libiconv.a ; OnTargetVarDelete $(_t) : LINKLIBS : -lsupc++ ; OnTargetVarAppend $(_t) : LINKLIBS : -lstdc++ ; LINKFLAGS on $(_t) += $(dev_LINKFLAGS) ; LINKLIBS on $(_t) += $(dev_LINKLIBS) ; case SOLARIS : if $(TYPE_DYNAMIC) { local flags = -Wl,-R,/usr/sfw/lib ; if $(_rpath) != "NULL" { flags = -Wl,-R,'$(_rpath)' $(flags) ; } OnTargetVarPrepend $(_t) : LINKFLAGS : $(flags) ; } if ! $(TYPE_DYNAMIC) { # These libraries must be enumerated explicitly because our # static production Qt libs depend on them. QT4LIBLIST_STATIC += ICE SM Xrender Xfixes Xext fontconfig freetype X11 rt ; } OnTargetVarPrepend $(_t) : LINKFLAGS : -L$(QTDIR)/lib -L/usr/X11R6/lib -L/usr/openwin/lib -L/usr/sfw/lib -L/opt/lude/lib ; OnTargetVarPrepend $(_t) : LINKLIBS : -l$(QT4LIBLIST)$(QT_LIBINFIX:E) -l$(QT4LIBLIST_STATIC) -lm -lpthread -lrt ; OnTargetVarDelete $(_t) : LINKLIBS : -lsupc++ ; OnTargetVarAppend $(_t) : LINKLIBS : -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic ; LINKFLAGS on $(_t) += $(dev_LINKFLAGS) ; LINKLIBS on $(_t) += $(dev_LINKLIBS) ; case LINUX : if $(TYPE_DYNAMIC) && $(_rpath) != "NULL" { OnTargetVarPrepend $(_t) : LINKFLAGS : -Wl,-rpath,'$(_rpath)' ; } if ! $(TYPE_DYNAMIC) { # These libraries must be enumerated explicitly because our # static production Qt libs depend on them. QT4LIBLIST_STATIC += Xrender Xrandr Xcursor fontconfig ICE SM X11 Xext m rt dl ; } local _64 = "" ; if $(OSPLAT) = X86_64 { _64 = 64 ; } OnTargetVarPrepend $(_t) : LINKFLAGS : -L$(QTDIR)/lib -L/usr/X11R6/lib$(_64) ; OnTargetVarPrepend $(_t) : LINKLIBS : -l$(QT4LIBLIST)$(QT_LIBINFIX:E) -l$(QT4LIBLIST_STATIC) -pthread ; OnTargetVarDelete $(_t) : LINKLIBS : -lsupc++ ; OnTargetVarAppend $(_t) : LINKLIBS : -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic ; LINKFLAGS on $(_t) += $(dev_LINKFLAGS) ; LINKLIBS on $(_t) += $(dev_LINKLIBS) ; case MACOSX : # QtWebKit 4.5.0 and later depend on this framework. if ! $(3) && $(OSPLAT:U) = X86 { QT4LIBLIST += phonon ; } OnTargetVarAppend $(_t) : LINKFLAGS : # comment out -prebind flag, because Qt is # not built prebound #-prebind -L$(QTDIR)/lib # look here for normal libs -F$(QTDIR)/lib # ...for structured frameworks too # This (dynamic) library is listed here so that it appears # before any other objects and specifically before # libsupp.a, to avoid symbol name collisions. libz is # needed for the QuickTime framework. -lz ; if $(OSPLAT:U) = X86 { OnTargetVarAppend $(_t) : LINKLIBS : -framework QuickTime ; } OnTargetVarAppend $(_t) : LINKLIBS : # This is already on the global LINKLIBS #-framework ApplicationServices ; #-framework Foundation ; -framework OpenGL -framework AGL -framework AppKit ; # If you want to link with Qt4 as frameworks on mac, # use -sTYPE=dyn or dyng. Otherwise you get a static # (or unix-style dynamic but non-frameworks) link. if $(TYPE_DYNAMIC) { # This pads the executable header so that # we can later change dynamic shared # library paths recorded in the output file. # (See MacP4VdyldFixup action.) LINKFLAGS on $(_t) += -Wl,-headerpad_max_install_names ; for _frmwk in $(QT4LIBLIST)$(QT_LIBINFIX:E) { LINKLIBS on $(_t) += -framework $(_frmwk) ; } } else { # These libraries must be enumerated explicitly because our # static production Qt libs depend on them. QT4LIBLIST_STATIC += iconv ssl crypto ; LINKLIBS on $(_t) += -l$(QT4LIBLIST)$(QT_LIBINFIX:E) -l$(QT4LIBLIST_STATIC) ; } LINKFLAGS on $(_t) += $(dev_LINKFLAGS) ; LINKLIBS on $(_t) += $(dev_LINKLIBS) ; if $(_opt) != "console" { QtMacPackage $(<) ; } case NT : if ! $(3) { QT4LIBLIST += phonon ; } # warn about non-dynamic builds on NT if ! $(TYPE_DYNAMIC) && ! $(QTWARNED) { echo Warning: you usually want jam -sTYPE=dyn for QT on NT. ; QTWARNED = 1 ; } # no dos box unless debug if $(_opt) = "console" { OnTargetVarAppend $(_t) : LINKFLAGS : /subsystem:console ; } else if ! $(TYPE_DEBUG) { OnTargetVarAppend $(_t) : LINKFLAGS : /subsystem:windows ; } local d = "" ; if $(TYPE_DEBUG) { d = d ; } # We use QT_LIBINFIX=P4 for our production builds, but in Qt # 4.5 and earlier, qtmain doesn't get the infix string. In Qt # 4.6 and later, it does. Since we don't want to have to # "know" this (or parse the value of QTDIR to figure it out), # we just check the filesystem to see which one is there. # # Currently (as of p10.1) we are building DTG with a 4.5.x # version of Qt and the P4V family with Qt 4.6.x, so this # infix variability comes into play. local qtmain = [ FDirEntries $(QTDIR) lib : qtmain$(QT_LIBINFIX:E)$(d).lib qtmain$(d).lib ] ; OnTargetVarAppend $(_t) : LINKLIBS : [ FDirName $(QTDIR) lib $(qtmain[1]) ] ; for _lib in $(QT4LIBLIST)$(QT_LIBINFIX:E) { LINKLIBS on $(_t) += [ FDirName $(QTDIR) lib $(_lib)$(d)4.lib ] ; } LINKLIBS on $(_t) += advapi32.lib # for qtree user32.lib gdi32.lib comdlg32.lib ole32.lib oleaut32.lib shell32.lib uuid.lib imm32.lib winmm.lib ws2_32.lib winspool.lib version.lib ; if $(TYPE_DEBUG) && $(VLD) { LINKLIBS on $(_t) += $(VLD)/lib/vld.lib ; } case * : Exit Don't know how to link QT executables on $(OS). ; } } rule QtConsoleLinkage { # QtConsoleLinkage exe ; - QtLinkage for a console app on NT QtLinkage $(<) : console ; } rule QtDllLinkage { # QtLinkage exe ; - linkflags/libs for building with QT local QT4LIBLIST ; QT4LIBLIST += QtXml QtOpenGL QtNetwork QtGui QtCore ; if $(OS) = NT || ( $(OS) = MACOSX && $(OSPLAT:U) = X86) ) { QT4LIBLIST += phonon ; } # WebKit not built for static DLL on Windows if $(TYPE_DYNAMIC) && $(OS) = NT { QT4LIBLIST += QtWebKit ; } switch $(OS) { case NT : # warn about non-dynamic builds on NT if ! $(TYPE_DYNAMIC) && ! $(QTWARNED) { echo Warning: you usually want jam -sTYPE=dyn for QT on NT. ; QTWARNED = 1 ; } OnTargetVarAppend $(<) : LINKFLAGS : /DLL ; on $(<) echo Warning: you are building a dll with LINKFLAGS "=" $(LINKFLAGS) ; # no dos box unless debug if ! $(TYPE_DEBUG) { LINKFLAGS on $(<) += /subsystem:windows ; } # advertise symbols available if $(TYPE_DEBUG) && [ FVersionCmp $(MSVSVER) : 9 ] >= 0 { LINKFLAGS on $(<) += /ASSEMBLYDEBUG ; } local d = "" ; if $(TYPE_DEBUG) { d = d ; } local n = "" ; if $(TYPE_DYNAMIC) { n = 4 ; } # We use QT_LIBINFIX=P4 for our production builds, but in Qt # 4.5 and earlier, qtmain doesn't get the infix string. In Qt # 4.6 and later, it does. Since we don't want to have to # "know" this (or parse the value of QTDIR to figure it out), # we just check the filesystem to see which one is there. # # Currently (as of p10.1) we are building SCC with a 4.5.x # version of Qt and the P4V family with Qt 4.6.x, so this # infix variability comes into play. local qtmain = [ FDirEntries $(QTDIR) lib : qtmain$(QT_LIBINFIX:E)$(d).lib qtmain$(d).lib ] ; # n.b. discarding global LINKLIBS; we specify all the libs we need here. LINKLIBS on $(<) = [ FDirName $(QTDIR) lib $(qtmain[1]) ] ; for _lib in $(QT4LIBLIST)$(QT_LIBINFIX:E) { LINKLIBS on $(<) += [ FDirName $(QTDIR) lib $(_lib)$(d)$(n).lib ] ; } LINKLIBS on $(<) += advapi32.lib # for qtree user32.lib gdi32.lib comdlg32.lib ole32.lib oleaut32.lib shell32.lib uuid.lib imm32.lib winmm.lib ws2_32.lib winspool.lib shlwapi.lib version.lib ; if ! $(TYPE_DYNAMIC) { LINKLIBS on $(<) += opengl32.lib ; # for static QtOpenGL.lib } if $(TYPE_DEBUG) && $(VLD) { echo addding vld ; LINKLIBS on $(<) += $(VLD)/lib/vld.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 ] ; MacCreatorCode <$(<)>Info.plist : $(<) ; QtMacPackageInfo <$(<)>PkgInfo ; QMS on <$(<)>PkgInfo = [ MacCreatorCode $(<) ] ; QtMacPlist <$(<)>Info.plist : $(<) ; } actions QtMacPackageInfo { echo "APPL$(QMS)" > $(<) } rule QtMacIcons { File <$(<)>application.icns : $(>) ; } rule QtMacPlist { local osid = $(OS)$(OSVER:E)$(OSPLAT:E) ; Depends files : $(<) ; # Add the standard items to the Info.plist file # QtMacAddPListItem $(>) : CFBundleExecutable : $(>) ; QtMacAddPListItem $(>) : CFBundlePackageType : "APPL" ; QtMacAddPListItem $(>) : CFBundleShortVersionString : $(RELEASE:J=.) ; QtMacAddPListItem $(>) : CFBundleVersion : $(RELEASE:J=.)/$(PATCHLEVEL)$(SPECIAL:E) ; QtMacAddPListItem $(>) : CFBundleGetInfoString : "$(RELEASE:J=.), Copyright $(SUPPDATE[1]) Perforce Software, Inc." ; QtMacAddPListItem $(>) : CFBundleIconFile : application.icns ; QtMacAddPListItem $(>) : P4RevString : "$(>:U)/$(osid[1]:U)/$(RELEASE:J=.)/$(PATCHLEVEL)$(SPECIAL:E) ($(SUPPDATE[1])/$(SUPPDATE[2])/$(SUPPDATE[3]))" ; MODE on $(<) = $(FILEMODE) ; Chmod $(<) ; # This is just for the output hack in the action QtMacPList JOINER_VARIABLE on $(<) = " >> " ; } # Adds a string item to Info.plist # concatenates the XML description to a string which contains the contents # rule QtMacAddPListItem { MAC_PLIST_CONTENTS on <$(<)>Info.plist += " \" <key>$(2)</key>\"" ; MAC_PLIST_CONTENTS on <$(<)>Info.plist += " \" <string>$(3)</string>\"" ; } # Writes out an XML file that conforms to the Info.pllist format # # look at the central line very carefully # the whole thing gets expanded into multiple lines because # there are no spaces in this line. They are made into multiple # permutations of every value in MAC_PLIST_CONTENTS. # each value begins with a space (so there is a space after "echo" # and each one uses the one value in JOINER_VARIABLE so it can # put spaces between current the MAC_PLIST_CONTENTS value, and # the value of the file which it will be appended to # actions QtMacPlist { echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $(<) echo "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" >> $(<) echo "<plist version=\"1.0\">" >> $(<) echo "<dict>" >> $(<) echo$(MAC_PLIST_CONTENTS)$(JOINER_VARIABLE)$(<); echo "</dict>" >> $(<) echo "</plist>" >> $(<) } # 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) = "<include .*>(.*)</include>" ; HDRSEARCH on $(ui) = $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ; QtUicHdr $(h) : $(ui) ; QtUicCpp $(tcpp) : $(ui) $(h) ; QtMoc $(mcpp) : $(h) ; if $(INCREMENTAL_BUILD) != true { RmTemps $(mobj) : $(mcpp) ; RmTemps $(tobj) : $(tcpp) ; } Includes $(mcpp) : $(h) ; Includes $(tcpp) : $(h) ; } } rule QtForms { # QtForms *.ui ; make .h's # For each x.ui file we generate a single header file: # # ui_x.h (uic x.ui) local i ; for i in $(>) { local h = ui_$(i:S=.h) ; local ui = [ FGristSourceFiles $(i) ] ; Depends $(<) : $(h) ; QtUicHdr $(h) : $(ui) ; } } 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)) ; local gh = [ FGristFiles $(h) ] ; QtMoc $(cpp) : $(gh) ; if $(INCREMENTAL_BUILD) != true { RmTemps $(obj) : $(cpp) ; } } } # Source file rules rule FLocalPath { # path1 path2 ... -- turns / into / or \ as needed local r ; for i in $(<) { r = $(r) [ FDirName [ FSplit $(i) ] ] ; } return $(r) ; } rule QrcHdrRule { # Echo $(<) is $(>) ; local t = [ FLocalPath $(>) ] ; Includes $(<) : $(t) ; SEARCH on $(t) = $(HDRSEARCH) ; } actions Qrc { $(QTRCC) -binary -o $(<) $(>) } rule Qrc { # Qrc file.rcc : file.qrc ; MakeLocate $(<) : $(EXEC) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; QTRCC = [ FDirName $(QTDIR) bin rcc ] ; HDRRULE on $(>) = QrcHdrRule ; HDRSCAN on $(>) = "<file.*>(.*)</file>" ; HDRSEARCH on $(>) = $(SEARCH_SOURCE:E) ; Depends all : $(<) ; Depends $(<) : $(>) ; } 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 $(<) : [ FDirName $(LOCATE_SOURCE[1]) qt-moc $(SUBDIR_TOKENS) ] ; } actions QtMoc { $(QTMOC) -DOS_$(OS) -DOS_$(OS)$(OSPLAT:U) $(>) -o $(<) } rule QtHelpGenBuild { # QtHelpGenBuild target.qhc : source.qhp : command : default_target_suffix ; local dst = $(1) ; local src = [ FDirName $(2) ] ; local cmd = $(3) ; local default_suffix = $(4) ; if ! $(dst) { dst = $(src:B) $(default_suffix) ; dst = $(dst:J=".") ; } MakeLocate $(dst) : $(ALL_LOCATE_TARGET) ; Depends all : $(dst) ; Depends $(dst) : $(src) ; Clean clean : $(dst) ; QTHELPBIN on $(dst) = [ FDirName $(QTDIR) bin $(cmd) ] ; QTHELPSRC on $(dst) = $(src) ; QtHelpGenRun $(dst) : $(src) ; } rule QtHelpGen { QtHelpGenBuild $(1) : $(2) : qhelpgenerator : qhc ; } rule QtHelpCollectionGen { QtHelpGenBuild $(1) : $(2) : qcollectiongenerator : qch ; } # LD_LIBRARY_PATH is for unix. # DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH are for OSX. # The trolltech build process does not hardcode these so they need # to go into the environment. # # These help generation programs, at least as of version 4.4.2, # also seem to have a bunch of problems on several platforms # writing over NFS whether or not locking is enabled. So write to # /tmp and then copy back into place. actions QtHelpGenRun { LD_LIBRARY_PATH=$(QTDIR)/lib DYLD_LIBRARY_PATH=$(QTDIR)/lib DYLD_FRAMEWORK_PATH=$(QTDIR)/lib export LD_LIBRARY_PATH DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH $(QTHELPBIN) -o ${TMPDIR-/tmp}/$(<:B)$$ $(QTHELPSRC) && $(CP) ${TMPDIR-/tmp}/$(<:B)$$ $(<) } 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 $(<) : [ FDirName $(LOCATE_SOURCE[1]) qt-ui ] ; } # 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 $(<) : [ FDirName $(LOCATE_SOURCE[1]) qt-ui ] ; } actions QtUicHdr { $(QTUIC) $(>) -o $(<) } rule QtUnitTest { # $(1) = component to build unit test for # the component is defined in $(1).h and $(1).cpp # the unit test is defined in t_$(1).h and t_$(1).cpp # $(2) = list of other components this test depends on # $(3) = list of libraries this test depends on local lib = t_$(1) ; # Need to build component into differently named object file # because Library rule will delete normal object file. # Create unique names that don't conflict with the unit test # files by adding .ut suffix before extension. Object <$(SOURCE_GRIST)>$(1).ut$(SUFOBJ) : <$(SOURCE_GRIST)>$(1).cpp ; QtMoc <$(SOURCE_GRIST)>m$(1).ut.cpp : <$(SOURCE_GRIST)>$(1).h ; Object <$(SOURCE_GRIST)>m$(1).ut$(SUFOBJ) : <$(SOURCE_GRIST)>m$(1).ut.cpp ; LibraryFromObjects t_$(1) : <$(SOURCE_GRIST)>$(1).ut$(SUFOBJ) <$(SOURCE_GRIST)>m$(1).ut$(SUFOBJ) ; # Rebuild any dependencies for same reason. for dep in $(2) { Object <$(SOURCE_GRIST)>$(dep).$(1).ut$(SUFOBJ) : <$(SOURCE_GRIST)>$(dep).cpp ; QtMoc <$(SOURCE_GRIST)>m$(dep).$(1).ut.cpp : <$(SOURCE_GRIST)>$(dep).h ; Object <$(SOURCE_GRIST)>m$(dep).$(1).ut$(SUFOBJ) : <$(SOURCE_GRIST)>m$(dep).$(1).ut.cpp ; LibraryFromObjects t_$(1) : <$(SOURCE_GRIST)>$(dep).$(1).ut$(SUFOBJ) <$(SOURCE_GRIST)>m$(dep).$(1).ut$(SUFOBJ) ; } # Need to compile unit test too since we're forced to use MainFromObjects. # Moc'ed cpp files, and their obj files, end up with mt_ prefix. Object <$(SOURCE_GRIST)>t_$(1)$(SUFOBJ) : <$(SOURCE_GRIST)>t_$(1).cpp ; QtMoc <$(SOURCE_GRIST)>mt_$(1).cpp : <$(SOURCE_GRIST)>t_$(1).h ; Object <$(SOURCE_GRIST)>mt_$(1)$(SUFOBJ) : <$(SOURCE_GRIST)>mt_$(1).cpp ; MainFromObjects $(1) : <$(SOURCE_GRIST)>mt_$(1)$(SUFOBJ) <$(SOURCE_GRIST)>t_$(1)$(SUFOBJ) ; LinkLibraries $(1) : $(lib) $(3) ; QtConsoleLinkage $(1) ; } rule QtUnitTestSuite { for dep in $(2) { local exe = $(dep)$(SUFEXE) ; MakeLocate $(exe) : $(LOCATE_TARGET) ; Depends $(1) : $(exe) ; if $(RUNTESTS) { QtUnitTestCase $(1) : $(exe) ; } } } actions QtUnitTestCase { $(2) } rule P4QtCoreHdrs { SubDirHdrs $(P4QT) core primitives ; SubDirHdrs $(P4QT) core platform ; SubDirHdrs $(P4QT) core prefs ; SubDirHdrs $(P4QT) core util ; } rule P4QtApiHdrs { P4QtCoreHdrs ; SubDirHdrs $(P4QT) p4api agents ; SubDirHdrs $(P4QT) p4api models ; SubDirHdrs $(P4QT) p4api obj ; SubDirHdrs $(P4QT) p4api op ; } rule P4SccCoreHdrs { SubDirHdrs $(P4SCC) p4api include ; SubDirHdrs $(P4SCC) core include ; } ################################################# # # Section 8. Lua build rules and actions. # ################################################# # Rule to deal with Lua generated files and tool dependencies for # P4-Report. Note that there are cases where parallel builds will # fail. For example, if you make a clean build, edit scripts/file.lua, # then re-build, you'll still have old p4-bin/file.lb results, so # bin2c and luac might finish after or during the C++ compile. # # This problem only applies to incremental builds. If production # builds are from-scratch, then they should be safe. rule P4ReportDEPENDS { # Make sure we first build the Lua compiler and bin2c utility # before we try and make the header files. DEPENDS luacode.h : luac$(SUFEXE) bin2c$(SUFEXE) ; DEPENDS luaclicode.h : luac$(SUFEXE) bin2c$(SUFEXE) ; # Make sure we create the header files before compiling p4sql # and p4odbc.dll. DEPENDS p4sql$(SUFEXE) : luacode.h luaclicode.h ; DEPENDS p4odbc.dll : luacode.h luaclicode.h ; } rule Lua2c { local _t ; _t = [ FGristFiles $(>:S=.lb) ] ; LuaCompile $(>) ; LOCATE on $(<) = $(SEARCH_SOURCE) ; DEPENDS lib : $(<) ; DEPENDS $(<) : $(_t) ; LuaBin2c $(<) : $(_t) ; Clean clean : $(<) ; Clean clean : $(_t) ; } rule LuaCompile { local _t _i ; for _i in [ FGristFiles $(<:S=.lua) ] { _t = $(_i:S=.lb) ; SEARCH on $(_i) = $(SEARCH_SOURCE) ; LOCATE on $(_t) = $(LOCATE_TARGET) ; DEPENDS obj : $(_t) ; DEPENDS $(_t) : $(_i) ; Luac $(_t) : $(_i) ; Clean clean : $(_t) ; } } actions LuaBin2c { $(ALL_LOCATE_TARGET)$(SLASH)bin2c $(>) > $(<) } actions Luac { $(ALL_LOCATE_TARGET)$(SLASH)luac -s -o $(<) $(>) } ################################################# # # Section 9. Boost provides free peer-reviewed portable C++ source libraries. # ################################################# # Point to the root of the boost hierarchy. c.f. BoostHdrs rule. SetDefaultDirName BOOSTDIR : [ FSubDirPath AllP4 .. import boost 1.47.0 ] ; # The old boost rule - still used in p4sandbox and server code rule BoostHdrs { # Include boost without jam-crawling its maze of headers. # Don't use SubDirHdrs: Jam locks up if it tries to crawl boost. SubDirC++Flags -I$(BOOSTDIR) -I$(BOOSTDIR)/tr1 -I$(BOOSTDIR)/boost/tr1 ; } rule BoostDefines { _BOOSTDIR = [ FDirName $(AllP4) $(<) boost ] ; BOOSTINCLUDEDIR = [ FDirName $(_BOOSTDIR) include ] ; BOOSTLIBDIR = [ FDirName $(_BOOSTDIR) lib $(LIBRARY_DEPOLYMENT_DIRECTORY) ] ; SubDirC++Flags -I$(BOOSTINCLUDEDIR) -I$(BOOSTINCLUDEDIR)/boost/tr1 ; } # boost libraries are linked differently on windows - this is why we need special rule rule LinkBoostLib { if ! $(BOOSTLIBDIR) { exit exit You need to call BoostDefines first ; } if $(OS) != NT { for lib in $(>) { LinkLib $(<) : $(lib) ; if $(lib) = boost_thread { LinkLib $(<) : pthread ; } } } LinkDir $(<) : $(BOOSTLIBDIR) ; } ################################################# # # Section 10. Google protocol buffers build rules and actions. # ################################################# rule ProtoBaseDefines { PROTOBUFDIR = [ FDirName $(AllP4) $(<) protobuf ] ; PROTOBUFINCLUDEDIR = [ FDirName $(PROTOBUFDIR) include ] ; PROTOBUFLIBDIR = [ FDirName $(PROTOBUFDIR) lib $(LIBRARY_DEPOLYMENT_DIRECTORY) ] ; PROTOBUFC = [ FDirName $(PROTOBUFDIR) bin $(LIBRARY_DEPOLYMENT_DIRECTORY) protoc ] ; PROTOBUF_CPP_OUT = [ FDirName $(LOCATE_SOURCE[1]) protobuf ] ; PROTOBUF_OBJ_OUT = [ FDirName $(LOCATE_SOURCE[1]) objects protobuf ] ; } rule ProtobufDefines { # ProtobufDefines ; - Add defines/headers for building with Protocol buffers ProtoBaseDefines $(<) ; SubDirHdrs $(PROTOBUFINCLUDEDIR) ; SubDirHdrs $(LOCATE_SOURCE[1]) protobuf ; } rule ProtobufLinkage { if ! $(PROTOBUFDIR) { exit You need to call ProtobufDefines first ; } if $(NT) { LinkLib $(<) : libprotobuf ; } else { LinkLib $(<) : protobuf m ; } LinkDir $(<) : $(PROTOBUFLIBDIR) ; } rule ProtobufImportRule { local cc = $(<:S=.pb.cc) ; for proto in $(>:G=$(HDRGRIST:E)) { on $(proto) grist = $(grist_cc) ; Depends $(cc) : $(grist) ; } } rule ProtobufDummyIncludeRule { # do not scan generated pb.cc files for headers - they are always generated together # and we need reversed dependency to force generation when some other header file # includes pb.h file } rule ProtobufLibrary { # ProtobufLibrary lib : *.proto ; - protoc, compile, & archive # X.proto -> temp X.cc and X.h -> temp X.obj -> lib # Normal library rule on the generated *.cc files # Make X.cc and X.h from X.proto using protoc # X.cc is a temp local proto_source ; for proto_source in $(>) { local proto = $(proto_source) ; if $(OS) = NT { local proto_tokens = [ FSplit $(proto) ] ; proto = [ FDirName $(proto_tokens) ] ; } local grist = [ FGristSourceFiles $(proto) ] ; HDRSCAN on $(grist) = "^[ ]*import[ ]*\"([^\"]*)\".*$" ; HDRRULE on $(grist) = ProtobufImportRule ; local cc = $(proto:S=.pb.cc) ; Library $(<) : $(proto:S=.pb.cc) ; local grist_cc = [ FGristSourceFiles $(cc) ] ; grist_cc on $(proto_source) = $(grist_cc) ; local hd = $(proto:S=.pb.h) ; if $(OS) = NT { NotFile $(hd) ; local h = $(proto_source:S=.pb.h) ; # Prevents circular dependency issues when the header file is found in already generated pb.cc file HDRRULE on $(grist_cc) = ProtobufDummyIncludeRule ; NotFile $(h) ; Depends $(h) : $(grist_cc) ; ObjectC++Flags $(grist_cc) : /EHsc /wd4125 ; } local gproto = [ FGristFiles $(proto) ] ; ProtobufCompile $(grist_cc) $(hd) : $(gproto) ; } } rule ProtobufCompile { # ProtobufC x.proto ; - preprocess with protoc # Derive a .cc and .h from .proto using ProtoC NotFile protobuf ; Depends protobuf : $(<) ; NotFile src ; Depends src : protobuf ; Depends all : $(<) ; Depends $(<) : $(>) ; Clean clean : $(<) ; PROTO_PATH on $(<) = $(LOCATE_SOURCE) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; MakeLocateWithSubDirectory $(<) : $(PROTOBUF_CPP_OUT) ; } actions ProtobufCompile { $(PROTOBUFC) $(>) --cpp_out=$(PROTOBUF_CPP_OUT) --proto_path=$(PROTO_PATH) -I$(PROTO_HEADERS) } ################################################# # # Section 11. Google test rules # ################################################# rule P4VGTest { # Usage: P4VGTest component : lib1 lib2 ... ; GTest [ FDirName $(AllP4) p4-qt gtest ] : $(<) : $(>) ; } rule GTestQt { local TestAppName = $(1)-tests ; QtConsoleLinkage $(TestAppName) ; local test_h_files = [ GLOB $(LOCATE_SOURCE[2]) : *_qt_gtest.h ] ; if $(test_h_files) { local test_files = $(test_h_files:B).h ; QtMocLibrary $(TestAppName)-qt : $(test_files) ; LinkLibraries $(TestAppName) : $(TestAppName)-qt ; } } rule GTest { # GTest is for internal use only - so far # Test only on Windows, mac and linux if $(OS) != NT && $(OS) != MACOSX && $(OS) != LINUX { return ; } # Test only for dyn and dyng if $(TYPE) != dyn && $(TYPE) != dyng { return ; } local GTESTDIR = $(1) ; # Add gtest include directory SubDirHdrs [ FDirName $(GTESTDIR) include ] ; local TestAppName = $(2)-tests ; local TestApp = [ FAppendSuffix $(TestAppName) : $(SUFEXE) ] ; # Scan for all files with suffix _unittest local test_cpp_files = [ GLOB $(LOCATE_SOURCE[2]) : *_gtest.cpp ] ; local test_cc_files = [ GLOB $(LOCATE_SOURCE[2]) : *_gtest.cc ] ; local test_files = $(test_cpp_files:B).cpp ; test_files += $(test_cc_files:B).cc ; # add all *_unittest files to the test application if $(OS) = NT { ObjectC++Flags $(test_files) : /EHsc ; } # add gtest library directory GTESTLIBDIR = [ FDirName $(GTESTDIR) lib $(LIBRARY_DEPOLYMENT_DIRECTORY) ] ; LinkLib $(TestAppName) : gtest ; if $(OS) = LINUX { LinkLib $(TestAppName) : pthread ; } LinkDir $(TestAppName) : $(GTESTLIBDIR) ; if $(PROTOBUFDIR) { ProtobufLinkage $(TestAppName) ; } # add link libraries LinkLibraries $(TestAppName) : $(3) ; LINK_WITH_STDC++ += $(TestAppName) ; P4Main $(TestAppName) : $(test_files) ; # initilize unit test report GTestReport $(2)-report.xml : $(TestApp) ; } rule GTestReport { # GTestReport is fot internal use only NotFile ut ; Depends ut : $(<) ; Depends all : $(<) ; Depends $(<) : $(>) ; Clean clean : $(<) ; SEARCH on $(<) = $(SEARCH_SOURCE) ; MakeLocate $(<) : [ FDirName $(LOCATE_SOURCE[1]) tests ] ; } actions GTestReport { $(>) --gtest_output=xml:$(<) --gtest_filter=-*.Integration_* } ################################################# # # Section 12. Per-platform actions. # ################################################# if $(OS) = IPHONE { # The "security unlock-keychain" command here should have no effect # if the keychain is already unlocked, even if the supplied # password is incorrect. But it will unlock keychains with blank # passwords, which should avoid some accidental production failures. actions P4Scout_xcodebuild { security unlock-keychain -p '' login.keychain pwd=`pwd` cd $(SCOUTSRCDIR) && xcodebuild -configuration $(>) P4APIDIR=$pwd/$(P4APIDIR) && cd build/$(>)-iphoneos && zip -9 -r -y -q $(>)-$(<).zip $(<) && zip -9 -r -y -q $(>)-$(<).dSYM.zip $(<).dSYM && mv $(>)-$(<).zip $(>)-$(<).dSYM.zip $pwd/$(EXEC) } } if $(UNIX) || $(NT) { # Provide proper quoting for file names with spaces in them. actions File { $(CP) "$(>)" "$(<)" } } if $(NT) && $(MSVCNT) { if $(BUILD_WITH_SUB_DIRECTORIES) != true { actions updated together piecemeal Archive { pushd $(<:D) if exist $(<:BS) set _$(<:B)_=$(<:BS) $(AR) /nologo /out:$(<:BS) %_$(<:B)_% $(>:BS) if %ERRORLEVEL% neq 0 exit %ERRORLEVEL% popd } } # When embedding a manifest, the resource id should be 1 for exe files, 2 for dlls. actions Link bind NEEDLIBS DEFFILE { $(LINK) $(LINKFLAGS) /out:$(<) /def:$(DEFFILE) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) if %ERRORLEVEL% neq 0 exit %ERRORLEVEL% set _target=$(<) set _file=%_target:$(ALL_LOCATE_TARGET)$(SLASH)=% set _rsrc=1 if /i %_target:~-3,3% neq exe set _rsrc=2 if exist $(<).manifest mt -manifest $(<).manifest -outputresource:$(<);%_rsrc% } } if $(NT) { actions Cc { $(CC) /c /Fo$(<) /Fd$(PDBFILENAME) $(CCFLAGS) $(CCDEFS) "$(CCHDRS)" "/I$(STDHDRS)" $(>) } actions C++ { $(C++) /c /Fo$(<) /Fd$(PDBFILENAME) $(C++FLAGS) $(CCDEFS) "$(CCHDRS)" "/I$(STDHDRS)" /Tp$(>) } actions MkTarArchive { tar cf $(<) -C $(>:P) $(>:BE)$(>:SE) } # If someone beat us to creating the directory, don't bomb. actions MkDir1 { $(MKDIR) $(<) if exist $(<) exit 0 } } if $(VMS) { actions MkTarArchive { set default $(<:D) vmstar cvdzf $(<:B)$(<:S) [.$(>:B)...] set file/prot=(o:rwed) $(<:B)$(<:S) } actions MkZipArchive { set default $(<:D) zip "-9wrV" $(<:B)$(<:S) $(>:BS=.dir) } actions MkBckArchive { set default $(<:D) backup [.$(>:B)...] $(<:B)$(<:S)/save set file/prot=(o:rwed) $(<:B)$(<:S) } } ################################################# # # Section 13. Useful miscellanea # ################################################# # Numerous client packages use this variable: p4-dtg, p4-convert, # the scripted APIs, etc. # We can't set this in Section 1 because the rule isn't defined yet. { local _apidir = [ P4APIDirName p4api ] ; SetDefaultDirName P4APIDIR : [ FDirName $(EXEC) $(_apidir[1]) ] ; } if $(USE_P4APIDIR) && ! [ FileIsDir $(P4APIDIR) ] { exit I was told to use P4APIDIR"="$(P4APIDIR) but it does not exist. ; } # end of Jamrules
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 16129 | tjuricek |
Rename/move files again... this time to the hyphenated-approach. |
||
//guest/tjuricek/file_system_client/main/vendor/p4api-15.1/macosx105x86_64/sample/Jamrules | |||||
#1 | 16119 | tjuricek | Rename/move to meet workshop project conventions. | ||
//guest/tjuricek/fsclient/vendor/p4api-15.1/macosx105x86_64/sample/Jamrules | |||||
#1 | 16118 | tjuricek |
FSClient initial version: handles add, edit This is a proof-of-concept app that mirrors an existing Perforce workspace to handle running commands like "p4 add" and "p4 edit" automatically when your apps add and write files. See the readme for more information. |