Cake -Experimental Switch Compile Error - c#

I am trying to use the Cake-Plist addin and received an error that dynamic is not yet implemented in the version of Roslyn that was being used. Then from advise for someone else I was told to try the -Experimental switch. When using the switch I am receiving the following error when it is trying to compile the build script.
Error: Microsoft.CodeAnalysis.Scripting.CompilationErrorException: (2,1): error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
at Microsoft.CodeAnalysis.Scripting.Script.CompilationError(DiagnosticBag diagnostics)
at Microsoft.CodeAnalysis.Scripting.Script.GetExecutor(CancellationToken cancellationToken)
at Microsoft.CodeAnalysis.Scripting.Script.Run(Object globals)
at Microsoft.CodeAnalysis.Scripting.Script.Run(Object globals)
at Cake.Scripting.Roslyn.Nightly.DefaultRoslynNightlyScriptSession.Execute(Script script)
at Cake.Core.Scripting.ScriptRunner.Run(IScriptHost host, FilePath scriptPath, IDictionary`2 arguments)
at Cake.Commands.BuildCommand.Execute(CakeOptions options)
at Cake.CakeApplication.Run(CakeOptions options)
at Cake.Program.Main()
Does anyone know what is causing this error?

A reference needs to be added to Microsoft.CSharp.dll.
#reference "Microsoft.CSharp.dll"
https://gitter.im/cake-build/cake?at=57add5a3364ad7fc5acdb660

I had a similar issue when running it on a Mac (OSX El Capitan).
I couldn't find the Microsoft.CSharp.dll anywhere on the Mac (other than in my MS Windows installation), and didn't want to add it as a dependency into one of my projects just for the sake of getting it to build like this on a mac.
I noticed, however, that Mono.CSharp.dll was being downloaded into the ./tools/Cake folder. This serves roughly the same purpose, so I tried to reference it with
#r "Mono.CSharp.dll"
That didn't work either. But when I changed it to
#r "./tools/Cake/Mono.CSharp.dll"
It worked perfectly.
Now all I need to do is determine which platform it's running on and use the correct
#r "xxx.CSharp.dll"...

You can use reflection instead of dynamic. A little less elegant but avoids issues referencing Microsoft.CSharp.dll and Mono.CSharp.dll.
The example would be written as follows.
#addin "Cake.Plist"
Task("update-ios-version")
.Does(() =>
{
var plist = File("./src/Demo/Info.plist");
var data = DeserializePlist(plist);
var itemPropertyInfo = data.GetType().GetProperty("Item");
itemPropertyInfo.SetValue(data, gitVersion.AssemblySemVer, new[] { "CFBundleShortVersionString" });
itemPropertyInfo.SetValue(data, gitVersion.FullSemVer, new[] { "CFBundleVersion" });
SerializePlist(plist, data);
});

Related

Reference to type 'CancellationToken' claims it is defined in 'System.Runtime'

I'm trying to generate some class by using Roslyn api however I can't compile generated code successfully becouse of that error. It sounds:
error CS7069: Reference to type 'CancellationToken' claims it is defined in 'System.Runtime', but it could not be found
what I'm trying to do is:
var objLocation = typeof(object).GetTypeInfo().Assembly.Location;
var path = new FileInfo(objLocation);
var directory = path.Directory;
Compilation = Compilation.AddReferences(MetadataReference.CreateFromFile(objLocation));
Compilation = Compilation.AddReferences(MetadataReference.CreateFromFile(Path.Combine(directory.FullName, "System.dll")));
Compilation = Compilation.AddReferences(MetadataReference.CreateFromFile(Path.Combine(directory.FullName, "System.Runtime.dll")));
As far as I see, the System.Runtime.dll is only placeholder that references different libraries so I don't understand why the message appear and why the compiler is looking for that type here.
Could some point me something?
Sounds like you are compiling for .net core.
CancellationToken resides in mscorlib.dll, so you need to reference that as well.

Cake (C# make) use .Net Framework methods in build.cake

Maybe a dump question. Cake states that its a build automation system that can be written in C#. I'm actually playing around a bit and now want to know if it is possible to call .Net methods in build.cake. At the time I've the following build.cake:
var target = Argument("target", "Default");
Task("NuGet")
.Does(() =>
{
// Get local directory
// Get all packages.config files in local directory
// Call nuget restore for every file
var currentDir = System.IO.GetCurrentDirectory(); // This doesn't work
var allPgkConfigs = System.IO.Directory.GetFiles(currentDir, "packages.config", System.IO.SearchOption.AllDirectories); // This doesn't work
foreach (var pgk in allPgkConfigs)
{
// GetNuGetPackageId(pkg);
}
});
Task("Build")
.Does(() =>
{
MSBuild("MySolution.sln");
});
RunTarget(target);
When calling build.ps1 -target nuget I get the following error:
PS C:\> .\build.ps1 -Target nuget
Preparing to run build script...
Running build script...
Analyzing build script...
Processing build script...
Compiling build script...
Error: C:/Users/Mewald-T550/XAP_Playground/build.cake(6,26): error CS0234: The type or namespace name 'GetCurrentDirectory' does not exist in the namespace 'System.IO' (are you missing an assembly reference?)
As cake already states it can't find System.IO how can I add this reference to cake?
I know that cake offers some build-in file operations, but I want to know how to add .Net Framework methods to the cake script.
Thx
You're calling a method on a namespace
Change
System.IO.GetCurrentDirectory()
to
System.IO.Directory.GetCurrentDirectory()
Tried this script and it worked just fine
var directory = System.IO.Directory.GetCurrentDirectory();
Information(directory);
That said, Cake has several IO abstractions built in
I.e. this will achieve the same:
var allPgkConfigs = GetFiles("./**/packages.config");
foreach (var pgk in allPgkConfigs)
{
// GetNuGetPackageId(pkg);
}
If you just want the current directory you can use
Context.Environment.WorkingDirectory
or just
var curDir = MakeAbsolute(Directory("./"));
Information("Current directory is: {0}", curDir);
You can use a reference directive:
#r "bin/myassembly.dll"
or
#reference "bin/myassembly.dll"
See http://cakebuild.net/docs/fundamentals/preprocessor-directives
Reference directive
The reference directive is used to reference external assemblies for use in your scripts.
Usage
The directive has one parameter which is the path to the dll to load.
#r "bin/myassembly.dll"
or
#reference "bin/myassembly.dll"
Try make it point to C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.dll

Executable fails with weird exception

I am using ILMerge and Quartz.NET in a C# .NET 4.0 Windows Service application. The app runs fine without using ILMerge, but now that we're nearing shipping release, I wanted to combine all DLLs into a single executable.
Problem is, that ILMerge seems to work fine, but when I run the combined executable, it throws this exception:
Unhandled Exception: Quartz.SchedulerException: ThreadPool type 'Quartz.Simpl.SimpleThreadPool' could not be instantiated. ---> System.InvalidCastException: Unable to cast object of type 'Quartz.Simpl.SimpleThreadPool' to type 'Quartz.Spi.IThreadPool'.
at Quartz.Util.ObjectUtils.InstantiateType[T](Type type) in :line 0
at Quartz.Impl.StdSchedulerFactory.Instantiate() in :line 0
--- End of inner exception stack trace ---
at Quartz.Impl.StdSchedulerFactory.Instantiate() in :line 0
at Quartz.Impl.StdSchedulerFactory.GetScheduler() in :line 0
Does anyone have any idea why this is? I have been wasting over 4 hours already and I can't figure it out. If I don't combine with ILMerge, then everything runs fine (with the Quartz.dll and Common.Logging.dll in the same directory).
I'm sure someone must have tried packaging Quartz.net up like this before, any ideas?
Disclaimer: I don't know Quartz.NET at all, although I spent some time struggling with ILMerge. When I finally understood its limitations... I stopped using it.
ILMerge'd application tends to have problems with everything which contains the word "reflection".
I can guess (I've never used Quartz.NET) that some classes are resolved using reflection and driven by configuration files.
Class is not only identified by its name (with namespace) but also by assembly it is coming from (unfortunatelly it doesn't get displayed in exception message).
So, let's assume you had (before ILMerging) two assemblies A (for you Application) and Q (for Quartz.NET).
Assembly 'A' was referencing assembly 'Q' and was using a class 'Q:QClass' which was implementing 'Q:QIntf'.
After merging, those classes became 'A:QClass' and 'A:QIntf' (they were moved from assembly Q to A) and all the references in code has been replaced to use those (completely) new classes/interfaces, so "A:QClass" is implementing "A:QIntf" now.
But, it did not change any config files/embedded strings which may still reference "Q:QClass".
So when application is reading those not-updated config files it still loads "Q:QClass" (why it CAN find it is a different question, maybe you left assembly 'Q' in current folder or maybe it is in GAC - see 1).
Anyway, "Q:QClass" DOES NOT implement "A:QIntf", it still implements "Q:QIntf" even if they are binary identical - so you can't cast 'Q:QClass' to 'A:QIntf'.
The not-ideal-but-working solution is to "embed" assemblies instead of "merging" them. I wrote a open-source tool which does it (embedding instead of merging) but it is not related to this question. So if you decide to embed just ask me.
You can test it by removing (hiding, whatever works for you) every single instance of Q.dll on your PC. If I'm right, the exception should say now 'FileNotFound'.
You could try creating your own ISchedulerFactory and avoid using reflection to load all of your types.
The StdSchedulerFactory uses this code to creat a threadpool. It's where your error is happening and would be the place to start looking at making changes:
Type tpType = loadHelper.LoadType(cfg.GetStringProperty(PropertyThreadPoolType)) ?? typeof(SimpleThreadPool);
try
{
tp = ObjectUtils.InstantiateType<IThreadPool>(tpType);
}
catch (Exception e)
{
initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e);
throw initException;
}
The ObjectUtils.InstantiateType method that is called is this one, and the last line is the one throwing your exception:
public static T InstantiateType<T>(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type", "Cannot instantiate null");
}
ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
if (ci == null)
{
throw new ArgumentException("Cannot instantiate type which has no empty constructor", type.Name);
}
return (T) ci.Invoke(new object[0]);
}
Right after this section in the factory, datasources are loaded using the same pattern and then the jobs themselves are also loaded dynamically which means you'd also have to write your own JobFactory. Since Quartz.Net loads a bunch of bits and pieces dynamically at runtime going down this road means you might end up rewriting a fair amount of things.

Embedding boo in C#, does not recognise executing assembly

scripts/ai/Dream.boo
import CultLib
import LonelyHero
class Dream(Enemy):
pass
C#
var bc = new BooCompiler();
bc.Parameters.Input.Add(new FileInput("rsc/script/ai/" + "Dream" + ".boo"));
bc.Parameters.Pipeline = new CompileToMemory();
bc.Parameters.References.Add(Assembly.GetExecutingAssembly());
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("CultLib.dll").FullName));
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("sfmlnet-audio-2.dll").FullName));
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("sfmlnet-graphics-2.dll").FullName));
bc.Parameters.References.Add(Assembly.LoadFile(new DirectoryInfo("sfmlnet-window-2.dll").FullName));
var cc = bc.Run();
if(cc.GeneratedAssembly!=null)
{
cc.GeneratedAssembly.CreateInstance("Dream", true, BindingFlags.NonPublic, null,
new object[] {Parent, pos}, null, null);
}
else
{
foreach (var error in cc.Errors)
Console.WriteLine(error);
}
In the line bc.Parameters.References.Add(Assembly.GetExecutingAssembly()); I add the executing assembly, which contains the namespace "LonelyHero". However, the error
rsc/script/ai/Dream.boo(2, 8): BCE0021: Namespace LonelyHero not found. maybe you forgot to add an assembly reference?
appears.
LonelyHero should exist, why does this error occur and what can I do to resolve it?
Note:
Upon replacing Assembly.GetExecutingAssmebly() with Assembly.GetAssembly(typeof(Enemy)) , thus assuring it adds the assembly with a class under the LonelyHero namespace, the same error occurs. Also with Assembly.LoadFile(new DirectoryInfo("LonelyHero.exe").FullName)
Occurs in Boo 0.9.4.9 and booxw-1203
Imported namespaces in BOO need to contain at least one public type for the import to succeed; otherwise you will get the BCE0021 error, so you want to make sure the Enemy type is public (or another one).
I don't know Boo or C# but I found someone asking a similar question on the Boo Programming Google Group. The question they were asking:
"Namespace 'Pathfinding' not found, maybe you forgot to add an assembly reference?"
Specifically they were getting this error:
I am converting some existing code I had from C# into Boo. One of my
classes had a "using Pathfinding" which got converted to "import
Pathfinding" by the script converter.
I get this error when trying to compile:
Assets/Script/VehicleController.boo(4,8): BCE0021: Namespace
'Pathfinding' not found, maybe you forgot to add an assembly
reference?
The Pathfinding library I'm using is written in C#. Could this cause
problems? Is there anything additional I need to do to make this work?
This looked like your error message and the solution someone mentioned was that you needed to put your scripts into your compilation phase earlier to ensure that they're accessible from scripts written in other languages.
This URL was cited as a reference/source for more information on script compilation.

How to load referenced script libraries from a Roslyn script file?

I figured out I cannot load one script library from another easily:
module.csx
string SomeFunction() {
return "something";
}
script.csx
ExecuteFile("module.csx");
SomeFunction() <-- causes compile error "SomeFunction" does not exist
This is because the compiler does not know of module.csx at the time it compiles script.csx afaiu. I can add another script to load the two files from that one, and that will work. However thats not that pretty.
Instead I like to make my scripthost check for a special syntax "load module" within my scripts, and execute those modules before actual script execution.
script.csx
// load "module.csx"
SomeFunction()
Now, with some basic string handling, I can figure out which modules to load (lines that contains // load ...) and load that files (gist here https://gist.github.com/4147064):
foreach(var module in scriptModules) {
session.ExecuteFile(module);
}
return session.Execute(script)
But - since we're talking Roslyn, there should be some nice way to parse the script for the syntax I'm looking for, right?
And it might even exist a way to handle module libraries of code?
Currently in Roslyn there is no way to reference another script file. We are considering moving #load from being a host command of the Interactive Window to being a part of the language (like #r), but it isn't currently implemented.
As to how to deal with the strings, you could parse it normally, and then look for pre-processor directives that are of an unknown type and delve into the structure that way.
Support for #load in script files has been added as of https://github.com/dotnet/roslyn/commit/f1702c.
This functionality will be available in Visual Studio 2015 Update 1.
Include the script:
#load "common.csx"
...
And configure the source resolver when you run the scripts:
Script<object> script = CSharpScript.Create(code, ...);
var options = ScriptOptions.Default.WithSourceResolver(new SourceFileResolver(new string[] { }, baseDirectory));
var func = script.WithOptions(options).CreateDelegate()
...

Categories