Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't run msc project. Finishes with error #179

Open
yeabu369 opened this issue Jun 3, 2022 · 2 comments
Open

Can't run msc project. Finishes with error #179

yeabu369 opened this issue Jun 3, 2022 · 2 comments

Comments

@yeabu369
Copy link

yeabu369 commented Jun 3, 2022

dotnet run --project src/msc/msc.csproj samples/hello/hello.ms

The required type 'any' ('System.Object') cannot be resolved among the given references.
The required type 'bool' ('System.Boolean') cannot be resolved among the given references.
The required type 'int' ('System.Int32') cannot be resolved among the given references.
The required type 'string' ('System.String') cannot be resolved among the given references.
The required type 'void' ('System.Void') cannot be resolved among the given references.
The required type 'System.Object' cannot be resolved among the given references.
The required type 'System.Console' cannot be resolved among the given references.
The required type 'System.Console' cannot be resolved among the given references.
The required type 'System.String' cannot be resolved among the given references.
The required type 'System.String' cannot be resolved among the given references.
The required type 'System.String' cannot be resolved among the given references.
The required type 'System.String' cannot be resolved among the given references.
The required type 'System.Convert' cannot be resolved among the given references.
The required type 'System.Convert' cannot be resolved among the given references.
The required type 'System.Convert' cannot be resolved among the given references.
The required type 'System.Random' cannot be resolved among the given references.
The required type 'System.Random' cannot be resolved among the given references.
The required type 'System.Random' cannot be resolved among the given references.
@MarlonDSC
Copy link

Did you find a solution for it?

@GlebSBrykin
Copy link

GlebSBrykin commented Aug 8, 2023

I also ran into a problem and I managed to find a solution (simple, but not too beautiful). You should download netstandard.dll (2.0) and when compiling with msc.exe, explicitly specify a reference to the assembly (/r=netstandard.dll). The fact is that when importing types, msc searches for metadata among assemblies explicitly specified in the compiler parameters.

Minsk\CodeAnalysis\Emit\Emitter.cs:

var assemblies = new List<AssemblyDefinition>();

foreach (var reference in references)
{
    try
    {
        var assembly = AssemblyDefinition.ReadAssembly(reference);
        assemblies.Add(assembly);
    }
    catch (BadImageFormatException)
    {
        _diagnostics.ReportInvalidReference(reference);
    }
}

and then

var foundTypes = assemblies.SelectMany(a => a.Modules)
                           .SelectMany(m => m.Types)
                           .Where(t => t.FullName == metadataName)
                           .ToArray();
if (foundTypes.Length == 1)
{
    var typeReference = _assemblyDefinition.MainModule.ImportReference(foundTypes[0]);
    return typeReference;
}
else if (foundTypes.Length == 0)
{
    _diagnostics.ReportRequiredTypeNotFound(minskName, metadataName);
}
else
{
    _diagnostics.ReportRequiredTypeAmbiguous(minskName, metadataName, foundTypes);
}

In msc\Program.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Minsk.CodeAnalysis;
using Minsk.CodeAnalysis.Syntax;
using Minsk.IO;
using Mono.Options;

namespace Minsk
{
    internal static class Program
    {
        private static int Main(string[] args)
        {
            var outputPath = (string?) null;
            var moduleName = (string?) null;
            var referencePaths = new List<string>();
            var sourcePaths = new List<string>();
            var helpRequested = false;

            var options = new OptionSet
            {
                "usage: msc <source-paths> [options]",
                { "r=", "The {path} of an assembly to reference", v => referencePaths.Add(v) },
                { "o=", "The output {path} of the assembly to create", v => outputPath = v },
                { "m=", "The {name} of the module", v => moduleName = v },
                { "?|h|help", "Prints help", v => helpRequested = true },
                { "<>", v => sourcePaths.Add(v) }
            };

            options.Parse(args);

            if (helpRequested)
            {
                options.WriteOptionDescriptions(Console.Out);
                return 0;
            }

            if (sourcePaths.Count == 0)
            {
                Console.Error.WriteLine("error: need at least one source file");
                return 1;
            }

            if (outputPath == null)
                outputPath = Path.ChangeExtension(sourcePaths[0], ".exe");

            if (moduleName == null)
                moduleName = Path.GetFileNameWithoutExtension(outputPath);

            var syntaxTrees = new List<SyntaxTree>();
            var hasErrors = false;

            foreach (var path in sourcePaths)
            {
                if (!File.Exists(path))
                {
                    Console.Error.WriteLine($"error: file '{path}' doesn't exist");
                    hasErrors = true;
                    continue;
                }

                var syntaxTree = SyntaxTree.Load(path);
                syntaxTrees.Add(syntaxTree);
            }

            foreach (var path in referencePaths)
            {
                if (!File.Exists(path))
                {
                    Console.Error.WriteLine($"error: file '{path}' doesn't exist");
                    hasErrors = true;
                    continue;
                }
            }

            if (hasErrors)
                return 1;

            var compilation = Compilation.Create(syntaxTrees.ToArray());
            var diagnostics = compilation.Emit(moduleName, referencePaths.ToArray(), outputPath);

            if (diagnostics.Any())
            {
                Console.Error.WriteDiagnostics(diagnostics);
                return 1;
            }

            return 0;
        }
    }
}

As you can see, there are no any automatic link for mscorlib.dll (or netstandard.dll in our case) as in csc.exe, so you should define reference manually. And also msc have no access to GAC, so you can't simply reference preinstalled assembly, you should specify the path to it.

The nice solution is referencing basic types in compiler via typeof(object) typeof(int) etc. and not via type name.

For now I put netstandard.dll into msc's binaries folder and compile sources via this command:

msc.exe SomeSourceFile.ms /r=netstandard.dll

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants