[tasque/xbuild] [xbuild] Added Substitute task



commit 9fc5af6725c1d07226927ba32c557a5742464107
Author: Antonius Riha <antoniusriha gmail com>
Date:   Tue Sep 18 11:39:06 2012 +0200

    [xbuild] Added Substitute task
    
    This task subtitutes values much the same way as autoconf does it. A
    substitution can be specified by providing an Item of ItemGroup
    "Substitution" with the Include attribute set to:
    
    <pattern>|<value>|<valueType>
    
    where <pattern> is usually something like @prefix@
    <value> can be any string - also a path to a text file
    <valueType> can be "text" or "path", thus determining if <value> should
    be taken directly for substitution or if <value> points to a text file from
    which the value for substitution should be taken.
    
    Files that are to be considered in the substitution process must be part
    of the "Substitute" ItemGroup

 build/Substitute.cs  |  109 ++++++++++++++++++++++++++++++++++++++++++++++++++
 build/Tasque.targets |   33 ++++++++++++++-
 build/build.csproj   |    3 +
 3 files changed, 143 insertions(+), 2 deletions(-)
---
diff --git a/build/Substitute.cs b/build/Substitute.cs
new file mode 100644
index 0000000..d49426f
--- /dev/null
+++ b/build/Substitute.cs
@@ -0,0 +1,109 @@
+// 
+// Substitute.cs
+//  
+// Author:
+//       Antonius Riha <antoniusriha gmail com>
+// 
+// Copyright (c) 2012 Antonius Riha
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// 
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+
+namespace Tasque.Build
+{
+	public class Substitute : Task
+	{
+		[Required]
+		public ITaskItem [] DestinationFiles { get; set; }
+		
+		[Required]
+		public ITaskItem [] SourceFiles { get; set; }
+		
+		[Required]
+		public ITaskItem [] Substitutions { get; set; }
+		
+		public override bool Execute ()
+		{
+			try {
+				CheckItems ();
+				ParseSubstitutions ();
+				
+				for (int i = 0; i < SourceFiles.Length; i++) {
+					var source = File.ReadAllText (SourceFiles [i].GetMetadata ("FullPath"));
+					foreach (var subst in substitutions) {
+						string value = subst [1];
+						if (subst [2] == "path")
+							value = File.ReadAllText (subst [1]);
+						source = source.Replace (subst [0], value);
+					}
+					var path = DestinationFiles [i].GetMetadata ("FullPath");
+					var dirPath = Path.GetDirectoryName (path);
+					if (!Directory.Exists (dirPath))
+						Directory.CreateDirectory (dirPath);
+					File.WriteAllText (path, source);
+				}
+			} catch (Exception ex) {
+				Log.LogErrorFromException (ex, true);
+				return false;
+			}
+			return true;
+		}
+		
+		void CheckItems ()
+		{
+			if (DestinationFiles.Length != SourceFiles.Length)
+				throw new Exception ("The number of SourceFiles must be equal to " +
+					"the number of DestinationFiles.");
+		}
+		
+		void ParseSubstitutions ()
+		{
+			/* 
+			 * <pattern>|<value>|<valueType> where <pattern> and
+			 * <valueType> must not contain "|"
+			 * 
+			 * <valueType> is one of the following:
+			 * 	text	- the <value> should be inserted directly
+			 * 	path	- the <value> represents a path to a *text* file of which
+			 * the contents will be the substitution value.
+			 * 
+			 * pattern can be any pattern, but usually is @pattern@
+			 */
+			
+			// parse in files last to first, so that later added items
+			// override more general earlier items.
+			for (int i = Substitutions.Length - 1; i >= 0; i--) {
+				var line = Substitutions [i].ItemSpec;
+				var subst = new string [3];
+				var firstDelimiter = line.IndexOf ('|');
+				var lastDelimiter = line.LastIndexOf ('|');
+				subst [0] = line.Substring (0, firstDelimiter);
+				subst [1] = line.Substring (firstDelimiter + 1, lastDelimiter - firstDelimiter - 1);
+				subst [2] = line.Substring (lastDelimiter + 1);
+				substitutions.Add (subst);
+			}
+		}
+		
+		List<string []> substitutions = new List<string[]> ();
+	}
+}
diff --git a/build/Tasque.targets b/build/Tasque.targets
index 20dcd0c..d30b775 100644
--- a/build/Tasque.targets
+++ b/build/Tasque.targets
@@ -4,14 +4,28 @@
   	<_tmpInstallFileNames>obj\Tasque.RelInstallFileNames.txt</_tmpInstallFileNames>
     <OutputPath>.</OutputPath>
     <SrcDir Condition=" '$(SrcDir)' == '' ">.</SrcDir>
-    <PkgLibDir Condition=" '$(PkgLibDir)' == '' ">$(Prefix)\lib\tasque</PkgLibDir>
-    <DataDir Condition=" '$(DataDir)' == '' ">$(Prefix)\share</DataDir>
+    <LibDir Condition=" '$(LibDir)' == '' ">$(Prefix)\lib</LibDir>
     <BinDir Condition=" '$(BinDir)' == '' ">$(Prefix)\bin</BinDir>
+    <PkgLibDir Condition=" '$(PkgLibDir)' == '' ">$(LibDir)\$(PackageName)</PkgLibDir>
+    <DataDir Condition=" '$(DataDir)' == '' ">$(Prefix)\share</DataDir>
+    <PkgDataDir Condition=" '$(PkgDataDir)' == '' ">$(DataDir)\$(PackageName)</PkgDataDir>
+    <PkgConfigDir Condition=" '$(PkgConfigDir)' == '' ">$(LibDir)\pkgconfig</PkgConfigDir>
     <DestDir Condition=" '$(DestDir)' != '' And !HasTrailingSlash('$(DestDir)')">$(DestDir)\</DestDir>
     <BuildingSolutionFile>True</BuildingSolutionFile>
+    <Wrapper Condition=" '$(Wrapper)' == '' ">$(PackageName)</Wrapper>
+    <Version Condition=" '$(Version)' == '' ">1.0.0</Version>
   </PropertyGroup>
   <ItemGroup>
     <InstallFileName Include="$(TargetFileName)" />
+    <Substitution Include="@prefix@|$(Prefix)|text" />
+    <Substitution Include="@libdir@|$(LibDir)|text" />
+    <Substitution Include="@pkglibdir@|$(PkgLibDir)|text" />
+    <Substitution Include="@bindir@|$(BinDir)|text" />
+    <Substitution Include="@exec_prefix@|$(BinDir)|text" />
+    <Substitution Include="@datadir@|$(DataDir)|text" />
+    <Substitution Include="@wrapper@|$(Wrapper)|text" />
+    <Substitution Include="@version@|$(Version)|text" />
+    <Substitution Include="@PACKAGE@|$(PackageName)|text" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <Target Name="_CheckProperties">
@@ -55,6 +69,21 @@
     <Copy SourceFiles="@(InstallFileName)" DestinationFiles="$(DestDir)$(PkgLibDir)\%(RelativeDir)%(FileName)%(Extension)" SkipUnchangedFiles="true" />
     <WriteLinesToFile File="$(_tmpInstallFileNames)" Lines="@(InstallFileName)" Overwrite="true" />
   </Target>
+  <UsingTask TaskName="Tasque.Build.Substitute" AssemblyFile="build.dll" />
+	
+  <!-- Substitute -->
+  <Target Name="Substitute" DependsOnTargets="BeforeSubstitute;CoreSubstitute;AfterSubstitute" />
+  <Target Name="BeforeSubstitute" />
+  <Target Name="AfterSubstitute" />
+  <Target Name="CoreSubstitute" Condition=" '@(Substitute)' != '' ">
+    <CreateItem Include="$(SrcDir)\%(Substitute.RelativeDir)%(FileName)%(Extension)">
+      <Output TaskParameter="Include" ItemName="_SubstSourceFiles" />
+    </CreateItem>
+    <CreateItem Include="%(Substitute.RelativeDir)%(FileName)">
+      <Output TaskParameter="Include" ItemName="_SubstDestFiles" />
+    </CreateItem>
+    <Substitute SourceFiles="@(_SubstSourceFiles)" DestinationFiles="@(_SubstDestFiles)" Substitutions="@(Substitution)" />
+  </Target>
   
   <!-- Uninstall -->
   <Target Name="Uninstall" DependsOnTargets="BeforeUninstall;CoreUninstall;AfterUninstall" />
diff --git a/build/build.csproj b/build/build.csproj
index 22a4599..5337ac4 100644
--- a/build/build.csproj
+++ b/build/build.csproj
@@ -27,9 +27,12 @@
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="Microsoft.Build.Utilities.v4.0" />
+    <Reference Include="Microsoft.Build.Framework" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AssemblyInfo.cs" />
+    <Compile Include="Substitute.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="build.csproj" />



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]