mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-14 22:00:05 +00:00
302 lines
13 KiB
Plaintext
302 lines
13 KiB
Plaintext
[% FILTER null;
|
|
#==============================================================================
|
|
# TemplateToolkit2 utility macros for MSVC project generation
|
|
# 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.
|
|
#
|
|
#==============================================================================
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Return input string with forward slashes changed to backward slashes.
|
|
#------------------------------------------------------------------------------
|
|
MACRO slash(s) GET s.replace('/','\\');
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given a path, strip off any prefix found in the my.doc.striproot[] array.
|
|
# For example, if my.doc.striproot[] contains '/usr/local/', and this macro is
|
|
# invoked as striproot('/usr/local/foo.bar'), then the return value will be
|
|
# 'foo.bar'.
|
|
#------------------------------------------------------------------------------
|
|
MACRO striproot(p) BLOCK;
|
|
IF my.doc.striproot;
|
|
UNLESS my.doc.striprootpat;
|
|
r = [];
|
|
FOREACH c IN my.doc.striproot;
|
|
IF c != '.';
|
|
c = c.replace('[/\\\\]?$', '/?') IF c != './';
|
|
r.push(c.replace('[.]', '\\.'));
|
|
END;
|
|
END;
|
|
my.doc.striprootpat = '^(?i:' _ r.join('|') _ ')';
|
|
END;
|
|
p.replace(my.doc.striprootpat, '');
|
|
ELSE;
|
|
GET p;
|
|
END;
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an array of paths, invoke striproot() upon each and return the results.
|
|
# Note that, because TemplateToolkit macros can not return true lists, the
|
|
# return value is actually a string with the elements delimited by the token
|
|
# `|'; thus clients must split() the return value if a real list result is
|
|
# desired. For instance: myfiles = striproots(allfiles).split('|')
|
|
#------------------------------------------------------------------------------
|
|
MACRO striproots(p) BLOCK;
|
|
r = [];
|
|
FOREACH c IN p;
|
|
r.push(striproot(c));
|
|
END;
|
|
r.join('|');
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an array of path components, return the concatenation of the components
|
|
# (using backslash '\' as a delimiter) after possibly stripping an optional
|
|
# prefix from each component. The list of prefixes which may be stripped are
|
|
# found in the my.doc.striproot[] array. For example, if my.doc.striproot[]
|
|
# contains '/usr/local/', and this macro is invoked as
|
|
# path(['/usr/local/foo', 'bar', 'cow.baz']), then the return value will be
|
|
# 'foo\bar\cow.baz'.
|
|
#------------------------------------------------------------------------------
|
|
MACRO path(p) BLOCK;
|
|
r = [];
|
|
FOREACH c IN p;
|
|
r.push(striproot(c));
|
|
END;
|
|
slash(r.join('\\'));
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given a string specifying a set of options for a tool (compiler, linker,
|
|
# etc.) of the form `/opt1 "arg1" /opt2 "arg2"' (or `/opt1:arg1 /opt2:arg2', or
|
|
# the like), translate forward slashes in `arg' (which is assumed to be a
|
|
# pathname) to backward slashes. For example, given
|
|
# `/I "foo/bar" /out:cow/baz', returns `/I "foo\bar" /out:cow\baz'.
|
|
#------------------------------------------------------------------------------
|
|
MACRO flags(s) GET slash(s).replace('\A\\\\','/').replace('\s\\\\',' /');
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an array of items, return only the items which match the set of regular
|
|
# expressions in my.doc.accept[] and which do not match the set of expressions
|
|
# in my.doc.reject[]. For example, if my.doc.accept[] contains the one pattern
|
|
# '\.cpp$', and my.doc.reject[] contains the one pattern 'ow', then, given the
|
|
# list ['foo.h', 'bar.cpp', 'cow.cpp'], the list of returned items will be
|
|
# ['bar.cpp']. Note that, because TemplateToolkit macros can not return true
|
|
# lists, the return value is actually a string with the elements delimited by
|
|
# the token `|'; thus clients must split() the return value if a real list
|
|
# result is desired. For instance: myfiles = filter(allfiles).split('|')
|
|
#------------------------------------------------------------------------------
|
|
MACRO filter(x) BLOCK;
|
|
IF my.doc.accept;
|
|
UNLESS my.doc.acceptpat;
|
|
my.doc.acceptpat = my.doc.accept.join('|');
|
|
END;
|
|
x = x.grep(my.doc.acceptpat);
|
|
END;
|
|
IF my.doc.reject;
|
|
UNLESS my.doc.acceptpat;
|
|
my.doc.rejectpat = my.doc.reject.join('|');
|
|
END;
|
|
y = [];
|
|
FOREACH i IN x;
|
|
UNLESS i.match(my.doc.rejectpat);
|
|
y.push(i);
|
|
END;
|
|
END;
|
|
y.join('|');
|
|
ELSE;
|
|
x.join('|');
|
|
END;
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an input string, return a globally unique identifier (GUID)
|
|
# representing the string (essentially a textual representation of an MD5
|
|
# checksum). The returned string has the form
|
|
# XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, where each `X' represents some
|
|
# (uppercase) hexadecimal digit.
|
|
#------------------------------------------------------------------------------
|
|
MACRO guid(s) BLOCK;
|
|
USE md5 = Digest::MD5;
|
|
CALL md5.add(s);
|
|
digest = md5.hexdigest.chunk(4);
|
|
GET digest.0 _
|
|
digest.1 _ '-' _
|
|
digest.2 _ '-' _
|
|
digest.3 _ '-' _
|
|
digest.4 _ '-' _
|
|
digest.5 _
|
|
digest.6 _
|
|
digest.7 | upper;
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an arbitrary identifier (the `tag'), attempt to locate macros named
|
|
# after variations of that tag and the current build mode and project type;
|
|
# then invoke any discovered macros and concatenate their results, delimited by
|
|
# `delim' (which may be omitted if no explicit delimiter is needed). Macro
|
|
# names are composed of `tag', the current build mode (given by the global
|
|
# `build.mode' property, where `build' typically is a reference to a hash
|
|
# contained in the global builds[] array), and the current project type as
|
|
# indicated by the global my.doc.projtype.0 property. The full list of macros
|
|
# consulted by interpolate() is presented below. The macros are invoked in the
|
|
# order shown.
|
|
#
|
|
# tag_build
|
|
# tag_projtype
|
|
# tag_projtype_build
|
|
#------------------------------------------------------------------------------
|
|
MACRO interpolate(tag, delim) BLOCK;
|
|
p = [];
|
|
s = ${"${tag}_${build.tag}"};
|
|
p.push(s) IF s.length > 0;
|
|
s = ${"${tag}_${my.doc.projtype.0}"};
|
|
p.push(s) IF s.length > 0;
|
|
s = ${"${tag}_${my.doc.projtype.0}_${build.tag}"};
|
|
p.push(s) IF s.length > 0;
|
|
GET p.join(delim);
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an array of strings, return the concatenation of the elements,
|
|
# delimited by `delim'. Prior to concatenation, `prefix' and `suffix' (if
|
|
# provided) are attached to each element. For example,
|
|
# glue(['foo','bar'],':','<','>') returns "<foo>:<bar>".
|
|
#------------------------------------------------------------------------------
|
|
MACRO glue(array, delim, prefix, suffix) BLOCK;
|
|
delim = suffix _ delim _ prefix;
|
|
s = array.join(delim);
|
|
IF s.length > 0;
|
|
s = prefix _ s _ suffix;
|
|
END;
|
|
GET s;
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an arbitrary identifier (the `tag'), attempt to access several in-scope
|
|
# or globally visible arrays in order to extract additional options for a given
|
|
# build mode and project type. The elements of the accessed arrays, along with
|
|
# a `seed' array, are concatentated, delimited by `delim'. Each element is
|
|
# optionally modified by `prefix' and `suffix' as described in the glue()
|
|
# macro. The actual list of arrays consulted is:
|
|
#
|
|
# build.tag
|
|
# projtypes.projtype.tag
|
|
# my.doc.tagkey
|
|
#
|
|
# The above list assumes that a hash named `build' is in scope. Typically,
|
|
# this is a reference to an element of the global builds[] array
|
|
# (control.tlib). Furthermore, `projtype' is shorthand for my.doc.projtype.0,
|
|
# which is assumed to exist globally, and is specific to the project being
|
|
# generated. Finally, `tagkey' is actually the value of the "${tag}key" key
|
|
# within the `build' hash. As a practical example, if generating a project
|
|
# file for a "plugin" and emitting the "debug" configuration, given a `tag' of
|
|
# "cflags", then the following arrays may be consulted:
|
|
#
|
|
# build.cflags
|
|
# projtypes.plugin.cflags
|
|
# my.doc.cflagsdebug
|
|
#
|
|
# In this example, the name "cflagsdebug" comes from the
|
|
# builds['debug'].cflagskey property (control.tlib).
|
|
#------------------------------------------------------------------------------
|
|
MACRO compose(tag, seed, delim, prefix, suffix) BLOCK;
|
|
p = [];
|
|
p = p.merge(build.$tag).
|
|
merge(projtypes.${my.doc.projtype.0}.$tag).
|
|
merge(my.doc.${${"build.${tag}key"}}).
|
|
merge(seed);
|
|
GET glue(p, delim, prefix, suffix);
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Given an arbitrary `tag', concatenate the list of pathnames in my.doc.tag[],
|
|
# along with a `seed' list, delimited by `delim'. Each item is mutated by
|
|
# path() prior to concatenation. The optional `prefix' and `suffix' modify
|
|
# each item as described in the glue() macro. For example, if my.doc.libdir[]
|
|
# contains the elements "foo/bar" and "baz/snorz", then the invocation
|
|
# composepaths('libdir',['cow/fish'],' ','/I "','"') will return the string
|
|
# `/I "cow\fish" /I "foo\bar" /I "baz\snorz"'. Likewise,
|
|
# composepaths('libdir',[],',') will return `foo\bar,baz\snorz'.
|
|
#------------------------------------------------------------------------------
|
|
MACRO composepaths(tag, seed, delim, prefix, suffix) BLOCK;
|
|
p = seed;
|
|
FOREACH d IN my.doc.$tag;
|
|
p.push(path([d]).replace('\\\\$',''));
|
|
END;
|
|
GET glue(p, delim, prefix, suffix);
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Loads a data file containing key/value tuples and stores the tuples in the
|
|
# hash named my.tag, where `tag' is provided by the caller. The key/value
|
|
# tuples appear one per line in the data file, and the key must be separated
|
|
# from the value via a literal '|'. The very first line of the data file
|
|
# _must_ be the literal string "key|value" (sans quotes). Each key in the data
|
|
# file becomes a key in the my.tag hash. Typically, the name "doc" is used for
|
|
# `tag', and is meant to represent attributes (such as special compiler and
|
|
# linker flags, list of files, etc.) of the current "project file document"
|
|
# under construction. Indeed, many of the macros defined here (macros.tlib)
|
|
# assume the presence of the my.doc hash, and consult it to learn about
|
|
# properties specific to the project file being synthesized. It is legal for
|
|
# the same key to appear multiple times in the data file; this is how an array
|
|
# of values is defined for a given key. In fact, _all_ values in the hash are
|
|
# assumed to be arrays. Consequently, even if you know that a particular key
|
|
# will appear in the data file only a single time, you must still perform an
|
|
# array access to obtain its value (for instance, `my.doc.projtype.0'). Values
|
|
# from the loaded data file are typically accessed via the FOREACH directive
|
|
# (for example, `FOREACH cflag IN my.doc.cflags'), but can also be accessed
|
|
# individually (`my.doc.cflags.0', `my.doc.cflags.1', etc.).
|
|
#------------------------------------------------------------------------------
|
|
MACRO load(path, tag) BLOCK;
|
|
my.$tag = {};
|
|
USE f = datafile(path, delim = '|');
|
|
FOREACH r IN f;
|
|
IF my.$tag.exists(r.key);
|
|
my.$tag.${r.key}.push(r.value);
|
|
ELSE;
|
|
my.$tag.${r.key} = [ r.value ];
|
|
END;
|
|
END;
|
|
END;
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Build-specific path composition macros.
|
|
#
|
|
# workroot
|
|
# Return the root of the directory hierarchy in which build temporaries
|
|
# and some targets will be placed.
|
|
# worklibout
|
|
# Return the location where built static libraries will be placed.
|
|
# workbuild
|
|
# Return the location of a build temporary. If `tail' is omitted, then
|
|
# this will be the directory into which temporary build output will be
|
|
# placed (a subdirectory of `workroot'). If `tail', an array of
|
|
# pathname components, is provided, then it can specify a directory or
|
|
# file beneath the `workbuild' directory. The elements of `tail' are
|
|
# concatenated without any delimiter. For example, workbuild([]) might
|
|
# return "..\out\build", whereas workbuild(['myapp']) would return
|
|
# "..\out\build\myapp", and workbuild(['myapp/test','.obj']) would
|
|
# return "..\out\build\myapp\test.obj".
|
|
#------------------------------------------------------------------------------
|
|
MACRO workroot GET path([my.doc.buildroot.0, 'out', glue([build.tag, my.doc.msvcversion.0])]);
|
|
MACRO worklibout GET path([workroot, 'libs']);
|
|
MACRO workbuild(tail)
|
|
GET path([workroot, 'build', my.doc.project.0, tail.join('')]);
|
|
|
|
END %]
|