diff --git a/Directory.Packages.props b/Directory.Packages.props
index 15a8a8ca41..41686049fc 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,6 +1,5 @@
-
diff --git a/build/Tests.lua b/build/Tests.lua
index 62a3d734da..0685e991be 100644
--- a/build/Tests.lua
+++ b/build/Tests.lua
@@ -84,7 +84,9 @@ function SetupTestProjectsCSharp(name, depends, extraFiles, suffix)
str = "Std"
end
- SetupExternalManagedTestProject(name .. ".CSharp")
+ if name ~= "NamespacesDerived" then
+ SetupExternalManagedTestProject(name .. ".CSharp")
+ end
SetupExternalManagedTestProject(name .. ".Tests.CSharp")
end
diff --git a/src/Generator/CppSharp.Generator.csproj b/src/Generator/CppSharp.Generator.csproj
index b232da628b..a96a8f7831 100644
--- a/src/Generator/CppSharp.Generator.csproj
+++ b/src/Generator/CppSharp.Generator.csproj
@@ -12,8 +12,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs
index 5932b75ddf..655c9ec1da 100644
--- a/src/Generator/Driver.cs
+++ b/src/Generator/Driver.cs
@@ -1,26 +1,23 @@
using System;
-using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text;
using CppSharp.AST;
using CppSharp.Generators;
+using CppSharp.Generators.C;
using CppSharp.Generators.CLI;
+using CppSharp.Generators.Cpp;
using CppSharp.Generators.CSharp;
using CppSharp.Parser;
using CppSharp.Passes;
using CppSharp.Utils;
-using Microsoft.CSharp;
using CppSharp.Types;
-using CppSharp.Generators.Cpp;
-using CppSharp.Generators.C;
namespace CppSharp
{
public class Driver : IDisposable
{
- public DriverOptions Options { get; private set; }
+ public DriverOptions Options { get; }
public ParserOptions ParserOptions { get; set; }
public BindingContext Context { get; private set; }
public Generator Generator { get; private set; }
@@ -351,68 +348,29 @@ private void WriteGeneratedCodeToFile(string file, string generatedCode)
File.WriteAllText(file, generatedCode);
}
- private static readonly Dictionary libraryMappings = new Dictionary();
-
- public void CompileCode(Module module)
+ public bool CompileCode(Module module)
{
- var assemblyFile = Path.Combine(Options.OutputDir, module.LibraryName + ".dll");
-
- var docFile = Path.ChangeExtension(assemblyFile, ".xml");
+ File.WriteAllText(Path.Combine(Options.OutputDir, "Directory.Build.props"), "");
- var compilerOptions = new StringBuilder();
- compilerOptions.Append($" /doc:\"{docFile}\"");
- compilerOptions.Append(" /debug:pdbonly");
- compilerOptions.Append(" /unsafe");
+ var msBuildGenerator = new MSBuildGenerator(Context, module, libraryMappings);
+ msBuildGenerator.Process();
+ string csproj = Path.Combine(Options.OutputDir,
+ $"{module.LibraryName}.{msBuildGenerator.FileExtension}");
+ File.WriteAllText(csproj, msBuildGenerator.Generate());
- var compilerParameters = new CompilerParameters
+ string output = ProcessHelper.Run("dotnet", $"build {csproj}",
+ out int error, out string errorMessage);
+ if (error == 0)
{
- GenerateExecutable = false,
- TreatWarningsAsErrors = false,
- OutputAssembly = assemblyFile,
- GenerateInMemory = false,
- CompilerOptions = compilerOptions.ToString()
- };
-
- if (module != Options.SystemModule)
- compilerParameters.ReferencedAssemblies.Add(
- Path.Combine(Options.OutputDir, $"{Options.SystemModule.LibraryName}.dll"));
- // add a reference to System.Core
- compilerParameters.ReferencedAssemblies.Add(typeof(Enumerable).Assembly.Location);
-
- var location = System.Reflection.Assembly.GetExecutingAssembly().Location;
- var outputDir = Path.GetDirectoryName(location);
- var locationRuntime = Path.Combine(outputDir, "CppSharp.Runtime.dll");
- compilerParameters.ReferencedAssemblies.Add(locationRuntime);
-
- compilerParameters.ReferencedAssemblies.AddRange(
- (from dependency in module.Dependencies
- where libraryMappings.ContainsKey(dependency)
- select libraryMappings[dependency]).ToArray());
-
- compilerParameters.ReferencedAssemblies.AddRange(module.ReferencedAssemblies.ToArray());
-
- Diagnostics.Message($"Compiling {module.LibraryName}...");
- CompilerResults compilerResults;
- using (var codeProvider = new CSharpCodeProvider(
- new Dictionary {
- { "CompilerDirectoryPath", ManagedToolchain.FindCSharpCompilerDir() } }))
- {
- compilerResults = codeProvider.CompileAssemblyFromFile(
- compilerParameters, module.CodeFiles.ToArray());
+ Diagnostics.Message($@"Compilation succeeded: {
+ libraryMappings[module] = Path.Combine(
+ Options.OutputDir, $"{module.LibraryName}.dll")}.");
+ return true;
}
- var errors = compilerResults.Errors.Cast().Where(e => !e.IsWarning &&
- // HACK: auto-compiling on OS X produces "errors" which do not affect compilation so we ignore them
- (!Platform.IsMacOS || !e.ErrorText.EndsWith("(Location of the symbol related to previous warning)", StringComparison.Ordinal))).ToList();
- foreach (var error in errors)
- Diagnostics.Error(error.ToString());
-
- HasCompilationErrors = errors.Count > 0;
- if (!HasCompilationErrors)
- {
- libraryMappings[module] = Path.Combine(outputDir, assemblyFile);
- Diagnostics.Message("Compilation succeeded.");
- }
+ Diagnostics.Error(output);
+ Diagnostics.Error(errorMessage);
+ return false;
}
public void AddTranslationUnitPass(TranslationUnitPass pass)
@@ -433,6 +391,7 @@ public void Dispose()
}
private bool hasParsingErrors;
+ private static readonly Dictionary libraryMappings = new Dictionary();
}
public static class ConsoleDriver
@@ -498,12 +457,7 @@ public static void Run(ILibrary library)
driver.SaveCode(outputs);
if (driver.Options.IsCSharpGenerator && driver.Options.CompileCode)
- foreach (var module in driver.Options.Modules)
- {
- driver.CompileCode(module);
- if (driver.HasCompilationErrors)
- break;
- }
+ driver.Options.Modules.Any(m => !driver.CompileCode(m));
}
}
}
diff --git a/src/Generator/Generators/MSBuildGenerator.cs b/src/Generator/Generators/MSBuildGenerator.cs
new file mode 100644
index 0000000000..ab6fe8c5d5
--- /dev/null
+++ b/src/Generator/Generators/MSBuildGenerator.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using CppSharp.AST;
+
+namespace CppSharp.Generators
+{
+ public class MSBuildGenerator : CodeGenerator
+ {
+ public MSBuildGenerator(BindingContext context, Module module,
+ Dictionary libraryMappings)
+ : base(context)
+ {
+ this.module = module;
+ this.libraryMappings = libraryMappings;
+ }
+
+ public override string FileExtension => "csproj";
+
+ public override void Process()
+ {
+ var location = System.Reflection.Assembly.GetExecutingAssembly().Location;
+ Write($@"
+
+
+ netstandard2.0
+ {(Context.TargetInfo.PointerWidth == 64 ? "x64" : "x86")}
+ {Options.OutputDir}
+ {module.LibraryName}.xml
+ Release
+ true
+ false
+ false
+ false
+
+
+ {string.Join(Environment.NewLine, module.CodeFiles.Select(c =>
+ $""))}
+
+
+ {string.Join(Environment.NewLine,
+ new[] { Path.Combine(Path.GetDirectoryName(location), "CppSharp.Runtime.dll") }
+ .Union(module.Dependencies.Where(libraryMappings.ContainsKey).Select(d => libraryMappings[d]))
+ .Select(reference =>
+ $@"
+ {reference}
+ "))}
+
+".Trim());
+ }
+
+ private readonly Module module;
+ private readonly Dictionary libraryMappings;
+ }
+}
diff --git a/src/Generator/Types/Std/Stdlib.CSharp.cs b/src/Generator/Types/Std/Stdlib.CSharp.cs
index 93c0eb70ed..32ad5b3ccc 100644
--- a/src/Generator/Types/Std/Stdlib.CSharp.cs
+++ b/src/Generator/Types/Std/Stdlib.CSharp.cs
@@ -101,7 +101,7 @@ public override Type CSharpSignatureType(TypePrinterContext ctx)
if (enconding == Encoding.ASCII)
return new CustomType("[MarshalAs(UnmanagedType.LPStr)] string");
else if (enconding == Encoding.UTF8)
- return new CustomType("[MarshalAs(UnmanagedType.LPUTF8Str)] string");
+ return new CustomType("[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(CppSharp.Runtime.UTF8Marshaller))] string");
else if (enconding == Encoding.Unicode || enconding == Encoding.BigEndianUnicode)
return new CustomType("[MarshalAs(UnmanagedType.LPWStr)] string");
else if (enconding == Encoding.UTF32)
diff --git a/src/Package/CppSharp.Package.csproj b/src/Package/CppSharp.Package.csproj
index cd315f2634..0530914d2b 100644
--- a/src/Package/CppSharp.Package.csproj
+++ b/src/Package/CppSharp.Package.csproj
@@ -14,7 +14,6 @@ It can also be used as a library to parse native code into a syntax tree with a
-
diff --git a/src/Runtime/UTF8Marshaller.cs b/src/Runtime/UTF8Marshaller.cs
new file mode 100644
index 0000000000..6ac831ed51
--- /dev/null
+++ b/src/Runtime/UTF8Marshaller.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace CppSharp.Runtime
+{
+ // HACK: .NET Standard 2.0 which we use in auto-building to support .NET Framework, lacks UnmanagedType.LPUTF8Str
+ public class UTF8Marshaller : ICustomMarshaler
+ {
+ public void CleanUpManagedData(object ManagedObj)
+ {
+ }
+
+ public void CleanUpNativeData(IntPtr pNativeData)
+ => Marshal.FreeHGlobal(pNativeData);
+
+ public int GetNativeDataSize() => -1;
+
+ public IntPtr MarshalManagedToNative(object managedObj)
+ {
+ if (managedObj == null)
+ return IntPtr.Zero;
+ if (!(managedObj is string))
+ throw new MarshalDirectiveException(
+ "UTF8Marshaler must be used on a string.");
+
+ // not null terminated
+ byte[] strbuf = Encoding.UTF8.GetBytes((string) managedObj);
+ IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1);
+ Marshal.Copy(strbuf, 0, buffer, strbuf.Length);
+
+ // write the terminating null
+ Marshal.WriteByte(buffer + strbuf.Length, 0);
+ return buffer;
+ }
+
+ public unsafe object MarshalNativeToManaged(IntPtr str)
+ {
+ if (str == IntPtr.Zero)
+ return null;
+
+ int byteCount = 0;
+ var str8 = (byte*) str;
+ while (*(str8++) != 0) byteCount += sizeof(byte);
+
+ return Encoding.UTF8.GetString((byte*) str, byteCount);
+ }
+
+ public static ICustomMarshaler GetInstance(string pstrCookie)
+ {
+ if (marshaler == null)
+ marshaler = new UTF8Marshaller();
+ return marshaler;
+ }
+
+ private static UTF8Marshaller marshaler;
+ }
+}
diff --git a/tests/NamespacesBase/NamespacesBase.CSharp.csproj b/tests/NamespacesBase/NamespacesBase.CSharp.csproj
deleted file mode 100644
index 4ca9764e98..0000000000
--- a/tests/NamespacesBase/NamespacesBase.CSharp.csproj
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- NamespacesDerived.Gen
- $(MSBuildProjectDirectory)\..\NamespacesDerived\
- false
- $(GenDir)NamespacesDerived
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/NamespacesBase/premake4.lua b/tests/NamespacesBase/premake4.lua
index 51e1512f05..0c46c42af1 100644
--- a/tests/NamespacesBase/premake4.lua
+++ b/tests/NamespacesBase/premake4.lua
@@ -8,5 +8,4 @@ end
group "Tests/Namespaces"
SetupTestNativeProject("NamespacesBase")
- targetdir (path.join(gendir, "NamespacesDerived"))
- SetupWrapper("NamespacesBase")
\ No newline at end of file
+ targetdir (path.join(gendir, "NamespacesDerived"))
\ No newline at end of file
diff --git a/tests/NamespacesDerived/NamespacesDerived.CSharp.csproj b/tests/NamespacesDerived/NamespacesDerived.CSharp.csproj
deleted file mode 100644
index 73be09d8ef..0000000000
--- a/tests/NamespacesDerived/NamespacesDerived.CSharp.csproj
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
- false
- NamespacesDerived.CSharp.xml
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/NamespacesDerived/NamespacesDerived.Gen.cs b/tests/NamespacesDerived/NamespacesDerived.Gen.cs
index cc017ff1ef..427a0f7dac 100644
--- a/tests/NamespacesDerived/NamespacesDerived.Gen.cs
+++ b/tests/NamespacesDerived/NamespacesDerived.Gen.cs
@@ -1,5 +1,4 @@
using System.IO;
-using System.Reflection;
using CppSharp.AST;
using CppSharp.Generators;
using CppSharp.Utils;
@@ -18,6 +17,7 @@ public override void Setup(Driver driver)
base.Setup(driver);
driver.Options.GenerateDefaultValuesForArguments = true;
driver.Options.GenerateClassTemplates = true;
+ driver.Options.CompileCode = true;
driver.Options.DependentNameSpaces.Add("System.Runtime.CompilerServices");
driver.Options.Modules[1].IncludeDirs.Add(GetTestsDirectory("NamespacesDerived"));
var @base = "NamespacesBase";
diff --git a/tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj b/tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj
index a6968989f3..b6509a70d3 100644
--- a/tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj
+++ b/tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj
@@ -1 +1,13 @@
-
\ No newline at end of file
+
+
+
+
+
+
+ ..\..\build\gen\NamespacesDerived\NamespacesBase.dll
+
+
+ ..\..\build\gen\NamespacesDerived\NamespacesDerived.dll
+
+
+
\ No newline at end of file
diff --git a/tests/NamespacesDerived/premake4.lua b/tests/NamespacesDerived/premake4.lua
index 62b7c64a11..a369545b55 100644
--- a/tests/NamespacesDerived/premake4.lua
+++ b/tests/NamespacesDerived/premake4.lua
@@ -6,7 +6,4 @@ group "Tests/Namespaces"
end
SetupTestGeneratorProject("NamespacesDerived")
- SetupTestProjectsCSharp("NamespacesDerived", "NamespacesBase")
-
- project("NamespacesDerived.Tests.CSharp")
- links { "NamespacesBase.CSharp" }
\ No newline at end of file
+ SetupTestProjectsCSharp("NamespacesDerived", "NamespacesBase")
\ No newline at end of file
diff --git a/tests/Test.props b/tests/Test.props
index ee6f57779b..46c86991a8 100644
--- a/tests/Test.props
+++ b/tests/Test.props
@@ -9,7 +9,7 @@
-
+