# p4/Jamrules
#
# This Jamrules describes how to build most of Perforce, exclusive of
# windows only products.
#
# This file is organized into sections:
#
# Section 1. Global variable settings.
# Section 2. Library names.
# Section 3. Per-build type variable settings.
# Section 4. Per-platform variable settings.
# Section 5. Perforce-special rules and actions.
# Section 6. Perforce-special Windows rules.
# Section 7. QT build rules and actions.
# Section 8. Lua build rules and actions.
# Section 9. Per-platform actions.
# Section 10. Useful miscellanea
#
#################################################
#
# 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")
# 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) = 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_LIB_TOKENS =
P4BIN
lib.$(OS:L)$(OSVER:EL)$(OSPLAT:EL)
;
EXEC_LIB ?= [ FSubDirPath $(EXEC_LIB_TOKENS) ] ;
EXEC_LIBEXEC_TOKENS =
P4BIN
libexec.$(OS:L)$(OSVER:EL)$(OSPLAT:EL)
;
EXEC_LIBEXEC ?= [ FSubDirPath $(EXEC_LIBEXEC_TOKENS) ] ;
# Build dir: p4-bin/bin.xxx[/build][/type]
EXEC_TOKENS =
P4BIN
bin.$(OS:L)$(OSVER:EL)$(OSPLAT:EL)
$(BUILD)
$(TYPE:L)
;
EXEC ?= [ FSubDirPath $(EXEC_TOKENS) ] ;
ALL_LOCATE_TARGET = $(EXEC) ;
# version file
# Ident'ed executables depend on this
SEARCH on Version Jamrules = $(P4) ;
include Version ;
STRIP = strip ;
COMPRESS = gzip -9 ;
# 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" ;
}
# can be overridden on jam cmdline with -sSMARTHEAP=no
# Smartheap is currently only used on NT and Linux.
SMARTHEAP ?= yes ;
DEFINES +=
OS_$(OS)
OS_$(OS)$(OSVER)
OS_$(OS)$(OSPLAT)
OS_$(OS)$(OSVER)$(OSPLAT) ;
HDRS +=
[ FSubDirPath P4 msgs ]
[ FSubDirPath P4 support ]
[ FSubDirPath P4 sys ] ;
# Which Zeroconf implementation to select. Default is
# Apple's bonjour.
ZEROCONF = bonjour ;
# 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 ;
}
# Point to the root of the boost hierarchy. c.f. BoostHdrs rule.
BOOSTDIR ?= [ FDirName $(AllP4) .. import boost 1.37 ] ;
#################################################
#
# 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 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 QTZEROCONFLIB : libqtzeroconf ;
SetLibName RPCLIB : librpc ;
SetLibName SANDSTORM : libstorm ;
SetLibName P4ALIB : libp4a ;
SetLibName P4V : libp4v ;
SetLibName P4VTEST : libp4vtest ;
SetLibName SCCDLLLIB : p4scc2 ;
SetLibName SERVERLIB : libserver ;
SetLibName SUPPORTLIB : libsupp ;
SetLibName WEBGIZMOLIB : libp4web ;
SetLibName ZEROCONFLIB : libzeroconf ;
#################################################
#
# Section 3. Per-build type variable settings.
#
#################################################
TYPE ?= opt ;
switch $(TYPE)
{
# These are official builds
#
# dyn: windows guis must be dynamic
# opt: our standard, optimized built
# pic: for special customer requests
case dyn : OPTIM = -O2 ;
case opt : OPTIM = -O2 ;
case pic : OPTIM = -O2 -fPIC ;
# These are for internal testing/playing
#
# g/dyng/optg: debugging
# pg: profiled executable on unix
# fast: a fast compile (no optimization)
# lower: case insensitive on UNIX
# lpg: lower profiled
case g : OPTIM = -g ;
case dyng : OPTIM = -g ;
case fast : OPTIM = ;
case lower : OPTIM = -DCASE_INSENSITIVE -O2 ;
case lpg : OPTIM = -DCASE_INSENSITIVE -O2 -pg ; LINKFLAGS = -pg ;
case optg : OPTIM = -O2 -g ;
case pg : OPTIM = -pg -O ; LINKFLAGS = -pg ;
case sym : OPTIM = -opt off -sym full ; LINKFLAGS = -sym full ;
case FSgSSP : OPTIM = -g -D_FORTIFY_SOURCE=2 -fstack-protector-all ;
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.
switch $(TYPE) { case *g : TYPE_DEBUG = true ; }
switch $(TYPE) { case dyn* : TYPE_DYNAMIC = true ; }
# Some things don't get built dynamically/statically.
if ! $(TYPE_DYNAMIC) || $(OS) != NT { BUILD_P4D = true ; }
#################################################
#
# Section 4. Per-platform variable settings.
#
#################################################
# Flags for Perforce
#
# CASE_INSENSITIVE -- case folding server
# ENUM_INT -- force enums to int sized for watcom
# USE_CRLF -- ascii opened as binary needs special handling
# USE_CR -- special CR <-> LF translation for mac
# USE_EBCDIC -- ascii <-> ebcdic translation in rpc
GENFLAGS = CCFLAGS C++FLAGS ;
switch $(OS)$(OSVER) $(OS)
{
case AIX53 :
C++ = g++ ;
CC = gcc ;
LINK = gcc ;
C++FLAGS += -DBSD -Dunix -D_LARGE_FILES=1 ;
LINKLIBS += -lsupc++ ;
switch $(OSPLAT)
{
case PPC64 :
$(GENFLAGS) += -maix64 ;
LINKFLAGS += -maix64 ;
AR = ar -X 64 -ru ;
STRIP = strip -X 64 ;
}
case AS400 :
CC = icc ;
C++ = icc ;
LINK = icc ;
OPTIM = -O4 ;
$(GENFLAGS) += -DUSE_EBCDIC ;
LINKFLAGS += -qDUPPROC ;
AR = qar -cru ;
STRIP = ;
ZEROCONF = none ;
# This QSYS library must be pre-created before building
QSYSLIB = p4 ;
case CYGWIN :
CC = gcc ;
C++ = gcc ;
LINK = g++ ;
C++FLAGS += -DUSE_CRLF ;
STRIP = ;
case DARWIN :
CC = cc ;
C++ = cc ;
C++FLAGS += -DCASE_INSENSITIVE ;
case DARWIN60cs : #case-sensitive
CC = cc ;
C++ = cc ;
LINK = g++ ;
case DARWIN8* :
CC = gcc ;
C++ = g++ ;
LINK = g++ ;
MACOSX_SDK ?= /Developer/SDKs/MacOSX10.4u.sdk ;
LINKFLAGS += -Wl,-syslibroot,$(MACOSX_SDK) ;
switch $(OSVER:U)
{
case *CS :
case * : C++FLAGS += -DCASE_INSENSITIVE ;
}
# OSPLAT=U : universal binary
switch $(OSPLAT)
{
case PPC : _arch = -arch ppc ;
case X86 : _arch = -arch i386 ;
case X86_64 : _arch = -arch x86_64 ;
case U : _arch = -arch ppc
-arch i386
-arch x86_64 ;
NOARSCAN = true ; # can't scan "fat" archives
}
$(GENFLAGS) += $(_arch) -DOS_DARWIN80 ;
LINKFLAGS += $(_arch) ;
case DARWIN9* :
CC = gcc ;
C++ = g++ ;
LINK = g++ ;
MACOSX_SDK ?= /Developer/SDKs/MacOSX10.5.sdk ;
LINKFLAGS += -Wl,-syslibroot,$(MACOSX_SDK) ;
LINKLIBS += -framework CoreServices ;
switch $(OSVER:U)
{
case *CS :
case * : C++FLAGS += -DCASE_INSENSITIVE ;
}
# OSPLAT=U : universal binary
switch $(OSPLAT)
{
case PPC : _arch = -arch ppc ;
case X86 : _arch = -arch i386 ;
case X86_64 : _arch = -arch x86_64 ;
case U : _arch = -arch ppc
-arch i386
-arch x86_64 ;
NOARSCAN = true ; # can't scan "fat" archives
}
$(GENFLAGS) += $(_arch) -DOS_DARWIN90 ;
LINKFLAGS += $(_arch) ;
case DARWIN10* :
CC = gcc ;
C++ = g++ ;
LINK = g++ ;
MACOSX_SDK ?= /Developer/SDKs/MacOSX10.6.sdk ;
LINKFLAGS += -Wl,-syslibroot,$(MACOSX_SDK) ;
LINKLIBS += -framework CoreServices ;
switch $(OSVER:U)
{
case *CS :
case * : C++FLAGS += -DCASE_INSENSITIVE ;
}
# OSPLAT=U : universal binary
# There is no ppc support in osx 10.6 / darwin 10
switch $(OSPLAT)
{
case X86 : _arch = -arch i386 ;
case X86_64 : _arch = -arch x86_64 ;
case U : _arch = -arch i386
-arch x86_64 ;
NOARSCAN = true ; # can't scan "fat" archives
}
$(GENFLAGS) += $(_arch) -DOS_DARWIN10 ;
LINKFLAGS += $(_arch) ;
case FREEBSD :
Exit Set OSVER to 4, 5, or 6 for FreeBSD ;
case FREEBSD4 :
CC = gcc ;
C++ = g++ ;
LINK = gcc ;
switch $(OSCOMP)
{
case GCC3 : LINKLIBS += -lsupc++ ;
}
if $(OSPLAT) != AXP { LINKFLAGS += -static ; }
$(GENFLAGS) += -pipe ;
ZEROCONF = avahi ;
case FREEBSD[56789]* :
CC = gcc ;
C++ = g++ ;
LINK = gcc ;
# supc++ library on freebsd5.x and later is missing some
# modules (this is a bug), so we can't use it.
# Since every major version of the OS requires relinking
# anyway, there's no harm in linking stdc++ dynamically.
LINKLIBS += -lstdc++ ;
_mflags = ;
switch $(OSPLAT)
{
case X86 : _mflags = -m32 ;
case X86_64 : _mflags = -m64 ;
}
$(GENFLAGS) += $(_mflags) -pipe ;
LINKFLAGS += $(_mflags) ;
QTOPENGL ?= no ;
ZEROCONF = avahi ;
case HPUX11 :
switch $(OSPLAT:E)-$(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++
$(GENFLAGS) += +DD64 +noeh -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?
$(GENFLAGS) += +W2611,2997 ;
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)
{
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] :
# 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".
CC = $(CROSS_COMPILE:E)gcc ;
C++ = $(CROSS_COMPILE:E)g++ ;
LINK = $(CROSS_COMPILE:E)gcc ;
STRIP = $(CROSS_COMPILE:E)strip ;
RANLIB = $(CROSS_COMPILE:E)ranlib ;
LINKLIBS += -lsupc++ # Assumes gcc 3.x or later
-ldl ; # for zeroconf
# 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)
{
case X86 : _mflags = -m32 ;
case X86_64 : _mflags = -m64 ;
case ARM* : _mflags = -march=armv4t ;
}
if $(SMARTHEAP) = yes { $(GENFLAGS) += -DUSE_SMARTHEAP ; }
$(GENFLAGS) += $(_mflags) -D_GNU_SOURCE ;
LINKFLAGS += $(_mflags) ;
QTOPENGL ?= no ;
ZEROCONF = avahi ;
case MACOSX :
CC = cc ;
C++ = cc ;
$(GENFLAGS) += -DCASE_INSENSITIVE ;
$(GENFLAGS) += -fpascal-strings ;
# This looks like a flag but it is really a library macro
# kind of thing and causes link problems if it at the front
# of the link command so we make it a LIB
LINKLIBS += -framework ApplicationServices ;
LINKLIBS += -framework Foundation ;
LINKLIBS += -framework CoreServices ;
case MACOSX104 : # assumes using gcc 4.0.1 or newer
CC = gcc ;
C++ = g++ ;
LINK = g++ ;
MACOSX_SDK ?= /Developer/SDKs/MacOSX10.4u.sdk ;
# 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) += -DCASE_INSENSITIVE
-fpascal-strings
-isysroot$(MACOSX_SDK) ;
LINKFLAGS += -Wl,-syslibroot,$(MACOSX_SDK) ;
# This looks like a flag but it is really a library macro
# and causes link problems if it's at the front of the link
# command, so we make it a LIB.
LINKLIBS += -framework ApplicationServices ;
LINKLIBS += -framework Foundation ;
LINKLIBS += -framework CoreServices ;
# OSPLAT=U : universal binary
#
# Unlike the OS=DARWIN case we don't build x86_64 into the
# universal binaries because Qt still uses the Carbon API,
# which has no 64-bit implementation.
switch $(OSPLAT)
{
case PPC : _arch = -arch ppc ;
case X86 : _arch = -arch i386 ;
case X86_64 : _arch = -arch x86_64 ;
case U : _arch = -arch ppc
-arch i386 ;
NOARSCAN = true ; # can't scan "fat" archives
}
$(GENFLAGS) += $(_arch) -DCASE_INSENSITIVE ;
LINKFLAGS += $(_arch) ;
# This adds $(QTDIR)/lib as a frameworks directory, in case
# Qt is built as frameworks. On the mac, it can be built
# either as frameworks, regular unix-style shared
# libraries, or unix-style static libaries.
$(GENFLAGS) += -F$(QTDIR)/lib ;
case MACOSX105 : # assumes using gcc 4.0.1 or newer
CC = gcc ;
C++ = g++ ;
LINK = g++ ;
MACOSX_SDK ?= /Developer/SDKs/MacOSX10.5.sdk ;
# 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) += -DCASE_INSENSITIVE
-fpascal-strings
-isysroot$(MACOSX_SDK) ;
LINKFLAGS += -Wl,-syslibroot,$(MACOSX_SDK)
-mmacosx-version-min=10.5 ;
# This looks like a flag but it is really a library macro
# and causes link problems if it's at the front of the link
# command, so we make it a LIB.
LINKLIBS += -framework ApplicationServices ;
LINKLIBS += -framework Foundation ;
LINKLIBS += -framework CoreServices ;
# OSPLAT=U : universal binary
#
# Unlike the OS=DARWIN case we don't build x86_64 into the
# universal binaries because Qt still uses the Carbon API,
# which has no 64-bit implementation.
switch $(OSPLAT)
{
case PPC : _arch = -arch ppc ;
case X86 : _arch = -arch i386 ;
case X86_64 : _arch = -arch x86_64 ;
case U : _arch = -arch ppc
-arch i386 ;
NOARSCAN = true ; # can't scan "fat" archives
}
$(GENFLAGS) += $(_arch) -DCASE_INSENSITIVE ;
LINKFLAGS += $(_arch) ;
# This adds $(QTDIR)/lib as a frameworks directory, in case
# Qt is built as frameworks. On the mac, it can be built
# either as frameworks, regular unix-style shared
# libraries, or unix-style static libaries.
$(GENFLAGS) += -F$(QTDIR)/lib ;
case MACOSX106 : # assumes using gcc 4.0.1 or newer
CC = gcc ;
C++ = g++ ;
LINK = g++ ;
MACOSX_SDK ?= /Developer/SDKs/MacOSX10.6.sdk ;
# 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) += -DCASE_INSENSITIVE
-fpascal-strings
-isysroot$(MACOSX_SDK) ;
LINKFLAGS += -Wl,-syslibroot,$(MACOSX_SDK) ;
# This looks like a flag but it is really a library macro
# and causes link problems if it's at the front of the link
# command, so we make it a LIB.
LINKLIBS += -framework ApplicationServices ;
LINKLIBS += -framework Foundation ;
LINKLIBS += -framework CoreServices ;
# OSPLAT=U : universal binary
#
# Unlike the OS=DARWIN case we don't build x86_64 into the
# universal binaries because Qt still uses the Carbon API,
# which has no 64-bit implementation.
#
# No PPC support in OSX 10.6.
switch $(OSPLAT)
{
case X86 : _arch = -arch i386 ;
case X86_64 : _arch = -arch x86_64 ;
case U : _arch = -arch i386 ;
}
$(GENFLAGS) += $(_arch) -DCASE_INSENSITIVE ;
LINKFLAGS += $(_arch) ;
# This adds $(QTDIR)/lib as a frameworks directory, in case
# Qt is built as frameworks. On the mac, it can be built
# either as frameworks, regular unix-style shared
# libraries, or unix-style static libaries.
$(GENFLAGS) += -F$(QTDIR)/lib ;
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 ;
ZEROCONF = none ;
case NETBSD* :
OSCOMPDIR ?= /usr/pkg/gcc34/bin/ ;
CC = $(OSCOMPDIR:E)gcc ;
C++ = $(OSCOMPDIR:E)g++ ;
LINK = $(OSCOMPDIR:E)gcc ;
LINKLIBS += -lsupc++ ;
$(GENFLAGS) += -pipe -Dunix ;
# NetBSD gcc choked on -O2 -fPIC
if $(TYPE) = pic { OPTIM = -O1 -fPIC ; }
case VMS* :
# use C++ compiler: we're cheap
CC = cxx ;
C++ = cxx ;
DEFINES += NO_MEMCPY ;
STRIP = ;
OPTIM = ;
case NT* :
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 file directory. Visual Studio 9
# (VS2008) and later apparently are ok.
PDBDIR ?= $(EXEC) ;
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 = ;
}
BINDIR = e:\\perforce ;
JAMSHELL ?= $(P4)\\Jamsh.bat $(OSPLAT) % "!" ;
C++FLAGS += /DCASE_INSENSITIVE /DUSE_CRLF /wd4996 ;
if $(SMARTHEAP) = yes { $(GENFLAGS) += /DUSE_SMARTHEAP ; }
# 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 = setargv.obj advapi32.lib oldnames.lib
kernel32.lib ws2_32.lib ;
if $(MSVSVER) >= 8
&& ! $(TYPE_DYNAMIC) # 2008-10-17: static only for now
{
local _dyn ;
if $(TYPE_DYNAMIC) = true { _dyn = -dyn ; }
LINKLIBS += $(EXEC_LIB)/wild-vs$(MSVSVER)$(_dyn:E).obj ;
}
if $(OSPLAT) = IA64
{
# 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 = ;
# Now, unset STDHDRS so Jam doesn't scan system headers (takes
# too long when using compiler on networked machine):
STDHDRS = ;
if $(BCCROOT)
{
# Jeff Anton compiles with borland.
OPTIM = -O2 ;
RCFLAGS = /d NDEBUG /r ;
AR = tlib /C /P128 ;
LINKLIBS = $(BCCROOT)/lib/wildargs.obj ;
}
else if $(TYPE) = g
{
# Debugging build
OPTIM = $(_Z) /Gm ;
RCFLAGS = /d DEBUG /r ;
LINKFLAGS += /DEBUG ;
if $(CRT) = dyn
{
$(GENFLAGS) += /MDd ;
}
else
{
$(GENFLAGS) += /MTd ;
}
}
else if $(TYPE) = dyn
{
# Dynamic link version, for qt products
OPTIM = $(_Z) /O2 ;
RCFLAGS = /d NDEBUG /r ;
$(GENFLAGS) += /MD ;
LINKFLAGS += /MAP /DEBUG /OPT:REF /OPT:ICF ;
}
else if $(TYPE) = 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 ;
}
else if $(TYPE) = 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 ;
}
else if $(TYPE) = 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 ;
}
else if $(OSVER) = 98
{
# Dynamic link version for win98 version of p4win
# Goes into bin.win98 -- oddity.
EXEC = [ FSubDirPath P4BIN bin.win98 ] ;
ALL_LOCATE_TARGET = $(EXEC) ;
OPTIM = /O2 ;
if $(TYPE_DEBUG) = true { OPTIM += $(_Z) ; }
RCFLAGS = /d NDEBUG /r ;
$(GENFLAGS) += /MD ;
LINKFLAGS = /MAP ;
}
else
{
# 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) = 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 = CC ;
C++ = CC ;
LINK = CC ;
OPTIM = -xO3 ;
if $(TYPE) = pic { OPTIM += -KPIC ; }
switch $(OSPLAT)
{
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 = CC ;
C++ = CC ;
LINK = CC ;
OPTIM = -xO3 ;
if $(TYPE) = pic { OPTIM += -KPIC ; }
switch $(OSPLAT)
{
case *64 :
$(GENFLAGS) += -m64 ;
LINKFLAGS += -m64 ;
}
case * : # GCC
CC = gcc ;
C++ = g++ ;
LINK = gcc ;
switch $(OSPLAT)
{
case *64 : # X86_64 or SPARC64
LINKFLAGS += -m64 ;
$(GENFLAGS) += -m64 ;
}
# supc++ needed for all apps since we use gcc >= 3.2.
LINKLIBS += -lsupc++ ;
}
$(GENFLAGS) += -Dsolaris
-D_LARGEFILE64_SOURCE
-I/opt/lude/include ;
LINKLIBS += -lsocket -lnsl ;
AR = /usr/ccs/bin/ar ru ;
STRIP = /usr/ccs/bin/strip ;
QTOPENGL ?= no ;
case * :
Exit Don't know "$(OS)$(OSVER) or " $(OS) ;
}
# Set build flags for chosen Zeroconf implementation
if $(ZEROCONF) = bonjour
{
DEFINES += USE_BONJOUR ;
}
if $(ZEROCONF) = avahi
{
DEFINES += USE_AVAHI ;
}
if $(UNIX)
{
# Don't fail if directory already exists.
MKDIR = mkdir -p ;
}
#################################################
#
# Section 5. Perforce-special rules and actions.
#
#################################################
#
# Special Rules
#
# FRemoveAny x : y ; - return new array of x minus any values in y
# 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
# MakeP4ThumbDist file ; Create p4thumb package
# MakeP4Vdist ; create p4v.tgz on unix systems or P4V.dmg on macosx
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 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 DefineVar
{
# Usage: DefineVar foo.cc : VARNAME
# Defines it if set
if $($(>))
{
ObjectDefines $(<) :
[ Fconcat $(>)= [ FQuote \"$($(>))\" ] ] ;
}
}
rule Ident
{
# Set up special defines
local osid = $(OS)$(OSVER:E)$(OSPLAT:E) ;
rule Fconcat { return $(<:J) ; }
ObjectDefines $(<) :
[ Fconcat ID_OS= [ FQuote $(osid[1]:U) ] ]
[ Fconcat ID_REL= [ FQuote $(RELEASE: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 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 P4Library
{
Library $(<) : $(>) ;
}
rule P4DLibrary
{
if $(BUILD_P4D) { Library $(<) : $(>) ; }
}
rule P4Main
{
Main $(<) : $(>) ;
Strip $(<) ;
if $(BINDIR) { InstallBin $(BINDIR) : $(<) ; }
}
rule P4DMain
{
if $(BUILD_P4D)
{
P4Main $(<) : $(>) ;
}
else
{
P4NoBuild $(<) : BUILD_P4D ;
}
}
rule P4NoBuild
{
NotFile $(>) ;
}
actions quietly P4NoBuild
{
echo Set $(>) to force build of $(<).
}
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
{
local _striptypes = opt pic dyn ; # don't strip g variants
if $(STRIP) && ( $(TYPE:E=opt) in $(_striptypes) )
{
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
_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
{
switch $(<:S)
{
case .tar : MkTarArchive $(<) : $(>) ;
case .tgz : MkComressedTarArchive $(<) : $(>) ;
case .tar.gz : MkComressedTarArchive $(<) : $(>) ;
case .zip : MkZipArchive $(<) : $(>) ;
case .bck : MkBckArchive $(<) : $(>) ;
case * : exit "Don't know how to make $(<)" ;
}
}
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 bugzdir = $(EXEC) $(dirname) doc bugz3mysql5 ;
local mysqldir = $(EXEC) $(dirname) doc mysql5 ;
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 bugz3mysql5.so : bugz3mysql5.so ;
CopyRec p4dtg-dist : $(topdir) plugins mysql5.so : mysql5.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 : $(bugzdir) patch.bugzilla-3 : $(P4DTG) sdk bugz patch.bugzilla-3 ;
CopyRec p4dtg-dist : $(bugzdir) patch.bugzilla-3.4 : $(P4DTG) sdk bugz patch.bugzilla-3.4 ;
CopyRec p4dtg-dist : $(bugzdir) README.txt : $(P4DTG) sdk bugz README.txt ;
CopyRec p4dtg-dist : $(bugzdir) README.p4dti.txt : $(P4DTG) sdk bugz README.p4dti.txt ;
CopyRec p4dtg-dist : $(bugzdir) mk_dtgdtissue.pl : $(P4DTG) sdk bugz mk_dtgdtissue.pl ;
CopyRec p4dtg-dist : $(bugzdir) dti_to_dtg.pl : $(P4DTG) sdk bugz dti_to_dtg.pl ;
CopyRec p4dtg-dist : $(bugzdir) changeid.pl : $(P4DTG) sdk bugz changeid.pl ;
CopyRec p4dtg-dist : $(bugzdir) jobspec.txt : $(P4DTG) sdk bugz jobspec.txt ;
CopyRec p4dtg-dist : $(mysqldir) README.txt : $(P4DTG) sdk mysql README.txt ;
CopyRec p4dtg-dist : $(mysqldir) import.pl : $(P4DTG) sdk mysql import.pl ;
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 = plugins/bugz3mysql5.so plugins/p4jobdt.so plugins/mysql5.so ;
local _f ;
for _f in $(_strip_bin)
{
_f = [ FDirName $(topdir) $(_f) ] ;
Strip $(_f) ;
}
for _f in $(_strip_lib)
{
_f = [ FDirName $(topdir) $(_f) ] ;
STRIP on $(_f) = $(STRIP) -x ;
Strip1 $(_f) ;
}
LOCATE on $(<) = $(EXEC) ;
Depends $(<) : p4dtg-dist ;
Depends all : $(<) ;
MkDistArchive $(<) : $(dirname) ;
}
rule MakeP4ThumbDist
{
local topdir ;
if $(OS) = NT
{
# Hopefully this is temporary, to be replaced with a proper installer.
topdir = p4thumb ;
local bindir = $(EXEC) $(topdir) ;
local libdir = $(EXEC) $(topdir) ;
local rscdir = $(EXEC) $(topdir) ;
MakeLocate $(topdir) : $(EXEC) ;
Depends p4thumb-dist : $(topdir) ;
CopyRec p4thumb-dist : $(bindir) p4thumb.exe : p4thumb.exe ;
CopyRec p4thumb-dist : $(bindir) vcredist_x86.exe : $(EXEC_LIB) vcredist_x86.exe ;
CopyRec p4thumb-dist : $(bindir) assistant.exe : $(EXEC_LIB) assistant.exe ;
CopyRec p4thumb-dist : $(libdir) plugins : $(EXEC_LIB) qt4 plugins : : *.dll ;
CopyRec p4thumb-dist : $(rscdir) p4thumbnotes.txt : $(AllP4) p4-doc user p4thumbnotes.txt ;
CopyRec p4thumb-dist : $(rscdir) translations : $(EXEC_LIB) qt4 translations ;
for _f in p4thumb_$(QtLanguages).qm
{
CopyRec p4thumb-dist : $(rscdir) translations $(_f) : $(_f) ;
}
local Qtdlls = [ FDirEntries $(EXEC_LIB) : *4.dll ] ;
local _dll ;
for _dll in $(Qtdlls)
{
CopyRec p4thumb-dist : $(libdir) $(_dll) : $(EXEC_LIB) $(_dll) ;
}
MakeQtConf p4thumb-dist : $(bindir) ;
}
else
{
local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ;
topdir = p4thumb-$(release_info:J=.) ;
local bindir = $(EXEC) $(topdir) bin ;
local libdir = $(EXEC) $(topdir) lib p4v ;
local rscdir = $(EXEC) $(topdir) lib p4v P4VResources ;
MakeLocate $(topdir) : $(EXEC) ;
Depends p4thumb-dist : $(topdir) ;
CopyRec p4thumb-dist : $(bindir) p4thumb.bin : p4thumb ;
CopyRec p4thumb-dist : $(bindir) p4thumb : $(AllP4) p4-qt apps p4v p4vwrapper.sh ;
CopyRec p4thumb-dist : $(libdir) qt4 : $(EXEC_LIB) qt4 ;
CopyRec p4thumb-dist : $(rscdir) translations : $(EXEC_LIB) qt4 translations ;
for _f in p4thumb_$(QtLanguages).qm
{
CopyRec p4thumb-dist : $(rscdir) translations $(_f) : $(_f) ;
}
MakeQtConf p4thumb-dist : $(bindir) ;
STRIP on [ FDirName $(bindir) p4thumb.bin ] = $(STRIP) -x ;
Strip1 [ FDirName $(bindir) p4thumb.bin ] ;
}
LOCATE on $(<) = $(EXEC) ;
Depends $(<) : p4thumb-dist ;
Depends all : $(<) ;
MkDistArchive $(<) : $(topdir) ;
}
rule MakeP4Vdist
{
if $(OS) = MACOSX
{
MakeP4Vdist_macosx $(<) ;
}
else if $(UNIX)
{
MakeP4Vdist_unix $(<) ;
}
# TODO: Add switch for NT to build installer
}
rule MakeP4Vdist_unix
{
local release_info = $(RELEASE[1-2]) $(PATCHLEVEL) $(RELEASE[3-]) ;
local topdir = p4v-$(release_info:J=.) ;
local bindir = $(EXEC) $(topdir) bin ;
local libdir = $(EXEC) $(topdir) lib p4v ;
local rscdir = $(EXEC) $(topdir) lib p4v P4VResources ;
local helpsrc = $(AllP4) p4-doc help ;
local _f ;
MakeLocate $(topdir) : $(EXEC) ;
Depends p4v-dist : $(topdir) ;
## Copy in the qt-based commands with shell wrapper
local qtcmd = p4v p4merge p4admin ;
for _f in $(qtcmd)
{
CopyRec p4v-dist : $(bindir) $(_f).bin : $(_f) ;
CopyRec p4v-dist : $(bindir) $(_f) : $(AllP4) p4-qt apps p4v p4vwrapper.sh ;
# Make sure they're all at least stripped of local symbols
_f = [ FDirName $(bindir) $(_f).bin ] ;
STRIP on $(_f) = $(STRIP) -x ;
Strip1 $(_f) ;
}
## Offline broker and server components.
local p4ddir = $(EXEC) ;
if $(TYPE_DYNAMIC) { p4ddir += .. ; }
CopyRec p4v-dist : $(rscdir) p4d : $(p4ddir) p4d ;
CopyRec p4v-dist : $(rscdir) p4ob : p4ob ;
_f = [ FDirName $(rscdir) p4ob ] ;
STRIP on $(_f) = $(STRIP) -x ;
Strip1 $(_f) ;
## Assistant executable
CopyRec p4v-dist : $(bindir) assistant : $(EXEC_LIB) assistant_dyn ;
# Libraries, plugins, qt standard translation catalogs
CopyRec p4v-dist : $(libdir) qt4 lib : $(EXEC_LIB) qt4 lib ;
CopyRec p4v-dist : $(libdir) qt4 plugins : $(EXEC_LIB) qt4 plugins ;
CopyRec p4v-dist : $(rscdir) translations : $(EXEC_LIB) qt4 translations ;
## Image resources
CopyRec p4v-dist : $(rscdir) images.rcc : images.rcc ;
# job034811 - people use these for shortcut icons
CopyRec p4v-dist : $(rscdir) icons : $(helpsrc) icons ;
## Documentation
for _f in $(QtLanguages)
{
# FIXME (noahf): This is almost ready but needs some runtime (nfs locking) debugging
# For now we are just copying pre-built collections below.
#QtHelpGen : $(helpsrc) p4v-html-pure $(_f) p4vhelp_$(_f).qhp ;
#QtHelpCollectionGen : $(helpsrc) p4v-html-pure $(_f) p4vhelp_$(_f).qhcp ;
#
#QtHelpGen : $(helpsrc) p4merge $(_f) p4mergehelp_$(_f).qhp ;
#QtHelpCollectionGen : $(helpsrc) p4merge $(_f) p4mergehelp_$(_f).qhcp ;
#
#QtHelpGen : $(helpsrc) p4admin-html-pure $(_f) p4adminhelp_$(_f).qhp ;
#QtHelpCollectionGen : $(helpsrc) p4admin-html-pure $(_f) p4adminhelp_$(_f).qhcp ;
CopyRec p4v-dist : $(rscdir) p4vhelp p4vhelp_$(_f).qhc : $(helpsrc) p4v-html-pure $(_f) p4vhelp_$(_f).qhc ;
CopyRec p4v-dist : $(rscdir) p4vhelp p4vhelp_$(_f).qch : $(helpsrc) p4v-html-pure $(_f) p4vhelp_$(_f).qch ;
CopyRec p4v-dist : $(rscdir) p4mergehelp p4mergehelp_$(_f).qhc : $(helpsrc) p4merge $(_f) p4mergehelp_$(_f).qhc ;
CopyRec p4v-dist : $(rscdir) p4mergehelp p4mergehelp_$(_f).qch : $(helpsrc) p4merge $(_f) p4mergehelp_$(_f).qch ;
CopyRec p4v-dist : $(rscdir) p4adminhelp p4adminhelp_$(_f).qhc : $(helpsrc) p4admin-html-pure $(_f) p4adminhelp_$(_f).qhc ;
CopyRec p4v-dist : $(rscdir) p4adminhelp p4adminhelp_$(_f).qch : $(helpsrc) p4admin-html-pure $(_f) p4adminhelp_$(_f).qch ;
}
CopyRec p4v-dist : $(rscdir) p4vhelp p4v-gs.pdf : $(AllP4) p4-doc manuals p4v-gs p4v-gs.pdf ;
CopyRec p4v-dist : $(rscdir) p4vhelp p4v-gs_ja.pdf : $(AllP4) p4-doc manuals p4v-gs p4v-gs_ja.pdf ;
## Translation files
for _f in $(qtcmd)_$(QtLanguages).qm
{
CopyRec p4v-dist : $(rscdir) translations $(_f) : $(_f) ;
}
CopyRec p4v-dist : $(rscdir) translations msg_ja.txt : $(AllP4) p4-offline translations msg_ja.txt ;
## Example files
local examples = basic_p4vdefaults.xml
basic_p4vfeatures.xml
p4vdefaults.xml
p4vfeatures.xml ;
for _f in $(examples)
{
CopyRec p4v-dist : $(rscdir) examples $(_f) : $(AllP4) p4-qt doc $(_f) ;
}
MakeQtConf p4v-dist : $(bindir) ;
LOCATE on $(<) = $(EXEC) ;
Depends $(<) : p4v-dist ;
Depends all : $(<) ;
MkDistArchive $(<) : $(topdir) ;
}
rule MakeP4Vdist_macosx
{
local apps = p4v p4merge p4admin ;
local Contents Resources ;
local _f ;
LOCATE on $(<) = $(EXEC) ;
Depends $(<) : p4v-dist ;
Depends p4v-dist : $(apps) ;
# For each app, do the following:
# * Copy in frameworks and plugins
# * Copy in common image resources.
# * Generate qt.conf
# * Fix dylib references in exe and install VersionCheck wrapper
local app ;
for app in $(apps)
{
Contents = $(EXEC) $(app).app Contents ;
Resources = $(Contents) Resources ;
CopyRec p4v-dist : $(Contents) Frameworks : $(EXEC_LIB) Frameworks ;
CopyRec p4v-dist : $(Contents) PlugIns : $(EXEC_LIB) PlugIns ;
CopyRec p4v-dist : $(Resources) translations : $(EXEC_LIB) translations ;
CopyRec p4v-dist : $(Resources) images.rcc : images.rcc ;
CopyRec p4v-dist : $(Resources) empty.lproj : /dev/null ;
# Translation files
for _f in $(app)_$(QtLanguages).qm
{
CopyRec p4v-dist : $(Resources) translations $(_f) : $(_f) ;
}
MakeQtConf p4v-dist : $(Resources) ;
local _real = [ FDirName $(Contents) MacOS $(app) ] ;
# Must use the same grist here as in QtMacPackage.
_real = $(_real:G=$(app)) ;
_real = $(_real).real ;
Depends p4v-dist : $(_real) ;
Depends $(_real) : $(app) ;
MacP4VdyldFixup $(_real) : $(app) ;
}
#
# app-specific prep for p4v.app
#
Resources = $(EXEC) p4v.app Contents Resources ;
MacP4Vassistant p4v-dist : $(Resources) : $(AllP4) p4-qt apps p4v img p4v_help.icns ;
for _f in $(QtLanguages)
{
CopyRec p4v-dist : $(Resources) Help p4vhelp_$(_f).qhc : $(AllP4) p4-doc help p4v-html-pure $(_f) p4vhelp_$(_f).qhc ;
CopyRec p4v-dist : $(Resources) Help p4vhelp_$(_f).qch : $(AllP4) p4-doc help p4v-html-pure $(_f) p4vhelp_$(_f).qch ;
}
CopyRec p4v-dist : $(Resources) Help p4v-gs.pdf : $(AllP4) p4-doc manuals p4v-gs p4v-gs.pdf ;
CopyRec p4v-dist : $(Resources) Help p4v-gs_ja.pdf : $(AllP4) p4-doc manuals p4v-gs p4v-gs_ja.pdf ;
# Offline broker and p4d components
CopyRec p4v-dist : $(Resources) p4d : [ MakeP4Vdist_macosx_compute_p4d_directory ] p4d ;
CopyRec p4v-dist : $(Resources) p4ob : p4ob ;
CopyRec p4v-dist : $(Resources) translations msg_ja.txt : $(AllP4) p4-offline translations msg_ja.txt ;
local examples = basic_p4vdefaults.xml
basic_p4vfeatures.xml
p4vdefaults.xml
p4vfeatures.xml ;
for _f in $(examples)
{
CopyRec p4v-dist : $(Resources) examples $(_f) : $(AllP4) p4-qt doc $(_f) ;
}
#
# app-specific prep for p4merge.app
#
Resources = $(EXEC) p4merge.app Contents Resources ;
MacP4Vassistant p4v-dist : $(Resources) : $(AllP4) p4-qt apps p4merge img p4_merge_help.icns ;
for _f in $(QtLanguages)
{
CopyRec p4v-dist : $(Resources) Help p4mergehelp_$(_f).qhc : $(AllP4) p4-doc help p4merge $(_f) p4mergehelp_$(_f).qhc ;
CopyRec p4v-dist : $(Resources) Help p4mergehelp_$(_f).qch : $(AllP4) p4-doc help p4merge $(_f) p4mergehelp_$(_f).qch ;
}
CopyRec p4v-dist : $(Resources) launchp4merge : p4merge_mac_shim ;
#
# app-specific prep for p4admin.app
#
Resources = $(EXEC) p4admin.app Contents Resources ;
# TODO: p4admin assistant may need its own icon; check with dev
MacP4Vassistant p4v-dist : $(Resources) : $(AllP4) p4-qt apps p4v img p4v_help.icns ;
for _f in $(QtLanguages)
{
CopyRec p4v-dist : $(Resources) Help p4adminhelp_$(_f).qhc : $(AllP4) p4-doc help p4admin-html-pure $(_f) p4adminhelp_$(_f).qhc ;
CopyRec p4v-dist : $(Resources) Help p4adminhelp_$(_f).qch : $(AllP4) p4-doc help p4admin-html-pure $(_f) p4adminhelp_$(_f).qch ;
}
buildDMG $(<) : $(EXEC:G=dir)/$(apps:S=.app) ;
}
rule MakeP4Vdist_macosx_compute_p4d_directory
{
# Finding the server executable for the offline component of p4v on
# the mac is slightly nasty because we build with OS=MACOSX for the
# Qt components, and OS=DARWIN for the server component.
#
# Furthermore, we have to keep a map of the corresponding OSVER
# numbers between OSX and Darwin. And, we want to use the nightly
# builds of the server if we are making a nightly build.
local _darwin_osver ;
switch $(OSVER)
{
case 104 : _darwin_osver = 80 ;
case 105 : _darwin_osver = 90 ;
}
local _platform = darwin $(_darwin_osver) $(OSPLAT:L) ;
local _path = $(AllP4) p4-bin bin.$(_platform:J="") $(BUILD) ;
return $(_path) ;
}
rule MacP4Vassistant
{
# Install the assistant into app's resources directory.
# The assistant comes straight from the TrollTech distribution for
# now, though someday we may make our own branded version.
local target = $(1) ;
local Resources = [ FDirName $(2) ] ;
local icons = [ FDirName $(3) ] ;
local assistant_tar = assistant_dyn.tar ;
LOCATE on $(assistant_tar) = $(EXEC_LIB) ;
local dst = <$(Resources)>Assistant.app ;
MakeLocate $(dst) : $(Resources) ;
Depends $(target) : $(dst) ;
ASSISTANT_ICONS on $(dst) = $(icons) ;
MacP4Vassistant_install $(dst) : $(assistant_tar) ;
local asst_Resources = $(Resources) Assistant.app Contents Resources ;
MakeQtConf $(dst) : $(asst_Resources) ;
CopyRec $(target) : $(asst_Resources) translations : $(EXEC_LIB) translations ;
}
# Untar the assistant tar file and copy our custom icon into the assistant.
actions MacP4Vassistant_install
{
tar -xpvf $(>) -C $(<:P)
cp $(ASSISTANT_ICONS) $(<)/Contents/Resources/assistant.icns
}
# The copying of SystemVersionCheck ideally should be a separate
# rule/action, but it's difficult to get Jam to replace one file
# with another except incidentally, and here we are kind of moving
# (and modifying) the original target, so here is as good a place
# as any to do it.
actions MacP4VdyldFixup
{
$(CP) -p "$(>)" "$(<)" || exit 1
otool -X -L "$(<)" \
| sed -n \
-e '/@executable_path/d' \
-e 's/ *(compat.*//' \
-e 's/^[ ]*//' \
-e '/^\//!p' \
| while read dep ; do
toprel=`echo "$dep" \
| sed -e 's=.*/\([^/]*.framework/\)=\1=' \
-e 's=^/.*/=='`
new=@executable_path/../Frameworks/$toprel
install_name_tool -change "$dep" "$new" "$(<)"
done
$(CP) $(EXEC_LIBEXEC)/SystemVersionCheck "$(>)"
}
actions buildDMG
{
$(AllP4)/tools/scripts/buildDMG.pl \
-debug \
-compressionLevel 9 \
-buildDir $(EXEC) \
-dmgName $(<:B) \
-volName $(<:B) \
$(>)
}
rule MakeQtConf
{
local target = $(1) ;
local dir = [ FDirName $(2:G=) ] ;
local qtconf = <$(dir)>qt.conf ;
MakeLocate $(qtconf) : $(dir) ;
Depends $(target) : $(qtconf) ;
MakeQtConf1 $(qtconf) ;
MODE on $(qtconf) = $(FILEMODE) ;
Chmod $(qtconf) ;
}
actions MkTarArchive
{
tar -cf $(<) -C $(>:P) $(>:BE)$(>:SE)
}
actions MkZipArchive
{
cd $(<:P)
zip -9 -r -q $(<:BE)$(<:SE) $(>:BE)$(>:SE)
}
actions MkComressedTarArchive
{
tar -cf - -C $(>:P) $(>:BE)$(>:SE) | $(COMPRESS) > $(<)
}
actions Unix2Dos
{
unix2dos -q $(<) ;
}
rule LinkSmartHeap
{
if $(SMARTHEAP) = yes
{
local _64 = "" ;
local d = "" ;
if $(OSPLAT) = X86_64 || $(OSPLAT) = X64 { _64 = 64 ; }
if $(TYPE) = g { d = d ; }
switch $(OS)-$(OSVER:E)-$(OSPLAT:E)-$(OSCOMP:E)
{
case NT-*-X*-* :
SMARTHPLIB ?= $(EXEC_LIB)\\shlSMP$(_64)Mt$(d).lib ;
local e = [ FAppendSuffix $(<) : $(SUFEXE) ] ;
LINKLIBS on $(e) = $(SMARTHPLIB) $(LINKLIBS) ;
case LINUX-*-X86*-* :
SMARTHPLIB ?= $(EXEC_LIB)/libsmartheapC$(d)$(_64).a
$(EXEC_LIB)/libsmartheap$(d)$(_64).a ;
# Per-target LINKLIBS need to incorporate global libs
# too (e.g. libsupc++), but they should come after the
# smartheap libs.
LINKLIBS on $(<) = $(SMARTHPLIB) $(LINKLIBS) ;
# 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.
LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-z,muldefs ;
}
}
}
#################################################
#
# Section 5. 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 ;
switch $(TYPE_DEBUG)
{
case true : _lf += /DEBUG ;
case * : _lf += /MAP ;
}
_lf += /DLL ;
_lf += /INCREMENTAL:NO ;
_lf += /NODEFAULTLIB:"libcmt" ;
_lf += /NODEFAULTLIB:"libc" ;
switch $(OSPLAT)
{
case X86 : _lf += /MACHINE:x86 ;
case X64 : _lf += /MACHINE:x64 ;
}
LINKFLAGS on $(<) = $(LINKFLAGS) $(_lf) ;
if $(OSPLAT) != X64 {
LINKLIBS on $(<) =
$(P4GT)/htmlhelp/htmlhelp.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 $(2) ;
}
else {
LINKLIBS on $(<) =
$(P4GT)/htmlhelp/htmlhelp_x64.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 $(2) ;
}
}
rule P4GTDefines
{
if $(MSVSVER) >= 8 {
C++FLAGS += /Zc:wchar_t- ;
WinDefines /GR : _USRDLL _WINDLL NT_PLUGIN ;
}
else
{
WinDefines /GR /GX : _USRDLL _WINDLL NT_PLUGIN ;
}
#
# Setting environment variable "LANG=ja" triggers Japanese
# localized P4GT builds only.
#
switch $(LANG)
{
case ja : C++FLAGS += /DLANG_ja ;
}
}
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) ;
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 deeply 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
# directory "lupdate.merged_ts" 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.$(OS:L)$(OSVER:EL)$(OSPLAT:EL) ;
if $(LUPDATE_MERGE) { tmpdir = lupdate.merged_ts ; }
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 ] ;
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
BoostHdrs ;
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 $(MSVSVER) >= 8
{
# 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 ;
}
}
}
SubDirC++Flags [ FDefines $(_d) ] $(_f) ;
}
rule QtCoreHeaders
{
QtAllHeaders : Qt 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 =
Qt
QtCore
QtGui
QtAssistant
QtNetwork
QtWebKit
QtXml
QtXmlPatterns ;
}
if $(OS) = NT || $(OS) = MACOSX
{
QtModules += phonon ;
}
if $(QTOPENGL) != no
{
QtModules += QtOpenGL ;
}
for module in $(QtModules)
{
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)
{
SubDirHdrs [ FDirName $(QTDIR) lib $(module).framework Headers ] ;
}
}
SubDirHdrs [ FDirName $(QTDIR) include ] ;
SubDirHdrs $(LOCATE_SOURCE[1]) ;
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 $(TESTS) # 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 :
LINKFLAGS on $(_t) +=
# -Wl,-rpath,$(QTDIR)/lib
-L$(QTDIR)/lib
-L/usr/X11R6/lib
$(LINKFLAGS) $(dev_LINKFLAGS) ;
if ! $(TYPE_DYNAMIC)
{
QT4LIBLIST_STATIC +=
Xrender
Xrandr
Xcursor
fontconfig
SM
Xfixes
X11
m ;
}
LINKLIBS on $(_t) +=
-l$(QT4LIBLIST)$(QT_LIBINFIX:E)
-l$(QT4LIBLIST_STATIC)
-pthread
/usr/local/lib/libiconv.a
$(LINKLIBS) $(dev_LINKLIBS) ;
case SOLARIS :
LINKFLAGS on $(_t) +=
-L$(QTDIR)/lib
-L/usr/X11R6/lib
-L/usr/openwin/lib
-L/usr/sfw/lib
-L/opt/lude/lib
$(LINKFLAGS) $(dev_LINKFLAGS) ;
if $(TYPE_DYNAMIC)
{
if $(_rpath) != "NULL"
{
LINKFLAGS on $(_t) += -Wl,-R,'$(_rpath)' ;
}
LINKFLAGS on $(_t) += -Wl,-R,/usr/sfw/lib ;
}
else # ! $(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 ;
}
LINKLIBS on $(_t) +=
-l$(QT4LIBLIST)$(QT_LIBINFIX:E)
-l$(QT4LIBLIST_STATIC)
-lm -lpthread -lrt
$(LINKLIBS) $(dev_LINKLIBS) ;
case LINUX :
if $(TYPE_DYNAMIC) && $(_rpath) != "NULL"
{
LINKFLAGS on $(_t) += -Wl,-rpath,'$(_rpath)' ;
}
switch $(OSPLAT)
{
case X86 :
LINKFLAGS on $(_t) +=
-L$(QTDIR)/lib
-L/usr/X11R6/lib
$(LINKFLAGS) $(dev_LINKFLAGS) ;
case X86_64 :
LINKFLAGS on $(_t) +=
-L$(QTDIR)/lib
-L/usr/X11R6/lib64
$(LINKFLAGS) $(dev_LINKFLAGS) ;
}
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 ;
}
LINKLIBS on $(_t) +=
-l$(QT4LIBLIST)$(QT_LIBINFIX:E)
-l$(QT4LIBLIST_STATIC)
-pthread
$(LINKLIBS) $(dev_LINKLIBS) ;
case MACOSX :
# QtWebKit 4.5.0 and later depend on this framework.
QT4LIBLIST += phonon ;
LINKFLAGS on $(_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
$(dev_LINKFLAGS) ;
LINKLIBS on $(_t) += $(LINKLIBS)
# This is already on the global LINKLIBS
#-framework ApplicationServices ;
#-framework Foundation ;
-framework QuickTime
-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) ;
}
LINKLIBS on $(_t) += $(dev_LINKLIBS) ;
if $(_opt) != "console"
{
QtMacPackage $(<) ;
}
case NT :
QT4LIBLIST += phonon ;
# warn about non-dynamic builds on NT
if ! $(TYPE_DYNAMIC) && ! $(QTWARNED)
{
echo Warning: you really want jam -sTYPE=dyn for QT on NT. ;
QTWARNED = 1 ;
}
# no dos box unless debug
if $(_opt) = "console"
{
LINKFLAGS on $(_t) += $(LINKFLAGS) /subsystem:console ;
}
else if ! $(TYPE_DEBUG)
{
LINKFLAGS on $(_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 ] ;
LINKLIBS on $(_t) = [ 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
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 really want jam -sTYPE=dyn for QT on NT. ;
QTWARNED = 1 ;
}
LINKFLAGS on $(<) += $(LINKFLAGS) /DLL ;
echo Warning: you are building a dll $(LINKFLAGS) ;
# no dos box unless debug
if ! $(TYPE_DEBUG)
{
LINKFLAGS on $(<) += $(LINKFLAGS) /subsystem:windows ;
}
# advertise symbols available
if $(TYPE_DEBUG) && $(MSVSVER) >= 9
{
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 ] ;
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 ! $(TYPE_DEBUG) { RmTemps $(mobj) : $(mcpp) ; }
if ! $(TYPE_DEBUG) { 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 ! $(TYPE_DEBUG) { RmTemps $(obj) : $(cpp) ; }
}
}
# Source file rules
rule FSplit
{
# string : delim (default /)
local s = $(>:E=/) ;
local x = [ MATCH ([^$(s)]*)$(s)(.*) : $(<) ] ;
if ! $(x) { return $(<) ; }
return $(x[1]) [ FSplit $(x[2]) : $(>) ] ;
}
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 $(<) : $(LOCATE_SOURCE) ;
}
actions QtMoc
{
$(QTMOC) -DOS_$(OS) $(>) -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 $(<) : $(LOCATE_SOURCE) ;
}
# don't include dir name in x.h
actions QtUicCpp
{
$(QTUIC) $(>[1]) -i $(>[2]:D=) -o $(<)
}
rule QtUicHdr
{
# QtUicHdr x.h : x.ui ; - preprocess with uic to make .h
NotFile src ;
Depends src : $(<) ;
Depends all : $(<) ;
Depends $(<) : $(>) ;
Clean clean : $(<) ;
SEARCH on $(>) = $(SEARCH_SOURCE) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
}
actions QtUicHdr
{
$(QTUIC) $(>) -o $(<)
}
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) p4api include ;
SubDirHdrs $(P4QT) 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. 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)
{
actions updated together piecemeal Archive {
pushd $(<:D)
if exist $(<:BS) set _$(<:B)_=$(<:BS)
$(AR) /nologo /out:$(<:BS) %_$(<:B)_% $(>:BS)
popd
}
# When embedding a manifest, the resource id should be 1 for exe files,
# 2 for dlls. Various P4-GT plugins require 1, despite being dlls.
# P4-GT targets are identified with the prefix string "P4GT".
actions Link bind NEEDLIBS DEFFILE
{
$(LINK) $(LINKFLAGS) /out:$(<) /def:$(DEFFILE) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
set _target=$(<)
set _file=%_target:$(ALL_LOCATE_TARGET)$(SLASH)=%
set _rsrc=1
if /i %_target:~-3,3% neq exe set _rsrc=2
if /i %_file:~0,4% equ P4GT set _rsrc=1
if exist $(<).manifest mt -manifest $(<).manifest -outputresource:$(<);%_rsrc%
}
}
if $(NT)
{
actions Cc
{
$(CC) /c /Fo$(<) /Fd$(PDBDIR)\ $(CCFLAGS) $(CCDEFS) "$(CCHDRS)" "/I$(STDHDRS)" $(>)
}
actions C++
{
$(C++) /c /Fo$(<) /Fd$(PDBDIR)\ $(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 $(<) set ERRORLEVEL=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)
}
}
#
# MakeQtConf
#
if $(OS) = MACOSX
{
actions MakeQtConf1
{
echo "[paths]" > $(<)
echo "plugins = PlugIns" >> $(<)
echo "translations = Resources/translations" >> $(<)
}
}
else if $(UNIX)
{
actions MakeQtConf1
{
echo "[paths]" > $(<)
echo "plugins = ../lib/p4v/qt4/plugins" >> $(<)
echo "translations = ../lib/p4v/P4VResources/translations" >> $(<)
}
}
else if $(NT)
{
actions MakeQtConf1
{
echo "[paths]" > $(<)
echo "plugins = plugins" >> $(<)
echo "translations = translations" >> $(<)
}
}
#################################################
#
# Section 10. Useful miscellanea
#
#################################################
# Tell the user where the top of the code tree is.
#
# For example if you were in say, some arbitrary working directory
# deeply under p4-qt/..., how could you easily get back to the
# p4-bin directory?
#
# $ alias topdir='jam locate-topdir 2>&1 | sed -ne "/^TOPDIR=/s///p"'
# $ cd `topdir`/p4-bin
#
# This is probably more useful for scripts, however.
rule LocateTopDir
{
local loc = [ FSubDirPath AllP4 ] ;
NOTFILE $(loc:G=locate) ;
EchoLocate $(<) : $(loc:G=locate) ;
}
actions EchoLocate
{
echo "TOPDIR=$(>:G=:E=.)" ;
}
LocateTopDir locate-topdir ;
# end of Jamrules