aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-09-08 20:57:30 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-09-08 20:57:30 +0200
commit3f100fe0470f379d6573ae0484600cebfc2d2415 (patch)
treee3d0c1b936be1a2d541331d7298061b2015d8992
parent92c0ea2540562213770f4f36eb9c4e0009eaf95c (diff)
Support for VC++ solutions and tests, other improvements
-rwxr-xr-xbuild/meta/autoconf3
-rwxr-xr-xbuild/meta/automake3
-rw-r--r--build/meta/common.m421
-rwxr-xr-xbuild/meta/vc10proj2
-rw-r--r--build/meta/vc10proj-functions.make18
-rw-r--r--build/meta/vc10proj.m47
-rw-r--r--build/meta/vc10sln-functions.make30
-rw-r--r--build/meta/vc10sln.make6
-rwxr-xr-xbuild/meta/vc9proj1
-rw-r--r--build/meta/vc9proj-functions.make18
-rw-r--r--build/meta/vc9proj.m48
-rw-r--r--build/meta/vc9sln-functions.make30
-rw-r--r--build/meta/vc9sln.make6
-rwxr-xr-xbuild/meta/vcsln135
-rw-r--r--build/meta/vcsln.m483
-rwxr-xr-xbuild/meta/vctest137
-rw-r--r--build/meta/vctest-functions.make29
-rw-r--r--build/meta/vctest.m418
-rw-r--r--build/meta/vctest.make6
-rw-r--r--build/meta/windows-common.m450
20 files changed, 580 insertions, 31 deletions
diff --git a/build/meta/autoconf b/build/meta/autoconf
index 933faf8..aaaa20f 100755
--- a/build/meta/autoconf
+++ b/build/meta/autoconf
@@ -81,4 +81,5 @@ export config_files=$files
#
$install -d -m 755 `dirname $output`
-exec $m4 -P -D__meta_base__=$meta $meta/autoconf.m4 $input >$output
+$m4 -P -D__meta_base__=$meta $meta/autoconf.m4 $input >$output
+chmod 644 $output
diff --git a/build/meta/automake b/build/meta/automake
index ef5db66..612412e 100755
--- a/build/meta/automake
+++ b/build/meta/automake
@@ -61,4 +61,5 @@ install=$build/install/install
#
$install -d -m 755 `dirname $output`
-exec $m4 -P -D__meta_base__=$meta $meta/automake.m4 $input >$output
+$m4 -P -D__meta_base__=$meta $meta/automake.m4 $input >$output
+chmod 644 $output
diff --git a/build/meta/common.m4 b/build/meta/common.m4
index 84988b9..9a9781f 100644
--- a/build/meta/common.m4
+++ b/build/meta/common.m4
@@ -72,9 +72,26 @@ m4_define([m4_dquote], [m4_changequote([])])
m4_define([__env_impl__], [m4_esyscmd([echo -n $$1])])
m4_define([__env__], [m4_equote()__env_impl__([$1])[]m4_dquote()])
+m4_define([__value_impl__], [__env_impl__([$1])])
+m4_define([__value__], [m4_equote()__value_impl__([$1])[]m4_dquote()])
+
m4_define([__uuid_impl__],
[m4_translit(m4_strip_nl(m4_esyscmd([uuidgen])), [a-z], [A-Z])])
m4_define([__uuid__], [m4_equote()__uuid_impl__([$1])[]m4_dquote()])
-m4_define([__value_impl__], [__env_impl__([$1])])
-m4_define([__value__], [m4_equote()__value_impl__([$1])[]m4_dquote()])
+m4_define([__upcase_impl__], [m4_translit([$1], [a-z], [A-Z])])
+m4_define([__upcase__], [m4_equote()__upcase_impl__([$1])[]m4_dquote()])
+
+m4_define([__xml_impl__],
+[m4_patsubst(
+ m4_patsubst(
+ m4_patsubst(
+ [$1],
+ [&],
+ [&amp;]),
+ [<],
+ [&lt;]),
+ ["],
+ [&quot;])])
+
+m4_define([__xml__], [m4_equote()__xml_impl__([$1])[]m4_dquote()])
diff --git a/build/meta/vc10proj b/build/meta/vc10proj
index a8cae97..01b1638 100755
--- a/build/meta/vc10proj
+++ b/build/meta/vc10proj
@@ -73,6 +73,8 @@ $install -d -m 755 `dirname $output`
$m4 -P -D__meta_base__=$meta $meta/vc10proj.m4 $input >$output
$u2d $output
+chmod 644 $output
$m4 -P -D__meta_base__=$meta $meta/vc10proj.m4 $input.filters >$output.filters
$u2d $output.filters
+chmod 644 $output.filters
diff --git a/build/meta/vc10proj-functions.make b/build/meta/vc10proj-functions.make
index 5781de8..f06e239 100644
--- a/build/meta/vc10proj-functions.make
+++ b/build/meta/vc10proj-functions.make
@@ -8,17 +8,21 @@
#
# Arguments:
#
-# $1 - template path, if doesn't start with /, assume relative to src_base
-# $2 - output name (optional)
+# $1 - template path, if doesn't start with /, assume relative to src_base
+# $2 - output name (optional)
+# $3-8 - optional pairs of additional varibales and values $3=$4, $5=$6, etc
+#
#
$(out_base)/%: meta-vc10proj = \
$(call meta-vc10proj-body,$(if $(filter /%,$1),$1,$(src_base)/$1),$(if \
-$2,$2,$(notdir $1)),$(subst $(src_root),,$(src_base)))
+$2,$2,$(notdir $1)),$(subst $(src_root),,$(src_base)),$3,$4,$5,$6,$7,$8)
-# $1 - template
-# $2 - output name
-# $3 - difference between src_base and src_root with leading '\'
+# $1 - template
+# $2 - output name
+# $3 - difference between src_base and src_root with leading '\'
+# $4-9 - additional varibales
#
$(out_base)/%: meta-vc10proj-body = \
-$(call message,meta $(dist_prefix)$3/$2,$(bld_root)/meta/vc10proj \
+$(call message,meta $(dist_prefix)$3/$2,$(if $4,$4='$5'; export $4; )$(if \
+$6,$6='$7'; export $6; )$(if $8,$8='$9'; export $8; )$(bld_root)/meta/vc10proj \
-o $(dist_prefix)$3/$2 $1)
diff --git a/build/meta/vc10proj.m4 b/build/meta/vc10proj.m4
index 2263d65..a361635 100644
--- a/build/meta/vc10proj.m4
+++ b/build/meta/vc10proj.m4
@@ -7,12 +7,7 @@ m4_divert(-1)
m4_changequote([, ])
m4_include(__meta_base__[/common.m4])
-
-m4_define([__path_impl__], [m4_translit(__env_impl__([$1]),[/],[\])])
-m4_define([__path__], [m4_equote()__path_impl__([$1])[]m4_dquote()])
-
-m4_define([__file_impl__], [__env_impl__([$1])])
-m4_define([__file__], [m4_equote()__file_impl__([$1])[]m4_dquote()])
+m4_include(__meta_base__[/windows-common.m4])
# header
#
diff --git a/build/meta/vc10sln-functions.make b/build/meta/vc10sln-functions.make
new file mode 100644
index 0000000..d0958c6
--- /dev/null
+++ b/build/meta/vc10sln-functions.make
@@ -0,0 +1,30 @@
+# file : build/meta/vc10sln-functions.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+# Process VC++ solution template and write output to $(dist_prefix)/<path>.
+# Where path is computed as difference between src_base and src_root.
+#
+# Arguments:
+#
+# $1 - template path, if doesn't start with /, assume relative to src_base
+# $2 - output name (optional)
+# $3 - solution suffix (.vcxproj by default)
+# $4-9 - optional pairs of additional varibales and values $4=$5, $6=$7, etc
+#
+$(out_base)/%: meta-vc10sln = \
+$(call meta-vc10sln-body,$(if $(filter /%,$1),$1,$(src_base)/$1),$(if \
+$2,$2,$(notdir $1)),$(subst \
+$(src_root),,$(src_base)),$(if $3,$3,.vcxproj),$4,$5,$6,$7,$8,$9)
+
+# $1 - template
+# $2 - output name
+# $3 - difference between src_base and src_root with leading '\'
+# $4 - solution suffix
+# $4-10 - additional varibales
+#
+$(out_base)/%: meta-vc10sln-body = \
+$(call message,meta $(dist_prefix)$3/$2,$(if $5,$5='$6'; export $5; )$(if \
+$7,$7='$8'; export $7; )$(if $9,$9='$(10)'; export $9; )$(bld_root)/meta/vcsln \
+-b $(dist_prefix)$3 -e '$4' -o $(dist_prefix)$3/$2 $1)
diff --git a/build/meta/vc10sln.make b/build/meta/vc10sln.make
new file mode 100644
index 0000000..433114d
--- /dev/null
+++ b/build/meta/vc10sln.make
@@ -0,0 +1,6 @@
+# file : build/meta/vc10sln.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(call include-once,$(bld_root)/meta/vc10sln-functions.make,$(out_base))
diff --git a/build/meta/vc9proj b/build/meta/vc9proj
index 7a19b11..b01a2e0 100755
--- a/build/meta/vc9proj
+++ b/build/meta/vc9proj
@@ -73,3 +73,4 @@ $install -d -m 755 `dirname $output`
$m4 -P -D__meta_base__=$meta $meta/vc9proj.m4 $input >$output
$u2d $output
+chmod 644 $output
diff --git a/build/meta/vc9proj-functions.make b/build/meta/vc9proj-functions.make
index 5b6905a..134da4b 100644
--- a/build/meta/vc9proj-functions.make
+++ b/build/meta/vc9proj-functions.make
@@ -8,17 +8,21 @@
#
# Arguments:
#
-# $1 - template path, if doesn't start with /, assume relative to src_base
-# $2 - output name (optional)
+# $1 - template path, if doesn't start with /, assume relative to src_base
+# $2 - output name (optional)
+# $3-8 - optional pairs of additional varibales and values $3=$4, $5=$6, etc
+#
#
$(out_base)/%: meta-vc9proj = \
$(call meta-vc9proj-body,$(if $(filter /%,$1),$1,$(src_base)/$1),$(if \
-$2,$2,$(notdir $1)),$(subst $(src_root),,$(src_base)))
+$2,$2,$(notdir $1)),$(subst $(src_root),,$(src_base)),$3,$4,$5,$6,$7,$8)
-# $1 - template
-# $2 - output name
-# $3 - difference between src_base and src_root with leading '\'
+# $1 - template
+# $2 - output name
+# $3 - difference between src_base and src_root with leading '\'
+# $4-9 - additional varibales
#
$(out_base)/%: meta-vc9proj-body = \
-$(call message,meta $(dist_prefix)$3/$2,$(bld_root)/meta/vc9proj \
+$(call message,meta $(dist_prefix)$3/$2,$(if $4,$4='$5'; export $4; )$(if \
+$6,$6='$7'; export $6; )$(if $8,$8='$9'; export $8; )$(bld_root)/meta/vc9proj \
-o $(dist_prefix)$3/$2 $1)
diff --git a/build/meta/vc9proj.m4 b/build/meta/vc9proj.m4
index f771966..e7bbc87 100644
--- a/build/meta/vc9proj.m4
+++ b/build/meta/vc9proj.m4
@@ -7,12 +7,7 @@ m4_divert(-1)
m4_changequote([, ])
m4_include(__meta_base__[/common.m4])
-
-m4_define([__path_impl__], [m4_translit(__env_impl__([$1]),[/],[\])])
-m4_define([__path__], [m4_equote()__path_impl__([$1])[]m4_dquote()])
-
-m4_define([__file_impl__], [__env_impl__([$1])])
-m4_define([__file__], [m4_equote()__file_impl__([$1])[]m4_dquote()])
+m4_include(__meta_base__[/windows-common.m4])
# file
#
@@ -100,7 +95,6 @@ m4_define([__source_entries_impl__],
m4_define([__source_entries__],
[m4_equote()__source_entries_impl__([$1])[]m4_dquote()])
-
# Disable comments and quoting.
#
m4_changecom([])
diff --git a/build/meta/vc9sln-functions.make b/build/meta/vc9sln-functions.make
new file mode 100644
index 0000000..1182417
--- /dev/null
+++ b/build/meta/vc9sln-functions.make
@@ -0,0 +1,30 @@
+# file : build/meta/vc9sln-functions.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+# Process VC++ 9 solution template and write output to $(dist_prefix)/<path>.
+# Where path is computed as difference between src_base and src_root.
+#
+# Arguments:
+#
+# $1 - template path, if doesn't start with /, assume relative to src_base
+# $2 - output name (optional)
+# $3 - solution suffix (.vcproj by default)
+# $4-9 - optional pairs of additional varibales and values $4=$5, $6=$7, etc
+#
+$(out_base)/%: meta-vc9sln = \
+$(call meta-vc9sln-body,$(if $(filter /%,$1),$1,$(src_base)/$1),$(if \
+$2,$2,$(notdir $1)),$(subst \
+$(src_root),,$(src_base)),$(if $3,$3,.vcproj),$4,$5,$6,$7,$8,$9)
+
+# $1 - template
+# $2 - output name
+# $3 - difference between src_base and src_root with leading '\'
+# $4 - solution suffix
+# $4-10 - additional varibales
+#
+$(out_base)/%: meta-vc9sln-body = \
+$(call message,meta $(dist_prefix)$3/$2,$(if $5,$5='$6'; export $5; )$(if \
+$7,$7='$8'; export $7; )$(if $9,$9='$(10)'; export $9; )$(bld_root)/meta/vcsln \
+-b $(dist_prefix)$3 -e '$4' -o $(dist_prefix)$3/$2 $1)
diff --git a/build/meta/vc9sln.make b/build/meta/vc9sln.make
new file mode 100644
index 0000000..c50c2dc
--- /dev/null
+++ b/build/meta/vc9sln.make
@@ -0,0 +1,6 @@
+# file : build/meta/vc9sln.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(call include-once,$(bld_root)/meta/vc9sln-functions.make,$(out_base))
diff --git a/build/meta/vcsln b/build/meta/vcsln
new file mode 100755
index 0000000..c714afd
--- /dev/null
+++ b/build/meta/vcsln
@@ -0,0 +1,135 @@
+#! /usr/bin/env bash
+
+# file : build/meta/vcsln
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+# Process VC++ solution templates.
+#
+# Options:
+#
+# -b <base-dir>
+# -o <output-file>
+# -e <project-ext>
+#
+# Arguments:
+#
+# <template-file>
+#
+trap 'exit 1' ERR
+
+function error ()
+{
+ echo "$*" 1>&2
+}
+
+base=
+output=
+projext=
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -b)
+ base=$2
+ shift 2
+ ;;
+ -o)
+ output=$2
+ shift 2
+ ;;
+ -e)
+ projext=$2
+ shift 2
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+input=$1
+
+if [ "$input" = "" ]; then
+ error "no input file"
+ exit 1
+fi
+
+if [ "$base" = "" ]; then
+ error "no base directory"
+ exit 1
+fi
+
+if [ "$output" = "" ]; then
+ error "no output file"
+ exit 1
+fi
+
+if [ "$projext" = "" ]; then
+ error "no VC++ project file extension"
+ exit 1
+fi
+
+m4=m4
+u2d=unix2dos
+
+# Assume this script is never found via PATH.
+#
+meta=`dirname $0`
+
+build="$meta/.."
+install=$build/install/install
+
+# Find all the solution files.
+#
+proj_files=`find $base -name '*'$projext`
+proj_names=`echo "$proj_files" | sed -e "s%^$base/\(.*\)/.*$%\1%"`
+
+# Determine available configurations and project uuids.
+#
+for f in $proj_files; do
+
+ if [ "$conf" = "" ]; then
+ if [ "$projext" = ".vcproj" ]; then
+ conf=`cat $f | dos2unix | sed -n -e \
+ '/^[ ]*<Configuration$/{n;s/[ ]*Name="\([^"]*\)"$/"\1",/p};d' -`
+ conf=`echo $conf | sed -e 's/,$//'`
+ else
+ conf=`cat $f | dos2unix | sed -n -e \
+ 's/^[ ]*<ProjectConfiguration Include="\([^"]*\)">$/"\1",/p;d' -`
+ conf=`echo $conf | sed -e 's/,$//'`
+ fi
+ fi
+
+ if [ "$projext" = ".vcproj" ]; then
+ uuid=`cat $f | dos2unix | sed -n -e \
+ 's/^[ ]*ProjectGUID="{\([^}]*\)}"$/\1/p;d'`
+ else
+ uuid=`cat $f | dos2unix | sed -n -e \
+ 's/^[ ]*<ProjectGuid>{\([^}]*\)}<\/ProjectGuid>$/\1/p;d'`
+ fi
+
+ if [ "$proj_uuids" = "" ]; then
+ proj_uuids=$uuid
+ else
+ proj_uuids="$proj_uuids $uuid"
+ fi
+done
+
+proj_files=`echo "$proj_files" | sed -e "s%^$base/%%"`
+
+#echo $proj_names
+#echo $proj_uuids
+
+export configurations=$conf
+export project_files=$proj_files
+export project_names=$proj_names
+export project_uuids=$proj_uuids
+
+# Make sure the output directory exist.
+#
+$install -d -m 755 `dirname $output`
+
+$m4 -P -D__meta_base__=$meta $meta/vcsln.m4 $input >$output
+$u2d $output
+chmod 644 $output
diff --git a/build/meta/vcsln.m4 b/build/meta/vcsln.m4
new file mode 100644
index 0000000..632bbc9
--- /dev/null
+++ b/build/meta/vcsln.m4
@@ -0,0 +1,83 @@
+m4_divert(-1)
+# file : build/meta/vcsln.m4
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+m4_changequote([, ])
+
+m4_include(__meta_base__[/common.m4])
+m4_include(__meta_base__[/windows-common.m4])
+
+# solution_configuration
+#
+m4_define([__solution_configuration_entry_impl__], [ [$1] = [$1]])
+
+m4_define([__solution_configurations_impl__],
+ [m4_foreach([__c],
+ [__value_impl__([configurations])],
+ [__solution_configuration_entry_impl__(m4_patsubst(__c, ["], []))
+])])
+
+m4_define([__solution_configurations__],
+ [m4_equote()__solution_configurations_impl__()[]m4_dquote()])
+
+# project_configuration
+#
+m4_define([__project_configuration_entry_item_impl__],
+[ {[$1]}.[$2].ActiveCfg = [$2]
+ {[$1]}.[$2].Build.0 = [$2]])
+
+m4_define([__project_configuration_entry_impl__],
+ [m4_foreach(
+ [__c],
+ [__value_impl__([configurations])],
+ [__project_configuration_entry_item_impl__([$1], m4_patsubst(__c, ["], []))
+])])
+
+m4_define([__project_configurations_impl__],
+ [m4_foreach_w(
+ [__u],
+ [__value_impl__([project_uuids])],
+ [__project_configuration_entry_impl__(__u)])])
+
+m4_define([__project_configurations__],
+ [m4_equote()__project_configurations_impl__()[]m4_dquote()])
+
+# project_entry(name, file, uuid)
+#
+m4_define([__project_entry_impl__],
+[Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "[$1]", "[$2]", "{[$3]}"
+EndProject])
+
+m4_define([__project_entry__],
+ [m4_equote()__project_entry_impl__([$1], [$2], [$3])[]m4_dquote()])
+
+# projects
+#
+m4_define([__project_step_impl__],
+[__project_entry_impl__(
+ m4_substr([$1], 0, m4_ifelse(m4_index([$1], [ ]), [-1], [m4_len([$1])], [m4_index([$1], [ ])])),
+ m4_substr([$2], 0, m4_ifelse(m4_index([$2], [ ]), [-1], [m4_len([$2])], [m4_index([$2], [ ])])),
+ m4_substr([$3], 0, m4_ifelse(m4_index([$3], [ ]), [-1], [m4_len([$3])], [m4_index([$3], [ ])])))[]m4_dnl
+m4_ifelse(m4_index([$1], [ ]), [-1],, [
+__project_step_impl__(
+ m4_substr([$1], m4_incr(m4_index([$1], [ ]))),
+ m4_substr([$2], m4_incr(m4_index([$2], [ ]))),
+ m4_substr([$3], m4_incr(m4_index([$3], [ ]))))])])
+
+m4_define([__projects_impl__],
+[__project_step_impl__(
+ __value_impl__([project_names]),
+ __path_impl__([project_files]),
+ __value_impl__([project_uuids]))])
+
+m4_define([__projects__],
+ [m4_equote()__projects_impl__()[]m4_dquote()])
+
+# Disable comments and quoting.
+#
+m4_changecom([])
+m4_changequote([])
+
+m4_divert(0)m4_dnl
diff --git a/build/meta/vctest b/build/meta/vctest
new file mode 100755
index 0000000..5aa70eb
--- /dev/null
+++ b/build/meta/vctest
@@ -0,0 +1,137 @@
+#! /usr/bin/env bash
+
+# file : build/meta/vctest
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+# Process VC++ test templates.
+#
+# Options:
+#
+# -b <base-dir>
+# -r <root-dir>
+# -o <output-file>
+# -s <vc-solution>
+#
+# Arguments:
+#
+# <template-file>
+#
+trap 'exit 1' ERR
+
+function error ()
+{
+ echo "$*" 1>&2
+}
+
+base=
+root=
+output=
+sln=
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -b)
+ base=$2
+ shift 2
+ ;;
+ -r)
+ root=$2
+ shift 2
+ ;;
+ -o)
+ output=$2
+ shift 2
+ ;;
+ -s)
+ sln=$2
+ shift 2
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+input=$1
+
+if [ "$input" = "" ]; then
+ error "no input file"
+ exit 1
+fi
+
+if [ "$base" = "" ]; then
+ error "no base directory"
+ exit 1
+fi
+
+if [ "$root" = "" ]; then
+ error "no root directory"
+ exit 1
+fi
+
+if [ "$output" = "" ]; then
+ error "no output file"
+ exit 1
+fi
+
+if [ "$sln" = "" ]; then
+ error "no solution file"
+ exit 1
+fi
+
+m4=m4
+u2d=unix2dos
+
+# Assume this script is never found via PATH.
+#
+meta=`dirname $0`
+
+build="$meta/.."
+install=$build/install/install
+
+# Figure out topdir
+#
+if [ "$base" = "$root" ]; then
+ topdir=.
+else
+ topdir=`echo $base | sed -e "s%^$root/%%" - | \
+sed -e 's%[^/][^/]*/%../%g;s%[^./][^./]*$%..%' -`
+fi
+
+#
+
+# Determine possible configurations.
+#
+sln_conf=`cat $sln | dos2unix | sed -n -e \
+'/^[ ]*GlobalSection(SolutionConfigurationPlatforms).*$/{\
+: loop;\
+n;\
+/^[ ]*EndGlobalSection$/q;\
+s/^[ ]*\([^=]*\) = \([^=]*\)$/\1/p;\
+b loop};\
+d' -`
+
+conf=
+for c in $sln_conf; do
+ build=`echo $c | sed -e 's/^\(.*\)|.*$/\1/'`
+ arch=`echo $c | sed -e 's/^.*|\(.*\)$/\1/'`
+
+ if [ "$arch" = "Win32" ]; then
+ conf="$conf $build"
+ else
+ conf="$conf $arch/$build"
+ fi
+done
+
+export topdir
+export configurations=$conf
+
+# Make sure the output directory exist.
+#
+$install -d -m 755 `dirname $output`
+
+$m4 -P -D__meta_base__=$meta $meta/vctest.m4 $input >$output
+$u2d $output
+chmod 644 $output
diff --git a/build/meta/vctest-functions.make b/build/meta/vctest-functions.make
new file mode 100644
index 0000000..20d6c61
--- /dev/null
+++ b/build/meta/vctest-functions.make
@@ -0,0 +1,29 @@
+# file : build/meta/vctest-functions.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+# Process VC++ solution and test template and write output to
+# $(dist_prefix)/<path>. Where path is computed as difference
+# between src_base and src_root.
+#
+# Arguments:
+#
+# $1 - solution path, if doens't start with /, assume relative to
+# dist_prefix/<path>
+# $2 - template path, if doesn't start with /, assume relative to src_base
+# $3 - output name (optional)
+#
+$(out_base)/%: meta-vctest = \
+$(call meta-vctest-body,$1,$(if $(filter /%,$2),$2,$(src_base)/$2),$(if \
+$3,$3,$(notdir $2)),$(subst $(src_root),,$(src_base)))
+
+# $1 - solution
+# $2 - template
+# $3 - output name
+# $4 - difference between src_base and src_root with leading '\'
+#
+$(out_base)/%: meta-vctest-body = \
+$(call message,meta $(dist_prefix)$4/$3,$(bld_root)/meta/vctest \
+-r $(dist_prefix) -b $(dist_prefix)$4 \
+-s $(if $(filter /%,$1),$1,$(dist_prefix)$4/$1) -o $(dist_prefix)$4/$3 $2)
diff --git a/build/meta/vctest.m4 b/build/meta/vctest.m4
new file mode 100644
index 0000000..abead48
--- /dev/null
+++ b/build/meta/vctest.m4
@@ -0,0 +1,18 @@
+m4_divert(-1)
+# file : build/meta/vctest.m4
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+m4_changequote([, ])
+
+m4_include(__meta_base__[/common.m4])
+m4_include(__meta_base__[/windows-common.m4])
+
+
+# Disable comments and quoting.
+#
+m4_changecom([])
+m4_changequote([])
+
+m4_divert(0)m4_dnl
diff --git a/build/meta/vctest.make b/build/meta/vctest.make
new file mode 100644
index 0000000..154669e
--- /dev/null
+++ b/build/meta/vctest.make
@@ -0,0 +1,6 @@
+# file : build/meta/vctest.make
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+$(call include-once,$(bld_root)/meta/vctest-functions.make,$(out_base))
diff --git a/build/meta/windows-common.m4 b/build/meta/windows-common.m4
new file mode 100644
index 0000000..665790c
--- /dev/null
+++ b/build/meta/windows-common.m4
@@ -0,0 +1,50 @@
+# file : build/meta/windows-common.m4
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+# license : GNU GPL v2; see accompanying LICENSE file
+
+m4_define([__path_impl__], [m4_translit(__env_impl__([$1]),[/],[\])])
+m4_define([__path__], [m4_equote()__path_impl__([$1])[]m4_dquote()])
+
+m4_define([__file_impl__], [__env_impl__([$1])])
+m4_define([__file__], [m4_equote()__file_impl__([$1])[]m4_dquote()])
+
+# Convert POSIX shell quoting to Windows. Arguments that are in
+# single quotes (') are converted to double quotes ("). Double
+# quotes that are nested in single quotes are converted to \".
+# Quote escaping is not recognized. Single-quoted arguments
+# should be quoted as a whole, for example 'foo-bar' and not
+# foo-'bar'.
+#
+
+m4_define([__shell_quotes_convert_impl__], [m4_patsubst([$1], ["], [\\"])])
+
+# $1 string without the opening quote
+# $2 index of the closing quote
+#
+m4_define([__shell_quotes_in_quote_impl__],
+["__shell_quotes_convert_impl__(m4_substr([$1], [0], [$2]))"[]m4_dnl
+ __shell_quotes_impl__(m4_substr([$1], m4_incr([$2])))])
+
+# $1 string without the leading space
+# $2 index of the next space or -1
+#
+m4_define([__shell_quotes_in_space_impl__],
+[m4_substr([$1], [0], m4_ifelse([$2], [-1], [m4_len([$1])], [$2]))[]m4_dnl
+m4_ifelse(
+ [$2], [-1],
+ [],
+ [ __shell_quotes_impl__(m4_substr([$1], m4_incr([$2])))])])
+
+#
+#
+m4_define([__shell_quotes_impl__],
+[m4_ifelse(
+ m4_index([$1], [']), [0],
+ [__shell_quotes_in_quote_impl__(
+ m4_substr([$1], [1]),
+ m4_index(m4_substr([$1], [1]), [']))],
+ [__shell_quotes_in_space_impl__([$1], m4_index([$1], [ ]))])])
+
+m4_define([__shell_quotes__],
+[m4_equote()__shell_quotes_impl__([$1])[]m4_dquote()])