moved files around

This commit is contained in:
ejcoumans
2006-05-25 19:18:29 +00:00
commit e061ec1ebf
1024 changed files with 349445 additions and 0 deletions

151
mk/jam/application.jam Normal file
View File

@@ -0,0 +1,151 @@
#============================================================================
# Rules for compiling applications
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# Use a more sensible and typical mode for executables than Jam's default.
if "$(EXEMODE)" = "711" { EXEMODE = "+x" ; }
## Application appname : sources [ : options ]
## Build an application out of sourcefiles. All sourcefiles will be passed
## to the Objects rule which tries to compile them into object-files. You
## can create rules for your own filetypes with the UserObject rule. Header
## files will just be ignored. They are only used for MSVC projectfile
## generation.
## Possible options are "noinstall" if you don't want a default install
## target to be created and "console" if you're building a console
## application (an application without any graphical output which is
## intended to be used on commandline)
## Some notes: You should not add the .exe extension to the appname - jam
## will do that on win32.
## Options:
## console: Create a console application
## noinstall: Do not set up a default installation targets.
## independent: The target will not be made a dependency of the apps and
## all target.
## nohelp: Do not invoke Help for this target.
## notest: Do not set up unit-testing support for this target.
## nomanifest: (Win32/MSVC) Don't generate manifest for application.
rule Application
{
# check options
CheckOptions noinstall console independent nohelp notest nomanifest : $(3) : $(<) ;
local target = [ ConstructApplicationTarget $(<) : $(3) ] ;
local sources = [ DoSourceGrist $(>) ] ;
local objects = [ CompileObjects $(sources) ] ;
$(<)_TYPE = application ;
$(<)_OBJECTS = $(objects) ;
$(<)_SOURCES = $(sources) ;
$(<)_TARGET = $(target) ;
# create target clean rule
Always $(<)clean ;
NotFile $(<)clean ;
Clean $(<)clean : $(objects) ; # create target clean rule
# so 'jam foo' works when it's really foo.exe (Windows) or foo.app (MacOS/X)
if $(target) != $(<)
{
Depends $(<) : $(target) ;
NotFile $(<) ;
}
# make dependency on apps target
if ! [ IsElem independent : $(3) ]
{
Depends apps : $(<) ;
}
# construct Install target
if ! [ IsElem noinstall : $(3) ]
{
local install_opts ;
if [ IsElem console : $(3) ]
{
install_opts += console ;
}
SystemInstallApplication $(target) : : $(install_opts) ;
}
# Link
MakeLocate $(target) : $(LOCATE.TARGETS) ;
SystemLinkApplication $(<) : $(objects) : $(3) ;
CFlags $(<) : $(APPLICATION.CFLAGS) ;
LFlags $(<) : $(LINKLIBS) $(APPLICATION.LFLAGS) ;
if ! [ IsElem nohelp : $(3) ]
{
local desc = [ Description $(<) ] ;
if ! $(desc) { desc = "$(<) application" ; }
Help $(<) : "Build the $(desc)" ;
}
if ! [ IsElem notest : $(options) ]
{
# @@@ Disabled for now; see docs/todo_jam.txt
#UnitTest $(<) ;
}
}
## ShellScript scriptname : rule [ : options ]
## Build a shell script by invoking `rule', the script creation rule, which
## is passed `scriptname' and `options'.
## Options:
## noinstall: Do not set up a default installation target.
## nohelp: Do not invoke Help for this target.
rule ShellScript
{
CheckOptions noinstall nohelp : $(3) : $(<) ;
Always $(<)clean ;
NotFile $(<)clean ;
Clean clean : $(<) ;
Clean $(<)clean : $(<) ;
Depends apps : $(<) ;
MakeLocate $(<) : $(LOCATE.TARGETS) ;
if ! [ IsElem noinstall : $(3) ]
{
Depends install_bin : [ DoInstall $(<) : $(bindir) : $(INSTALL_PROGRAM) ] ;
}
$(2) $(<) : $(3) ;
MODE on $(<) = $(EXEMODE) ;
SUBDIR on $(<) = $(SUBDIR) ;
Chmod $(<) ;
if ! [ IsElem nohelp : $(3) ]
{
local desc = [ Description $(<) ] ;
if ! $(desc) { desc = "$(<) script" ; }
Help $(<) : "Build the $(desc)" ;
}
}
#----------------------------------------------------------------------------
# private part
# Construct pseudo target apps which is used instead of the pseudo target exe
# in Jambase
Depends exe : apps ;
NotFile apps ;
Help apps : "Build all applications" ;

50
mk/jam/assembler.jam Normal file
View File

@@ -0,0 +1,50 @@
#============================================================================
# Rules for handling assembler files
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
if $(CMD.NASM)
{
rule NasmRule
{
local object = [ DoObjectGrist [ PrefixSuffix $(>)_ : $(<) : $(SUFOBJ) ] ] ;
Nasm $(object) : $(<) ;
return $(object) ;
}
RegisterFileType NasmRule : .asm ;
rule Nasm
{
Depends $(<) : $(>) ;
NASM.FLAGS on $(<) += $(NASM.FLAGS) ;
# NASM doesn't scan for headers in current dir of the files, so add the dir of
# the file to the -I flags
local includeflags = [ FIncludes $(SEARCH_SOURCE)/$(<:D) $(SUBDIRHDRS) $(HDRS) ] ;
# NASM requires that -I paths have a trailing slash.
INCLUDEFLAGS on $(<) = $(includeflags)$(SLASH) ;
}
NASM.HDRPATTERN = "^[ ]*%[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
RegisterHeaderRule HeaderRule : $(NASM.HDRPATTERN) : .asm .ash ;
actions Nasm
{
$(CMD.NASM) $(NASM.FLAGS) $(INCLUDEFLAGS) -o $(<) $(>)
}
}

165
mk/jam/bisonflex.jam Normal file
View File

@@ -0,0 +1,165 @@
#============================================================================
# Rules for flex and bison
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
if $(CMD.FLEX)
{
# Some versions of Flex-generated files want to include <unistd.h> which is
# not normally available on Windows, so we need to protect it. We also
# filter out CVS `Header' keywords in order to prevent CVS from thinking that
# the file has changed simply because the Header information is different.
FLEX.SED_SCRIPT =
"'s/\\([ ]*#[ ]*include[ ][ ]*<unistd.h>\\)/#ifndef WIN32\\
\\1\\
#endif/;/\$Header:/d'" ;
# Compilers such as MSVC do not like #line directives. Since the generated
# file might get stored in CVS and used by MSVC users (even if generated on
# Unix, for instance), we want to suppress #line directives in all cases.
FLEX.FLAGS += -L ;
rule FlexRule
{
local object ;
local cfile = [ DoObjectGrist $(<:S=.c) ] ;
MakeLocate $(cfile) : $(LOCATE_TARGET) ;
SEARCH on $(cfile) = $(LOCATE_TARGET) ;
Flex $(cfile) : $(<) ;
object = [ CompileObjects $(cfile) : $(>) ] ;
return $(object) ;
}
RegisterFileType FlexRule : .l ;
rule Flex++Rule
{
local object ;
local cppfile = [ DoObjectGrist $(<:S=.cpp) ] ;
MakeLocate $(cppfile) : $(LOCATE_TARGET) ;
SEARCH on $(cppfile) = $(LOCATE_TARGET) ;
Flex $(cppfile) : $(<) ;
object = [ CompileObjects $(cppfile) : $(>) ] ;
return $(object) ;
}
RegisterFileType Flex++Rule : .ll ;
rule Flex
{
Depends $(<) : $(>) ;
FLEX.FLAGS on $(<) += $(FLEX.FLAGS) ;
}
# Use -t and output redirection to avoid flex choosing undesirable names for
# its output files. Also apply FLEX.SED_SCRIPT.
actions Flex
{
$(CMD.FLEX) -t $(FLEX.FLAGS) $(>) | $(SED) $(FLEX.SED_SCRIPT) > $(<)
}
}
if $(CMD.BISON)
{
rule BisonRule
{
local object ;
local cfile = [ DoObjectGrist $(<:S=.c) ] ;
local headerfile = [ DoObjectGrist $(<:S=.h) ] ;
# Jam's header file scannning doesn't use grist so we have to workaround
# this here.
Includes $(headerfile:G=$(SOURCE_GRIST:E)!$(SUBVARIANT:J=!)) : $(headerfile) ;
MakeLocate $(cfile) $(headerfile) : $(LOCATE_TARGET) ;
BISON.FLAGS on $(cfile) =
[ on [ DoSourceGrist $(<:S=.c) ] GetVar BISON.FLAGS ] ;
Bison $(cfile) : $(<) ;
# Work around for jam warning about independant target when we put both
# headerfile and cppfile in the bison line...
Includes $(cppfile) : $(headerfile) ;
object = [ CompileObjects $(cfile) : $(>) ] ;
SEARCH on $(cfile) = $(LOCATE_TARGET) ;
SEARCH on $(headerfile) = $(LOCATE_TARGET) ;
return $(object) ;
}
RegisterFileType BisonRule : .y ;
rule Bison++Rule
{
local object ;
local cppfile = [ DoObjectGrist $(<:S=.cpp) ] ;
local headerfile = [ DoObjectGrist $(<:S=.hpp) ] ;
# Jam's header file scannning doesn't use grist so we have to workaround
# this here.
Includes $(headerfile:G=$(SOURCE_GRIST:E)!$(SUBVARIANT:J=!)) : $(headerfile) ;
MakeLocate $(cppfile) : $(LOCATE_TARGET) ;
MakeLocate $(headerfile) : $(LOCATE_TARGET) ;
BISON.FLAGS on $(cppfile) =
[ on [ DoSourceGrist $(<:S=.cpp) ] GetVar BISON.FLAGS ] ;
Bison $(cppfile) : $(<) ;
# Work around for jam warning about independant target when we put both
# headerfile and cppfile in the bison line...
Includes $(cppfile) : $(headerfile) ;
object = [ CompileObjects $(cppfile) : $(>) ] ;
SEARCH on $(cppfile) = $(LOCATE_TARGET) ;
SEARCH on $(headerfile) = $(LOCATE_TARGET) ;
return $(object) ;
}
RegisterFileType Bison++Rule : .yy ;
rule Bison
{
Depends $(<) : $(>) ;
BISON.FLAGS on $(<) += $(BISON.FLAGS) ;
}
rule BisonFlags
{
local target ;
if $(<:S) = .yy
{
target = [ DoSourceGrist $(<:S=.cpp) $(<:S=.hpp) ] ;
}
else
{
target = [ DoSourceGrist $(<:S=.c) $(<:S=.h) ] ;
}
BISON.FLAGS on $(target) += $(>) ;
}
# Compilers such as MSVC do not like #line directives. Since the generated
# file might get stored in CVS and used by MSVC users (even if generated on
# Unix, for instance), we want to suppress #line directives in all cases.
BISON.FLAGS += --no-lines ;
actions Bison
{
$(CMD.BISON) -d $(BISON.FLAGS) -o $(<[1]) $(>)
}
}

82
mk/jam/build.jam Normal file
View File

@@ -0,0 +1,82 @@
#============================================================================
# Main rules file - Includes all important rulefiles in correct order
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# Enable if you want debug messages.
JAM_DEBUG ?= 1 ;
jamrulesdir = $(TOP)/mk/jam ;
# Utility and compatibility rules used by all other scripts.
include $(jamrulesdir)/jamcompatibility.jam ;
include $(jamrulesdir)/subdir.jam ;
include $(jamrulesdir)/property.jam ;
# This needs to be included before _and_ after all other includes (except the
# super low-level utility files above) since it optionally overrides built-in
# rules to glean information about targets being defined.
include $(jamrulesdir)/dump.jam ;
include $(jamrulesdir)/options.jam ;
include $(jamrulesdir)/variant.jam ;
include $(jamrulesdir)/resource.jam ;
include $(jamrulesdir)/helper.jam ;
include $(jamrulesdir)/help.jam ;
include $(jamrulesdir)/groups.jam ;
include $(jamrulesdir)/install.jam ;
include $(jamrulesdir)/clean.jam ;
include $(jamrulesdir)/objects.jam ;
include $(jamrulesdir)/compiler.jam ;
include $(jamrulesdir)/objectivec.jam ;
include $(jamrulesdir)/assembler.jam ;
include $(jamrulesdir)/bisonflex.jam ;
include $(jamrulesdir)/swig.jam ;
include $(jamrulesdir)/flags.jam ;
include $(jamrulesdir)/library.jam ;
include $(jamrulesdir)/static.jam ;
include $(jamrulesdir)/application.jam ;
include $(jamrulesdir)/plugin.jam ;
include $(jamrulesdir)/docs.jam ;
include $(jamrulesdir)/unittest.jam ;
# Include OS specific rules
switch $(TARGET.OS)
{
case WIN32 :
include $(jamrulesdir)/win32.jam ;
case MACOS_X :
include $(jamrulesdir)/macosx.jam ;
case UNIX :
include $(jamrulesdir)/unix.jam ;
case * :
echo "WARNING: TARGET.OS not defined. Using unix" ;
include $(jamrulesdir)/unix.jam ;
}
# This needs to be included after all others because it overrides some of the
# earlier defined rules when enabled. It even overrides Win32 rules, so it
# needs to be after platform-specific includes, as well.
include $(jamrulesdir)/msvcgen.jam ;
# This needs to included be before _and_ after all other includes since it
# optionally overrides rules defined earlier.
include $(jamrulesdir)/dump.jam ;

37
mk/jam/clean.jam Normal file
View File

@@ -0,0 +1,37 @@
#============================================================================
# Rules for cleaning build detritus.
# Copyright (C)2003 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# CleanDir <tag> : <dir> ...
# Forcibly delete a set of directories, even if they are not empty.
# Tag is one of the standard targets used with the "Clean" rule, such as
# "clean" or "distclean".
rule CleanDir
{
Always $(<) ;
NotFile $(<) ;
NoCare $(>) ;
}
actions piecemeal together existing CleanDir
{
$(DELTREE) $(>)
}
Help clean : "Remove all built targets from project" ;

76
mk/jam/compiler.jam Normal file
View File

@@ -0,0 +1,76 @@
#============================================================================
# Rules for C and C++ files
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
if $(CMD.CC)
{
rule CcRule
{
local object =
[ DoObjectGrist [ PrefixSuffix $(>)_ : $(<) : $(SUFOBJ) ] ] ;
Cc $(object) : $(<) ;
return $(object) ;
}
RegisterFileType CcRule : .c ;
RegisterHeaderRule HeaderRule : $(HDRPATTERN) : .c ;
rule Cc
{
Depends $(<) : $(>) ;
CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions Cc
{
$(CMD.CC) -c -o $(<) $(CCHDRS) $(CCFLAGS) $(CCDEFS) $(>)
}
} # end if $(CMD.CC)
if $(CMD.C++)
{
rule C++Rule
{
local object =
[ DoObjectGrist [ PrefixSuffix $(>)_ : $(<) : $(SUFOBJ) ] ] ;
C++ $(object) : $(<) ;
return $(object) ;
}
RegisterFileType C++Rule : .cpp .cc .c++ ;
RegisterHeaderRule HeaderRule : $(HDRPATTERN) : .cpp .cc .c++ ;
rule C++
{
Depends $(<) : $(>) ;
C++FLAGS on $(<) += $(C++FLAGS) $(SUBDIRC++FLAGS) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions C++
{
$(CMD.C++) -c -o $(<) $(CCHDRS) $(C++FLAGS) $(CCDEFS) $(>)
}
} # end if $(CMD:C++)

688
mk/jam/docs.jam Normal file
View File

@@ -0,0 +1,688 @@
#============================================================================
# Rules for creating Documentation
# Copyright (C)2005 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# Do-nothing implementations which avoid Jam error messages if client Jamfiles
# attempt to invoke documantation-generation rules despite lack of availability
# of appropriate tools. This simplifies client Jamfiles since the client does
# not need to check for the presence of the various tools. These rules will be
# re-defined later if the necessary tools are available.
rule Texi2Info { }
rule Texi2HTML { }
rule Texi2DVI { }
rule Texi2PS { }
rule Texi2PDF { }
rule Doxygen { }
rule RepairNodes { }
if $(PERL)
{
PATH.TEXI2HTML.HOME ?= [ ConcatDirs $(TOP) docs support ] ;
PATH.TEXI2HTML ?= [ ConcatDirs $(PATH.TEXI2HTML.HOME) texi2html.pl ] ;
CMD.TEXI2HTML ?= "$(PERL) $(PATH.TEXI2HTML)" ;
}
if $(CMD.MAKEINFO)
{
## Texi2Info targetname : texifiles : outputformat [ : subdir : [ outfile :
## [ options ]]]
## Invoke the makeinfo utility to convert Texinfo source (typically) to Info
## format when the pseudo target 'targetname' is invoked. 'texifiles' is a
## list of Texinfo files to be converted. The first element of 'texifiles'
## should be the top-level Texinfo document which includes the remaining
## files. It is okay for 'texifiles' to mention only a single Texinfo source
## if the entire document is contained in the one file. 'outputformat' is
## one of "info", "html", "xml", or "docbook". If not specified, it
## defaults to "info". The optional 'subdir' is a subdirectory of
## $(LOCATE.DOCS) into which the generated files should be placed. The
## optional 'outfile' is the name of the output file. Some output formats
## may generate multiple output files (such as "outfile.info",
## "outfile-1.info", "outfile-2.info", etc.). If 'outfile' is omitted, then
## the output filename is derived from the first element of 'texifiles' with
## the extension changed to reflect 'outputformat' (one of .info, .html,
## .xml, or .docbook). 'options' is a set of command-line flags passed
## directly to makeinfo. Returns the gristed output file name.
rule Texi2Info
{
local target = $(1) ;
local texifiles = $(2) ;
local format = $(3) ;
local subdir = $(4) ;
local outfile = $(5) ;
local options = $(6) ;
if ! $(format) { format = info ; }
local fmtoptions ;
switch $(format)
{
case info : fmtoptions = ;
case html : fmtoptions = --html ;
case xml : fmtoptions = --xml ;
case docbook : fmtoptions = --docbook ;
}
return [ _Texinfo $(target) : $(texifiles) : $(format) : $(outfile) :
RunMakeInfo : $(fmtoptions) $(options) : $(subdir) ] ;
}
}
if $(CMD.TEXI2HTML)
{
## Texi2HTML targetname : texifiles [ : subdir : [ outfile : [ options ]]]
## Invoke the texi2html utility to convert Texinfo source to HTML format
## when the pseudo target 'targetname' is invoked. 'texifiles' is a list of
## Texinfo files to be converted. The first element of 'texifiles' should
## be the top-level Texinfo document which includes the remaining files. It
## is okay for 'texifiles' to mention only a single Texinfo source if the
## entire document is contained in the one file. The optional 'subdir' is a
## subdirectory of $(LOCATE.DOCS) into which the generated files should be
## placed. The optional 'outfile' is the name of the root output file
## (typically "index.html"). If the input files contain multiple Texinfo
## @nodes, then texi2html may generate multiple output files (depending upon
## local texi2html configuration) based upon the section numbering, and
## 'outfile' will reference the other generated files. If 'outfile' is
## omitted, then the output filename is derived from the first element of
## 'texifiles' with the extension changed to .html. 'options' is a set of
## command-line flags passed directly to texi2html. Returns the gristed
## output file name.
rule Texi2HTML
{
local target = $(1) ;
local texifiles = $(2) ;
local subdir = $(3) ;
local outfile = $(4) ;
local options = $(5) ;
return [ _Texinfo $(target) : $(texifiles) : html : $(outfile) :
RunTexi2HTML : $(options) : $(subdir) ] ;
}
}
if $(CMD.TEXI2DVI)
{
## Texi2DVI targetname : texifiles [ : subdir [ : outfile [ : options ]]]
## Invoke the texi2dvi utility to convert Texinfo source to DVI format when
## the pseudo target 'targetname' is invoked. 'texifiles' is a list of
## Texinfo files to be converted. The first element of 'texifiles' should
## be the top-level Texinfo document which includes the remaining files. It
## is okay for 'texifiles' to mention only a single Texinfo source if the
## entire document is contained in the one file. The optional 'subdir' is a
## subdirectory of $(LOCATE.DOCS) into which the generated file should be
## placed. The optional 'outfile' is the name of the output file. If
## 'outfile' is omitted, then the output filename is derived from the first
## element of 'texifiles' with the extension changed to .dvi. 'options' is a
## set of command-line flags passed directly to texi2dvi. Returns the
## gristed output file name.
rule Texi2DVI
{
return [ _Texi2DVI $(1) : $(2) : $(3) : $(4) : $(5) : dvi ] ;
}
if $(CMD.DVIPS)
{
## Texi2PS targetname : texifile [ : subdir [ : outfile [ : psoptions
## [ : dvioptions ]]]]
## Invoke the texi2dvi and dvips utilities to convert Texinfo source to
## PostScript format when the pseudo target 'targetname' is invoked.
## 'texifiles' is a list of Texinfo files to be converted. The first
## element of 'texifiles' should be the top-level Texinfo document which
## includes the remaining files. It is okay for 'texifiles' to mention only
## a single Texinfo source if the entire document is contained in the one
## file. The optional 'subdir' is a subdirectory of $(LOCATE.DOCS) into
## which the generated file should be placed. The optional 'outfile' is the
## name of the output file. If 'outfile' is omitted, then the output
## filename is derived from the first element of 'texifiles' with the
## extension changed to .ps. 'psoptions' is a set of command-line flags
## passed directly to dvips. 'dvioptions' is a set of command-line flags
## passed directly to texi2dvi. Returns the gristed output file name.
rule Texi2PS
{
local target = $(1) ;
local texifiles = $(2) ;
local subdir = $(3) ;
local outfile = $(4) ;
local psoptions = $(5) ;
local dvioptions = $(6) ;
return [ _Dvi $(target) : $(texifiles) : ps : $(outfile:S=.ps) : RunDVIPS :
$(psoptions) : $(dvioptions) : $(subdir) ] ;
}
}
if $(CMD.DVIPDF)
{
## Texi2PDF targetname : texifiles [ : subdir [ : outfile [ : pdfoptions
## [ : dvioptions ]]]]
## Invoke the texi2dvi and dvipdf utilities to convert Texinfo source to PDF
## format when the pseudo target 'targetname' is invoked. 'texifiles' is a
## list of Texinfo files to be converted. The first element of 'texifiles'
## should be the top-level Texinfo document which includes the remaining
## files. It is okay for 'texifiles' to mention only a single Texinfo source
## if the entire document is contained in the one file. The optional
## 'subdir' is a subdirectory of $(LOCATE.DOCS) into which the generated
## file should be placed. The optional 'outfile' is the name of the output
## file. If 'outfile' is omitted, then the output filename is derived from
## the first element of 'texifiles' with the extension changed to .pdf.
## 'pdfoptions' is a set of command-line flags passed directly to
## dvipdf. 'dvioptions' is a set of command-line flags passed directly to
## texi2dvi. Returns the gristed output file name.
rule Texi2PDF
{
local target = $(1) ;
local texifiles = $(2) ;
local subdir = $(3) ;
local outfile = $(4) ;
local pdfoptions = $(5) ;
local dvioptions = $(6) ;
local pdffile = [ _Dvi $(target) : $(texifiles) : pdf : $(outfile:S=.pdf) :
RunDVIPDF : $(pdfoptions) : $(dvioptions) : $(subdir) ] ;
CONVERTER on $(pdffile) = $(CMD.DVIPDF) ;
return pdffile ;
}
}
else if $(CMD.TEXI2PDF)
{
## Texi2PDF targetname : texifiles [ : subdir [ : outfile [ : options ]]]
## Invoke the texi2pdf utility to convert Texinfo source to PDF format when
## the pseudo target 'targetname' is invoked. 'texifiles' is a list of
## Texinfo files to be converted. The first element of 'texifiles' should
## be the top-level Texinfo document which includes the remaining files. It
## is okay for 'texifiles' to mention only a single Texinfo source if the
## entire document is contained in the one file. The optional 'subdir' is a
## subdirectory of $(LOCATE.DOCS) into which the generated file should be
## placed. The optional 'outfile' is the name of the output file. If
## 'outfile' is omitted, then the output filename is derived from the first
## element of 'texifiles' with the extension changed to .pdf. 'options' is a
## set of command-line flags passed directly to texi2pdf. Returns the
## gristed output file name.
rule Texi2PDF
{
local target = $(1) ;
local texifiles = $(2) ;
local subdir = $(3) ;
local outfile = $(4) ;
local options = $(5) ;
local pdffile = [ _Texinfo $(target) : $(texifiles) : pdf : $(outfile) :
RunTexi2DVI : -I $(SUBDIR) $(options) : $(subdir) ] ;
CONVERTER on $(pdffile) = $(CMD.TEXI2PDF) ;
OPTIONS on $(pdffile) += $(FLAGS.TEXI2PDF) ;
return pdffile ;
}
}
}
if $(PERL)
{
PATH.NODEFIX ?= [ ConcatDirs $(TOP) docs support nodefix.pl ] ;
CMD.NODEFIX ?= $(PERL) $(PATH.NODEFIX) ;
## RepairNodes targetname : texifile [ : srcdir ]
## When 'targetname' is invoked, perform in-place repair of @node and @menu
## directives in 'texifile' so that they correctly reflect the documentation
## hierarchy defined by @chapter, @section, @subsection, etc. directives.
## 'srcdir' is the directory containing 'texifile' as well as any files
## included via @include{} or @import{} directives. If 'srcdir' is omitted,
## then $(SUBDIR) is assumed.
rule RepairNodes
{
local target = $(1) ;
local texifile = $(2) ;
local srcdir = $(3) ;
if ! $(srcdir) { srcdir = $(SUBDIR) ; }
SEARCH on $(texifile) = $(srcdir) ;
TEXINFO.INCDIR on $(target) = $(srcdir) ;
Depends $(target) : $(texifile) ;
NotFile $(target) ;
Always $(target) ;
}
actions RepairNodes
{
$(CMD.NODEFIX) --include-dir="$(TEXINFO.INCDIR)" "$(>)" ;
}
}
if $(CMD.DOXYGEN)
{
actions WriteCppWrapper
{
echo "$(DOXYCPP_COMMAND)" > "$(1)"
}
rule GenerateDoxygenCppWrapper
{
local target = $(1) ;
local cxxcpp = $(2) ;
local outfile cmdpath command ;
if $(TARGET.OS) = WIN32
{
# On Win32, MSYS is not used but the "native" process running, so we can't
# launch the preprocessor with sh.
outfile = "cpp.cmd" ;
local p = [ SplitToList $(LOCATE.DOCS) : "/" ] $(outfile) ;
cmdpath = $(p:J=\\\\) ;
command = "$(cxxcpp)" %1 ;
}
else
{
outfile = "cpp.sh" ;
local p = $(LOCATE.DOCS) $(outfile) ;
cmdpath = $(p:J=/) ;
command = "$(cxxcpp)" \\$1 ;
}
MakeLocate $(outfile) : $(LOCATE.DOCS) ;
DOXYCPP_COMMAND on $(outfile) = $(command) ;
WriteCppWrapper $(outfile) ;
MODE on $(outfile) = "+x" ;
Chmod $(outfile) ;
Always $(outfile) ;
Depends $(target) : $(outfile) ;
Clean $(target)clean : $(outfile) ;
return $(cmdpath) ;
}
## Doxygen targetname : doxyprofile-and-resources [ : subdir [ : outfile
## [ : options ]]]
## Invoke the Doxygen utility to generate API documentation based upon
## 'doxyprofile' when the pseudo target 'targetname' is invoked. The first
## element of 'doxyprofile-and-resources' is the Doxygen configuration file
## which controls the API generation. The remaining optional elements are
## additional resources which should be copied verbatim to the output
## directory. Typical additional resources include CSS and related image
## files. It is assumed that the source files mentioned by
## 'doxyprofile-and-resources' reside in $(SUBDIR). The optional 'subdir'
## is a subdirectory of $(LOCATE.DOCS) into which the generated files should
## be placed. The optional 'outfile' is the name of the root output file
## (typically "index.html"). This file will reference any other files
## generated by Doxygen. If 'outfile' is omitted, then the output filename
## defaults to "index.html". 'options' is a set of command-line flags
## passed directly to Doxygen. Returns the gristed output file name.
rule Doxygen
{
local target = $(1) ;
local infiles = $(2) ;
local subdir = $(3) ;
local outfile = $(4) ;
local optioins = $(5) ;
local doxyfile = $(infiles[1]) ;
local resources = $(infiles[2-]) ;
local outdir = [ FDirName $(LOCATE.DOCS) $(subdir) ] ;
local grist = "$(SOURCE_GRIST)!$(target)" ;
if ! $(outfile)
{
outfile = index.html ;
}
outfile = $(outfile:G=$(grist)) ;
local r ;
for r in $(resources)
{
local src = $(r:G=$(grist)!src) ;
local dst = $(r:G=$(grist)!dst) ;
SEARCH on $(src) = $(SUBDIR) ;
MakeLocate $(dst) : $(outdir) ;
Copy $(dst) : $(src) ;
Depends $(dst) : $(src) ;
Depends $(outfile) : $(dst) ;
Clean $(target)clean : $(dst) ;
}
local doxycpp ;
if $(CMD.C++CPP)
{
doxycpp = [ GenerateDoxygenCppWrapper $(outfile) :
$(CMD.C++CPP) [ FDefines DOXYGEN_RUN ] ] ;
}
local have_dot = "NO" ;
local dot_path ;
if $(CMD.DOT)
{
local dotpath = [ Reverse [ SplitToList $(CMD.DOT) : / ] ] ;
if $(dotpath[1]) != "dot"
{
Echo "doxygen expects the dot binary to be named 'dot' exactly" ;
}
else
{
dot_path = [ Reverse $(dotpath[2-]) ] ;
dot_path = $(dot_path:J=/) ;
have_dot = "YES" ;
}
}
SEARCH on $(doxyfile) = $(SUBDIR) ;
OPTIONS on $(target) = $(options) ;
DOXYCPP on $(target) = $(doxycpp) ;
HAVE_DOT on $(target) = $(have_dot) ;
DOT_PATH on $(target) = $(dot_path) ;
MakeLocate $(outfile) : $(outdir) ;
Depends $(outfile) : $(doxyfile) ;
Depends $(target) : $(outfile) ;
RunDoxygen $(target) : $(doxyfile) ;
NotFile $(target) ;
Always $(target) ;
Clean $(target)clean : $(outfile) ;
if $(subdir)
{
CleanDir $(target)clean : $(outdir) ;
}
Depends cleandoc : $(target)clean ;
return outfile ;
}
}
#----------------------------------------------------------------------------
# Private helper rules and actions.
## _Texinfo targetname : texifiles : format : [ outfile ] : converter
## [ : options [ : subdir ]]
## The workhorse of the various Texinfo conversion rules. This rule sets up
## a pseudo-target 'targetname' which takes care of copying image files to
## the output directory if needed by the output format, gristing intput and
## output files, invoking the specified low-level conversion rule, and
## cleaning up temporary files upon completion. 'texifiles' is a list of
## Texinfo files to be converted. The first element of 'texifiles' should
## be the top-level Texinfo document which @includes the remaining files. It
## is okay for 'texifiles' to mention only a single Texinfo source if the
## entire document is contained in the one file. 'format' is one of "info",
## "html", "xml", "docbook", "dvi", "ps", or "pdf", and is used in the
## formulation of the grist, and as the extension of 'outfile' if omitted.
## The format also determines which type of image files (if any) should be
## copied to the output directory, and whether the copied images should be
## cleaned up upon completion. 'outfile' is the name of the root output
## file. If 'outfile' is omitted, then the output filename is derived from
## the first element of 'texifiles' with the extension changed to reflect
## 'format'. 'converter' is the Jam rule which will perform the actual
## conversion. It is passed 'outfile' as $(<), and the first element of
## 'texifiles' as $(>). The optional 'subdir' is a subdirectory of
## $(LOCATE.DOCS) into which the generated files should be placed.
## 'options' is a set of command-line flags to be passed directly to the
## underlying conversion tool. Returns the gristed output file name. The
## following variables may be accessed from within the 'converter' action:
## $(SRCDIR) - Value of $(SUBDIR) when this rule was invoked.
## $(OUTDIR) - Directory into which output files should be emitted.
## $(OUTLOG) - Name of a log file within $(OUTDIR) into which 'converter'
## may direct diagnostic output of conversion tool if needed.
## $(FORMAT) - Value of 'format'.
## $(OPTIONS) - Value of 'options'.
rule _Texinfo
{
local target = $(1) ;
local texifiles = $(2) ;
local format = $(3) ;
local outfile = $(4) ;
local converter = $(5) ;
local options = $(6) ;
local subdir = $(7) ;
local outdir = [ FDirName $(LOCATE.DOCS) $(subdir) ] ;
local grist = "$(SOURCE_GRIST)!$(target)!$(format)" ;
local outlog ;
local texifile = $(texifiles[1]:G=$(grist)) ;
local texideps = $(texifiles[2-]) ;
if ! $(outfile)
{
outfile = $(texifile:BS=.$(format)) ;
}
outfile = $(outfile:G=$(grist)) ;
outlog = $(outfile:G=:R=$(outdir):S=$(outfile:S)log) ;
local inftypes = .txt ;
local xmltypes = .jpg .png .gif ;
local dvitypes = .eps .pdf ;
local pstypes = .eps ;
local pdftypes = .eps .pdf ;
local imagetypes copyimages ;
switch $(format)
{
case info : imagetypes = $(inftypes) ; copyimages = no ;
case html : imagetypes = $(xmltypes) ; copyimages = yes ;
case xml : imagetypes = $(xmltypes) ; copyimages = yes ;
case docbook : imagetypes = $(xmltypes) ; copyimages = yes ;
case dvi : imagetypes = $(dvitypes) ; copyimages = yes ;
case ps : imagetypes = $(pstypes) ; copyimages = no ;
case pdf : imagetypes = $(pdftypes) ; copyimages = no ;
case * : Error "Texinfo: unrecognized output format" $(format) ;
}
local images ;
if $(imagetypes) { images = [ Recurse : $(imagetypes) ] ; }
local image ;
for image in $(images)
{
local imagegrist = "$(grist)!$(image:D)" ;
local src = $(image:BSG=$(imagegrist)) ;
local srcdir = [ ConcatDirs $(SUBDIR) $(image:D) ] ;
SEARCH on $(src) = $(srcdir) ;
if $(copyimages) = no
{
Includes $(texifile) : $(src) ;
}
else
{
local dst = $(image:BSG=$(imagegrist)built) ;
local dstdir = [ ConcatDirs $(outdir) $(image:D) ] ;
MakeLocate $(dst) : $(dstdir) ;
Copy $(dst) : $(src) ;
Depends $(dst) : $(src) ;
Depends $(outfile) : $(dst) ;
Clean $(target)clean : $(dst) ;
}
}
SRCDIR on $(outfile) = $(SUBDIR) ;
OUTDIR on $(outfile) = $(outdir) ;
OUTLOG on $(outfile) = $(outlog) ;
FORMAT on $(outfile) = $(format) ;
OPTIONS on $(outfile) = $(options) ;
SEARCH on $(texifile) = $(SUBDIR) ;
SEARCH on $(texideps) = $(SUBDIR) ;
Includes $(texifile) : $(texideps) ;
MakeLocate $(outfile) : $(outdir) ;
Depends $(outfile) : $(texifile) ;
Depends $(target) : $(outfile) ;
$(converter) $(outfile) : $(texifile) ;
NotFile $(target) ;
Clean $(target)clean : $(outfile) ;
if $(subdir)
{
CleanDir $(target)clean : $(outdir) ;
}
Depends cleandoc : $(target)clean ;
return $(outfile) ;
}
## _Texi2DVI targetname : texifiles [ : subdir [ : outfile [ : options
## [ : format ]]]]
## A thin wrapper around the _Texinfo rule which invokes TeX-wrapping tools
## such as texi2dvi and texi2pdf. The action for this rule captures the
## output of TeX into a log file and tells the user to consult the log file
## if TeX fails. It also monitors the log file for TeX `hbox' warnings, and
## informs the user to consult the log if any are discovered. The log file
## is removed silently if no problems are detected. Returns the gristed
## output DVI file name. In addition to the variables exported by the
## _Texinfo rule, the following variables may be accessed from within the
## action:
## $(CONVERTER) - The actual command-line tool wrapping TeX.
rule _Texi2DVI
{
local target = $(1) ;
local texifiles = $(2) ;
local subdir = $(3) ;
local outfile = $(4) ;
local options = $(5) ;
local format = $(6) ;
local dvifile = [ _Texinfo $(target) : $(texifiles) : $(format) :
$(outfile) : RunTexi2DVI : -I $(SUBDIR) $(options) : $(subdir) ] ;
CONVERTER on $(dvifile) = $(CMD.TEXI2DVI) ;
OPTIONS on $(dvifile) += $(FLAGS.TEXI2DVI) ;
return $(dvifile) ;
}
## _Dvi targetname : texifiles : format : outfile : converter [ : options
## [ : dvioptions [ : subdir ]]]
## A wrapper around the _Texi2DVI rule which also runs a secondary
## conversion rule/action on the generated DVI file. Examples of secondary
## conversions include dvips, dvipdf, etc. The arguments 'targetname',
## 'format', 'outfile', and 'subdir' have the same meaning as for the
## _Texinfo and _Texi2DVI rules. 'converter' is the rule/action which
## converts the generated DVI file to the final output format. 'options' is
## a set of command-line flags to be passed directly to the underlying
## secondary conversion tool. 'dvioptions' are the command-line options
## passed to _Texi2DVI. As with the _Texi2DVI rule, this rule captures the
## output of the secondary conversion tool to a log file and instructs the
## user to consult it when a problem is detected. Returns the gristed
## output file name.
rule _Dvi
{
local target = $(1) ;
local texifiles = $(2) ;
local format = $(3) ;
local outfile = $(4) ;
local converter = $(5) ;
local options = $(6) ;
local dvioptions = $(7) ;
local subdir = $(8) ;
local dvifile = [ _Texi2DVI _$(target)_dvi : $(texifiles) : $(subdir) :
$(outfile:S=.dvi) : $(dvioptions) : $(format) ] ;
if ! $(outfile)
{
outfile = $(dvifile:BS=.$(format)) ;
}
local outdir = [ FDirName $(LOCATE.DOCS) $(subdir) ] ;
local outlog = $(outfile:G=:R=$(outdir):S=$(outfile:S)log) ;
SRCDIR on $(outfile) = $(SUBDIR) ;
OUTLOG on $(outfile) = $(outlog) ;
FORMAT on $(outfile) = $(format) ;
OPTIONS on $(outfile) = $(psoptions) ;
MakeLocate $(outfile) : $(outdir) ;
Depends $(outfile) : $(dvifile) ;
Depends $(target) : $(outfile) ;
$(converter) $(outfile) : $(dvifile) ;
RmTemps $(outfile) : $(dvifile) ;
Clean $(target)clean : $(outfile) $(dvifile) ;
NotFile $(target) ;
NotFile $(target)clean ;
if $(subdir)
{
CleanDir $(target)clean : $(outdir) ;
}
return $(outfile) ;
}
# Unfortunately, `makeinfo' 4.3, which ships with MSYS, does not respect the
# search path (-I) for @image{} directives, so we need to `cd' into the source
# directory to work around this shortcoming. With modern versions of
# `makeinfo', we could instead just use `-I$(SRCDIR)' instead of the pwd/cd
# goop.
actions RunMakeInfo
{
dir=`pwd` ; \
cd $(>:D) ; \
$(CMD.MAKEINFO) $(OPTIONS) $(FLAGS.MAKEINFO) --output="${dir}/$(<)" $(>:B)
}
actions RunTexi2HTML
{
T2H_HOME="$(PATH.TEXI2HTML.HOME)" \
$(CMD.TEXI2HTML) $(OPTIONS) $(FLAGS.TEXI2HTML) -subdir="$(OUTDIR)" \
-top-file="$(<:BS)" "$(>)"
}
actions RunTexi2DVI
{
$(CONVERTER) $(OPTIONS) --batch --output=$(<) $(>) > $(OUTLOG) 2>&1
if test $? -ne 0; then
echo "*** ERROR: $(CONVERTER) reported one or more errors."
echo "*** ERROR: See $(OUTLOG) for details."
false
fi
if test $? -eq 0; then
grep hbox $(OUTLOG) >/dev/null 2>&1
if test $? -eq 0; then
echo "*** WARNING: $(CONVERTER) reported 'hbox' warnings." && \
echo "*** WARNING: See $(OUTLOG) for details."
else
$(RM) $(OUTLOG)
fi
true
else
false
fi
}
actions RunDVIPS
{
TEXPICTS="$(SRCDIR)" \
$(CMD.DVIPS) $(OPTIONS) -o $(<) $(>) > $(OUTLOG) 2>&1
if test $? -ne 0; then
echo "*** ERROR: $(CMD.DVIPS) reported one or more errors."
echo "*** ERROR: See $(OUTLOG) for details."
false
else
$(RM) $(OUTLOG)
true
fi
}
actions RunDVIPDF
{
TEXPICTS="$(SRCDIR)" \
$(CMD.DVIPDF) $(OPTIONS) $(>) $(<) > $(OUTLOG) 2>&1
if test $? -ne 0; then
echo "*** ERROR: $(CMD.DVIPDF) reported one or more errors."
echo "*** ERROR: See $(OUTLOG) for details."
false
else
$(RM) $(OUTLOG)
true
fi
}
actions RunDoxygen
{
TOP=$(TOP) DOXYCPP=$(DOXYCPP) HAVE_DOT=$(HAVE_DOT) DOT_PATH=$(DOT_PATH) $(CMD.DOXYGEN) $(OPTIONS) $(FLAGS.DOXYGEN) $(>)
}
#----------------------------------------------------------------------------
# Additional clean rules.
CleanDir cleandoc : $(LOCATE.DOCS) ;
Depends clean : cleandoc ;
Help cleandoc : "Remove built documentation files" ;
Always docclean ;
NotFile docclean ;
Depends docclean : cleandoc ;

128
mk/jam/dump.jam Normal file
View File

@@ -0,0 +1,128 @@
#==============================================================================
# Utility functions for collecting information about the Jam environment.
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#==============================================================================
#------------------------------------------------------------------------------
# When the target "dumptargets" is invoked, dump the top-level, user-visible
# build targets as a whitespace-delimited list to the file named by the Jam
# variable DUMPTARGETS_FILE. Example:
#
# jam -sDUMPTARGETS_FILE=targets.txt dumptargets
#
# This output might be useful, for instance, when composing documentation (via
# some automated mechanism) which lists the targets visible to the user.
#
# IMPLEMENTATION NOTES
#
# The emitted target names are collected from several locations:
#
# - All single-word arguments to NotFile composed of ._- and alphanumerics.
#
# - Targets defined by the Application rule. Unlike other rules (Plugin,
# Library, etc.) which compose a top-level pseudo-target using NotFile
# (which is thus caught by the above case), on Unix, the Application rule
# does not invoke NotFile since the top-level target has the same name as
# the generated executable.
#
# - Targets defined by the ShellScript rule, since the emitted shell scripts
# have the same name as the top-level target.
#
# Collection occurs in two phases. This file must be included by build.jam
# before any other utility *.jam files are included, and it must also be
# included after all other utility *.jam files are included. In the first
# phase, the NotFile rule is re-defined so that we can catch pseudo-targets
# created by the other utility *.jam files (we must re-define NotFile before
# they are included), as well as any NotFile pseudo-targets created by Jamfiles
# throughout the project. In the second phase, the Application and ShellScript
# rules are re-defined (we must do so after application.jam has defined the
# implementations which we override). These overrides allow us to catch
# application and shell-script targets which project-wide Jamfiles define.
#------------------------------------------------------------------------------
if $(DUMPTARGETS_FILE)
{
# Jam does not support arithmetic, so we fake it with Roman numerals.
DUMPTARGETS_PASS ?= "" ;
DUMPTARGETS_PASS = "$(DUMPTARGETS_PASS)I" ;
switch $(DUMPTARGETS_PASS)
{
case I :
actions InitPseudoTargets
{
$(RM) $(<)
}
rule DumpPseudoTargets
{
NotFile $(<) ;
Always $(<) ;
Depends $(<) : $(>) ;
Always $(>) ;
InitPseudoTargets $(>) ;
}
DumpPseudoTargets dumptargets : "$(DUMPTARGETS_FILE)" ;
actions together piecemeal EmitPseudoTarget
{
echo "$(>)" >> $(<)
}
rule PossiblePseudoTarget
{
# NoCare and Includes are not actually required; they are used here merely to
# avoid Jam's "using independent target" warning. Note, however, that Jam
# 2.4 and BoostJam try building the target despite the fact that we NoCare
# about it. (Presumably this is because the targets have updating actions,
# and those actions override the NoCare.) Consequently, we have to put up
# with the "using independent target" warnings for these older Jam versions.
NoCare $(<) ;
if $(JAMVERSION) != 2.4 { Includes dumptargets : $(<) ; }
local i ;
for i in $(<)
{
local s = [ Match ^([A-Za-z0-9_.-]+)$ : $(i) ] ;
if $(s)
{
EmitPseudoTarget "$(DUMPTARGETS_FILE)" : $(i) ;
}
}
}
rule NotFile
{
PossiblePseudoTarget $(<) ;
}
case II :
rule Application
{
PossiblePseudoTarget $(<) $(<)clean ;
}
rule ShellScript
{
PossiblePseudoTarget $(<) $(<)clean ;
}
}
}

172
mk/jam/flags.jam Normal file
View File

@@ -0,0 +1,172 @@
#============================================================================
# Rules for specifying compiler and linker flags
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
## LinkWith target : libs
## Link an application with libraries. The specified libraries should have
## build rules in the same project. For external libraries use the
## ExternalLibs rule. Specify the library names without any extensions or
## the leading "lib".
rule LinkWith
{
local rawlibs = [ ResolveLibs $(>) ] ;
if ( $($(<)_TYPE) = library ) && ( "$($(<)_SHARED)" = "" )
{
# LibDepends for shared libs invokes LinkWith, so prevent recursion
LibDepends $(<) : $(rawlibs) ;
}
local i libs ;
for i in $(rawlibs)
{
libs += [ ConstructLibraryLinkTarget $(i) : $($(i)_SHARED) ] ;
}
Depends $($(<)_TARGET) : $(libs) ;
NEEDLIBS on $($(<)_TARGET) += $(libs) ;
$(<).NEEDLIBS += $(rawlibs) ;
LFlags $(<) : $($($(rawlibs).EXTERNALLIBS).LFLAGS) ;
}
## CFlags target : flags [ : options ]
## Sets cflags on all sourcefiles of a library, plugin or application target
## This rule affects c++ and c compiler flags.
rule CFlags
{
CheckOptions nostatic : $(3) : $(<) ;
CCFLAGS on $($(<)_OBJECTS) += $(>) ;
C++FLAGS on $($(<)_OBJECTS) += $(>) ;
UnitTestCFlags $(<) : $(>) : $(3) ;
}
## MergeLFlags flags1 : flags2
## Merge two arrays of linker flags. Removes duplicate entries, however,
## ensures that the correct relative right-to-left order of both flag arrays
## is kept.
rule MergeLFlags
{
local result = ;
local libs2 = $(2) ;
for l in $(1)
{
if [ IsElem $(l) : $(libs2) ]
{
# If a flag from set 1 is in set 2, add all flags from start of set 2
# to the occurance of the flag to result.
while "$(libs2[1])" != "" && $(libs2[1]) != $(l)
{
result += $(libs2[1]) ;
libs2 = $(libs2[2-]) ;
}
result += $(libs2[1]) ;
libs2 = $(libs2[2-]) ;
}
else
{
# Just add the flag.
result += $(l) ;
}
}
result += $(libs2) ;
return $(result) ;
}
## LFlags target : flags [ : options ]
## Sets linker flags for a library, plugin or application target
rule LFlags
{
CheckOptions nostatic : $(3) : $(<) ;
NotFile $(>) ;
NEEDLIBS on $($(<)_TARGET) += $(>) ;
$(<).LFLAGS += $(>) ;
UnitTestLFlags $(<) : $(>) : $(3) ;
}
## ExternalLibs target : identifiers
## Specify a dependency between 'target' and the external libraries
## indicated by 'identifiers'. If 'target' is an application or plugin,
## then it is linked against the indicated external libraries. If 'target'
## is a library, then its dependency upon 'identifiers' is noted, and
## applications or plugins which link against 'target' will also be linked
## against the libraries indicated by 'identifiers'. 'identifiers' is a
## list of base names of a set of variables which provide build tool
## information about each external library. In particular, assuming that
## `ident' is one element of `identifiers', the value of $(ident).CFLAGS
## should provide compiler flags needed for the external library indicated
## by 'ident'; and $(ident).LFLAGS should provide linker flags for the
## library.
rule ExternalLibs
{
local extlib ;
for extlib in $(>)
{
CFlags $(<) : $($(extlib).CFLAGS) ;
LFlags $(<) : $($(extlib).LFLAGS) ;
$(<).EXTERNALLIBS += $(extlib) ;
}
}
## ExtraObjects target : objectfiles [ : options ]
## Link additional object files with a target.
## Options:
## inheritcflags: The mentioned object files will inherit compiler flags
## assigned to target's normal object files (in addition to any flags
## already set manually).
rule ExtraObjects
{
CheckOptions inheritcflags : $(3) : $(<) ;
if [ IsElem inheritcflags : $(3) ]
{
$(<)_OBJECTS += $(>) ;
}
EXTRAOBJECTS on $($(<)_TARGET) += $(>) ;
Depends $($(<)_TARGET) : $(>) ;
Clean $(<)clean : $(>) ;
Clean clean : $(>) ;
}
#----------------------------------------------------------------------------
# private part
## ResolveLibs libs
## Given a list of libraries, augment the list by adding other libraries
## upon which the given libraries depend. Dependencies between libraries
## are specified via LibDepends (or LinkWith when the target is a library).
## The returned list is ordered such that it is suitable for Unix linkers
## which are sensitive to the order of libraries in the invocation
## statement.
rule ResolveLibs
{
local i libs ;
for i in $(<)
{
libs += $(i) $($(i)_depends) ;
}
# We must eliminate the duplicates in reverse order in order to ensure that
# we do not destroy the overall library ordering since Unix linkers are
# order-sensitive.
return [ Reverse [ RemoveDups [ Reverse $(libs) ] ] ] ;
}

61
mk/jam/groups.jam Normal file
View File

@@ -0,0 +1,61 @@
#============================================================================
# Rules for building compile groups
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
COMPILE_GROUPS = ;
## CompileGroups target : groups
## Adds a target to a list of compile groups. A compile group is a virtual
## target which combines several targets. This is useful for things like a
## creating a target which compiles all image loaders, all renderers, etc.
rule CompileGroups
{
local _i ;
for _i in $(>)
{
Depends $(_i) : $(<) ;
Depends $(_i)clean : $(<)clean ;
if ! [ IsElem $(_i) : $(COMPILE_GROUPS) ]
{
NotFile $(_i) ;
Echo "Warning: $(_i) not registered via RegisterCompileGroups" ;
}
}
}
## RegisterCompileGroups
## Registers compile groups. You must specify all compile groups here before
## can use them.
rule RegisterCompileGroups
{
NotFile $(<) ;
COMPILE_GROUPS += $(<) ;
local i ;
for i in $(<)
{
local desc = [ Description $(i) ] ;
if $(desc)
{
Help $(i) : "Build the $(desc)" ;
}
}
}

85
mk/jam/help.jam Normal file
View File

@@ -0,0 +1,85 @@
#============================================================================
# Rules for collecting and emitting descriptions about targets
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
## Description target [ : description ]
## Provides access to the description of 'target'. The description may be
## used by other rules, such as those which generate project files, or which
## present informative messages to the user regarding 'target'. If invoked
## with two arguments, then it sets the description of 'target'. If invoked
## with one argument, then it returns the description of 'target'. You
## should invoke this rule to set the description before invoking other
## rules which might need access to target's description, such as the
## Application, Library, and Plugin rules. As a convenience, several generic
## rules, such as Application, Library, and Plugin will automatically invoke
## the Help rule for 'target' using the provided 'description'.
rule Description
{
local desc = $(>) ;
if $(desc)
{
$(<)_description = $(desc) ;
}
else
{
desc = $($(<)_description) ;
}
return $(desc) ;
}
## Help target : description
## Specify the 'description' to emit for 'target' when the user invokes "jam
## help".
rule Help
{
local target = $(<) ;
local desc = $(>) ;
if ! $(target) { target = "" ; }
if ! $(desc) { desc = "" ; }
# target width:20, description width:54
local target_pad = " " ;
local target_pat = "...................." ;
local desc_pad = " " ;
local desc_pat = "......................................................" ;
local m = Match ; # Indirect invocation allows variables in pattern regex.
local target_str = [ $(m) "($(target_pat)).*" : "$(target)$(target_pad)" ] ;
local desc_str = [ $(m) "($(desc_pat)).*" : "$(desc)$(desc_pad)" ] ;
local help = "jam $(target_str) $(desc_str)" ;
target = $(target:G=help) ;
Depends help : $(target) ;
NotFile $(help) ;
PrintHelp $(target) : $(help) ;
Always $(target) ;
NotFile $(target) ;
}
actions quietly PrintHelp
{
echo "$(>)"
}
NotFile help ;
Always help ;
Help all : "Build the entire project" ;

594
mk/jam/helper.jam Normal file
View File

@@ -0,0 +1,594 @@
#============================================================================
# Helper rules
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
SED ?= sed ;
DEEPCOPY ?= "cp -R" ;
DELTREE ?= "rm -rf" ;
# The -f option to `cp' is not supported on older platforms.
# The convolution of the conditional arises because CP is defined in Jambase as
# two tokens rather than a single string, so we must check the tokens
# individually; yet we also check it as a simple string for future robustness.
if $(CP) = "cp -f" || $(CP[1]) = "cp" && $(CP[2]) = "-f"
{
CP = cp ;
}
## IncludeDir [ dir [ : target [ : options ]]]
## Specify the location of a directory containing header files for a target,
## or for the whole project if no target is given. "dir" is a list of
## components composing the path. This rule will automatically generate the
## -I compiler flags and makes sure the dependency scanner is able to locate
## your header files. "dir" is assumed to be relative to the current
## subdirectory specified with the SubDir rule unless the "literal"
## option is given, in which case "dir" is used literally. If "dir" is
## omitted, then the current subdirectory specified with SubDir is used as
## the header directory. An omitted "dir" and the "literal" option are
## mutually exclusive. You may invoke this rule multiple times to specify
## any number of header file directories.
## Options:
## literal: "dir" is to be used literally without any interpretation.
## transient: "dir" is to be used at build-time only; and should not be
## recorded in any generated resources, such as project files.
##
## Implementation: The directory is simply added to the HDRS variable which
## is respected by all Jam rules.
rule IncludeDir
{
local dir = $(1) ;
local target = $(2) ;
local options = $(3) ;
CheckOptions literal transient : $(options) : $(dir) ;
if ! $(dir)
{
dir = $(SUBDIR) ;
}
else if ! [ IsElem literal : $(options) ]
{
dir = $(SUBDIR) $(dir) ;
}
dir = [ ConcatDirs $(dir) ] ;
if $(target)
{
local o ;
for o in $($(target)_OBJECTS)
{
CCHDRS on $(o) += [ FIncludes $(dir) ] ;
}
}
else
{
HDRS += $(dir) ;
}
}
## Wildcard [ dir : ] patterns
## Create a list of files in a directory which match the pattern. You can
## optionally specify a subdirectory. The files will be returned with
## stripped pathnames. The difference from GLOB is that this rule respects
## subdirectories which may have been entered with the SubDir rule.
rule Wildcard
{
local files dir sdir wildcards ;
# Is a directory given?
if $(>)
{
dir = $(<)/ ;
sdir = [ ConcatDirs $(<) ] ;
wildcards = $(>) ;
}
else
{
dir = "" ;
sdir = "" ;
wildcards = $(<) ;
}
files = [ GLOB [ ConcatDirs $(SUBDIR) $(dir) ] : $(wildcards) ] ;
return $(files:BSR=$(sdir)) ;
}
## Recurse [ rule ] : types [ : prefix ]
## Recursively scan current directory, $(SUBDIR), for files matching 'types'
## and invoke 'rule' for each file which matches one of the 'types'.
## 'types' is a list of file extensions (with the leading dot). 'rule' will
## be invoked with two arguments: (1) the basename of the file including the
## extension, (2) a list of the path components from the current directory
## to the file's directory. When 'rule' is invoked, it will see a $(SUBDIR)
## value of the directory containing the file (as if the rule had been
## invoked from within the file's directory). 'prefix' is an optional list
## of path components which will be prepended to rule's second argument.
## Returns the list of visited files. It is legal to omit 'rule', if you
## are interested only in obtaining the list of files matching 'types'.
rule Recurse
{
local innerrule = $(1) ;
local types = $(2) ;
local prefix = $(3) ;
local files = [ GLOB $(SUBDIR) : * ] ;
local visited ;
local i ;
for i in $(files)
{
if [ IsElem $(i:S) : $(types) ]
{
visited += [ FDirName $(prefix) $(i:BS) ] ;
if $(innerrule)
{
$(innerrule) $(i:BS) : $(prefix) ;
}
}
else
{
if ! [ IsElem $(i:BS) : $(DOT) $(DOTDOT) ]
{
local SUBDIR = $(i) ; # Called rules see this new temporary value.
visited += [ Recurse $(innerrule) : $(types) : $(prefix) $(i:BS) ] ;
}
}
}
return $(visited) ;
}
## ResponseFile file : [ items [ : options [ : directory [ : delim ]]]]
## Jam places a fairly restrictive limit on the length of the command string
## emitted by an 'actions' block. If the limit is exceeded, Jam rudely
## aborts. This problem is easily triggered when actions are invoked
## 'together' but not 'piecemeal'; especially when the command arguments
## involve many lengthy pathnames. To work around this type of problem,
## some tools allow the client to furnish a file containing information
## which would otherwise be specified via the command-line. This is often
## called a "response file". The ResponseFile rule can be used to create a
## response file named 'file' in 'directory' containing 'items', one per
## line. As a convenience, if 'directory' is not specified, and if the
## MakeLocate rule has not already been invoked for 'file' or LOCATE has not
## been set for 'file', then the file is placed in $(LOCATE_TARGET). If
## there is a possibility that the same 'file' name might be used in other
## contexts, be sure to grist it appropriately to avoid conflicts. This
## rule assumes that 'items' contains bound entries unless the "notfile"
## option is specified, in which case the NotFile rule is automatically
## invoked for each item. This rule may be invoked multiple times for the
## same 'file' in order to populate the file incrementally. As an internal
## optimization to keep performance relatively sane, ResponseFile
## temporarily inserts 'delim' between 'items' when emitting them, and then
## substitutes newline for 'delim' just before writing the items to
## 'file'. 'delim' must be a one-character string. If not specified, "@" is
## used. If "@" is likely to appear in 'items', then choose a different
## character for 'delim'; one which is known to not appear in 'items'. The
## rule returns 'file' to make it convenient to daisy-chain with invocations
## of other rules, such as RmTemps, Depends, or Always.
## Options:
## notfile: Invoke NotFile for each item automatically; otherwise, assume
## that each item is a bound file.
rule ResponseFile
{
local file = $(1) ;
local items = $(2) ;
local options = $(3) ;
local dir = $(4) ;
local delim = $(5) ;
CheckOptions notfile : $(options) : $(file) ;
if ! $(delim) { delim = "@" ; }
DELIM on $(file) = $(delim) ;
local firsttime = no ;
if ! [ IsElem $(file) : $(RESPONSE_FILE_REGISTRY) ]
{
firsttime = yes ;
RESPONSE_FILE_REGISTRY += $(file) ;
}
if ! $(items) && $(firsttime) = yes
{
items = "" ; # Force file creation even if list is empty.
options += notfile ;
}
if [ IsElem notfile : $(options) ] && $(items)
{
NotFile $(items) ;
}
if $(dir)
{
MakeLocate $(file) : $(dir) ;
}
else
{
local target_dir = [ on $(file) GetVar LOCATE ] ;
if ! $(target_dir)
{
MakeLocate $(file) : $(LOCATE_TARGET) ;
}
}
local i ;
for i in $(items)
{
if $(firsttime) = yes
{
ResponseFile1 $(file) : $(i) ;
firsttime = no ;
}
else
{
ResponseFile2 $(file) : $(i) ;
}
}
return $(file) ;
}
actions ResponseFile1
{
echo '$(>)' > $(<)
}
actions piecemeal together quietly ResponseFile2
{
echo '$(>)$(DELIM)' | $(SED) 's/$(DELIM) /$(DELIM)/g' | tr '$(DELIM)' '
' >> $(<)
}
## Sort list
## Given a list of items, returns a list containing the items sorted
## alphabetically.
rule Sort
{
local i sorted ;
for i in $(<)
{
local inserted = no ;
local j accum ;
for j in $(sorted)
{
if $(inserted) != yes && $(i:L) < $(j:L)
{
accum += $(i) ;
inserted = yes ;
}
accum += $(j) ;
}
if $(inserted) != yes
{
accum += $(i) ;
}
sorted = $(accum) ;
}
return $(sorted) ;
}
## StripCommon list1 : list2
## Strips from the beginning of list1 the items which it has in common with
## the beginning of list2 and returns what remains of list1.
rule StripCommon
{
local l = $(<) ;
local r = $(>) ;
FStripCommon l : r ;
return $(l) ;
}
## MasterHeader header [ : files [ : pre-boilerplate [ : post-boilerplate
## [ : options ]]]]
## Given a list of 'files', construct a 'header' file which #includes those
## files. If 'header' does not already have a suffix, ".h" will be
## appended. The generated header will be emitted to $(LOCATE_TARGET), and
## will be protected against multiple-inclusion via the standard
## #ifndef __HEADER_H__ / #define / #endif mechanism. If provided,
## 'pre-boilerplate' will be inserted verbatim immediately after the opening
## multiple-inclusion protection, but before the first #include. Likewise,
## 'post-boilerplate' will be inserted verbatim after the last #include, but
## before the closing multiple-inclusion protection. If the boilerplate
## arguments are lists, the items will be emitted one per line. 'files'
## is sorted before the #include statements are generated, unless the
## "nosort" option is given. For convenience, the gristed 'header' is
## returned. Also sets up the following pseudo-targets:
##
## masterheaders: Synthesize all requested master headers.
## cleanmasterheaders: Delete synthesized files.
## freezemasterheaders: Copy synthesized files to back into the source
## tree at $(SUBDIR).
##
## Options:
## nosort: Do not sort 'files'.
rule MasterHeader
{
local header = [ FAppendSuffix $(1) : .h ] ;
local files = $(2) ;
local boilerpre = $(3) ;
local boilerpost = $(4) ;
local options = $(5) ;
local target = $(header:G=masterheader) ;
local protect = "__$(header:US=)_H__" ;
CheckOptions nosort : $(options) : $(header) ;
if ! [ IsElem nosort : $(options) ]
{
files = [ Sort $(files) ] ;
}
Always $(target) ;
ResponseFile $(target) :
"/* $(header) -- Generated automatically; do not edit. */"
"#ifndef $(protect)"
"#define $(protect)"
$(boilerpre)
"#include \"$(files)\""
$(boilerpost)
"#endif /* $(protect) */"
: notfile ;
Depends masterheaders : $(target) ;
Clean cleanmasterheaders : $(target) ;
Clean clean : cleanmasterheaders ;
local frozen = $(target:G=frozenmasterheader) ;
MakeLocate $(frozen) : $(SUBDIR) ;
Depends $(frozen) : $(target) ;
Copy $(frozen) : $(target) ;
Depends freezemasterheaders : $(frozen) ;
if $(MASTER_HEADER_GLOBAL_TARGETS) != yes
{
MASTER_HEADER_GLOBAL_TARGETS = yes ;
Always masterheaders ;
NotFile masterheaders ;
Help masterheaders : "Generate master header files" ;
Always freezemasterheaders ;
NotFile freezemasterheaders ;
Help freezemasterheaders :
"Copy generated master headers to source tree" ;
}
return $(target) ;
}
## DirectoryMasterHeaders dirs [ : pre-boilerplate [ : post-boilerplate
## [ : options [ : rejects ]]]]
## A convenience wrapper around MasterHeader which generates a set of master
## header files for each directory in 'dirs', which are assumed to be
## subdirectories of the current directory. For each item in 'dirs', the
## subdirectory is recursively scanned for files, and MasterHeader is
## invoked with the gleaned file list. The generated header for a directory
## is emitted to the current directory; not within the subdirectory. The
## optional 'rejects' is a list of header files which should not be emitted
## to the synthesized master headers. 'pre-boilerplate',
## 'post-boilerplate', and 'options' carry the same interpretation as for
## MasterHeader.
rule DirectoryMasterHeaders
{
local dirs = $(1) ;
local boilerpre = $(2) ;
local boilerpost = $(3) ;
local options = $(4) ;
local rejects = $(5) ;
local masters ;
local d ;
for d in $(dirs)
{
local files ;
{
local SUBDIR = [ ConcatDirs $(SUBDIR) $(d) ] ; # Recurse from here...
files = [ Recurse : .h : $(d) ] ;
}
if $(rejects)
{
files = [ Filter $(files) : $(rejects) ] ;
}
masters += [ MasterHeader $(d) : $(files) : $(boilerpre) : $(boilerpost) :
$(options) ] ;
}
return $(masters) ;
}
## Prefix list : prefix
## Adds a prefix to a all elements in list.
rule Prefix
{
return $(>)$(<) ;
}
if $(JAMVERSION) >= 2.5
{
## IsElem element : list
## Returns "true" if the element is in the list. Otherwise nothing is
## returned.
rule IsElem
{
local i ;
for i in $(>)
{
if $(i) = $(<)
{
return "true" ;
}
}
return ;
}
}
else
{
# Jam <2.4's return statement doesn't exit the function
rule IsElem
{
local i result ;
for i in $(>)
{
if $(i) = $(<)
{
result = "true" ;
$(>) = ;
}
}
return $(result) ;
}
}
## Filter list : filter
## Returns the list without the words contained in filter.
rule Filter
{
local i result ;
for i in $(<)
{
if ! [ IsElem $(i) : $(>) ]
{
result += $(i) ;
}
}
return $(result) ;
}
## RemoveDups list
## Removes duplicates in the list (this function tries to preserve the list
## order)
rule RemoveDups
{
local i result ;
for i in $(<)
{
if ! [ IsElem $(i) : $(result) ]
{
result += $(i) ;
}
}
return $(result) ;
}
## Reverse list
## Reverse the order of items in the list.
rule Reverse
{
local result ;
for i in $(<)
{
result = $(i) $(result) ;
}
return $(result) ;
}
## GetVar argument
## Simply returns the value of the variable with name argument.
## This is useful to query on target variables:
## bla = [ on TARGET GetVar CFlags ] ;
rule GetVar
{
return $($(<)) ;
}
## ConcatDirs dirs
## Concatenates a set of directories. This is a substitute for FDirName in
## Jambase. It works also correctly for several rooted paths, where FDirName
## fails.
## The advantage over $(dir1)/$(dir2) is that this also works correctly if
## $(dir1) or $(dir2) is not set.
rule ConcatDirs
{
local i ;
local result = $(<[1]) ;
if ! $(result) { $result = "" ; }
local dir1 dir2 ;
for i in $(<[2-])
{
# eleminate multiple slashes because jam is somewhat buggy here
dir1 = [ MATCH (.*[^/]?) : $(result) ] ;
dir2 = [ MATCH ([^/].*) : $(i) ] ;
if ! $(dir1) { dir1 = "" ; }
if $(dir1) != "" { dir1 = $(dir1)/ ; }
if ! $(dir2) { dir2 = "" ; }
result = $(dir1)$(dir2) ;
}
return $(result) ;
}
## SplitToList var [ : separator ]
## Splits the value of var into a list using space as the separator unless
## an alterante separator is specified.
## IMPLEMENTATION NOTE
## When Jam sees an invocation of the `Match' function, it treats its first
## argument as a literal regular expression, and does not do any variable
## interpolation. This means that an expression, such as "(.*)$(sep)(.*)"
## will not be interpreted as expected; it will instead be interpreted as an
## invalid regex. To work around this limitation, we invoke `Match'
## indirectly.
rule SplitToList
{
local list = ;
local matcher = Match ; # See IMPLEMENTATION NOTE above.
local unsplit = $(<) ;
local sep = $(2) ;
if ! $(sep) { sep = " " ; }
while $(unsplit) != ""
{
local split = [ $(matcher) "(.*)$(sep)(.*)" : $(unsplit) ] ;
if $(split[1]) = ""
{
list += $(unsplit) ;
unsplit = "" ;
}
else
{
list += $(split[2]) ;
unsplit = $(split[1]) ;
}
}
return [ Reverse $(list) ] ;
}
## Copy target : source
## Copy source to target.
actions Copy
{
$(RM) $(<)
$(CP) $(>) $(<)
}
## Move target : source
## Move (or rename) source to target.
actions ignore Move
{
$(MV) $(>) $(<)
}

213
mk/jam/install.jam Normal file
View File

@@ -0,0 +1,213 @@
#============================================================================
# Rules for installation
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
INSTALL ?= "install" ;
INSTALL_PROGRAM ?= $(INSTALL) ;
INSTALL_DATA ?= "$(INSTALL) -m 644" ;
# set some paths
appdatadir ?= [ ConcatDirs $(datadir) $(PACKAGE_NAME) ] ;
appdocdir ?= [ ConcatDirs $(datadir) doc $(PACKAGE_NAME)-$(PACKAGE_VERSION) ] ;
appconfdir ?= [ ConcatDirs $(sysconfdir) $(PACKAGE_NAME) ] ;
appincdir ?= [ ConcatDirs $(includedir) $(PACKAGE_NAME) ] ;
plugindir ?= [ ConcatDirs $(libdir) $(PACKAGE_NAME) ] ;
rule GristInstall
{
local i, files ;
for i in $(<)
{
if $(i:G) { files += $(i) ; }
else { files += $(i:G=$(SUBDIR)) ; }
}
return $(files) ;
}
## InstallHeader headername [ : subdir ]
## DoInstall a header file into the includedir directory. A subdirectory
## relative to the includedir can be specified.
rule InstallHeader
{
local files = [ GristInstall $(<) ] ;
SEARCH on $(files) = $(SUBDIR) ;
Depends install_include : [ DoInstall $(files) : $(appincdir) $(2) ] ;
}
## InstallData files [ : subdir ]
## Installs data files
rule InstallData
{
local files = [ GristInstall $(<) ] ;
SEARCH on $(files) = $(SUBDIR) ;
Depends install_data : [ DoInstall $(files) : $(appdatadir) $(2) ] ;
}
## InstallConfig files [ : subdir ]
## Installs configuration files
rule InstallConfig
{
local files = [ GristInstall $(<) ] ;
SEARCH on $(files) = $(SUBDIR) ;
Depends install_config : [ DoInstall $(files) : $(appconfdir) $(2) ] ;
}
## InstallDoc files [ : subdir ]
## Installs documentation files
rule InstallDoc
{
local files = [ GristInstall $(<) ] ;
SEARCH on $(files) = $(SUBDIR) ;
Depends install_doc : [ DoInstall $(files) : $(appdocdir) $(2) ] ;
}
## InstallMan files
## Installs Unix manual files
rule InstallMan
{
local files = [ GristInstall $(<) ] ;
SEARCH on $(files) = $(SUBDIR) ;
local i ;
for i in $(files)
{
local dir = $(mandir) ;
switch $(i:S)
{
case .1 : dir += man1 ;
case .2 : dir += man2 ;
case .3 : dir += man3 ;
case .4 : dir += man4 ;
case .5 : dir += man5 ;
case .6 : dir += man6 ;
case .7 : dir += man7 ;
case .8 : dir += man8 ;
case .9 : dir += man9 ;
case * :
echo "WARNING: manfile has no *.[0-9] ending." ;
}
Depends install_man : [ DoInstall $(i) : $(dir) ] ;
}
}
## InstallProgram files [ : directories ]
## Installs program files (executable or shell script). This is a
## convenience wrapper for DoInstall when the resources to be installed is
## of an invocable nature. It sets SEARCH on `files', and uses
## $(INSTALL_PROGRAM) to perform the actual installation. Unlike
## SystemInstallApplication, it does not assume that all such targets should
## be installed into $(bindir); instead, you can provide `directories' to
## specify the installation location. If `directories' is not given, then
## $(bindir) is assumed. Also, unlike SystemInstallApplication, this rule
## does not have any platform-specific knowledge (such as how to install a
## Cocoa application wrapper on MacOS/X). Always use
## SystemInstallApplication for installation of full-fledged applications. A
## typical use for InstallProgram would be to install an already-existing
## shell script. This differs from the ShellScript rule which both creates a
## shell script from scratch at build time, and arranges for it to be
## installed. Like DoInstall, this rule returns the names of the installed
## targets, so it is convenient to use the results as the input for another
## rule, such as Depends.
rule InstallProgram
{
local files = [ GristInstall $(1) ] ;
local dir = $(2) ;
if ! $(dir) { dir = $(bindir) ; }
SEARCH on $(files) = $(SUBDIR) ;
return [ DoInstall $(files) : $(dir) : $(INSTALL_PROGRAM) ] ;
}
## DoInstall sourcenames : directories [ : installapp : [ postinstallrules ]]
## Creates a new install target for the given sources named by
## `sourcenames'. `directories' is a list of directory components
## indicating the installation directory for `sourcename'. `installapp' is
## the actual program to run to install the sources. If not specified, then
## $(INSTALL_DATA) is used. If the optional `postinstallrules' is provided,
## it is a list of Jam rules to invoke on the installed target after it is
## installed. Each rule is invoked with the installed target as the first
## argument, and the source target as the second. An obvious instance where
## `postinstallrules' proves useful is when the Ranlib rule should be
## invoked on just-installed static library (.a) files. The DoInstall rule
## returns the names of the installed targets, so it is convenient to use
## the results as the input for another rule. For example:
## Depends install : [ DoInstall $(docfiles) : $(installdocdir) ] ;
## (Implementation Note: We did not name this rule Install, because Jambase
## already defines an action named Install :-/)
rule DoInstall
{
local targets target i dir gdir ;
dir = [ ConcatDirs $(DESTDIR) $(2) ] ;
gdir = $(dir:G=dir) ;
MkDir $(gdir) ;
for i in $(1)
{
target = $(i:BSR=$(dir):G=install) ;
targets += $(target) ;
Depends $(target) : $(gdir) $(i) ;
Install1 $(target) : $(i) ;
if "$(3)"
{
INSTALL_APP on $(target) = $(3) ;
}
else
{
INSTALL_APP on $(target) = $(INSTALL_DATA) ;
}
if "$(4)"
{
local postrule ;
for postrule in $(4)
{
$(postrule) $(target) : $(i) ;
}
}
}
Always $(targets) ;
return $(targets) ;
}
#----------------------------------------------------------------------------
INSTALLTARGETS = install_bin install_plugin install_lib install_include
install_data install_config install_doc ;
Always install $(INSTALLTARGETS) ;
NotFile install $(INSTALLTARGETS) ;
Depends install : $(INSTALLTARGETS) ;
if ! $(PACKAGE_INSTALL_NAME) { PACKAGE_INSTALL_NAME = $(PACKAGE_LONGNAME) ; }
if ! $(PACKAGE_INSTALL_NAME) { PACKAGE_INSTALL_NAME = $(PACKAGE_NAME) ; }
if ! $(PACKAGE_INSTALL_NAME) { PACKAGE_INSTALL_NAME = "the project" ; }
Help install : "Install $(PACKAGE_INSTALL_NAME)" ;
actions Install1
{
$(INSTALL_APP) $(INSTALLFLAGS) $(>) $(<)
}
actions CopyDirs
{
$(DEEPCOPY) $(>) $(<)
}

349
mk/jam/jamcompatibility.jam Normal file
View File

@@ -0,0 +1,349 @@
#============================================================================
# Several hacks to make the build compatible with certain old/broken jam
# versions
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# BoostJam is evil: It is compatible to Jam 2.4 but has a version number 3.1,
# we try to detect BoostJam with the ARGV extension.
if $(ARGV[0])
{
# BoostJam hacks.
JAMVERSION = 2.4 ;
rule FIncludes
{
return -I$(<) ;
}
rule FDefines
{
return -D$(<) ;
}
}
if $(JAMVERSION) < 2.4
{
EXIT "Error: This buildsystem requires jam version 2.4 or later." ;
}
# All scripts invoked by the build system expect a Bourne or compatible shell.
# Reject C-shell and its variants (such as tcsh). Unfortunately, this is a bit
# of an ugly hack. It would be nicer to perform this logic at the very end of
# this file as a last-minute assertion. Unfortunately, however, it seems that
# references to $(SHELL) in any of the included files get bound at the point
# of reference, thus we need to perform this filtering as early as possible.
# Furthermore, on Windows, if the MSYS installation path contains a space (such
# as "c:\Program Files\msys"), the space will cause `actions' to fail which
# employ $(SHELL) indirectly through some other variable. Therefore, handle
# this case as well.
if [ Match (csh) : $(SHELL) ] || $(SHELL[2])
{
SHELL = "/bin/sh" ;
}
# Jam 2.4's SubDir rule had some problems and misses the useful SUBDIRRULES
# extension. So we override it here with a better version (from jam 2.5rc3).
# Likewise, 2.4 is missing FReverse and FStrip, which are needed by SubDir and
# other custom rules we define.
if $(JAMVERSION) = 2.4
{
rule FReverse
{
# FReverse a1 a2 a3 ... ;
# return ... a3 a2 a1 ;
if $(1) { return [ FReverse $(1[2-]) ] $(1[1]) ; }
}
rule FStripCommon
{
# FStripCommon v1 : v2 ;
# Strip common initial elements of variables v1 and v2.
# Modifies the variable values themselves.
if $($(<)[1]) && $($(<)[1]) = $($(>)[1])
{
$(<) = $($(<)[2-]) ;
$(>) = $($(>)[2-]) ;
FStripCommon $(<) : $(>) ;
}
}
rule SubDir
{
#
# SubDir TOP d1 d2 ... ;
#
# Support for a project tree spanning multiple directories.
#
# SubDir declares a Jamfile's location in a project tree, setting
# Jambase variables (SEARCH_SOURCE, LOCATE_TARGET) so that source
# files can be found.
#
# TOP is a user-select variable name for root of the tree, and
# d1 d2 ... are the directory elements that lead from the root
# of the tree to the directory of the Jamfile.
#
# TOP can be set externally, but normally the first SubDir call
# computes TOP as the path up from the current directory; the
# path contains one ../ for each of d1 d2 ...
#
# SubDir reads once the project-specific rules file Jamrules
# in the TOP directory, if present. This can be overridden
# with the variable TOPRULES.
#
# SubDir supports multiple, overlaid project trees: SubDir
# invocations with different TOPs can appear in the same Jamfile.
# The location established by the first SubDir call is used set
# the TOPs for the subsequent SubDir calls.
#
# SubDir's public variables:
#
# $(TOP) = path from CWD to root.
# $(SUBDIR) = path from CWD to the directory SubDir names.
# $(SUBDIR_TOKENS) = path from $(TOP) to $(SUBDIR) as dir names
# $(SEARCH_SOURCE) = $(SUBDIR)
# $(LOCATE_SOURCE) = $(ALL_LOCATE_TARGET) $(SUBDIR)
# $(LOCATE_TARGET) = $(ALL_LOCATE_TARGET) $(SUBDIR)
# $(SOURCE_GRIST) = $(SUBDIR_TOKENS) with !'s
#
local _top = $(<[1]) ;
local _tokens = $(<[2-]) ;
#
# First time through sets up relative root and includes Jamrules.
#
if ! $(_top)
{
Exit SubDir syntax error ;
}
if ! $($(_top)-SET)
{
$(_top)-SET = true ;
# First time we've seen this TOP.
# We'll initialize a number of internal variables:
#
# $(TOP-UP) = directories from ROOT to a common point
# $(TOP-DOWN) = directories from common point to TOP
# $(TOP-ROOT) = root directory for UP/DOWN -- normally CWD
# $(SUBDIR_UP) = current value of $(TOP-UP)
# $(SUBDIR_DOWN) = current value of $(TOP-DOWN)
# $(SUBDIR_ROOT) = current value of $(TOP-ROOT)
#
if $($(_top))
{
# TOP externally set.
# We'll ignore the relative (UP/DOWN) path that
# got us here, and instead remember the hard ROOT.
$(_top)-UP = ;
$(_top)-DOWN = ;
$(_top)-ROOT = $($(_top)) ;
}
else
{
# TOP not preset.
# Establishing a new TOP. In the simplest case,
# (SUBDIR_UP/SUBDIR_DOWN/SUBDIR_ROOT unset), it's
# merely a certain number of directories down from
# the current directory, and FSubDirPath will set
# TOP to a path consisting of ../ for each of the
# elements of _tokens, because that represents how
# far below TOP the current directory sits.
#
# In the more complicated case, the starting directory
# isn't the directory of jam's invocation but an
# location established by previous SubDir call. The
# starting directory is SUBDIR_UP directories up from
# SUBDIR_ROOT, and then SUBDIR_DOWN directories down
# from that. If SUBDIR_ROOT is not set, that means
# SUBDIR_DOWN and SUBDIR_UP represent the path from
# the directory of jam's invocation.
#
# In the most complicated case, the _tokens also
# represents directories down, because TOP is being
# estalished in a directory other than TOP's root.
# Hopefully, _tokens and SUBDIR_DOWN represent the
# same final directory, relative to the new TOP and
# the previous SubDIr's TOP. To find the new TOP,
# we have to chop off any common directories from
# then ends of _tokens and SUBDIR_DOWN. To do so,
# we reverse each of them, call FStripCommon to
# remove the initial common elements, and then
# reverse them again. After this process, if
# both _tokens and SUBDIR_DOWN have elements, it
# means the directory names estalished by the two
# SubDir calls don't match, and a warning is issued.
# All hell will likely break loose at this point,
# since the whole SubDir scheme relies on the SubDir
# calls accurately naming the current directory.
# Strip common trailing elements of _tokens and SUBDIR_DOWN.
_tokens = [ FReverse $(_tokens) ] ;
SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
FStripCommon _tokens : SUBDIR_DOWN ;
SUBDIR_DOWN = [ FReverse $(SUBDIR_DOWN) ] ;
_tokens = [ FReverse $(_tokens) ] ;
if $(SUBDIR_DOWN) && $(_tokens)
{
Echo Warning: SubDir $(<) misplaced! ;
}
# We'll remember the relative (UP/DOWN) path that
# got us here, plus any hard ROOT starting point
# for the UP/DOWN. If TOP is never set externally,
# ROOT will always be "" (directory of jam's invocation).
$(_top)-UP = $(SUBDIR_UP) $(_tokens) ;
$(_top)-DOWN = $(SUBDIR_DOWN) ;
$(_top)-ROOT = $(SUBDIR_ROOT:E="") ;
$(_top) = [ FSubDirPath $(_top) ] ;
}
# Set subdir vars for the inclusion of the Jamrules,
# just in case they have SubDir rules of their own.
# Note that SUBDIR_DOWN is empty: it's all the way
# up where the Jamrules live. These gets overrided
# just after the inclusion.
SUBDIR_UP = $($(_top)-UP) ;
SUBDIR_DOWN = ;
SUBDIR_ROOT = $($(_top)-ROOT) ;
# Include $(TOPRULES) or $(TOP)/Jamrules.
# Include $(TOPRULES) if set.
# Otherwise include $(TOP)/Jamrules if present.
if $($(_top)RULES) {
include $($(_top)RULES) ;
} else {
NoCare $(JAMRULES:R=$($(_top)):G=$(_top)) ;
include $(JAMRULES:R=$($(_top)):G=$(_top)) ;
}
}
# Get path from $(TOP) to named directory.
# Save dir tokens for other potential uses.
SUBDIR_UP = $($(_top)-UP) ;
SUBDIR_DOWN = $($(_top)-DOWN) $(_tokens) ;
SUBDIR_ROOT = $($(_top)-ROOT) ;
SUBDIR_TOKENS = $(SUBDIR_DOWN) ;
SUBDIR = [ FSubDirPath $(<) ] ;
# Now set up SEARCH_SOURCE, LOCATE_TARGET, SOURCE_GRIST
# These can be reset if needed. For example, if the source
# directory should not hold object files, LOCATE_TARGET can
# subsequently be redefined.
SEARCH_SOURCE = $(SUBDIR) ;
LOCATE_SOURCE = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
LOCATE_TARGET = $(ALL_LOCATE_TARGET) $(SUBDIR) ;
SOURCE_GRIST = [ FGrist $(SUBDIR_TOKENS) ] ;
# Reset per-directory ccflags, hdrs, etc,
# listed in SUBDIRRESET.
# Note use of variable expanded assignment var
SUBDIR$(SUBDIRRESET) = ;
# Invoke user-specific SubDir extensions,
# rule names listed in SUBDIRRULES.
# Note use of variable expanded rule invocation
$(SUBDIRRULES) $(<) ;
}
rule FSubDirPath
{
# FSubDirPath TOP d1 ... ;
# Returns path to named directory.
# If jam is invoked in a subdirectory of the TOP, then we
# need to prepend a ../ for every level we must climb up
# (TOP-UP), and then append the directory names we must
# climb down (TOP-DOWN), plus the named directories d1 ...
# If TOP was set externally, or computed from another TOP
# that was, we'll have to reroot the whole thing at TOP-ROOT.
local _r = [ FRelPath $($(<[1])-UP) : $($(<[1])-DOWN) $(<[2-]) ] ;
return $(_r:R=$($(<[1])-ROOT)) ;
}
rule SubInclude
{
# SubInclude TOP d1 ... ;
#
# Include a subdirectory's Jamfile.
# We use SubDir to get there, in case the included Jamfile
# either doesn't have its own SubDir (naughty) or is a subtree
# with its own TOP.
if ! $($(<[1]))
{
Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ;
}
SubDir $(<) ;
include $(JAMFILE:D=$(SUBDIR)) ;
}
rule SubRules
{
# SubRules TOP d1 ... : Other-TOP ;
#
# Read another tree's Jamrules, by giving it's path according
# to this tree and it's own name.
if ! $($(<[1]))
{
Exit SubRules $(<[1]) without prior SubDir $(<[1]) ;
}
SubDir $(<) ;
SubDir $(>) ;
}
## Now we try to fix up the already messed settings
## XXX We can only hope that Jam 2.4 users don't try starting Jam from
## subdirectories
TOP-SET = true ;
TOP-UP = ;
TOP-DOWN = ;
TOP-ROOT = $(TOP) ;
SUBDIR_UP = $(TOP-UP) ;
SUBDIR_DOWN = ;
SUBDIR_ROOT = $(TOP-ROOT) ;
#SubDir TOP ;
} # end if $(JAMVERSION) = 2.4

314
mk/jam/library.jam Normal file
View File

@@ -0,0 +1,314 @@
#============================================================================
# Rules for library creation
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# Suppress ar's noisy report that it created the archive we asked it to create.
if $(AR) && $(AR[2]) = ru { AR = $(AR[1]) ruc ; }
## Library libname : sources [ : options ]
## Build a library out of sourcefiles. All sourcefiles will be passed
## to the Objects rule which tries to compile them into object-files. You
## can create rules for your own filetypes with the UserObject rule. Header
## files will just be ignored. They are only used for MSVC projectfile
## generation.
## Available options are 'shared' if you want to build a shared library on
## platforms which support that. You can specify the 'noinstall' option if
## you don't want an install target generated.
## Don't specify any extensions for the library name, also leave out the
## leading "lib".
## Options:
## noinstall: Do not set up a default installation target.
## independent: The target will not be made a dependency of the libs and
## all targets.
## shared: Create as a shared library on supported platforms.
## nohelp: Do not invoke Help for this target.
## notest: Do not set up unit-testing support for this target.
## optional: Affects handling of the library in cs-config; it is only
## reported as available when actually built.
rule Library
{
local options = $(3) ;
CheckOptions noinstall independent shared nohelp notest optional : $(options) : $(<) ;
local target = [ ConstructLibraryTarget $(<) : $(options) ] ;
local sources = [ DoSourceGrist $(>) ] ;
local objects ;
local i ;
for i in $(sources)
{
if $(i:S) = $(SUFOBJ)
{
objects += $(i) ;
}
else
{
objects += [ CompileObjects $(i) ] ;
}
}
$(<)_TYPE = library ;
$(<)_OBJECTS = $(objects) ;
$(<)_SOURCES = $(sources) ;
$(<)_TARGET = $(target) ;
# create target clean rule
Always $(<)clean ;
NotFile $(<)clean ;
Clean $(<)clean : $(objects) ; # create target clean rule
# so 'jam foo' works when it's really foo.exe (Windows) or foo.app (MacOS/X)
if $(target) != $(<)
{
Depends $(<) : $(target) ;
NotFile $(<) ;
}
# library depends on its member objects
if ! [ IsElem independent : $(options) ]
{
if $(KEEPOBJS)
{
Depends obj : $(objects) ;
}
else
{
Depends libs : $(<) ;
}
}
if ( ! [ IsElem shared : $(options) ] ) || ( $(BUILD_SHARED_LIBS) != "yes" )
{
$(<)_SHARED = "" ;
LibraryStatic $(<) : $(objects) : [ Filter $(options) : shared ] :
$(target) ;
}
else
{
$(<)_SHARED = "shared" ;
LibraryShared $(<) : $(objects) : $(options) : $(target) ;
}
CFlags $(<) : $(LIBRARY.CFLAGS) ;
LFlags $(<) : $(LIBRARY.LFLAGS) ;
if ! [ IsElem nohelp : $(options) ]
{
local desc = [ Description $(<) ] ;
if ! $(desc) { desc = "$(<) library" ; }
Help $(<) : "Build the $(desc)" ;
}
if ! [ IsElem notest : $(options) ]
{
UnitTest $(<) ;
}
}
## LibDepends libname : dependant libraries
## Make Library dependant on other libraries. This will tell the build
## system that your library uses functions from other libraries in the
## project. Note that a library shouldn't be linked with any external
## library that should be done by the final application which uses the
## library.
rule LibDepends
{
$(<)_depends += $(>) ;
if "$($(<)_SHARED)"
{
LinkWith $(<) : $(>) ;
}
UnitTestLibDepends $(<) : $(>) ;
}
#----------------------------------------------------------------------------
# private part
# LibraryStatic libname : sources : options : decoratedtarget
rule LibraryStatic
{
local objects = $(>) ;
local options = $(3) ;
local target = $(4) ;
# Set LOCATE for the library and its contents. The bound
# value shows up as $(NEEDLIBS) on the Link actions.
# For compatibility, we only do this if the library doesn't
# already have a path.
if ! $(target:D)
{
MakeLocate $(target) $(target)($(objects:BS)) : $(LOCATE.OBJECTS)/libs ;
}
if $(NOARSCAN)
{
# If we can't scan the library to timestamp its contents,
# we have to just make the library depend directly on the
# on-disk object files.
Depends $(target) : $(objects) ;
}
else
{
# If we can scan the library, we make the library depend
# on its members and each member depend on the on-disk
# object file.
Depends $(target) : $(target)($(objects:BS)) ;
local i ;
for i in $(objects)
{
Depends $(target)($(i:BS)) : $(i) ;
}
}
# Generate install rules
if ! [ IsElem noinstall : $(options) ]
{
if "$(RANLIB)"
{
Depends install_lib : [ DoInstall $(target) : $(libdir) : : Ranlib ] ;
}
else
{
Depends install_lib : [ DoInstall $(target) : $(libdir) ] ;
}
# Add to global library list
if [ IsElem optional : $(options) ]
{
INSTALLEDLIBS_OPTIONAL += $(<) ;
}
else
{
INSTALLEDLIBS += $(<) ;
}
}
if $(CRELIB)
{
CreLib $(target) : $(objects[1]) ;
}
Archive $(target) : $(objects) ;
Clean $(<)clean : $(target) ;
Depends clean : $(<)clean ;
if $(RANLIB)
{
Ranlib $(target) ;
}
# If we can't scan the library, we have to leave the .o's around.
if ! ( $(NOARSCAN) || $(NOARUPDATE) || $(KEEPOBJS) )
{
RmTemps $(target) : $(objects) ;
}
}
# LibraryStatic libname : sources : options : decoratedtarget
rule LibraryShared
{
local objects = $(>) ;
local options = $(3) ;
local target = $(4) ;
local linklib = [ ConstructSharedLibraryLinkLib $(<) : $(options) ] ;
local deplibs ;
local i ;
for i in $(LIBDEPENDS)
{
deplibs += [ ConstructLibraryLinkTarget $(i) : $(options) ] ;
}
# Generate install rules
if ! [ IsElem noinstall : $(options) ]
{
if $(TARGET.OS) != WIN32
{
Depends install_lib : [ DoInstall $(target) : $(libdir) ] ;
}
else
{
Depends install_lib : [ DoInstall $(target) : $(bindir) ] ;
Depends install_lib : [ DoInstall $(linklib) : $(libdir) ] ;
}
# Add to global library list
if [ IsElem optional : $(options) ]
{
INSTALLEDLIBS_OPTIONAL += $(<) ;
}
else
{
INSTALLEDLIBS += $(<) ;
}
}
Depends $(<) : $(linklib) ;
if $(linklib) != $(target)
{
Depends $(linklib) : $(target) ;
MakeLocate $(linklib) : $(LOCATE.OBJECTS)/libs ;
SEARCH on $(linklib) = $(LOCATE.OBJECTS)/libs ;
}
Depends $(target) : $(objects) ;
Clean $(<)clean : $(linklib) $(target) ;
Depends clean : $(<)clean ;
Depends $(target) : $(deplibs) ;
CFlags $(<) : [ FDefines CS_$(<:U)_LIB ] ;
LFlags $(<) : $(LINKLIBS) ;
SystemLinkSharedLibrary $(target) : $(objects) $(deplibs) : $(linklib) ;
}
rule ConstructLibraryTarget
{
if ( ! [ IsElem shared : $(>) ] ) || ( $(BUILD_SHARED_LIBS) != "yes" )
{
return [ ConstructStaticLibraryTarget $(<) : [ Filter $(>) : shared ] ] ;
}
else
{
return [ ConstructSharedLibraryTarget $(<) : $(>) ] ;
}
}
rule ConstructLibraryLinkTarget
{
if ( ! [ IsElem shared : $(>) ] ) || ( $(BUILD_SHARED_LIBS) != "yes" )
{
return [ ConstructStaticLibraryTarget $(<) : [ Filter $(>) : shared ] ] ;
}
else
{
return [ ConstructSharedLibraryLinkLib $(<) : $(>) ] ;
}
}
actions together Ranlib
{
$(RANLIB) $(<)
}
# Construct pseudo target libs which is used instead of the pseudo target lib
# in Jambase
Depends lib : libs ;
NotFile libs ;
Help libs : "Build all link libraries" ;

354
mk/jam/macosx.jam Normal file
View File

@@ -0,0 +1,354 @@
#==============================================================================
# Jam configuration and actions for MacOS/X
# Copyright (C) 2003-2005 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#==============================================================================
SHELL ?= "/bin/sh" ;
MACOSX_ENVIRONMENT = "export MACOSX_DEPLOYMENT_TARGET=10.2" ;
PLUGIN.LFLAGS += "-bundle" ;
# We use the ugly -Wl form, which does not contain embedded whitespace (unlike
# "-framework AppKit"), to help external projects which use the result of
# "cs-config --libs" in conjunction with GNU libtool, since libtool likes to
# re-arrange arguments, not realizing that "-framwork" and "AppKit" need to
# stay together.
LINKLIBS += "-Wl,-framework,AppKit" "-Wl,-framework,Foundation" ;
# Jambase in Jam 2.4 has a bug where it incorrectly defines RANLIB as "" for
# MacOS/X, and this bogus value will override a RANLIB set via ?= in Jamconfig,
# by a configure script, thus we must give RANLIB an appropriate value here if
# we find that it has the bogus value. Jam 2.5 does not contain this bug.
# Furthermore, MacOS/X Panther expects us to use the -s option with ranlib.
if ! $(RANLIB) { RANLIB = "ranlib" ; }
RANLIB += "-s" ;
# Experience seems to indicate that library scanning misbehaves on MacOS/X with
# Jam 2.4, consequently we disable it.
NOARSCAN = true ;
#------------------------------------------------------------------------------
# Public rules.
#------------------------------------------------------------------------------
# ConstructApplicationTarget target : options
# Constructs the application target name.
rule ConstructApplicationTarget
{
return $(<) ;
}
# ConstructStaticLibraryTarget target : options
# Constructs the static library target name.
rule ConstructStaticLibraryTarget
{
return lib$(<)$(SUFLIB) ;
}
# ConstructSharedLibraryTarget target : options
# Constructs the shared library target name.
rule ConstructSharedLibraryTarget
{
return lib$(<).$(PACKAGE_VERSION).dylib ;
}
# ConstructSharedLibraryLinkLib target : options
# Constructs the name of a shared library against which some other target
# links.
rule ConstructSharedLibraryLinkLib
{
return lib$(<).$(PACKAGE_VERSION).dylib ;
}
# ConstructPluginTarget target : options
# Constructs the plugin target name.
rule ConstructPluginTarget
{
return $(<).csbundle ;
}
# SystemLinkApplication target : objects : options
# Apply appropriate rule to link the application based upon the options.
rule SystemLinkApplication
{
local target = $($(<)_TARGET) ;
Depends $(target) : $(>) ;
if [ IsElem console : $(3) ]
{
LinkApplicationConsole $(target) : $(>) ;
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
}
else
{
CreateApplicationWrapper $(target) : $(>) ;
CleanDir clean : [ Wrapper $(<) : app ] ;
CleanDir $(<)clean : [ Wrapper $(<) : app ] ;
}
}
# SystemInstallApplication target : subdirs : options
# Apply appropriate rule to install the application based upon the options.
rule SystemInstallApplication
{
if [ IsElem console : $(3) ]
{
Depends install_bin :
[ DoInstall $(<) : $(bindir) $(2) : $(INSTALL_PROGRAM) ] ;
}
else
{
InstallApplicationGUI $(<) : $(bindir) $(2) ;
}
}
# SystemInstallPlugin target : subdirs : options
# Apply appropriate rule to install the plugin based upon the options.
rule SystemInstallPlugin
{
Depends install_plugin :
[ DoInstall $(<) : $(plugindir) $(2) : $(INSTALL_PROGRAM) ] ;
}
# SystemLinkPlugin target : objects : options
# Link a plugin module and handle meta-data appropriately.
rule SystemLinkPlugin
{
local target = $($(<)_TARGET) ;
Depends $(target) : $(>) ;
LinkPlugin $(target) : $(>) ;
PluginMetaData $(<) : $($(<)_METAFILE) : $(3) ;
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
}
# LinkPlugin plugin : objects
# Link a plugin module from a set of object files.
actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS
{
$(MACOSX_ENVIRONMENT)
$(CMD.LINK) -bundle -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
# LinkApplicationConsole exe : objects
# Link a console (non-GUI) appliation from a set of object files.
actions LinkApplicationConsole bind NEEDLIBS bind EXTRAOBJECTS
{
$(MACOSX_ENVIRONMENT)
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
# CreateApplicationWrapper basename : objects
# Create a complete, though minimal, application wrapper given a set of
# object files. The rules ApplicationIconDefault and ApplicationIcon
# control the icon associated with the application wrapper.
rule CreateApplicationWrapper
{
WrapFile $(<) : $(<) : Contents MacOS : AppExe : $(>) ;
WrapFile $(<) : PkgInfo : Contents : AppPkgInfo : $(>) ;
WrapFile $(<) : version.plist : Contents : AppVersionPlist : $(>) ;
WrapFile $(<) : Info.plist : Contents : AppInfoPlist : $(>) ;
WrapFile $(<) : InfoPlist.strings : Contents Resources English.lproj :
AppInfoPlistStrings : $(>) ;
local icon = [ ApplicationIcon macosx : $(<) ] ;
if ! $(icon)
{
local apptype = gui ;
if [ IsElem console : $(>) ] { apptype = console ; }
icon = [ ApplicationIconDefault macosx : $(apptype) ] ;
}
if $(icon)
{
$(<)_APPICON = $(icon) ;
AppIcon $(<) : $(icon) ;
}
}
# Wrapper basename : suffix [ : pathcomponents ]
# Returns wrapper name in the directory specified by pathcomponents for
# the given basename. If pathcomponents is omitted, LOCATE.TARGETS is
# used.
rule Wrapper
{
local dir ;
if $(3) { dir = [ FDirName $(3) ] ; }
else { dir = $(LOCATE.TARGETS) ; }
return [ FDirName $(dir) $(1).$(2) ] ;
}
# WrapFile basename : file : pathcomponents : rule [ : objects : [ suffix ] ]
# Generate a file within a wrapper. pathcomponents is a list of names
# which compose the relative path within the wrapper where file should be
# placed. pathcomponents may be the empty list if the file should reside
# at the top-level of the wrapper. rule is rule/action which should be
# invoked to generate file. rule is invoked with arguments
# <basename.suffix/pathcomponents/file>, <objects>, and <basename>.
# objects is an optional list of files from which file should be built. It
# may be omitted if file does not depend upon any other files. suffix is
# the extension of the wrapper (not of file). If suffix is omitted, "app"
# is assumed.
#
# Implementation note: If basename and file are the same, then we do not
# grist file. (Obviously, we also do not want to set the file dependent
# upon itself.) The reason we do not grist file in this case is that the
# LinkWith, and LFlags rules associate the variables NEEDLIBS and
# LINKLIBS with the ungristed name, therefore in order to get access to
# these variables at AppExe action time, we must use the same (ungristed)
# name. It is otherwise impossible to gain access to those variables.
# This is an unfortunate hack which pollutes the otherwise general-purpose
# WrapFile rule.
rule WrapFile
{
local suffix ;
if $(6) { suffix = $(6) ; } else { suffix = app ; }
local target = $(2) ;
if $(target) != $(1)
{
target = $(target:G=$(1)) ;
Depends $(1) : $(target) ;
}
local dir = [ FDirName [ Wrapper $(1) : $(suffix) ] $(3) ] ;
MakeLocate $(target) : $(dir) ;
if $(5) { Depends $(target) : $(5) ; }
BASENAME on $(target) = $(1) ;
$(4) $(target) : $(5) : $(1) ;
Clean clean : [ FDirName $(dir) $(target) ] ;
Clean $(1)clean : [ FDirName $(dir) $(target) ] ;
}
# LinkApplication exe : objects
actions AppExe bind NEEDLIBS bind EXTRAOBJECTS
{
$(MACOSX_ENVIRONMENT)
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
# AppPkgInfo file
actions AppPkgInfo
{
echo 'APPL????' > $(<) ;
}
# AppInfoPlistStrings file
actions AppInfoPlistStrings
{
cat << EOT > $(<)
CFBundleName = "$(BASENAME)";
CFBundleShortVersionString = "$(PACKAGE_VERSION)";
CFBundleGetInfoString = "$(BASENAME), $(PACKAGE_VERSION)";
EOT
}
# AppVersionPlist file
actions AppVersionPlist
{
cat << EOT > $(<)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleShortVersionString</key>
<string>$(PACKAGE_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(PACKAGE_VERSION)</string>
<key>ProjectName</key>
<string>$(BASENAME)</string>
</dict>
</plist>
EOT
}
# AppInfoPlist filename : placeholder : basename
# Implementation Note: $(BASENAME)_APPICON might be empty in the actions of
# this rule, if the client did not specify a default icon or a
# target-specific icon, in which case we need to omit both the
# CFBundleIconFile key and value. To accomplish this, the key and value
# are placed on a single line with no intervening whitespace. When Jam
# interpolates a variable, if the variable is empty, it removes all
# adjacent text (the key and value, in this case) which is just what we
# desire.
actions AppInfoPlist
{
cat << EOT > $(<)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleName</key>
<string>$(BASENAME)</string>
<key>CFBundleExecutable</key>
<string>$(BASENAME)</string>
<key>CFBundleIconFile</key><string>$($(BASENAME)_APPICON)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0</string>
<key>CFBundleShortVersionString</key>
<string>$(PACKAGE_VERSION)</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
EOT
}
# AppIcon <basename> : <icon>
# Copy an icon into the wrapper. It is assumed that some other agent has
# already set SEARCH on the icon, if necessary.
rule AppIcon
{
local icon = $(>:G=$(<)) ;
Depends $(<) : $(icon) ;
Depends $(icon) : $(>) ;
MakeLocate $(icon) :
[ FDirName [ Wrapper $(<) : app ] Contents Resources ] ;
Copy $(icon) : $(>) ;
Clean clean : $(icon) ;
Clean $(<)clean : $(icon) ;
}
# InstallApplicationGUI app : installdirs
# Install a GUI application. Unlike applications on other platforms which
# exist as a single executable file, on MacOS/X, an application is wrapped
# in a directory hierarchy, thus a deep copy is needed (i.e. the typical
# Install rule does not work).
rule InstallApplicationGUI
{
local wrapper = $(<).app ;
Depends $(wrapper) : $(<) ;
SEARCH on $(wrapper) = $(LOCATE.TARGETS) ;
# Yuck! Internal knowledge of how DoInstall composes 'dir' and 'target'.
local dir = [ ConcatDirs $(DESTDIR) $(2) ] ;
local target = $(wrapper:BSR=$(dir):G=install) ;
InstallApplicationWrapperPrepare $(target) ;
Depends install_bin :
[ DoInstall $(wrapper) : $(2) : "$(DEEPCOPY)" ] ;
}
actions InstallApplicationWrapperPrepare
{
$(DELTREE) $(<) ;
}

1548
mk/jam/msvcgen.jam Normal file

File diff suppressed because it is too large Load Diff

80
mk/jam/objectivec.jam Normal file
View File

@@ -0,0 +1,80 @@
#============================================================================
# Rules for compiling Objective-C and Objective-C++ files
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
if $(CMD.OBJC)
{
rule ObjCRule
{
local object = [ DoObjectGrist [ PrefixSuffix $(>)_ : $(<) : $(SUFOBJ) ] ] ;
ObjC $(object) : $(<) ;
return $(object) ;
}
RegisterFileType ObjCRule : .m ;
RegisterHeaderRule HeaderRule : $(HDRPATTERN) : .m ;
rule ObjC
{
Depends $(<) : $(>) ;
CCFLAGS on $(<) += $(CCFLAGS) $(SUBDIRCCFLAGS) ;
OBJCFLAGS on $(<) += $(OBJCFLAGS) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions ObjC
{
$(CMD.OBJC) -c -o $(<) $(CCHDRS) $(CCFLAGS) $(OBJCFLAGS) $(CCDEFS) $(>)
}
}
if $(CMD.OBJC++)
{
rule ObjC++Rule
{
local object = [ DoObjectGrist [ PrefixSuffix $(>)_ : $(<) : $(SUFOBJ) ] ] ;
ObjC++ $(object) : $(<) ;
return $(object) ;
}
RegisterFileType ObjC++Rule : .mm .M ;
RegisterHeaderRule HeaderRule : $(HDRPATTERN) : .mm .M ;
rule ObjC++
{
Depends $(<) : $(>) ;
# Ugly hack: Apple's gcc4 does not accept -fvisibility-inlines-hidden in
# Objective-C++ mode. Ideally, this issue should be resolved by the
# configure script, but it does not currently distinguish between flags
# intended for the C++ compiler and those intended for the Objective-C++
# compiler.
local rejects = -fvisibility-inlines-hidden ;
C++FLAGS on $(<) += [ Filter $(C++FLAGS) $(SUBDIRC++FLAGS) : $(rejects) ] ;
OBJC++FLAGS on $(<) += [ Filter $(OBJC++FLAGS) : $(rejects) ] ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions ObjC++
{
$(CMD.OBJC++) -c -o $(<) $(CCHDRS) $(C++FLAGS) $(OBJC++FLAGS) $(CCDEFS) $(>)
}
}

250
mk/jam/objects.jam Normal file
View File

@@ -0,0 +1,250 @@
#============================================================================
# Rules for compiling a set of sources to object files
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# These are slightly modified versions of the Object and Objects rules from
# jam. The problem with the original rules in Jambase is the handling of
# custom file types. The solution with the UserObject rule is monolithic, you
# can only have 1 such rule. Thus we construct a more flexible toolkit here
# which let's you register rules for certain filetypes.
## RegisterFileType Rulename : extensions
## Register a rule which is used to compile a filetype into object
## files. The registered rule is called with the name of the
## sourcefile as argument and should return a list of objectfiles which are
## created. You should set the grist of the object files by using the
## DoObjectGrist function.
rule RegisterFileType
{
local suffix ;
for suffix in $(>)
{
FILETYPE_$(suffix) = $(<) ;
}
}
## RegisterHeaderRule rulename : regexpattern : extensions
## Registers a rule and a regular expression which will be used for header
## file scanning of the specified extensions.
rule RegisterHeaderRule
{
local suffix ;
for suffix in $(3)
{
HDRRULE_$(suffix) = $(<) ;
HDRPATTERN_$(suffix) = $(>) ;
}
}
## CompileObjects sources [: objectfileprefix]
## Compile a set of sourcefiles into objectfiles (extension: SUFOBJ,
## usually .o). This rule takes care of setting the SEARCH and LOCATE
## variables to the values of $(SEARCH_SOURCE) and $(LOCATE_TARGET).
## The Application, Plugin and Library rules already use this rule
## internally. You should only use this rule if you have to avoid the
## Application, Plugin or Library rules.
rule CompileObjects
{
local source ;
local targets ;
# Search the source
SEARCH on $(<) = $(SEARCH_SOURCE) ;
for source in $(<)
{
# compile the sourcefile to targetfile
targets += [ CompileObject $(source) : $(>) ] ;
}
# locate the targets
MakeLocate $(targets) : $(LOCATE_TARGET) ;
return $(targets) ;
}
## PrefixSuffix [prefix] : filename : suffix
## Replaces the suffix of 'filename' with 'suffix' and prepends 'prefix' to
## it.
rule PrefixSuffix
{
local prefix = $(1) ;
local name = $(2) ;
local suffix = $(3) ;
if ! $(prefix) { prefix = "" ; }
return $(name:B=$(prefix)$(name:B):S=$(suffix)) ;
}
#----------------------------------------------------------------------------
# private part
# helper rule: Compiles a source file to an object file. Does header file
# scanning, sets LOCATE and SEARCH for source and target, grists the files
# with the current subdir and searches for the correct registered rule.
rule CompileObject
{
# handle #includes for source: Jam scans for headers with
# the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
# with the scanned file as the target and the found headers
# as the sources. HDRSEARCH is the value of SEARCH used for
# the found header files. Finally, if jam must deal with
# header files of the same name in different directories,
# they can be distinguished with HDRGRIST.
# $(SEARCH_SOURCE:E) is where cc first looks for #include
# "foo.h" files. If the source file is in a distant directory,
# look there. Else, look in "" (the current directory).
if $(HDRRULE_$(<:S))
{
HDRSEARCH on $(<) =
$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
HDRGRIST on $(<) = $(HDRGRIST) ;
HDRRULE on $(<) = $(HDRRULE_$(<:S)) ;
HDRSCAN on $(<) = $(HDRPATTERN_$(<:S)) ;
}
local targets ;
# Invoke filetype specific rule
if $(FILETYPE_$(<:S))
{
targets = [ $(FILETYPE_$(<:S)) $(<) : $(>) ] ;
}
else
{
echo Warning: no rules for file type $(<:S) defined (at file $(<)). ;
}
if $(targets)
{
# construct clean target
Clean clean : $(targets) ;
# Save HDRS for -I$(HDRS) on compile.
# We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers
# in the .c file's directory, but generated .c files (from
# yacc, lex, etc) are located in $(LOCATE_TARGET), possibly
# different from $(SEARCH_SOURCE).
HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
# propagate target specific-defines
DEFINES on $(<) += $(DEFINES) ;
}
return $(targets) ;
}
## HeaderRule source : headers
## This rule is the default header rule used by the objects rules. You
## might register custom rules with the RegisterHeaderRule rule.
rule HeaderRule
{
# N.B. This rule is called during binding, potentially after
# the fate of many targets has been determined, and must be
# used with caution: don't add dependencies to unrelated
# targets, and don't set variables on $(<).
# Tell Jam that anything depending on $(<) also depends on $(>),
# set SEARCH so Jam can find the headers, but then say we don't
# care if we can't actually find the headers (they may have been
# within ifdefs),
local s = $(>:G=$(HDRGRIST:E)) ;
Includes $(<) : $(s) ;
SEARCH on $(s) = $(HDRSEARCH) ;
NoCare $(s) ;
local i ;
for i in $(s)
{
HDRGRIST on $(i) = $(HDRGRIST) ;
HDRSEARCH on $(i) = $(HDRSEARCH) ;
HDRRULE on $(i) = [ on $(<) GetVar HDRRULE ] ;
HDRSCAN on $(i) = [ on $(<) GetVar HDRPATTERN ] ;
}
}
if $(JAMVERSION) < 2.5
{
## XXX XXX XXX a bug in jam 2.4 let's the version above fail. I'll let this
## non-optimal version in here until jam 2.5 is out.
rule HeaderRule
{
local s = $(>:G=$(HDRGRIST:E)) ;
Includes $(<) : $(s) ;
SEARCH on $(s) = $(HDRSEARCH) ;
NoCare $(s) ;
local i ;
for i in $(s)
{
if $(HDRRULE_$(i:S))
{
HDRGRIST on $(i) = $(HDRGRIST) ;
HDRSEARCH on $(i) = $(HDRSEARCH) ;
HDRRULE on $(i) = $(HDRRULE_$(i:S)) ;
HDRSCAN on $(i) = $(HDRPATTERN_$(i:S)) ;
}
else if $(JAM_DEBUG)
{
#echo "No Header rule for $(i:S) file $(i) " ;
}
}
}
} # end of if $(JAMVERSION) < 1.5
# Dummy rule: .o files are used as is.
rule UseObjectFile
{
return $(<) ;
}
RegisterFileType UseObjectFile : .o ;
# Ignore header files.
rule UseHeaderFile
{
return ;
}
RegisterFileType UseHeaderFile : .h .hpp ;
RegisterHeaderRule HeaderRule : $(HDRPATTERN) : .h .hpp .inc ;
# Generates a grist suitable for output objects based on
# SUBVARIANT and SUBDIR variable.
rule DoObjectGrist
{
return $(<:G=$(SOURCE_GRIST:E)!$(SUBVARIANT:J=!)) ;
}
# Generates a grist suitable for source files based on SUBDIR variable.
# Doesn't change an existing grist.
rule DoSourceGrist
{
local gristed ;
for g in $(<)
{
local grist ;
if $(g:G)
{
grist = $(g:G) ;
}
gristed += $(g:G=$(grist:E=$(SOURCE_GRIST:E))) ;
}
return $(gristed) ;
}

38
mk/jam/options.jam Normal file
View File

@@ -0,0 +1,38 @@
#============================================================================
# Rule for setting options at targets
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
#----------------------------------------------------------------------------
# private rule - please specify the options in Application, Plugin or Library
# rule and don't use this rule here directly.
## CheckOptions candidates : Options : target
rule CheckOptions
{
local i ;
for i in $(>)
{
if ! [ IsElem $(i) : $(<) ]
{
echo "WARNING: Unknown option $(i) specified at $(3)." ;
}
}
}

166
mk/jam/plugin.jam Normal file
View File

@@ -0,0 +1,166 @@
#============================================================================
# Rules for plugin creation
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
SUFMETA ?= .csplugin ;
GRISTMETA ?= pluginmeta ;
## Plugin pluginname : sources [ : options ]
## Build a plugin out of sourcefiles. All sourcefiles will be passed
## to the Objects rule which tries to compile them into object-files. You
## can create rules for your own filetypes with the UserObject rule. Header
## files will just be ignored. They are only used for MSVC projectfile
## generator.
## You can specify the noinstall option if you don't want that an install
## target is created.
## Options:
## noinstall: Don't setup a default installation target.
## independent: The target will not be made a dependency of the plugins
## and all target.
## nohelp: Do not invoke Help for this target.
## notest: Do not set up unit-testing support for this target.
rule Plugin
{
# check options
CheckOptions noinstall independent nohelp notest : $(3) : $(<) ;
local metafile ;
metafile = [ FAppendSuffix $(<) : $(SUFMETA) ] ;
SEARCH on $(metafile) = $(SEARCH_SOURCE) ;
local target = [ ConstructPluginTarget $(<) : $(3) ] ;
local sources = [ DoSourceGrist $(>) ] ;
local objects = [ CompileObjects $(sources) ] ;
$(<)_TYPE = plugin ;
$(<)_OBJECTS = $(objects) ;
$(<)_SOURCES = $(sources) ;
$(<)_TARGET = $(target) ;
$(<)_METAFILE = $(metafile) ;
# create target clean rule
Always $(<)clean ;
NotFile $(<)clean ;
Clean $(<)clean : $(objects) ; # create target clean rule
# Create a target for eventual static linking
if ! $(NO_STATIC_LINKING)
{
SubVariant static ;
local staticreginfoobject = [ BuildStaticRegFile $(<) : $(statictarget) ] ;
# Add objects to the list of candidates for potential inclusion in a
# monolithic static library containing objects for all plugins (useful for
# statically linking the plugins into an application if the client so
# desires).
local staticobjects = [ CompileObjects $(sources) : $(<) ] ;
local obj_remain = $(objects) ;
local staticobj_remain = $(staticobjects) ;
while $(obj_remain)
{
local obj = $(obj_remain[1]) ;
local staticobj = $(staticobj_remain[1]) ;
STATICPLUGINS.OBJECTS.$(staticobj) = $(obj) ;
obj_remain = $(obj_remain[2-]) ;
staticobj_remain = $(staticobj_remain[2-]) ;
}
MakeLocate $(staticobjects) : $(LOCATE_TARGET) ;
STATICPLUGINS.OBJECTS.$(<) += $(staticreginfoobject) ;
STATICPLUGINS.OBJECTS.$(<) += $(staticobjects) ;
STATICPLUGINS.SUBTARGETS += $(<) ;
SubVariant ;
}
# so 'jam foo' works when it's really foo.dll (Windows) or foo.csbundle
# (MacOS/X)
if $(target) != $(<)
{
Depends $(<) : $(target) ;
NotFile $(<) ;
}
if ! [ IsElem independent : $(3) ]
{
Depends plugins : $(<) ;
}
# construct install target
if ! [ IsElem noinstall : $(3) ]
{
SystemInstallPlugin $(target) ;
}
# Link
MakeLocate $(target) : $(LOCATE.TARGETS) ;
SystemLinkPlugin $(<) : $(objects) : $(3) ;
CFlags $(<) : $(PLUGIN.CFLAGS) : nostatic ;
LFlags $(<) : $(LINKLIBS) $(PLUGIN.LFLAGS) : nostatic ;
if ! [ IsElem nohelp : $(3) ]
{
local desc = [ Description $(<) ] ;
if ! $(desc) { desc = "$(<) plugin" ; }
Help $(<) : "Build the $(desc)" ;
}
if ! [ IsElem notest : $(options) ]
{
# @@@ Disabled for now; see docs/todo_jam.txt
#UnitTest $(<) ;
}
}
#----------------------------------------------------------------------------
# private rules
# PluginMetaData pluginname : metafile [ : options ]
# Copy a plugin's meta file so that it resides alongside the generated
# plugin module. This utility rule may be used by SystemLinkPlugin rules
# which employ the default behavior of having a plugin's meta-data file
# reside alongside the plugin executable (as opposed to bundling the
# metadata directly into the plugin).
# Options:
# noinstall: Don't setup a default installation target.
rule PluginMetaData
{
local target = $(>:G=$(GRISTMETA)) ;
Depends $(<) : $(target) ;
Depends $(target) : $(>) ;
MakeLocate $(target) : $(LOCATE.TARGETS) ;
Copy $(target) : $(>) ;
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
if ! [ IsElem noinstall : $(3) ]
{
Depends install_plugin : [ DoInstall $(target) : $(plugindir) ] ;
}
}
# Construct pseudo target plugins
Depends exe : plugins ;
NotFile plugins ;
Help plugins : "Build all plugin modules" ;

58
mk/jam/property.jam Normal file
View File

@@ -0,0 +1,58 @@
#==============================================================================
# Generic property-bag mechanism.
# Copyright (C) 2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#==============================================================================
# Property bag : name
# Returns the value of property 'name' in container 'bag' if present, else
# returns a null value. 'bag' and 'name' should be simple identifiers
# composed of alphanumeric characters and underscore, and with an alphabetic
# or an underscore as the first character.
rule Property
{
local p = [ _PropertyName $(<) : $(>) ] ;
return $($(p)) ;
}
# SetProperty bag : name [ : value ]
# Add property 'name' to container 'bag'. If 'value' is not provided, sets
# the property to "true".
rule SetProperty
{
local p = [ _PropertyName $(<) : $(>) ] ;
local v = $(3) ;
if ! $(v) { v = "true" ; }
$(p) = $(v) ;
}
# ClearProperty bag : name
# Remove property 'name' from container 'bag'.
rule ClearProperty
{
local p = [ _PropertyName $(<) : $(>) ] ;
$(p) = "" ;
}
#------------------------------------------------------------------------------
# Private utilitiy rules.
#------------------------------------------------------------------------------
rule _PropertyName
{
return "__property_$(<)_$(>)" ;
}

109
mk/jam/resource.jam Normal file
View File

@@ -0,0 +1,109 @@
#============================================================================
# Rules for handling additional resources.
# Platform-specific Jam files may override these if needed.
#
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
## ApplicationIconDefault platform : type [ : icon [ : pathcomponents ]]
## If invoked with three or more arguments, specifies the default icon for
## applications of the specified type for the given platform, which may be
## 'macosx', 'win32', or 'unix'. Type should be 'all', 'gui', or 'console'.
## If pathcomponents is omitted, SEARCH_SOURCE is used. This setting can be
## overriden for an individual application with the ApplicationIcon rule.
## This rule must be invoked before invoking any Application rules if it is
## to have any effect. If invoked with two arguments, returns the default
## icon (if any) for the given platform and type.
rule ApplicationIconDefault
{
local platform = $(1) ;
local type = $(2) ;
local icon = $(3) ;
local iconpath = $(4) ;
local key = default_$(platform)_$(type) ;
if $(icon)
{
SetProperty appicon : $(key) : $(icon) ;
if $(iconpath)
{
SEARCH on $(icon) = [ ConcatDirs $(iconpath) ] ;
}
else
{
SEARCH on $(icon) = $(SEARCH_SOURCE) ;
}
}
local result = [ Property appicon : $(key) ] ;
if ! $(result) && $(type) != all
{
result = [ Property appicon : default_$(platform)_all ] ;
}
return $(result) ;
}
## ApplicationIcon platform : basename [ : icon [ : pathcomponents ]]
## If invoked with three or more arguments, specifies the icon for the
## application given by basename for the indicated platform, which may be
## 'macosx', 'win32', or 'unix'. If pathcomponents is omitted,
## SEARCH_SOURCE is used. If this rule is not invoked, then the icon
## specified via ApplicationIconDefault is used, if any. This rule must be
## invoked before the Application rule to which this icon will apply. If
## invoked with two arguments, returns the icon (if any) explicitly
## registered for basename for the given platform.
rule ApplicationIcon
{
local platform = $(1) ;
local target = $(2) ;
local icon = $(3) ;
local iconpath = $(4) ;
local key = app_$(platform)_$(target) ;
if $(icon)
{
SetProperty appicon : $(key) : $(icon) ;
if $(iconpath)
{
SEARCH on $(icon) = [ ConcatDirs $(iconpath) ] ;
}
else
{
SEARCH on $(icon) = $(SEARCH_SOURCE) ;
}
# An ugly but effective way to detect incorrect usage.
if $($(target)_TARGET)
{
Echo "Warning: `ApplicationIcon:$(target):$(icon)' incorrectly invoked"
"after Application rule." ;
}
}
return [ Property appicon : $(key) ] ;
}
## Win32Resource basename : rcfiles
## Specify .rc files for the target known as basename. The .rc files should
## already have SEARCH set appropriately.
rule Win32Resource { }
## Win32RcFlags basename : rcfiles
## Specify flags passed to the resource compiler when compiling resources
## for the target known as basename.
rule Win32RcFlags { }

353
mk/jam/static.jam Normal file
View File

@@ -0,0 +1,353 @@
#============================================================================
# Utility rules for static builds without plugins
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
# all private
rule GenerateStaticPluginBoilerplate
{
ResponseFile $(<) :
"// This file is automatically generated."
"#include \"cssysdef.h\""
"#include \"csutil/scf.h\""
""
"// Put static linking stuff into own section."
"// The idea is that this allows the section to be swapped out but not"
"// swapped in again b/c something else in it was needed."
"#if !defined(CS_DEBUG) && defined(CS_COMPILER_MSVC)"
"#pragma const_seg(\".CSmetai\")"
"#pragma comment(linker, \"/section:.CSmetai,r\")"
"#pragma code_seg(\".CSmeta\")"
"#pragma comment(linker, \"/section:.CSmeta,er\")"
"#pragma comment(linker, \"/merge:.CSmetai=.CSmeta\")"
"#endif"
: notfile ;
}
rule GenerateStaticPluginInstantiation
{
GenerateStaticPluginBoilerplate $(<) ;
ResponseFile $(<) : "SCF_USE_STATIC_PLUGIN($(>:B))" : notfile ;
}
rule GenerateStaticPluginRegistration
{
GenerateStaticPluginBoilerplate $(<) ;
GenerateStaticPluginRegistration1 $(<) : $(>) ;
}
rule BuildStaticRegFile
{
local statictarget = $(>) ;
# prepare source files
local sources = [ DoObjectGrist _$(<)_static_reg.cpp ] ;
local object = [ CompileObject $(sources) ] ;
MakeLocate $(sources) : $(LOCATE_TARGET) ;
MakeLocate $(object) : $(LOCATE_TARGET) ;
local metalist metafile i ;
for i in $(<)
{
metafile = $($(i)_METAFILE) ;
metalist += $(metafile) ;
Depends $(sources) : $(metafile) ;
}
GenerateStaticPluginRegistration $(sources) : $(metalist) ;
Clean $(statictarget)clean : $(sources) ;
Clean $(statictarget)clean : $(object) ;
return $(object) ;
}
rule BuildStaticUseFile
{
local statictarget = $(2) ;
local package = $(3) ;
# prepare source files
local sources ;
if $(3)
{
sources = [ DoObjectGrist _cs_static_use_$(package).cpp ] ;
}
else
{
sources = [ DoObjectGrist _cs_static_use.cpp ] ;
}
local object = [ CompileObject $(sources) ] ;
MakeLocate $(sources) : $(LOCATE_TARGET) ;
SEARCH on $(sources) = $(LOCATE_TARGET) ;
MakeLocate $(object) : $(LOCATE_TARGET) ;
C++FLAGS on $(object) += $($($(>).EXTERNALLIBS).CFLAGS) ;
GenerateStaticPluginInstantiation $(sources) : $(<) ;
Clean $(statictarget)clean : $(sources) ;
Clean $(statictarget)clean : $(object) ;
return $(object) ;
}
## LinkStaticPlugins target : plugins [: optionalplugins] [: package]
## Builds the plugins in 'plugins' (and 'optionalplugins') statically into
## 'target'. Can be used both for static plugins from the local project or
## an external project. In the latter case, the project's static plugin
## library has to have been built, also, the "<package>.STATICDEPS"
## variable must contain a path to a specially generated Jamfile that
## contains information about the plugins provided by as well as external
## dependencies. The static plugins library for both local and external
## package must be explicitly linked into 'target'.
rule LinkStaticPlugins
{
local package target plugins optplugins ;
# Fetch the parameters
target = $(1) ;
plugins = $(2) ;
optplugins = $(3) ;
package = $(4) ;
if $(package)
{
# External static plugins.
# First include static plugin info
if ! $(HAVE_STATICDEPS.$(package))
{
include $($(package).STATICDEPS) ;
HAVE_STATICDEPS.$(package) = yes ;
}
local lflags p ;
# Collect optional plugins
for p in $(optplugins)
{
if [ IsElem $(p) : $(STATICPLUGINS.AVAILABLE) ]
{
plugins += $(p) ;
}
}
# Grab flags
for p in $(plugins)
{
NotFile $(p) ;
CFlags $(target) : $(STATICPLUGIN.$(p).CFLAGS) ;
lflags = [ MergeLFlags $(lflags) : $(STATICPLUGIN.$(p).LFLAGS) ] ;
}
LFlags $(target) : $(lflags) ;
}
else
{
# Local static plugins
local lflags libs p ;
# Collect optional plugins
for p in $(optplugins)
{
if $($(p)_TARGET)
{
plugins += $(p) ;
}
}
# Grab flags
for p in $(plugins)
{
lflags += [ Filter $($(p).LFLAGS) : $(LINKLIBS) $(PLUGIN.LFLAGS) ] ;
libs += $($(p).NEEDLIBS) ;
}
LFlags $(target) : [ Reverse [ RemoveDups [ Reverse $(lflags) ] ] ] ;
LinkWith $(target) : [ Reverse [ RemoveDups [ Reverse $(libs) ] ] ] ;
}
# construct initialization sourcefile
local staticobject = [ BuildStaticUseFile $(plugins) : $(target) : $(package) ] ;
ExtraObjects $(target) : $(staticobject) : inheritcflags ;
}
## StaticPluginLibrary name [: rejects]
## Create a library that monolithically contains statically linkable
## versions of all plugins, and also provides a target to install this
## library ("install_staticplugins") as well as resources to facilitate the
## use of that library from external projects. Also, most plugins will
## probably themselves depend on other libraries; while those are correctly
## linked in with the static plugins, they are not built or installed when
## the static plugin library is.
## This library is intended to be used together with the
## "LinkStaticPlugins" rule.
rule StaticPluginLibrary
{
local name = $(<) ;
local rejects = $(>) ;
local t ;
local targets = $(STATICPLUGINS.SUBTARGETS) ;
if $(rejects)
{
targets = [ Filter $(targets) : $(rejects) ] ;
}
local objects ;
for t in $(targets)
{
objects += $(STATICPLUGINS.OBJECTS.$(t)) ;
}
# Set up library
Library $(name) : $(objects) : noinstall notest independent nohelp ;
SEARCH on $(name) += $(LOCATE_TARGET) ;
MsvcDefine $(name) : $(STATICPLUGINS.MSVC_DEFINES) ;
CFlags $(name) :
[ FDefines CS_STATIC_LINKED ]
: nostatic ;
# Copy a variety of flags
local o ;
for o in $(objects)
{
local sourceobj = $(STATICPLUGINS.OBJECTS.$(o)) ;
if $(sourceobj)
{
CCFLAGS on $(o) += [ on $(sourceobj) GetVar CCFLAGS ] ;
C++FLAGS on $(o) += [ on $(sourceobj) GetVar C++FLAGS ] ;
}
}
# Write out needed CFLAGS, LFLAGS
STATICPLUGINS.DEPENDENCIES = $(name).jam ;
MakeLocate $(STATICPLUGINS.DEPENDENCIES) : $(LOCATE.OBJECTS)/libs ;
for t in $(targets)
{
WriteDependencies $(STATICPLUGINS.DEPENDENCIES) : $(t) : $(name) ;
}
Depends $(name) : $(STATICPLUGINS.DEPENDENCIES) ;
Clean $(name)clean : $(STATICPLUGINS.DEPENDENCIES) ;
# Install targets
Depends install_staticplugins :
[ DoInstall [ ConstructLibraryTarget $(name) ] : $(libdir) ] ;
Depends install_staticplugins : $(STATICPLUGINS.DEPENDENCIES) ;
Depends install_staticplugins :
[ DoInstall $(STATICPLUGINS.DEPENDENCIES) : $(libdir) ] ;
Depends install_staticplugins : install_libs ;
INSTALLEDLIBS_OPTIONAL += $(name) ;
# Collect library dependencies. The idea is to built all libs needed by the
# static plugins when "jam staticplugins" is invoked.
for t in $(targets)
{
local deplibs ;
if $($(t).NEEDLIBS)
{
deplibs += $($(t).NEEDLIBS) ;
}
deplibs = [ RemoveDups $(deplibs) ] ;
Depends staticplugins : $(deplibs) ;
}
Help staticplugins :
"Build the library with static versions of all plugins" ;
Depends staticplugins : libs $(name) ;
}
#----------------------------------------------------------------------------
# Write out CFLAGS, LFLAGS needed by a plugin
rule WriteDependencies
{
local cflags ;
local lflags ;
local depfile = $(<) ;
local plugin = $(>) ;
local name = $(3) ;
local depfile_gristed = $(depfile:G=$(plugin)) ;
MakeLocate $(depfile_gristed) : [ on $(depfile) GetVar LOCATE ] ;
# Collect flags
lflags += -l$(name) ;
local libs = [ ResolveLibs $($(plugin).NEEDLIBS) ] ;
lflags += -l$(libs) ;
local l ;
for l in $($(plugin).EXTERNALLIBS)
{
cflags += $($(l).CFLAGS) ;
lflags += [ Filter $($(l).LFLAGS) : $(LINKLIBS) $(PLUGIN.LFLAGS) ] ;
}
lflags += [ Filter $($(plugin).LFLAGS) : $(LINKLIBS) $(PLUGIN.LFLAGS) ] ;
CFLAGS on $(depfile_gristed) = "$(cflags)" ;
LFLAGS on $(depfile_gristed) = "$(lflags)" ;
if $($(depfile).FIRSTTIME) != "yes"
{
WriteDepFlags1 $(depfile_gristed) : $(plugin) ;
$(depfile).FIRSTTIME = "yes" ;
}
else
{
WriteDepFlags2 $(depfile_gristed) : $(plugin) ;
}
Depends $(depfile) : $(depfile_gristed) ;
}
actions WriteDepFlags1
{
cat << EOT > $(<)
STATICPLUGINS.AVAILABLE += $(>) ;
STATICPLUGIN.$(>).CFLAGS = $(CFLAGS) ;
STATICPLUGIN.$(>).LFLAGS = $(LFLAGS) ;
EOT
}
actions WriteDepFlags2
{
cat << EOT >> $(<)
STATICPLUGINS.AVAILABLE += $(>) ;
STATICPLUGIN.$(>).CFLAGS = $(CFLAGS) ;
STATICPLUGIN.$(>).LFLAGS = $(LFLAGS) ;
EOT
}
actions piecemeal GenerateStaticPluginRegistration1
{
echo 'namespace csStaticPluginInit' >> $(<)
echo '{' >> $(<)
for x in $(>)
do
n=`basename $x $(SUFMETA)`
echo "static char const metainfo_${n}[] =" >> $(<)
$(SED) 's:\\:\\\\:g;s:":\\":g;s:\(.*\):"\1":' < $x >>$(<)
echo ";" >> $(<)
$(SED) '/<implementation>/!d;s:[ ]*<implementation>\(..*\)</implementation>: #ifndef \1_FACTORY_REGISTER_DEFINED \
#define \1_FACTORY_REGISTER_DEFINED \
SCF_DEFINE_FACTORY_FUNC_REGISTRATION(\1) \
#endif:g' < $x >> $(<)
done
echo '' >> $(<)
for x in $(>)
do
n=`basename $x $(SUFMETA)`
echo "class ${n}" >> $(<)
echo "{" >> $(<)
echo "SCF_REGISTER_STATIC_LIBRARY($n,metainfo_${n})" >>$(<)
$(SED) '/<implementation>/!d;s:[ ]*<implementation>\(..*\)</implementation>: #ifndef \1_FACTORY_REGISTERED \
#define \1_FACTORY_REGISTERED \
\1_StaticInit \1_static_init__; \
#endif:g' < $x >> $(<)
echo "public:" >> $(<)
echo " ${n}();" >> $(<)
echo "};" >> $(<)
echo "$n::$n() {}" >> $(<)
echo "" >> $(<)
done
echo '}' >> $(<)
}

109
mk/jam/subdir.jam Normal file
View File

@@ -0,0 +1,109 @@
#============================================================================
# Work around problems the SubDir rule of Jambase
# (until jampeople accept my patches :-/ )
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
LOCATE.OBJECTS ?= $(BUILDTOP)/out/$(OSFULL[1]:L) ;
LOCATE.TARGETS ?= $(BUILDTOP) ;
LOCATE.DOCS ?= $(BUILDTOP)/out/docs ;
SUBDIRRULES += FixSubDirPath ;
CMD.MKDIR ?= mkdir ;
CMD.MKDIRS ?= "$(CMD.MKDIR) -p" ;
rule FixSubDirPath
{
LOCATE_SOURCE = [ FDirName $(LOCATE.OBJECTS) $(SUBDIR_TOKENS) ] ;
LOCATE_TARGET = [ FDirName $(LOCATE.OBJECTS) $(SUBDIR_TOKENS) ] ;
}
# Fix bug in Jambase where SubInclude in the middle of a Jamfile made it break.
rule SubInclude
{
if ! $($(<[1]))
{
Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ;
}
local save_SUBDIR_TOKENS = $(SUBDIR_TOKENS) ;
SubDir $(<) ;
include $(JAMFILE:D=$(SUBDIR)) ;
SubDir $(<[1]) $(save_SUBDIR_TOKENS) ;
}
# This MakeLocate rule differs from the Jambase one in that it also works with
# files being in subdirectories.
rule MakeLocate
{
# MakeLocate targets : directory ;
# Sets special variable LOCATE on targets, and arranges
# with MkDir to create target directory.
# Note we grist the directory name with 'dir',
# so that directory path components and other
# targets don't conflict.
if $(>) && $(>) != ""
{
local i ;
for i in $(<)
{
LOCATE on $(i) = $(>) ;
local targetfile = $(i:R=$(>)) ;
local targetdir = $(targetfile:D) ;
if ! $(targetdir) { targetdir = "." ; }
targetdir = $(targetdir:G=dir) ;
Depends $(i) : $(targetdir) ;
MkDir $(targetdir) ;
}
}
}
# The default MkDir rule in Jambase has problems when paths contains a sequence
# of multiple slashes (ie. bla////fup). We solve these problems and greatly
# simply this rule by using the "mkdir -p" or mkdirs command.
rule MkDir
{
# MkDir directory ;
# Make a directory and all its parent directories.
# Ignore timestamps on directories: we only care if they
# exist.
NoUpdate $(<) ;
# don't create the dir multiple times
if ! $($(<)-mkdir)
{
$(<)-mkdir = true ;
MkDir1 $(<) ;
}
}
actions MkDir1
{
$(CMD.MKDIRS) "$(<)"
}

225
mk/jam/swig.jam Normal file
View File

@@ -0,0 +1,225 @@
#============================================================================
# Rules for swig
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
if $(CMD.SWIG)
{
# Post-processing of the Swig-generated C++ file.
#
# (1) We need to ensure that <stdint.h> defines INT64_C() and cousins, which
# means that the __STDC_CONSTANT_MACROS and __STDC_LIMIT_MACROS macros must
# be defined before <stdint.h> is included. In some Python installations,
# Python.h includes <stdint.h>, and Swig-generated output includes Python.h
# before we ever have a chance to define the __STDC_* macros. There is no
# Swig-supported mechanism allowing us to insert these #defines before
# Python.h is included, so we post-process the output file.
#
# (2) We #undefine _DEBUG, to ensure that python23.lib is used by MSVC
# instead of python23_d.lib.
#
# (3) Delete any lines containing the CVS `Header' keyword to ensure that CVS
# does not consider the file changed simply because `Header' expansion
# differs.
#
# (4) Swig 1.3.22 for Perl emits illegal expressions `new (sometype)[n]'
# rather than `new sometype[n]' (at least gcc considers it illegal),
# therefore, we transform the expression by dropping the parentheses.
#
# (5) cs_pyth.cpp contains a macro "#define SWIG_init init_cspace". However,
# cs_pyth.cpp may reside in a shared lib, so we rather want the name
# SWIG_init and define init_cspace as a simple forwared ourselves.
#
# (6) perl.h includes dirent.h on some configurations which conflicts with
# the CS definitions of dirent, opendir, etc. So define _DIRENT_H_ to
# make dirent.h skip its body. This is hackish but no better solution
# has been found.
#
# (Despite the fact that these customizations might seem project-specific,
# they should be safe for all projects.)
SWIG.SED_SCRIPT =
"'s/\\([ ]*#[ ]*include[ ][ ]*[<\"]Python.h[>\"]\\)/\\
#ifndef __STDC_CONSTANT_MACROS\\
#define __STDC_CONSTANT_MACROS\\
#endif\\
#ifndef __STDC_LIMIT_MACROS\\
#define __STDC_LIMIT_MACROS\\
#endif\\
#ifndef DEBUG_PYTHON\\
#undef _DEBUG\\
#endif\\
\\1/g
/\$Header:/d
s/new[ ][ ]*(\\([^)][^)]*\\))[ ]*\\[/new \\1 [/g
s/[ ]*#[ ]*define[ ][ ]*SWIG_init[ ]*init_\\(.*\\)/#define SWIG_init SWIG_init_\\1/g
s/\\([ ]*#[ ]*include[ ][ ]*[<\"]perl.h[>\"]\\)/\\
#ifndef _DIRENT_H_\\
#define _DIRENT_H_\\
#endif\\
\\1/g'" ;
## Swig targets : swigfile : language [ : swigflags [ : swigincdirs
## [ : swigfiledir [ : frozendirs [ : tag [ : outdir ]]]]]]
## Given a Swig input file `swigfile', generate `targets' for scripting
## language `language'. The first element of `targets' should name the
## generated C or C++ file, and the remaining optional elements should name
## any other language-specific scripting files which Swig will generate.
## For instance, the files widgets.cpp and widgets.py might be emitted by
## Swig for the input file widgets.i. The generated files are placed in
## $(LOCATE_TARGET). `swigflags' specifies additional flags to pass to
## Swig. `swigincdirs' is a list of additional directories which Swig
## should search for files which it includes. `swigfiledir' specifies the
## location of `swigfile' if it does not reside in the present source
## directory. This rule defines top-level targets named "$(tag)swig",
## which generates `targets' on-demand; and "$(tag)swigclean", which
## deletes the generated files. `tag' is a simple identifier out of which
## top-level pseudo-targets names are constructed. If `tag' is not
## provided, then `language' is used instead. If `frozentargdirs' is
## provided, then an additional top-level target named "$(tag)freeze" is
## defined, which copies the generated files to the specified directories.
## If `frozentargdirs' contains only one element, then all generated files
## are copied to that directory. If it contains two elements, then the
## first element of `targets' is copied to the first element of
## `frozentargdirs', and all remaining elements of `targets' are copied to
## the second element of `frozentargdirs'. `outdir', if provided, is a list
## of path components which specify a subdirectory in which Swig should
## place the language-specific support files, rather than placing them in
## $(LOCATE_TARGET). This might be useful, for instance, when Swig is in
## Java mode, and the .java files must be placed in a directory hierarchy
## which reflects the full package name.
rule Swig
{
local target = $(1[1]) ;
local othertargets = $(1[2-]) ;
local swigfile = $(2) ;
local language = $(3) ;
local swigflags = $(4) ;
local swigincdirs = $(5) ;
local swigfiledir = $(6) ;
local frozentargetdir = $(7[1]) ;
local frozenotherdir = $(7[2-]) ;
local tag = $(8) ;
local outdir = $(9) ;
if ! $(frozenotherdir) { frozenotherdir = $(frozentargetdir) ; }
if ! $(tag) { tag = $(language) ; }
if ! $(outdir) { outdir = $(LOCATE_TARGET) ; }
Depends $(target) : $(swigfile) ;
MakeLocate $(target) : $(LOCATE_TARGET) ;
if $(othertargets)
{
MakeLocate $(othertargets) : $(outdir) ;
# If any target, such as an install target, depends upon the other files,
# we force them to be built with a dependency upon the target.
Depends $(othertargets) : $(target) ;
}
SWIG.FLAGS on $(target) +=
$(SWIG.FLAGS) -$(language) $(swigflags) -I$(swigincdirs)
-outdir [ ConcatDirs $(outdir) ] ;
# Allow Swig input file to reside at location other than $(SEARCH_SOURCE).
if $(swigfiledir)
{
SEARCH on $(swigfile) = $(swigfiledir) ;
}
else
{
SEARCH on $(swigfile) = $(SEARCH_SOURCE) ;
}
# Scan for special Swig includes.
HDRGRIST on $(swigfile) = $(HDRGRIST) ;
HDRSEARCH on $(swigfile) =
$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
HDRRULE on $(swigfile) = HeaderRule ;
HDRSCAN on $(swigfile) = $(SWIG.HDRPATTERN) ;
RunSwig $(target) : $(swigfile) ;
Depends $(tag)swig : $(target) ;
NotFile $(tag)swig ;
Always $(tag)swig ;
Help $(tag)swig : "Generate Swig files for $(tag)" ;
Clean $(tag)swigclean : $(target) $(othertargets) ;
Depends clean : $(tag)swigclean ;
if $(frozentargetdir)
{
local frozen_target = $(target:G=$(tag)freeze) ;
MakeLocate $(frozen_target) : $(frozentargetdir) ;
Depends $(frozen_target) : $(target) ;
Copy $(frozen_target) : $(target) ;
Depends $(tag)freeze : $(frozen_target) ;
if $(othertargets)
{
local frozen_other = $(othertargets:G=$(tag)freeze) ;
MakeLocate $(frozen_other) : $(frozenotherdir) ;
Depends $(frozen_other) : $(othertargets) ;
Copy $(frozen_other) : $(othertargets) ;
Depends $(tag)freeze : $(frozen_other) ;
}
NotFile $(tag)freeze ;
Help $(tag)freeze : "Copy generated Swig files to source directory" ;
}
}
actions RunSwig
{
$(CMD.SWIG) $(SWIG.FLAGS) -o $(<) $(>)
$(SED) $(SWIG.SED_SCRIPT) < $(<) > $(<).sed
$(RM) $(<)
$(MV) $(<).sed $(<)
}
SWIG.SIMPLE.LANGUAGE ?= python ;
SWIG.SIMPLE.EXT ?= py ;
SWIG.SIMPLE.FLAGS ?= -c++ -shadow ;
## SimpleSwig swigfile
## Given a Swig input file (.i), invokes Swig to generate a .cpp file with
## the same basename, and a script file with the same basename.
## SWIG.SIMPLE.LANGUAGE specifies the language for which Swig should emit a
## binding; SWIG.SIMPLE.EXT indicates the file extension of the generated
## script file; SWIG.SIMPLE.FLAGS specifies additional flags for Swig.
rule SimpleSwig
{
local object = [ DoObjectGrist $(<:S=$(SUFOBJ)) ] ;
local cppfile = $(<:S=.cpp) ;
local script = $(<:S=.$(SWIG.SIMPLE.EXT)) ;
C++ $(object) : $(cppfile) ;
Swig $(cppfile) $(script) : $(<) : $(SWIG.SIMPLE.LANGUAGE) :
$(SWIG.SIMPLE.FLAGS) ;
return $(object) ;
}
RegisterFileType SimpleSwig : .i ;
if ! $(NO_SWIG_HEADER_SCANNING)
{
SWIG.HDRPATTERN =
"^[ ]*[%#][ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
RegisterHeaderRule HeaderRule : $(SWIG.HDRPATTERN) : .i ;
}
}

576
mk/jam/unittest.jam Normal file
View File

@@ -0,0 +1,576 @@
#==============================================================================
# Jam rules for unit testing with CppTest (http://cpptest.sourceforge.net/)
# Copyright (C) 2005 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#==============================================================================
if $(CPPUNIT.AVAILABLE) = yes
{
UNITTEST_VERBOSE ?= yes ;
UNITTEST_RUNFLAGS ?= ;
if $(UNITTEST_VERBOSE) = yes
{
UNITTEST_RUNFLAGS += "--verbose" ;
}
## UnitTest module [ : testdirs [ : extensions ] ]
##
## This rule provides a dynamic unit testing framework which utilizes CppUnit
## (http://cpptest.sourceforge.net/). The invocation:
##
## UnitTest <module> ;
##
## sets up unit testing support for `module' if $(SUBDIR)/t/ exists for
## `module' and contains test fragment files (*.t) and/or header (*.h) files.
## If `testdirs' is provided, then it is a list of directory to scan for test
## fragments instead of `t/'. If `extensions' is provided, then it is a list of
## file extensions for which to search instead of `.t'.
##
## It is safe to invoke this rule for modules which do not have a `t/'
## subdirectory, in which case the rule invocation is silently ignored. The
## UnitTest rule automatically synthesizes an appropriate driver program which
## incorporates the test fragment files (*.t), thus eliminating a boring and
## error-prone task.
##
## The Application, Library, and Plugin rules automatically invoke UnitTest on
## behalf of the client (unless given the `notest' option), so the vast
## majority of modules in a project inherit unit testing support automatically
## and for free. Simply populating a `t/' subdirectory with unit testing
## fragment files (*.t) is typically all that is needed to enable unit testing
## for an application, library, or plugin.
##
## The unit testing Jam target for `module' is named "check_module". In
## addition to this module-level granularity, the UnitTest rule also provides
## dynamic directory-based granularity. For example, presume that the following
## abbreviated list of directories exist in a project tree:
##
## apps/example
## libs/common
## plugins/bindings/perl_b
## plugins/bindings/python_b
## plugins/bindings/ruby_b
##
## The following module-based unit testing Jam targets will be created
## (assuming that the appropriate test fragment files, $(SUBDIR)/t/*.t, exist
## in each directory):
##
## check_example
## check_common
## check_perl_b
## check_python_b
## check_ruby_b
##
## Furthermore, the following directory-based targets also will be created
## dynamically:
##
## check (and its alias check_all)
## check_apps
## check_apps_example
## check_libs
## check_libs_common
## check_plugins
## check_plugins_bindings
## check_plugins_bindings_perl_b
## check_plugins_bindings_python_b
## check_plugins_bindings_ruby_b
##
## The very neat thing about the directory-based targets is that they
## automatically synthesize a driver program which incorporates all of the
## tests contained in child directories. For instance, the `check_plugins'
## target creates a unit testing driver which incorporates the tests from the
## bindings/perl_b/t, bindings/python_b/t, and bindings/ruby_b/t directories;
## and the `check_all' target creates a driver which incorporates all tests in
## the entire project. This allows entire selected branches of tests to be run
## all at once rather than having to run several different driver programs to
## get a complete report.
##
## The unit testing framework automatically wraps each test fragment file (*.t)
## into a synthesized C++ source file containing CppUnit boilerplate, such as
## necessary #include directives, #defines, etc. This allows the fragment
## files to be as simple as possible. They need #include only headers related
## to the actual module being tested, but need not worry about setting up the
## CppUnit environment since that is done automatically. A typical fragment
## file might look like this:
##
## /* Test file: libs/common/t/array.t */
##
## #include "common/myarray.h"
##
## class MyArrayTest : public CppUnit::TestFixture
## {
## public:
## void setUp() { ...set up test data... }
## void tearDown() { ...destroy test data... }
##
## void testInsert() { ...test array insertion methods... }
## void testDelete() { ...test array deletion methods... }
##
## CPPUNIT_TEST_SUITE(MyArrayTest);
## CPPUNIT_TEST(testInsert);
## CPPUNIT_TEST(testDelete);
## CPPUNIT_TEST_SUITE_END();
## };
##
## When the UnitTest rule synthesizes C++ wrappers for the test fragments, it
## needs to figure out the names of classes which contain tests. The synthesis
## process makes this determination by examining *.t and *.h files for
## subclasses of CppUnit::TestFixture. For this to work correctly, the
## "class Foo : public CppUnit::TestFixture" declaration must not be split over
## multiple lines.
##
## It is possible to have extra text added at the beginning and end of the
## synthesized C++ source code for both the *.t wrappers and the driver
## programs by optionally defining the following Jam variables (perhaps in
## Jamrules) with whatever text you would like inserted into the synthesized
## files:
##
## UNITTEST_BOILERPLATE_TEST_PRE
## UNITTEST_BOILERPLATE_TEST_POST
## UNITTEST_BOILERPLATE_MAIN_PRE
## UNITTEST_BOILERPLATE_MAIN_POST
##
## Thest `TEST' variables apply to the *.t wrappers, and the `MAIN' variables
## apply to the driver programs into which the wrappers are linked. If you find
## that you are including common code in all of your *.t files, then you may
## want to simplify by propagating the common code to the `TEST' boilerplate
## instead.
##
rule UnitTest
{
local mod = $(1) ;
local testdirs = $(2) ;
local exts = $(3) ;
if ! $(testdirs) { testdirs = t ; }
if ! $(exts) { exts = .t ; }
local test_clean = [ UnitTestNameClean $(mod) ] ;
local oldsubdir = $(SUBDIR_TOKENS) ;
local testdir ;
for testdir in $(testdirs)
{
SubDir TOP $(oldsubdir) $(testdir) ;
local tests_obj ;
local tests = [ Recurse : $(exts) ] ;
local headers = [ Recurse : .h .hpp .hxx .H ] ;
if $(tests) || $(headers)
{
tests = [ DoSourceGrist $(tests) ] ;
SEARCH on $(tests) = $(SEARCH_SOURCE) ;
local tests_src = $(tests:S=.cpp) ;
MakeLocate $(tests_src) : $(LOCATE_TARGET) ;
Clean $(test_clean) : $(tests_src) ;
# For each fragment (*.t), create a C++ wrapper. Automatically register
# subclasses of CppUnit::TestFixture.
local i ;
for i in $(tests)
{
Includes $(i:S=.cpp) : $(i) ;
UnitTestSource $(i:S=.cpp) : $(i) ;
}
# Also search for CppUnit::TestFixture subclasses in headers (*.h) and
# synthesize a C++ wrapper which registers them.
if $(headers)
{
headers = [ DoSourceGrist $(headers) ] ;
SEARCH on $(headers) = $(SEARCH_SOURCE) ;
local suitereg = [ DoSourceGrist __suitereg.cpp ] ;
MakeLocate $(suitereg) : $(LOCATE_TARGET) ;
UnitTestSource $(suitereg) : $(headers) ;
Includes $(suitereg) : $(headers) ;
tests_src += $(suitereg) ;
}
# Compile all synthesized sources.
tests_obj = [ CompileObjects $(tests_src) ] ;
CCHDRS on $(tests_obj) += [ FIncludes $(SEARCH_SOURCE) ] ;
C++FLAGS on $(tests_obj) += $(COMPILER.C++FLAGS.EXCEPTIONS.ENABLE)
$(CPPUNIT.CFLAGS) ;
Clean $(test_clean) : $(tests_obj) ;
# Create the driver for "check_module".
UnitTestDriver $(mod) : $(tests_obj) ;
# Dynamically create the drivers for all parent directories.
UnitTestDynamicTargets $(mod) : $(tests_obj) : $(oldsubdir) ;
}
}
SubDir TOP $(oldsubdir) ;
}
#------------------------------------------------------------------------------
# PRIVATE UTILITY RULES
#------------------------------------------------------------------------------
# UnitTestDriver module : objs [ : owner ]
# Given a set of object files which represent test fragment wrappers for
# `module', set up the driver program which incorporates them, and create the
# "check_module" and "check_moduleclean" targets. For invocations which arise
# from the UnitTest rule, `module' will be the actual module for which
# testing is being arranged, and `objs' will be the complete set of test
# objects for `module'. For directory-based testing drivers, `module' will be
# the dynamically synthesized module name representing the directory for
# which testing is being arranged, and `objs' will be only a subset of all
# objects which ultimately will be incorporated into this synthesized driver
# (specifically, the subset will be the objects belonging to `owner'). This
# rule may be invoked multiple times for the same synthesized directory-based
# driver `module' in order to accumulate the object files from all child
# directories (recursively).
#
# Since the driver programs in parent directories are actually conglomerates
# of the objects from many different modules, this rule is invoked multiple
# times for any given directory-based driver program. Each invocations
# presents it with a different set of object files. Therefore, it must take
# special care. In particular, the first time this rule is invoked for a
# synthesized driver in a particular directory, it actually creates the
# application target; on subsequent invocations for the same directory, it
# merely adds `objs' to the already-created application target. This way,
# the a directory's dynamically synthesized driver program can incorporate
# objects from all of its child directories (recursively).
#
# The `owner' is the module which owns the object files, `objs'. In the
# example illustrated for the UnitTest rule, when the "check_libs" driver
# program is under creation from within the `UnitTest common' invocation, the
# owner will be "common". This information is needed in order to ensure that
# the driver program synthesized at the "libs" level, which incorporates
# "common"'s object files, can gain access to "common's" linker flags (since
# they will be needed for linking the directory-based driver). If `owner' is
# not provided, then it defaults to `module'.
rule UnitTestDriver
{
local mod = $(1) ;
local objs = $(2) ;
local owner = $(3) ;
if ! $(owner) { owner = $(mod) ; }
local test_name = [ UnitTestNameTest $(mod) ] ;
local test_clean = [ UnitTestNameClean $(mod) ] ;
# This is the low-level target name by which a unit testing driver program is
# known. We only create the target the first time we are called at a
# particular directory level (thus the module_UNITTESTS check). Upon
# subsequent invocations, we merely add the new objects files to the existing
# driver.
local test_driver = $(mod)_unittest ;
if ! $($(mod)_UNITTESTS)
{
$(mod)_UNITTESTS = $(test_driver) ;
# Create the actual driver program represented by the `test_driver' target.
local test_driver_target =
[ DoObjectGrist [ ConstructApplicationTarget __unittest : console ] ] ;
MakeLocate $(test_driver_target) : $(LOCATE_TARGET) ;
$(test_driver)_TYPE = application ;
$(test_driver)_TARGET = $(test_driver_target) ;
$(test_driver)_OBJECTS = $(objs) ;
SystemLinkApplication $(test_driver) : $(objs) [ UnitTestCommonObj ] :
console ;
CFlags $(test_driver) : $(APPLICATION.CFLAGS) ;
LFlags $(test_driver) : $(LINKLIBS) $(APPLICATION.LFLAGS)
$(CPPUNIT.LFLAGS) ;
Depends $(test_name) : $(test_driver_target) ;
Clean $(test_clean) : $(test_driver_target) ;
# Actually run the unit tests.
NotFile $(test_name) $(test_clean) ;
Always $(test_name) $(test_clean) ;
Depends checkclean : $(test_clean) ;
UnitTestRun $(test_name) : $(test_driver_target) ;
}
else
{
ExtraObjects $(test_driver) : $(objs) ;
}
# Apply appropriate linker flags to the driver program. This has two parts:
# (1) If these are the unit tests for a library, then, as a convenience,
# assume that the tests need to link against that library.
# (2) For directory-based test targets, the driver needs all of the linker
# flags required by its child directories (recursively). For example, in
# the earlier cited illustration, the "check_all", and "check_libs"
# targets will also need whatever linker flags libs/common itself
# requires.
if $($(owner)_TYPE) = library { LinkWith $(test_driver) : $(owner) ; }
LinkWith $(test_driver) : [ on $($(owner)_TARGET) GetVar NEEDLIBS ] ;
return $(test_driver) ;
}
# UnitTestCommonObj
# Create object files common to all driver programs. Presently, the only
# common component is the main() function, which utilizes CppUnit's automatic
# test discovery protocol to discover test classes. (These are the subclasses
# of CppUnit::TestFixture for which we scan and pass to the
# CPPUNIT_TEST_SUITE_REGISTRATION() macro.)
rule UnitTestCommonObj
{
if ! $(UNITTEST_COMMON_OBJ)
{
local test_main_dir = [ ConcatDirs $(LOCATE.OBJECTS) __unittest_common ] ;
local test_main_src = main.cpp ;
test_main_src = $(test_main_src:G=__unittest) ;
MakeLocate $(test_main_src) : $(test_main_dir) ;
UnitTestMain $(test_main_src) ;
Clean checkclean : $(test_main_src) ;
local test_main_obj = [ CompileObjects $(test_main_src) ] ;
MakeLocate $(test_main_obj) : $(test_main_dir) ;
C++FLAGS on $(test_main_obj) += $(COMPILER.C++FLAGS.EXCEPTIONS.ENABLE)
$(CPPUNIT.CFLAGS) ;
Clean checkclean : $(test_main_obj) ;
UNITTEST_COMMON_OBJ = $(test_main_obj) ;
}
return $(UNITTEST_COMMON_OBJ) ;
}
# UnitTestDynamicTargets module : objs : subdir_tokens
# Given a set of subdirectory tokens representing the location of `module' in
# the source tree, dynamically synthesize a test driver program in each
# parent directory leading up to module's location. Each synthesized test
# program will incorporate module's `objs', as well as the objects of all
# other children (recursively) of the directory containing each driver. (The
# additional objects will be incorporated by subsequent invocations for the
# same directories.)
rule UnitTestDynamicTargets
{
local mod = $(1) ;
local objs = $(2) ;
local subdir_tokens = $(3) ;
# There is no need to synthesize a driver for the directory in which `module'
# itself resides, since we already have a "check_module" target for that.
# Therefore, simply alias this directory entry to the existing "check_module"
# target.
local deepest_name = [ UnitTestNameTest $(subdir_tokens:J=_) ] ;
local deepest_clean = [ UnitTestNameClean $(subdir_tokens:J=_) ] ;
NotFile $(deepest_name) $(deepest_clean) ;
Depends $(deepest_name) : [ UnitTestNameTest $(mod) ] ;
Depends $(deepest_clean) : [ UnitTestNameClean $(mod) ] ;
# For each parent directory of `module', synthesize a driver target.
local tokens = [ FReverse $(subdir_tokens) ] ;
tokens = $(tokens[2-]) ;
while $(tokens)
{
UnitTestDynamicTarget $(mod) : $(objs) : [ FReverse $(tokens) ] ;
tokens = $(tokens[2-]) ;
}
# Synthesize a "check_all" target which incorporates all tests projectwide.
UnitTestDynamicTarget $(mod) : $(objs) : : all ;
}
# UnitTestDynamicTarget module : objs : dir_tokens [ : dyn_module ]
# The workhorse for UnitTestDynamicTargets which actually changes to the
# specified directory and creates the driver program. The "check_foo" target
# name is normally composed of the directory tokens joined with underscores
# (i.e. "check_dir_tokens") unless the optional `dyn_module' is provided, in
# which case the target name becomes "check_dyn_module".
rule UnitTestDynamicTarget
{
local mod = $(1) ;
local objs = $(2) ;
local dir_tokens = $(3) ;
local dyn_mod = $(4) ;
if ! $(dyn_mod) { dyn_mod = $(dir_tokens:J=_) ; }
local olddir = $(SUBDIR_TOKENS) ;
SubDir TOP $(dir_tokens) ;
local test_driver = [ UnitTestDriver $(dyn_mod) : $(objs) : $(mod) ] ;
# Use module_UNITTESTS to remember that this dynamically synthesized driver
# has a relation to `module'. This information is needed later when clients
# invoke CFlags, LFlags, and LibDepends for `module'. Not only must those
# settings be applied to `module', but we must also apply them to module's
# test driver, as well as all of the directory-based drivers which
# incorporate module's test objects. This is what the UnitTestCFlags,
# UnitTestLFlags, and UnitTestLibDepends rules do.
$(mod)_UNITTESTS += $(test_driver) ;
SubDir TOP $(olddir) ;
}
# UnitTestNameTest module
# Return the name of the "check_module" target for `module'.
rule UnitTestNameTest
{ return check_$(<) ; }
# UnitTestNameClean module
# Return the name of the "check_moduleclean" target for `module'.
rule UnitTestNameClean
{ local n = [ UnitTestNameTest $(<) ] ; return $(n)clean ; }
# UnitTestCFlags module : flags [ : options ]
# Hook invoked automatically by CFlags. Applies `flags' also to module's test
# driver.
rule UnitTestCFlags
{
# Empty for now. Presumably the compiler flags are needed only by the actual
# sources of `module'; not by its tests which merely link against module's
# objects. This assumption may be wrong, and may change in the future.
}
# UnitTestLFlags module : flags [ : options ]
# Hook invoked automatically by LFlags. Applies `flags' also to module's test
# driver and to all directory-based drivers which incorporate module's test
# objects.
rule UnitTestLFlags
{
local mod = $(1) ;
local flags = $(2) ;
local options = $(3) ;
local unittests = $($(mod)_UNITTESTS) ;
local u ;
for u in $(unittests)
{
LFlags $(u) : $(flags) : $(options) ;
}
}
# UnitTestLibDepends module : deps
# Hook invoked automatically by LibDepends. Applies `deps' also to module's
# test driver and to all directory-based drivers which incorporate module's
# test objects.
rule UnitTestLibDepends
{
local mod = $(1) ;
local libs = $(2) ;
local unittests = $($(mod)_UNITTESTS) ;
local u ;
for u in $(unittests)
{
LinkWith $(u) : $(libs) ;
}
}
# UnitTestSource wrapper : files
# Create a `wrapper' which #includes all `files' (which are probably *.t test
# fragments or headers). Also scan `files' for subclasses of
# CppUnit::TestFixture and invoke CPPUNIT_TEST_SUITE_REGISTRATION() for each
# discovery.
actions UnitTestSource
{
cat <<EOF > $(<)
// Automatically generated; do not edit.
#include <string>
#include <cppunit/TestCaller.h>
#include <cppunit/TestFixture.h>
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/HelperMacros.h>
$(UNITTEST_BOILERPLATE_TEST_PRE)
EOF
for i in $(>:BS); do
echo '#include "'$i'"' >> $(<)
done
for i in $(>); do
classes=`sed '/public[ ][ ]*CppUnit::TestFixture/!d;\
s/class[ ][ ]*\([^ ][^ ]*\)[ ]*:.*/\1/' < $i`
for c in $classes; do
echo "CPPUNIT_TEST_SUITE_REGISTRATION($c);" >> $(<)
done
done
cat <<EOF >> $(<)
$(UNITTEST_BOILERPLATE_TEST_POST)
EOF
}
# UnitTestMain file
# Create a generic main() which is used for all test driver programs. It
# uses CppUnit's automated test class discovery protocol to discover classes
# containing tests, therefore it is entirely generic and can be used by any
# number of driver programs.
actions UnitTestMain
{
cat <<EOF > $(<)
// Automatically generated; do not edit.
#include <string>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/TestResult.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
$(UNITTEST_BOILERPLATE_MAIN_PRE)
int main(int argc, char** argv)
{
bool verbose = false;
for (int i = 1; i < argc; i++)
{
char const* s = argv[i];
if (*s == '-')
{
do { s++; } while (*s == '-');
verbose = (*s == 'v' || *s == 'V');
if (verbose)
break;
}
}
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry& registry =
CppUnit::TestFactoryRegistry::getRegistry();
CppUnit::BriefTestProgressListener listener;
if (verbose)
runner.eventManager().addListener(&listener);
runner.addTest(registry.makeTest());
return runner.run("", false, true, !verbose) ? 0 : -1;
}
$(UNITTEST_BOILERPLATE_MAIN_POST)
EOF
}
# UnitTestRun check_target : program
# Actually run the unit test driver `program' for the invocation target
# `check_target'.
actions UnitTestRun
{
$(>) $(UNITTEST_RUNFLAGS)
}
}
else # !CPPUNIT.AVAILABLE
{
rule UnitTest { }
rule UnitTestCFlags { }
rule UnitTestLFlags { }
rule UnitTestLibDepends { }
actions UnitTestDisabled
{
echo "$(<): Unit testing disabled (CppUnit not installed)."
}
Always check_all ;
Depends check : check_all ;
UnitTestDisabled check_all ;
}
NotFile check checkclean check_all check_allclean ;
Depends check : check_all ;
Depends clean : checkclean ;
Help check : "Run unit tests" ;

151
mk/jam/unix.jam Normal file
View File

@@ -0,0 +1,151 @@
#============================================================================
# Jam configuration and actions for Unix (GNU/Linux, BSD, Darwin, etc.)
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
SHELL ?= "/bin/sh" ;
# Only use nasm on x86 for now...
NASM.FLAGS += -f elf ;
PLUGIN.CFLAGS += $(COMPILER.C++FLAGS.PIC) ;
LIBRARY.CFLAGS += $(COMPILER.C++FLAGS.PIC) ;
# The BFD tag name under which to embed meta-information into a plugin module.
# This much match the name expected by csGetPluginMetadata() (bfdplugins.cpp).
SECTION_TAG_NAME ?= .crystalspace ;
#----------------------------------------------------------------------------
# platform specific rules
## ConstructApplicationTarget target : options
## Constructs the application target name (ie. foo.exe for foo)
rule ConstructApplicationTarget
{
return $(<) ;
}
rule ConstructStaticLibraryTarget
{
return lib$(<)$(SUFLIB) ;
}
rule ConstructSharedLibraryTarget
{
return lib$(<).so.$(PACKAGE_VERSION) ;
}
rule ConstructSharedLibraryLinkLib
{
return lib$(<).so.$(PACKAGE_VERSION) ;
}
rule ConstructPluginTarget
{
return $(<).so ;
}
# SystemLinkApplication target : objects : options
# do system specific actions needed for linking the application and construct
# correct clean targets.
rule SystemLinkApplication
{
local target = $($(<)_TARGET) ;
Depends $(target) : $(>) ;
LinkApplication $(target) : $(>) ;
# setup clean rules
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
}
rule SystemInstallApplication
{
Depends install_bin :
[ DoInstall $(<) : $(bindir) $(2) : $(INSTALL_PROGRAM) ] ;
}
rule SystemInstallPlugin
{
Depends install_plugin : [ DoInstall $(<) : $(plugindir) $(2) :
$(INSTALL_PROGRAM) ] ;
}
# Put the meta data into the object file headers
rule ObjTagMetaData
{
Depends $(<) : $(>) ;
}
actions ObjTagMetaData
{
$(CMD.OBJCOPY) --add-section $(SECTION_TAG_NAME)=$(>) $(<)
}
# SystemLinkPlugin target : objects : options
# do system specific actions needed for linking the plugin and construct
# correct clean targets.
rule SystemLinkPlugin
{
local target = $($(<)_TARGET) ;
Depends $(target) : $(>) ;
LinkPlugin $(target) : $(>) ;
if $(EMBED_META) = "yes" && $(OBJCOPY.AVAILABLE) = "yes"
{
ObjTagMetaData $(target) : $($(<)_METAFILE) ;
}
else
{
PluginMetaData $(<) : $($(<)_METAFILE) : $(3) ;
}
# setup clean rules
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
}
rule SystemLinkSharedLibrary
{
LFlags $(<) : $(LINKLIBS) ;
Depends $(<) : $(>) ;
LinkSharedLibrary $(<) : $(>) : $(3) ;
Clean clean : $(<) ;
Clean $(<)clean : $(<) ;
}
actions LinkApplication bind NEEDLIBS bind EXTRAOBJECTS
{
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
if $(PLUGIN.LFLAGS.USE_SONAME) = "yes"
{
actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS
{
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS) \
-Wl,-soname,$(<:BS)
}
}
else
{
actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS
{
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
}
actions LinkSharedLibrary bind NEEDLIBS bind EXTRAOBJECTS
{
$(CMD.LINK) -shared -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS) \
-Wl,-soname,$(<:BS)
}

58
mk/jam/variant.jam Normal file
View File

@@ -0,0 +1,58 @@
#============================================================================
# Setup of compiler/linker flags for debug/optimize mode
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
if ! $(VARIANT)
{
VARIANT = $(MODE) ;
}
if $(VARIANT) != "debug" && $(VARIANT) != "optimize" && $(VARIANT) != "profile"
{
exit "Invalid modus set, please set VARIANT to debug, profile or optimize" ;
}
# Set modus related flags
CCFLAGS += $(COMPILER.CFLAGS) $(COMPILER.CFLAGS.$(VARIANT)) ;
C++FLAGS += $(COMPILER.CFLAGS) $(COMPILER.C++FLAGS)
$(COMPILER.CFLAGS.$(VARIANT)) $(COMPILER.C++FLAGS.$(VARIANT)) ;
LINKLIBS += $(COMPILER.LFLAGS) $(COMPILER.LFLAGS.$(VARIANT)) ;
LOCATE.OBJECTS = $(LOCATE.OBJECTS)/$(VARIANT) ;
## SubVariant variantname
## Specify subvariant which are placed in separate compilation directories.
SUBVARIANT ?= "" ;
SAVED_LOCATE_TARGET = "" ;
rule SubVariant
{
if ! $(<)
{
SUBVARIANT = $(SUBVARIANT[2]) ;
SUBVARIANT ?= "" ;
LOCATE_TARGET = $(SAVED_LOCATE_TARGET[1]) ;
SAVED_LOCATE_TARGET = $(SAVED_LOCATE_TARGET[2-]) ;
}
else
{
SUBVARIANT = $(<) $(SUBVARIANT) ;
SAVED_LOCATE_TARGET = $(LOCATE_TARGET) $(SAVED_LOCATE_TARGET) ;
LOCATE_TARGET = $(LOCATE_TARGET)/$(<) ;
}
}

563
mk/jam/win32.jam Normal file
View File

@@ -0,0 +1,563 @@
#============================================================================
# Jam configuration and actions for Win32
# Copyright (C)2003 by Matze Braun <matzebraun@users.sourceforge.net>
# Copyright (C)2004 by Eric Sunshine <sunshine@sunshineco.com>
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Library General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
# License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#============================================================================
SHELL ?= "/bin/sh" ;
CMD.WINDRES ?= windres ;
# DLL-tools not used by this script, but clients might have a need for them.
CMD.DLLTOOL ?= dlltool ;
CMD.DLLWRAP ?= dllwrap ;
USE_DLLWRAP ?= no ;
NASM.FLAGS += -f win32 -DEXTERNC_UNDERSCORE ;
CCFLAGS += -pipe ;
C++FLAGS += -pipe ;
LINKLIBS += -L/usr/lib/w32api -lgdi32 -lshell32 ;
PLUGIN.LFLAGS += -mwindows ;
WINDRES.FLAGS = --use-temp-file ;
if "$(USE_DLLWRAP)" = "yes"
{
PLUGIN.LFLAGS = [ Filter $(PLUGIN.LFLAGS) : -shared ] ;
}
# Natively-built Jam 2.5 (and probably earlier) on Cygwin fails to perform
# library scanning properly and think that all object files need to be rebuilt
# (along with everything which depends upon them) when "jam install" follows
# "jam all", so disable this feature.
if $(OS) = "CYGWIN"
{
NOARSCAN = true ;
}
#----------------------------------------------------------------------------
# resource handling
# Unfortunately we can't simply specify resources on the source list, because
# Mingw/Cygwin have the limitation that they can only link 1 resource file
# in. So we have to concatenate all resourcefiles here before compiling them.
actions GenerateWin32VersionRc
{
cat > $(<) << __EOF__
// This file is generated automatically.
1 VERSIONINFO
FILEVERSION $(PACKAGE_VERSION_LIST[1]), $(PACKAGE_VERSION_LIST[2]), $(PACKAGE_VERSION_LIST[3]), $(PACKAGE_VERSION_LIST[4])
PRODUCTVERSION $(PACKAGE_VERSION_LIST[1]), $(PACKAGE_VERSION_LIST[2]), $(PACKAGE_VERSION_LIST[3]), $(PACKAGE_VERSION_LIST[4])
#ifdef CS_DEBUG
FILEFLAGS 0x1
#else
FILEFLAGS 0x0
#endif
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "ProductName", "$(PRODUCT_NAME)"
VALUE "ProductVersion", "$(PACKAGE_VERSION)"
VALUE "FileVersion", "$(PACKAGE_VERSION)"
VALUE "LegalCopyright", "$(PACKAGE_COPYRIGHT)"
VALUE "FileDescription", "$(PRODUCT_DESCRIPTION)"
#ifdef CS_DEBUG
VALUE "Comments", "Debug build"
#else
VALUE "Comments", "Release build"
#endif
VALUE "WWW", "$(PACKAGE_HOMEPAGE)"
}
}
}
__EOF__
}
actions GenerateWin32ManifestRc
{
cat > $(<) << __EOF__
// This file is generated automatically.
1 24 "$(MANIFEST_NAME)"
__EOF__
}
actions GenerateWin32Manifest
{
cat > $(<) << __EOF__
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- This file is generated automatically. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
__EOF__
# Filter out non-numerical characters from the version number. Windows does
# not like them.
echo '$(PACKAGE_VERSION_LIST[1]).$(PACKAGE_VERSION_LIST[2]).$(PACKAGE_VERSION_LIST[3]).$(PACKAGE_VERSION_LIST[4])' | $(SED) 's/[^0123456789.]//g' | $(SED) 's/\(.*\)/ version="\1"/' >> $(<)
cat >> $(<) << __EOF__
processorArchitecture="X86"
name="$(PRODUCT_NAME)"
type="win32"
/>
<description>$(PRODUCT_DESCRIPTION)</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
__EOF__
}
actions GenerateWin32MetadataRc
{
cat > $(<) << __EOF__
// This file is automatically generated.
17485 RCDATA
{
__EOF__
cat $(>) | $(SED) "s:\":\"\":g" | $(SED) "s:\(.*\): \"\1\",:g" >> $(<)
cat >> $(<) << __EOF__
"\0"
}
__EOF__
}
actions GenerateIconRc
{
echo '1 ICON "$(>)"' > $(<)
}
actions together CompileResources
{
cat $(>) | $(CMD.WINDRES) $(WINDRES.FLAGS) $(RCFLAGS) --include-dir=$(>:D) -o $(<)
}
rule CompileResources
{
Depends $(<) : $(>) ;
}
## Win32Resource basename : rcfiles
## Specify .rc files for the target known as basename. The .rc files should
## already have SEARCH set appropriately.
rule Win32Resource
{
local target = $($(<)_TARGET) ;
local rcobject = [ DoObjectGrist $(<)_resource.o ] ;
LOCATE on $(rcobject) = $(LOCATE_TARGET) ;
SEARCH on $(rcobject) = $(LOCATE_TARGET) ;
# only add 1 resource object per target
if ! $($(<)_HASWIN32RESOURCE)
{
$(<)_HASWIN32RESOURCE = yes ;
ExtraObjects $(<) : $(rcobject) ;
}
CompileResources $(rcobject) : $(>) ;
}
## Win32RcFlags basename : rcfiles
## Specify flags passed to the resource compiler when compiling resources
## for the target known as basename.
rule Win32RcFlags
{
local rcobject = [ DoObjectGrist $(<)_resource.o ] ;
RCFLAGS on $(rcobject) += $(>) ;
}
if $(USE_DLLWRAP) = "yes"
{
rule GenerateExportDefs
{
SEARCH on $(<) = $(LOCATE_TARGET) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends $(<) : $(>) ;
}
actions GenerateExportDefs
{
echo "EXPORTS" > $(<)
echo " plugin_compiler" >> $(<)
$(SED) '/<implementation>/!d;s:[ ]*<implementation>\(..*\)</implementation>: \1_scfInitialize:;p;s:_scfInitialize:_scfFinalize:;p;s:_scfFinalize:_Create:' < $(>) >> $(<)
}
}
#----------------------------------------------------------------------------
# linking part
## ConstructApplicationTarget target : options
## Constructs the application target name (ie. foo.exe for foo)
rule ConstructApplicationTarget
{
return $(<).exe ;
}
rule ConstructStaticLibraryTarget
{
return lib$(<)$(SUFLIB) ;
}
rule ConstructSharedLibraryTarget
{
return $(<)-$(COMPILER.TYPE).dll ;
}
rule ConstructSharedLibraryLinkLib
{
return lib$(<)$(SUFLIB) ;
}
rule ConstructPluginTarget
{
return $(<).dll ;
}
# Also invoked by msvcgen.jam.
rule MakeVersionRc
{
# normalize version list
local v1, v2, v3, v4 ;
v1 = $(PACKAGE_VERSION_LIST[1]) ;
if ! $(v1) { v1 = 0 ; }
v2 = $(PACKAGE_VERSION_LIST[2]) ;
if ! $(v2) { v2 = 0 ; }
v3 = $(PACKAGE_VERSION_LIST[3]) ;
if ! $(v3) { v3 = 0 ; }
v4 = $(PACKAGE_VERSION_LIST[4]) ;
if ! $(v4) { v4 = 0 ; }
PACKAGE_VERSION_LIST on $(<) = $(v1) $(v2) $(v3) $(v4) ;
local desc = [ Description $(>) ] ;
if ! $(desc) { desc = "$(>)" ; }
PRODUCT_DESCRIPTION on $(<) = $(desc) ;
local name ;
if $(PACKAGE_LONGNAME) { name = $(PACKAGE_LONGNAME) ; }
else if $(PACKAGE_NAME) { name = $(PACKAGE_NAME) ; }
else { name = $(>) ; }
PRODUCT_NAME on $(<) = $(name) ;
GenerateWin32VersionRc $(<) ;
}
rule MakeManifestFile
{
# normalize version list
local v1, v2, v3, v4 ;
v1 = $(PACKAGE_VERSION_LIST[1]) ;
if ! $(v1) { v1 = 0 ; }
v2 = $(PACKAGE_VERSION_LIST[2]) ;
if ! $(v2) { v2 = 0 ; }
v3 = $(PACKAGE_VERSION_LIST[3]) ;
if ! $(v3) { v3 = 0 ; }
v4 = $(PACKAGE_VERSION_LIST[4]) ;
if ! $(v4) { v4 = 0 ; }
PACKAGE_VERSION_LIST on $(<) = $(v1) $(v2) $(v3) $(v4) ;
local desc = [ Description $(>) ] ;
if ! $(desc) { desc = "$(>)" ; }
PRODUCT_DESCRIPTION on $(<) = $(desc) ;
local name ;
if $(PACKAGE_NAME) { name = $(PACKAGE_NAME).$(>) ; }
else { name = $(>) ; }
PRODUCT_NAME on $(<) = $(name) ;
GenerateWin32Manifest $(<) ;
}
rule MakeManifestRc
{
manifestfile = $(<:S=.manifest) ;
MakeLocate $(manifestfile) : [ on $(<) GetVar LOCATE ] ;
MakeManifestFile $(manifestfile) : $(>) ;
MANIFEST_NAME on $(<) = $(manifestfile:G=) ;
GenerateWin32ManifestRc $(<) ;
Depends $(<) : $(manifestfile) ;
}
rule MakeMetadataRc
{
local metafile = $($(>)_METAFILE) ;
local metarc = $(<) ;
Depends $(metarc) : $(metafile) ;
GenerateWin32MetadataRc $(metarc) : $(metafile) ;
Clean $(>)clean : $(metarc) ;
Clean clean : $(metarc) ;
}
rule AppResourceWin32
{
local options = $(2) ;
local versionrc = [ DoObjectGrist _versionrc.rc ] ;
LOCATE on $(versionrc) = $(LOCATE_TARGET) ;
SEARCH on $(versionrc) = $(LOCATE_TARGET) ;
MakeVersionRc $(versionrc) : $(<) ;
Clean $(<)clean : $(versionrc) ;
Clean clean : $(versionrc) ;
Win32Resource $(<) : $(versionrc) ;
if ! [ IsElem nomanifest : $(options) ]
{
local manifestrc = [ DoObjectGrist _manifestrc.rc ] ;
LOCATE on $(manifestrc) = $(LOCATE_TARGET) ;
SEARCH on $(manifestrc) = $(LOCATE_TARGET) ;
MakeManifestRc $(manifestrc) : $(<) ;
Clean $(<)clean : $(manifestrc) ;
Clean clean : $(manifestrc) ;
Win32Resource $(<) : $(manifestrc) ;
}
local icon = [ ApplicationIcon win32 : $(<) ] ;
if ! $(icon)
{
local apptype = gui ;
if [ IsElem console : $(>) ] { apptype = console ; }
icon = [ ApplicationIconDefault win32 : $(apptype) ] ;
}
if $(icon)
{
local iconcopy = [ DoObjectGrist $(icon) ] ;
MakeLocate $(iconcopy) : $(LOCATE_TARGET) ;
Depends $(iconcopy) : $(icon) ;
Copy $(iconcopy) : $(icon) ;
Clean $(<)clean : $(iconcopy) ;
Clean clean : $(iconcopy) ;
local iconrc = [ DoObjectGrist $(<)_iconrc.rc ] ;
MakeLocate $(iconrc) : $(LOCATE_TARGET) ;
Depends $(iconrc) : $(iconcopy) ;
GenerateIconRc $(iconrc) : $(iconcopy) ;
Clean $(<)clean : $(iconrc) ;
Clean clean : $(iconrc) ;
Win32Resource $(<) : $(iconrc) ;
}
}
rule PluginResourceWin32
{
local versionrc, metarc ;
versionrc = [ DoObjectGrist $(<)_versionrc.rc ] ;
MakeLocate $(versionrc) : $(LOCATE_TARGET) ;
MakeVersionRc $(versionrc) : $(<) ;
if $(EMBED_META) = "yes"
{
metarc = [ DoObjectGrist $(<)_metarc.rc ] ;
MakeLocate $(metarc) : $(LOCATE_TARGET) ;
MakeMetadataRc $(metarc) : $(<) ;
}
Clean clean : $(versionrc) $(metarc) ;
Clean $(<)clean : $(versionrc) $(metarc) ;
Win32Resource $(<) : $(versionrc) $(metarc) ;
}
# SystemLinkApplication target : objects : options
rule SystemLinkApplication
{
local target = $($(<)_TARGET) ;
Depends $(target) : $(>) ;
LinkApplication $(target) : $(>) ;
# setup clean rules
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
AppResourceWin32 $(<) : $(3) ;
}
rule SystemInstallApplication
{
Depends install_bin :
[ DoInstall $(<) : $(bindir) $(2) : $(INSTALL_PROGRAM) ] ;
}
rule SystemInstallPlugin
{
Depends install_plugin : [ DoInstall $(<) : $(plugindir) $(2) :
$(INSTALL_PROGRAM) ] ;
}
# SystemLinkPlugin target : objects : options
rule SystemLinkPlugin
{
local target = $($(<)_TARGET) ;
if $(USE_DLLWRAP) = "yes"
{
local exportdefs = [ DoObjectGrist $(<).def ] ;
NAME on $(exportdefs) = $(<) ;
GenerateExportDefs $(exportdefs) : $($(<)_METAFILE) ;
Depends $(target) : $(exportdefs) ;
EXPORTDEFS on $(target) = $(exportdefs) ;
}
Depends $(target) : $(>) ;
LinkPlugin $(target) : $(>) ;
PluginResourceWin32 $(<) ;
if $(EMBED_META) != "yes"
{
PluginMetaData $(<) : $($(<)_METAFILE) : $(3) ;
}
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
}
rule MakeDllDefFile
{
local def = $(<) ;
local objects = $(>) ;
MakeLocate $(def) : $(LOCATE.OBJECTS)/libs ;
WriteDefHeader $(def) ;
for i in $(objects)
{
local drectve = $(i).drectve ;
MakeLocate $(drectve) : [ on $(i) GetVar LOCATE ] ;
Depends $(drectve) : $(i) ;
Depends $(def) : $(drectve) ;
ExtractDrectve $(drectve) : $(i) ;
DrectveToDef $(def) : $(drectve) ;
Clean clean : $(drectve) ;
Clean $(def)clean : $(drectve) ;
}
}
rule SystemLinkSharedLibrary
{
LFlags $(<) : $(LINKLIBS) ;
# The "crystalspace" library is so massive that it blows Jam's command line
# length limit when all object files are passed in at once to some command.
# However, a DLL, like an executable, needs to be built with all objects at
# once.
# Problem is, since dllwrap etc. don't support response files, there is no
# way to pass all objects at once to it. But, a static library can be built
# piecemeal, so we take the detour of creating a static library out of the
# DLL objects first.
# However, another bug hits us: on MinGW, symbols exported from objects in
# static libraries are not automatically exported from the DLL.
# We work this around by constructing a .DEF file with all exports of the
# DLL. Conveniently (somewhat), all exported symbols are into a section
# ".drectve" of an object file by gcc. After extracting these sections and
# some postprocessing, we finally have all .DEF entries. Phew.
local lib = $(<).a ;
MakeLocate $(lib) $(lib)($(>:BS)) : $(LOCATE.OBJECTS)/libs ;
Depends $(lib) : $(lib)($(>:BS)) ;
local i ;
for i in $(>)
{
Depends $(lib)($(i:BS)) : $(i) ;
}
Archive $(lib) : $(>) ;
Ranlib $(lib) ;
#RmTemps $(lib) : $(>) ;
Depends $(<) : $(lib) ;
local def = $(<).def ;
MakeDllDefFile $(def) : $(>) ;
Depends $(<) : $(def) ;
Clean clean : $(def) ;
Clean $(<)clean : $(def) ;
Depends $(<)clean : $(def)clean ;
EXPORTDEFS on $(<) = $(def) ;
IMPLIB on $(<) = $(3) ;
Depends $(3) : $(<) ;
LinkSharedLibrary $(<) : $(lib) ;
Clean clean : $(target) ;
Clean $(<)clean : $(target) ;
}
actions ExtractDrectve
{
$(CMD.OBJCOPY) -j .drectve -O binary $(>) $(<).tmp
echo >> $(<).tmp # Cheap trick to ensure there's always a .tmp file;
# the action should not break with no .drectve - no exports
# is a valid scenario.
$(CMD.STRINGS) -n 1 $(<).tmp > $(<) # Run strings since the section data may be
# padded with zeroes, get rid of those.
rm $(<).tmp
}
actions WriteDefHeader
{
echo "EXPORTS" > $(<)
}
actions piecemeal together DrectveToDef
{
for d in $(>)
do
sed -e "s/ /\\
/g" $d | sed -e "s/-export:\(.*\)/\1/g" | sed -e "s/,data/ DATA/g" >> $(<)
done
}
actions GenerateImportLib
{
$(CMD.DLLTOOL) -d $(>) -l $(<)
}
actions LinkApplication bind NEEDLIBS bind EXTRAOBJECTS
{
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
if $(USE_DLLWRAP) != "yes"
{
actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS
{
$(CMD.LINK) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
}
else
{
actions LinkPlugin bind NEEDLIBS bind EXTRAOBJECTS bind EXPORTDEFS
{
$(CMD.DLLWRAP) --driver-name=$(CMD.LINK) --dllname $(<:B) --def=$(EXPORTDEFS) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
}
}
actions LinkSharedLibrary bind NEEDLIBS bind EXTRAOBJECTS bind EXPORTDEFS bind IMPLIB
{
$(CMD.DLLWRAP) --driver-name=$(CMD.LINK) --dllname $(<:B).dll --def=$(EXPORTDEFS) --implib $(IMPLIB) -o $(<) $(>) $(EXTRAOBJECTS) $(NEEDLIBS) $(LINKLIBS)
touch $(IMPLIB) # ensure the IMPLIB is always newer than the DLL,
# since the IMPLIB depends on the DLL.
}