SushiHangover

PowerShell, Learn it or Perish ;-)

master nix
Gitter

Xamarin.iOS binding project for SVGKit

SushiHangover.SVGKit

This is a Xamarin.iOS binding project for SVGKit

  • SVGKit v2.x - live development, latest fixes/features
  • Xamarin.iOS Version: 10.4.0.4
  • Xcode 8.1 (11544) Build 8B62

SVGKit

SVGKit is a Cocoa framework for rendering SVG files natively: it’s fast and powerful. Some additional info and links are on the wiki

Ref: https://github.com/SVGKit/SVGKit

Nuget:

PM> Install-Package SushiHangover.SVGKit.Binding

Ref: https://www.nuget.org/packages/SushiHangover.SVGKit.Binding

Usage:

Namespace: SVGKit

using SVGKit;

Load SVG from a Bundle Resource

Build action: BundleResource

var image = new SVGKImage("Media/Sushi.svg");
var imageView = new SVGKFastImageView(image);
imageView.Frame = View.Frame;
View.Add(imageView);

Load SVG from a Bundle Path

Build action: Content

var image = new SVGKImage(Path.Combine(NSBundle.MainBundle.BundlePath, "Media/Joker.svg"));
var imageView = new SVGKFastImageView(image);
imageView.Frame = View.Frame;
View.Add(imageView);

JSON APIs to a Xamarin Realm Instance

RealmJson.Extensions

SushiHangover.RealmJson.Extensions

Extension Methods for adding JSON APIs to a Xamarin-based Realm Instance

Supported:

  • Xamarin.Forms
  • Xamarin.iOs
  • Xamarin.Android

Usage / Examples:

Single RealmObject from Json-based Strings:

using (var theRealm = Realm.GetInstance(RealmDBTempPath()))
{
    var realmObject = theRealm.CreateObjectFromJson<StateUnique>(jsonString);
}

Single RealmObject from a Stream:

using (var stream = new MemoryStream(byteArray))
using (var theRealm = Realm.GetInstance(RealmDBTempPath()))
{
    var testObject = theRealm.CreateObjectFromJson<StateUnique>(stream);
}

Using Json Arrays from a Xamarin.Android Asset Stream:

using (var theRealm = Realm.GetInstance(RealmDBTempPath()))
using (var assetStream = Application.Context.Assets.Open("States.json"))
{
    theRealm.CreateAllFromJson<State>(assetStream);
}

Using Json Arrays from a Xamarin.iOS Bundled Resource Stream:

using (var theRealm = Realm.GetInstance(RealmDBTempPath()))
using (var fileStream = new FileStream("./Data/States.json", FileMode.Open, FileAccess.Read))
{
    theRealm.CreateAllFromJson<State>(fileStream);
}

Sharpen - Part 3

Sharpen

Part 1: The correct Java version

Part 2: Building Sharpen

Sharpen Support Classes:

Converting your Java classes using the default config from ydanila you might want to look at the Sharpen support classes from ngit:

Type.FullName:

Sharpen.AccessController
Sharpen.AList`1
Sharpen.Arrays
Sharpen.AtomicInteger
Sharpen.AtomicLong
Sharpen.AtomicReference`1
Sharpen.AtomicReferenceArray`1
Sharpen.BufferedInputStream
Sharpen.BufferedOutputStream
Sharpen.BufferedReader
Sharpen.ByteArrayInputStream
Sharpen.ByteArrayOutputStream
Sharpen.Callable`1
Sharpen.CharBuffer
Sharpen.CharsetDecoder
Sharpen.CharsetEncoder
Sharpen.CodingErrorAction
Sharpen.Collections`1
Sharpen.Collections
Sharpen.ConcurrentHashMap`2
Sharpen.ConcurrentMap`2
Sharpen.CopyOnWriteArrayList`1
Sharpen.CountDownLatch
Sharpen.CRC32
Sharpen.CyclicBarrier
Sharpen.DataConverter
Sharpen.DataConverter+PackContext
Sharpen.DataConverter+CopyConverter
Sharpen.DataConverter+SwapConverter
Sharpen.DeflaterOutputStream
Sharpen.EnumerableWrapper`1
Sharpen.EnumeratorWrapper`1
Sharpen.Executors
Sharpen.FixedThreadPoolExecutorService
Sharpen.FutureBase
Sharpen.TaskFuture`1
Sharpen.CancellationException
Sharpen.RejectedExecutionException
Sharpen.ExecutorService
Sharpen.Extensions
Sharpen.FileChannel
Sharpen.FileChannel+MapMode
Sharpen.FileInputStream
Sharpen.FileLock
Sharpen.FileOutputStream
Sharpen.FileReader
Sharpen.FileWriter
Sharpen.Future`1
Sharpen.GZIPInputStream
Sharpen.GZIPOutputStream
Sharpen.InflaterInputStream
Sharpen.InheritableThreadLocal`1
Sharpen.InputStreamReader
Sharpen.LinkageError
Sharpen.LinkedHashMap`2
Sharpen.ListIterator`1
Sharpen.MappedByteBuffer
Sharpen.Matcher
Sharpen.MessageFormat
Sharpen.ObjectInputStream
Sharpen.ObjectOutputStream
Sharpen.OutputStreamWriter
Sharpen.Pattern
Sharpen.PipedInputStream
Sharpen.PipedOutputStream
Sharpen.PrintWriter
Sharpen.PrivilegedAction`1
Sharpen.RandomAccessFile
Sharpen.ReentrantLock
Sharpen.Reference`1
Sharpen.ReferenceQueue`1
Sharpen.Runtime
Sharpen.Runtime+ShutdownHook
Sharpen.SimpleDateFormat
Sharpen.SingletonList
Sharpen.SoftReference`1
Sharpen.SynchronizedList`1
Sharpen.Thread
Sharpen.ThreadGroup
Sharpen.TimeUnit
Sharpen.TimeUnitExtensions
Sharpen.WrappedSystemStream
Sharpen.AbstractCollection`1
Sharpen.AbstractList`1
Sharpen.AbstractList`1+SimpleIterator
Sharpen.AbstractMap`2
Sharpen.AbstractSet`1
Sharpen.Authenticator
Sharpen.ByteBuffer
Sharpen.ByteOrder
Sharpen.CharSequence
Sharpen.StringCharSequence
Sharpen.DigestOutputStream
Sharpen.EnumSet
Sharpen.EnumSet`1
Sharpen.VirtualMachineError
Sharpen.StackOverflowError
Sharpen.BrokenBarrierException
Sharpen.BufferUnderflowException
Sharpen.CharacterCodingException
Sharpen.DataFormatException
Sharpen.EOFException
Sharpen.Error
Sharpen.ExecutionException
Sharpen.InstantiationException
Sharpen.InterruptedIOException
Sharpen.MissingResourceException
Sharpen.NoSuchAlgorithmException
Sharpen.NoSuchElementException
Sharpen.NoSuchMethodException
Sharpen.OverlappingFileLockException
Sharpen.ParseException
Sharpen.RuntimeException
Sharpen.StringIndexOutOfBoundsException
Sharpen.UnknownHostException
Sharpen.UnsupportedEncodingException
Sharpen.URISyntaxException
Sharpen.ZipException
Sharpen.GitException
Sharpen.ConnectException
Sharpen.KeyManagementException
Sharpen.IllegalCharsetNameException
Sharpen.UnsupportedCharsetException
Sharpen.Executor
Sharpen.FilenameFilter
Sharpen.FilePath
Sharpen.FilterInputStream
Sharpen.FilterOutputStream
Sharpen.InputStream
Sharpen.Iterable`1
Sharpen.Iterator
Sharpen.Iterator`1
Sharpen.MessageDigest
Sharpen.MessageDigest`1
Sharpen.OutputStream
Sharpen.PasswordAuthentication
Sharpen.ResourceBundle
Sharpen.Runnable
Sharpen.TreeSet`1
Sharpen.LinkedHashSet`1
Sharpen.ProxySelector
Sharpen.Proxy
Sharpen.URLConnection
Sharpen.HttpsURLConnection
Sharpen.HttpURLConnection
Sharpen.URLEncoder
Sharpen.BitSet
Sharpen.Channels
Sharpen.BufferedWriter
Sharpen.X509TrustManager
Sharpen.X509Certificate
Sharpen.TrustManager
Sharpen.SSLContext
Sharpen.AtomicBoolean
Sharpen.ScheduledThreadPoolExecutor
Sharpen.ScheduledThreadPoolExecutor+Task`1
Sharpen.IScheduledITask
Sharpen.Scheduler
Sharpen.ThreadFactory
Sharpen.ThreadPoolExecutor
Sharpen.RunnableAction
Sharpen.JavaWeakReference`1
Sharpen.SystemProcess
Sharpen.DateFormat
Sharpen.DigestInputStream
Sharpen.FileHelper
Sharpen.JavaCalendar
Sharpen.JavaGregorianCalendar
<PrivateImplementationDetails>
<PrivateImplementationDetails>+$ArrayType=1024
Sharpen.FixedThreadPoolExecutorService+<Submit>c__AnonStorey0`1
Sharpen.Extensions+<ContainsAll>c__AnonStorey0`2
Sharpen.Extensions+<Contains>c__AnonStorey1`1
Sharpen.LinkedHashMap`2+<Put>c__AnonStorey0
Sharpen.LinkedHashMap`2+<Remove>c__AnonStorey1
Sharpen.AbstractMap`2+<ContainsKey>c__AnonStorey0
Sharpen.AbstractMap`2+<Get>c__AnonStorey1
Sharpen.Scheduler+<HasTasks>c__AnonStorey0

Via:

Assembly assembly = Assembly.ReflectionOnlyLoad("Sharpen");
foreach (Type type in assembly.GetTypes())
{
   Console.WriteLine(type.FullName);
}

Sharpen - Part 2

Sharpen Setup

Get Maven:

brew install maven

Check Maven:

mvn --version

Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T08:41:47-08:00)
Maven home: /usr/local/Cellar/maven/3.3.9/libexec
Java version: 1.8.0_92, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.11.6", arch: "x86_64", family: "mac"

Clone the repo(s):

git clone https://github.com/mono/sharpen.git
git clone https://github.com/ydanila/sharpen_imazen_config.git

Set your Java/JDK version to 1.7

Build the Sharpen config:

pushd sharpen_imazen_config
mvn install
popd

Note: This is a sample config and a great starting point

Build Sharpen

Note: Make sure that you are on the develop branch of Sharpen!
pushd sharpen
git checkout develop 

Edit the pom.xml file so the cmd line -help option works:

git diff pom.xml

diff --git a/pom.xml b/pom.xml
index 1098a2d..4fedcbc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -122,7 +122,7 @@
     <testSourceDirectory>src/test</testSourceDirectory>
     <resources>
       <resource>
-        <directory>src/test/resources</directory>
+        <directory>src/main/resources</directory>
       </resource>
     </resources>
     <testResources>

mvn clean test mvn install

Running Sharpen:

Cmd line help:

java -jar ${PWD}/src/target/sharpencore-0.0.1-SNAPSHOT-jar-with-dependencies.jar -help     

Convert Java to C# (with config)

Copy config:
cp ../sharpen_imazen_config/sharpen-all-options .
cp ../sharpen_imazen_config/sharpen.config/target/MEConfiguration.sharpenconfig .

Run with config:

java -jar \
   ${PWD}/src/target/sharpencore-0.0.1-SNAPSHOT-jar-with-dependencies.jar \
   /Users/sushi/code/github/PlayScriptParser/src \
   -configurationClass \
   MEConfiguration.sharpenconfig-jar @sharpen-all-options

~~~
Configuration Class: sharpen.config.MEConfiguration
Configuration Class: Sharpen.Runtime
project: asc
Pascal case mode: NamespaceAndIdentifiers
Native type system mode on.
Separating interface constants to their own classes.
Organize usings mode on.
~~~

Convert C# Location:

Your converted C# classes will be located NEXT the original source directory, /Users/sushi/code/github/PlayScriptParser, in my case, the asc.net directory

cd /Users/sushi/code/github/PlayScriptParser
ls -1
    asc.net
    build
    src

Sharpen

I needed to convert some Java code to C# and one of the best ways that I ever found is to use Sharpen. This used to be available as a Eclipse plugin but you can find a cli version at Mono’s Github account:

One of the issues in running Sharpen is that it requires Java 1.7, NOT 1.6, nor 1.8..

So you need to have a Java 7 install. An easy way if you are already using homebrew, is available via a cask:

brew install Caskroom/versions/java7

Note: If you get errors, make sure that your casks are updated, brew upgrade brew-cask

Current JDK:

/usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home

Get a list of Install JDKs:

ls -l1 /Library/Java/JavaVirtualMachines/
1.6.0.jdk
jdk1.7.0_71.jdk
jdk1.7.0_80.jdk
jdk1.8.0_92.jdk

Export a “new home”:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home

Now I can build and run sharpen, i.e.:

mvn clean test
mvn install
java -jar src/target/sharpencore-0.0.1-SNAPSHOT-jar-with-dependencies.jar /Users/sushi/github/PlayParser

Nuget and MSBuild Targets

In adding support for incremental MSBuild support for Mono’s Jay (Yacc-based) parser generator I could not get my resulting MSBuild target to automatically add the import statement to the .csproj via the nuget I created. The .target file was functional and correct and inside a “build” dir, but it would not update the project file, over and over I tested, looked at different nuget version, re-read the docs, etc… still no luck…

I ended up reading the blog posting for the Nuget v2.5 release for “Support for Native Projects” was my answer:

the file name must match your package id with either a “.props” or “.targets” extension

Also the release notes for version 2.5 they state this:

Under this folder, you can place two files with fixed names, {packageid}.targets or {packageid}.props.

Why are these ‘notes’ not in the ‘normal’ documention section and only listed on a blog posting and in release notes?

So in-case someone else needs this information:

Support for Native Projects

NuGet 2.5 Release Notes

Automatic import of msbuild targets and props files

A new conventional folder has been created at the top level of the NuGet package. As a peer to \lib, \content, and \tools, you can now include a ‘\build’ folder in your package. Under this folder, you can place two files with fixed names, {packageid}.targets or {packageid}.props. These two files can be either directly under \build or under framework-specific folders just like the other folders. The rule for picking the best-matched framework folder is exactly the same as in those.

When NuGet installs a package with \build files, it will add an MSBuild element in the project file pointing to the .targets and .props files. The .props file is added at the top, whereas the .targets file is added to the bottom.

MSBuild Integration

C++ projects tend to have many different configurations–more than what NuGet is able to handle. To address NuGet’s configuration limitations, we are relying heavily on MSBuild properties and targets for native packages. These MSBuild properties and targets do the heavy lifting of providing references at build time, based on your project’s configuration.

To make MSBuild integration better, NuGet has created a new convention for automatically importing MSBuild properties and targets from a NuGet package. Alongside the existing \content, \lib, and \tools folders, NuGet now recognizes a new top-level folder: \build.

Within the \build folder, you can provide a “.props” file and/or a “.targets” file that will be automatically imported into the project. For this convention, the file name must match your package id with either a “.props” or “.targets” extension. For example, the ‘cpprestsdk’ package includes a ‘cpprestsdk.targets’ file in its \build folder. Files with the “.props” extension will be imported at the top of the project file, and files with the “.targets” extension will be imported at the bottom of the project file.

Note that this \build folder can be used for all NuGet packages and not just native packages. The \build folder respects target frameworks just like the \content, \lib, and \tools folders do. This means you can create a \build\net40 folder and a \build\net45 folder and NuGet will import the appropriate props and targets files into the project. You no longer need to write PowerShell install.ps1/uninstall.ps1 scripts to import MSBuild targets files!

PlayScript and MSBuild Project Type GUIDs

Within the PlayScriptRedux/PlayScript.Addin there are two project guids defined for PlayScript and ActionScript projects.

These are the Project Types, not the unique ProjectGuid, i.e:

<ProjectTypeGuids></ProjectTypeGuids> 

Note: I do not know of a single authoritative source for Project Type GUIDs, seems like it should be Microsoft, but I can not find a master published list on their website.

Highlighted below (PlayScript & ActionScript):

Project Type

Guid

ActionScript (via PlayScript)

{464403d2-eb41-442a-a1f1-9bf858b8865f}

ASP.NET MVC 1

{603C0E0B-DB56-11DC-BE95-000D561079B0}

ASP.NET MVC 2

{F85E285D-A4E0-4152-9332-AB1D724D3325}

ASP.NET MVC 3

{E53F8FEA-EAE0-44A6-8774-FFD645390401}

ASP.NET MVC 4

{E3E379DF-F4C6-4180-9B81-6769533ABE47}

ASP.NET MVC 5

{349C5851-65DF-11DA-9384-00065B846F21}

C#

{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}

C++

{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}

Database

{A9ACE9BB-CECE-4E62-9AA4-C7E7C5BD2124}

Database (other project types)

{4F174C21-8C12-11D0-8340-0000F80270F8}

Deployment Cab

{3EA9E505-35AC-4774-B492-AD1749C4943A}

Deployment Merge Module

{06A35CCD-C46D-44D5-987B-CF40FF872267}

Deployment Setup

{978C614F-708E-4E1A-B201-565925725DBA}

Deployment Smart Device Cab

{AB322303-2255-48EF-A496-5904EB18DA55}

Distributed System

{F135691A-BF7E-435D-8960-F99683D2D49C}

Dynamics 2012 AX C# in AOT

{BF6F8E12-879D-49E7-ADF0-5503146B24B8}

F#

{F2A71F9B-5D33-465A-A702-920D77279786}

J#

{E6FDF86B-F3D1-11D4-8576-0002A516ECE8}

Legacy (2003) Smart Device (C#)

{20D4826A-C6FA-45DB-90F4-C717570B9F32}

Legacy (2003) Smart Device (VB.NET)

{CB4CE8C6-1BDB-4DC7-A4D3-65A1999772F8}

Model-View-Controller v2 (MVC 2)

{F85E285D-A4E0-4152-9332-AB1D724D3325}

Model-View-Controller v3 (MVC 3)

{E53F8FEA-EAE0-44A6-8774-FFD645390401}

Model-View-Controller v4 (MVC 4)

{E3E379DF-F4C6-4180-9B81-6769533ABE47}

Model-View-Controller v5 (MVC 5)

{349C5851-65DF-11DA-9384-00065B846F21}

Mono for Android

{EFBA0AD7-5A72-4C68-AF49-83D382785DCF}

MonoTouch

{6BC8ED88-2882-458C-8E55-DFD12B67127B}

MonoTouch Binding

{F5B4F3BC-B597-4E2B-B552-EF5D8A32436F}

PlayScript

{464403d2-eb41-442a-a1f1-9bf858b8865f}

Portable Class Library

{786C830F-07A1-408B-BD7F-6EE04809D6DB}

SharePoint (C#)

{593B0543-81F6-4436-BA1E-4747859CAAE2}

SharePoint (VB.NET)

{EC05E597-79D4-47f3-ADA0-324C4F7C7484}

SharePoint Workflow

{F8810EC1-6754-47FC-A15F-DFABD2E3FA90}

Silverlight

{A1591282-1198-4647-A2B1-27E5FF5F6F3B}

Smart Device (C#)

{4D628B5B-2FBC-4AA6-8C16-197242AEB884}

Smart Device (VB.NET)

{68B1623D-7FB9-47D8-8664-7ECEA3297D4F}

Solution Folder

{2150E333-8FDC-42A3-9474-1A3956D46DE8}

Test

{3AC096D0-A1C2-E12C-1390-A8335801FDAB}

VB.NET

{F184B08F-C81C-45F6-A57F-5ABD9991F28F}

Visual Database Tools

{C252FEB5-A946-4202-B1D4-9916A0590387}

Visual Studio Tools for Applications (VSTA)

{A860303F-1F3F-4691-B57E-529FC101A107}

Visual Studio Tools for Office (VSTO)

{BAA0C2D2-18E2-41B9-852F-F413020CAA33}

Web Application

{349C5851-65DF-11DA-9384-00065B846F21}

Web Site

{E24C65DC-7377-472B-9ABA-BC803B73C61A}

Windows (C#)

{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}

Windows (VB.NET)

{F184B08F-C81C-45F6-A57F-5ABD9991F28F}

Windows (Visual C++)

{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}

Windows Communication Foundation (WCF)

{3D9AD99F-2412-4246-B90B-4EAA41C64699}

Windows Phone 8/8.1 App (C#)

{C089C8C0-30E0-4E22-80C0-CE093F111A43}

Windows Phone 8/8.1 App (VB.NET)

{DB03555F-0C8B-43BE-9FF9-57896B3C5E56}

Windows Phone 8/8.1 Blank/Hub/Webview

{76F1466A-8B6D-4E39-A767-685A06062A39}

Windows Presentation Foundation (WPF)

{60DC8134-EBA5-43B8-BCC9-BB4BC16C2548}

Windows Store (Metro) Apps & Components

{BC8A1FFA-BEE3-4634-8014-F334798102B3}

Workflow (C#)

{14822709-B5A1-4724-98CA-57A101D1B079}

Workflow (VB.NET)

{D59BE175-2ED0-4C54-BE3D-CDAA9F3214C8}

Workflow Foundation

{32F31D43-81CC-4C15-9DE6-3FC5453562B6}

Xamarin.Android

{EFBA0AD7-5A72-4C68-AF49-83D382785DCF}

Xamarin.iOS

{6BC8ED88-2882-458C-8E55-DFD12B67127B}

XNA (Windows)

{6D335F3A-9D43-41b4-9D22-F6F17C4BE596}

XNA (XBox)

{2DF5C3F4-5A5F-47a9-8E94-23B4456F55E2}

XNA (Zune)

{D399B71A-8929-442a-A9AC-8BEC78BB2433}

PlayScript and NUnit

I’ve add a NUnit template to the PlayScriptRedux/PlayScript.Addin

I do not have a website for the .mpack setup yet, so grab the latest release here.

PlayScript NUnit

MonoDevelop.PlayScript_5.10.2.2.mpack

New:

  • Added NUnit template

Prior:

Functional, but it still needs a lot of love to be on par with CSharp’s NRefactory…

Adding nuget packages to your MonoDevelop Addin Templates

I recently created nugets for the PlayScript AOT assemblies as well as a separtate MSBuild target nuget and it ended up working really well in a x-plat way.

But one thing that I could not find quickly was how to tag my templates with the package info so they are automatically installed when the solution/projects are created.

Well the answer was kind-of right under my nose (RTFM):

Conditionally Adding a NuGet Package from a Project Template A NuGet package be conditionally installed based on a boolean parameter defined by the project template wizard.

<Packages>
    <Package id="Xamarin.GooglePlayServices" version="19.0.0.1" if="UseGooglePlayServices" />
</Packages>

The conditions that can be specified do not support the more complicated condition that grouped templates do.

Re: Conditionally Adding a NuGet Package from a Project Template

So in my templates I currently do not have to lock them to a version and want the most recent ones available so I skip the version attribute:

<Packages>
    <Package id="PlayScript.AOT" />
    <package id="PlayScript.MSBuild" />
</Packages>

MSBuild / xbuild - Steps of a build

I’m working on adding MSBuild style building to PlayScript.

The end goal is two fold.

1st) To support the standard MSBuild process in order to allow VS/MD/XS’s IDEs to use this std process via the project file’s target import tag.

2nd) Can I replace the compile portion of the process (with the PlayScript compiler) so I directly create Xamarin.Mac, Xamarin.iOS and Xamarin.Android libraries that are written in PlayScript/ActionScript by using Xamarin’s custom MSBuild process, but via a different compiler that produces the IL code?

A compiled PlayScript library (or exe) is just a standard CIL assembly and can be referenced by C# projects, Xamarin mobile projects or not, but directly referencing Xamarin iOS, Android or Mac libraries will not work as those project types are special (mainly licensing checks and build steps). So the 2nd part of this is really an experient is to see if we are stuck to only linking to PlayScript libraries or can we use PlayScript to directly code against the Xamarin’s mobile libraries and still comply with their licensing/build process.

Building via the psc CLI compiler is almost identical to using csc or mcs. There are a few different options are available in order to support some of the ActionScript 3 compiler options, but I digress…

The normal MSBuild / xbuild steps to compile a CSharp project (.csproj) involved the following high-level Targets:

  • PrepareForBuild:
  • CopyFilesMarkedCopyLocal:
  • GenerateSatelliteAssemblies:
  • CoreCompile:
  • DeployOutputFiles:

Ignoring the multimedia pipeline processing of assets (images, SWFs, vector transformations, 3D models, etc..) the only step that we need to focus on is the CoreCompile:

Import Project=“$(MSBuildBinPath)\Microsoft.CSharp.targets”

~~~
<Target
        Name="CoreCompile"
        Inputs="$(MSBuildAllProjects);@(Compile);@(ManifestResourceWithNoCulture);@(ManifestNonResxWithNoCultureOnDisk);@(CompiledLicenseFile);
                $(KeyOriginatorFile);@(ReferencePath);$(Win32Icon);$(Win32Resource)"
        Outputs="@(DocFileItem);@(IntermediateAssembly)"
        DependsOnTargets="$(CoreCompileDependsOn)">
        <Csc
                AdditionalLibPaths="$(AdditionalLibPaths)"
                AddModules="@(AddModules)"
                AllowUnsafeBlocks="$(AllowUnsafeBlocks)"
                BaseAddress="$(BaseAddress)"
~~~
                Win32Icon="$(Win32Icon)"
                Win32Resource="$(Win32Resource)"
                Resources="@(ManifestResourceWithNoCulture);@(ManifestNonResxWithNoCultureOnDisk);@(CompiledLicenseFile)"
                ToolExe="$(CscToolExe)"
                ToolPath="$(CscToolPath)" />

</Target>
~~~

Looking at the Csc section, if I can replace ToolExe and CscToolPath properties then I can have this Target use PlayScript (psc) vs. csc or mcs.

So as a quick test, copying Microsoft.CSharp.targets to PlayScript.MSBuild.Targetsand adding thisPropertyGroupsection with hardcoded paths before theCoreCompile` target section:

    <PropertyGroup>
            <PlayScriptBinPath Condition=" '$(PsBuildBinPath)' == '' ">/Users/sushi/Library/Application Support/XamarinStudio-5.0/LocalInstall/Addins/MonoDevelop.PlayScript.5.10.2/MonoDevelop.PlayScript.SupportPackages</PlayScriptBinPath>
            <CscToolExe Condition=" '$(CscToolExe)' == '' ">psc</CscToolExe>
            <CscToolPath Condition=" '$(CscToolPath)' == '' ">$(PsBuildBinPath)</CscToolPath>
    </PropertyGroup>

And replacing:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

with:

<Import Project="packages\PlayScript.MSBuild.5.10.2.2\build\PlayScript.MSBuild.Targets" />

>xbuild nuget-test.psproj

XBuild Engine Version 12.0
Mono, Version 4.2.2.0
Copyright (C) 2005-2013 Various Mono authors

Build started 1/1/2016 11:05:25 AM.
__________________________________________________
Project "/Users/sushi/code/XamTests/nuget-test/nuget-test.psproj" (default target(s)):
    Target PrepareForBuild:
        Configuration: Debug Platform: x86
    Target BeforeResolveReferences:
                         AssemblySearchPaths: {CandidateAssemblyFiles};{HintPathFromItem};{TargetFrameworkDirectory};{PkgConfig};{GAC};{RawFileName};bin/Debug/;/Users/sushi/mono/play32/bin
    Target GenerateSatelliteAssemblies:
    No input files were specified for target GenerateSatelliteAssemblies, skipping.
    Target GenerateTargetFrameworkMonikerAttribute:
    Skipping target "GenerateTargetFrameworkMonikerAttribute" because its outputs are up-to-date.
    Target CoreCompile:
         psc
         /Users/sushi/mono/play32/bin

        Tool /Users/sushi/mono/play32/bin/psc execution started with arguments: /noconfig /debug:full /debug+ /optimize- /out:obj/x86/Debug/nuget-test.exe Main.play /target:exe /define:DEBUG /nostdlib /platform:x86 /reference:/Library/Frameworks/Mono.framework/Versions/4.2.2/lib/mono/4.5/System.dll /reference:packages/PlayScript.AOT.5.10.2.0/lib/net45/PlayScript.Dynamic_aot.dll /reference:packages/PlayScript.AOT.5.10.2.0/lib/net45/pscorlib_aot.dll /reference:/Library/Frameworks/Mono.framework/Versions/4.2.2/lib/mono/4.5/System.Core.dll /reference:/Library/Frameworks/Mono.framework/Versions/4.2.2/lib/mono/4.5/mscorlib.dll /warn:4
    Target DeployOutputFiles:
        Copying file from '/Users/sushi/code/XamTests/nuget-test/obj/x86/Debug/nuget-test.exe.mdb' to '/Users/sushi/code/XamTests/nuget-test/bin/Debug/nuget-test.exe.mdb'
        Copying file from '/Users/sushi/code/XamTests/nuget-test/obj/x86/Debug/nuget-test.exe' to '/Users/sushi/code/XamTests/nuget-test/bin/Debug/nuget-test.exe'
Done building project "/Users/sushi/code/XamTests/nuget-test/nuget-test.psproj".

Build succeeded.
     0 Warning(s)
     0 Error(s)

Time Elapsed 00:00:01.8555370

That works, cool

But that requires mod'ing complete copy of Microsoft.CSharp.targets.

So lets strip out everything but our PlayScript changes and import the std CSharp targets.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

    <PropertyGroup>
        <DefaultLanguageSourceExtension>.cs</DefaultLanguageSourceExtension>
        <Language>PlayScript</Language>
    </PropertyGroup>

<!-- PlayScript -->
    <PropertyGroup>
        <PlayScriptBinPath Condition=" '$(PsBuildBinPath)' == '' ">/Users/sushi/Library/Application Support/XamarinStudio-5.0/LocalInstall/Addins/MonoDevelop.PlayScript.5.10.2/MonoDevelop.PlayScript.SupportPackages</PlayScriptBinPath>
        <CscToolExe Condition=" '$(CscToolExe)' == '' ">psc</CscToolExe>
        <CscToolPath Condition=" '$(CscToolPath)' == '' ">$(PsBuildBinPath)</CscToolPath>
    </PropertyGroup>
<!-- PlayScript -->

<!--
    Note: Microsoft.CSharp.targets already imports Microsoft.Common.targets
          so if we need to override/replacement would need to do it after the 
          Microsoft.CSharp.targets import either in this file or by importing another
          file, i.e. PlayScript.Common.targets
          (this is where we will include our multimedia pipeline tasks)
    <Import Project="$(MSBuildBinPath)\Microsoft.Common.targets" />
-->

<!-- PlayScript -->
    <Target Name="BeforeResolveReferences">
        <CreateProperty
            Value="$(AssemblySearchPaths);$(PsBuildBinPath)">
            <Output TaskParameter="Value" PropertyName="AssemblySearchPaths" />
        </CreateProperty>
    </Target>
<!-- PlayScript -->

    <Import Project="$(MSBuildThisFileDirectory)\PlayScript.MSBuild.Debug.Targets" />
</Project>

That works…

We still need to look into the custom Xamarin Mobile targets and remove the hardcoded paths from our PlayScript targets, but lets leave that for another post.