Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
<Compile Include="nanoSkeletonGenerator.cs" />
<Compile Include="SkeletonGenerator\AssemblyClass.cs" />
<Compile Include="SkeletonGenerator\AssemblyClassStubs.cs" />
<Compile Include="SkeletonGenerator\AssemblyClassTable.cs" />
<Compile Include="SkeletonGenerator\AssemblyLookupTable.cs" />
<Compile Include="Tables\ICustomStringSorter.cs" />
<Compile Include="Tables\nanoAssemblyReferenceTable.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public class AssemblyClassStubs

public string ProjectName;

public string AssemblyName;

public List<MethodStub> Functions = new List<MethodStub>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// Copyright (c) 2019 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

using System.Collections.Generic;

namespace nanoFramework.Tools.MetadataProcessor.Core
{
public class AssemblyClassTable
{
public string AssemblyName;
public string HeaderFileName;
public string ProjectName;

public List<Class> Classes = new List<Class>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,5 +235,56 @@ struct {{ClassName}}
NANOCLR_NOCLEANUP();
}
{{/each}}";

internal const string CMakeModuleTemplate =
@"#
# Copyright(c) 2018 The nanoFramework project contributors
# See LICENSE file in the project root for full license information.
#

#################################################################################################
# make sure that a valid path is set bellow #
# if this is for a class library it's OK to leave it as it is #
# if this is an Interop module the path has to be set where the build can find the source files #
#################################################################################################

# native code directory
set(BASE_PATH_FOR_THIS_MODULE ${BASE_PATH_FOR_CLASS_LIBRARIES_MODULES}/{{AssemblyName}})


# set include directories
list(APPEND {{AssemblyName}}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Core)
list(APPEND {{AssemblyName}}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/CLR/Include)
list(APPEND {{AssemblyName}}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/HAL/Include)
list(APPEND {{AssemblyName}}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/src/PAL/Include)
list(APPEND {{AssemblyName}}_INCLUDE_DIRS ${BASE_PATH_FOR_THIS_MODULE})

# source files
set({{AssemblyName}}_SRCS
{{HeaderFileName}}.cpp
{{#each Classes}}
{{HeaderFileName}}_{{Name}}_mshl.cpp
{{HeaderFileName}}_{{Name}}.cpp{{/each}}

)

foreach(SRC_FILE ${{{AssemblyName}}_SRCS})

set({{AssemblyName}}_SRC_FILE SRC_FILE-NOTFOUND)
find_file({{AssemblyName}}_SRC_FILE ${ SRC_FILE}
PATHS
""${BASE_PATH_FOR_THIS_MODULE}""
""${TARGET_BASE_LOCATION}""

CMAKE_FIND_ROOT_PATH_BOTH
)
# message(""${SRC_FILE} >> ${{{AssemblyName}}_SRC_FILE}"") # debug helper
list(APPEND {{AssemblyName}}_SOURCES ${{{AssemblyName}}_SRC_FILE})
endforeach()

include(FindPackageHandleStandardArgs)

FIND_PACKAGE_HANDLE_STANDARD_ARGS({{AssemblyName}} DEFAULT_MSG {{AssemblyName}}_INCLUDE_DIRS {{AssemblyName}}_SOURCES)
";
}
}
99 changes: 65 additions & 34 deletions source/MetadataProcessor.Core/nanoSkeletonGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ public sealed class nanoSkeletonGenerator
private readonly string _project;
private readonly bool _withoutInteropCode;
private readonly bool _isCoreLib;
private string _assemblyName;
private readonly string _assemblyName;

private string _safeProjectName => _project.Replace('.', '_');

public nanoSkeletonGenerator(
nanoTablesContext tablesContext,
Expand All @@ -40,13 +42,13 @@ public nanoSkeletonGenerator(
_project = project;
_withoutInteropCode = withoutInteropCode;
_isCoreLib = isCoreLib;
}

public void GenerateSkeleton()
{
// replaces "." with "_" so the assembly name can be part of C++ identifier name
_assemblyName = _name.Replace('.', '_');
}

public void GenerateSkeleton()
{
// create <assembly>.h with the structs declarations
GenerateAssemblyHeader();

Expand All @@ -59,38 +61,48 @@ public void GenerateSkeleton()

private void GenerateStubs()
{
var classList = new AssemblyClassTable
{
AssemblyName = _tablesContext.AssemblyDefinition.Name.Name,
ProjectName = _safeProjectName
};

foreach (var c in _tablesContext.TypeDefinitionTable.TypeDefinitions)
{
if (c.IncludeInStub() &&
!c.IsClassToExclude())
{
var className = NativeMethodsCrc.GetClassName(c);

var classStubs = new AssemblyClassStubs();
var classStubs = new AssemblyClassStubs
{
AssemblyName = _name,
ClassHeaderFileName = className,
ClassName = c.Name,
ShortNameUpper = $"{_assemblyName}_{_safeProjectName}_{className}".ToUpper(),
RootNamespace = _assemblyName,
ProjectName = _safeProjectName
};

if (!_withoutInteropCode)
{
// Interop code needs to use the root namespace

classStubs.HeaderFileName = $"{_assemblyName}_{_project}";
classStubs.ClassHeaderFileName = className;
classStubs.ClassName = c.Name;
classStubs.ShortNameUpper = $"{_assemblyName}_{_project}_{className}".ToUpper();
classStubs.RootNamespace = _assemblyName;
classStubs.ProjectName = _project;
classStubs.HeaderFileName = $"{_assemblyName}_{_safeProjectName}";
}
else
{
// projects with Interop can use a simplified naming

classStubs.HeaderFileName = _project;
classStubs.ClassHeaderFileName = className;
classStubs.ClassName = c.Name;
classStubs.ShortNameUpper = $"{_assemblyName}_{_project}_{className}".ToUpper();
classStubs.RootNamespace = _assemblyName;
classStubs.ProjectName = _project;
classStubs.HeaderFileName = _safeProjectName;
}

classList.Classes.Add(new Class()
{
Name = className
});
classList.HeaderFileName = classStubs.HeaderFileName;

foreach (var m in nanoTablesContext.GetOrderedMethods(c.Methods))
{
var rva = _tablesContext.ByteCodeTable.GetMethodRva(m);
Expand All @@ -101,7 +113,7 @@ private void GenerateStubs()
{
var newMethod = new MethodStub()
{
Declaration = $"Library_{_project}_{className}::{NativeMethodsCrc.GetMethodName(m)}"
Declaration = $"Library_{_safeProjectName}_{className}::{NativeMethodsCrc.GetMethodName(m)}"
};

if(!_withoutInteropCode)
Expand Down Expand Up @@ -213,7 +225,7 @@ private void GenerateStubs()
};
Generator generator = compiler.Compile(SkeletonTemplates.ClassWithoutInteropStubTemplate);

using (var headerFile = File.CreateText(Path.Combine(_path, $"{_project}_{className}.cpp")))
using (var headerFile = File.CreateText(Path.Combine(_path, $"{_safeProjectName}_{className}.cpp")))
{
var output = generator.Render(classStubs);
headerFile.Write(output);
Expand All @@ -229,7 +241,7 @@ private void GenerateStubs()
// user code stub
Generator generator = compiler.Compile(SkeletonTemplates.ClassStubTemplate);

using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_project}_{className}.cpp")))
using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_safeProjectName}_{className}.cpp")))
{
var output = generator.Render(classStubs);
headerFile.Write(output);
Expand All @@ -238,7 +250,7 @@ private void GenerateStubs()
// marshal code
generator = compiler.Compile(SkeletonTemplates.ClassMarshallingCodeTemplate);

using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_project}_{className}_mrsh.cpp")))
using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_safeProjectName}_{className}_mshl.cpp")))
{
var output = generator.Render(classStubs);
headerFile.Write(output);
Expand All @@ -247,7 +259,7 @@ private void GenerateStubs()
// class header
generator = compiler.Compile(SkeletonTemplates.ClassHeaderTemplate);

using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_project}_{className}.h")))
using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_safeProjectName}_{className}.h")))
{
var output = generator.Render(classStubs);
headerFile.Write(output);
Expand All @@ -256,6 +268,25 @@ private void GenerateStubs()
}
}
}

if (!_withoutInteropCode &&
classList.Classes.Count > 0)
{
FormatCompiler compiler = new FormatCompiler
{
RemoveNewLines = false
};

// CMake module
Generator generator = compiler.Compile(SkeletonTemplates.CMakeModuleTemplate);

// FindINTEROP-NF.AwesomeLib
using (var headerFile = File.CreateText(Path.Combine(_path, $"FindINTEROP-{_safeProjectName}.cmake")))
{
var output = generator.Render(classList);
headerFile.Write(output);
}
}
}

private void GenerateAssemblyLookup()
Expand All @@ -269,7 +300,7 @@ private void GenerateAssemblyLookup()
IsCoreLib = _isCoreLib,
Name = _name,
AssemblyName = _assemblyName,
HeaderFileName = _project,
HeaderFileName = _safeProjectName,
NativeVersion = nativeVersion,
NativeCRC32 = "0x" + _tablesContext.NativeMethodsCrc.Current.ToString("X")
};
Expand Down Expand Up @@ -298,7 +329,7 @@ private void GenerateAssemblyLookup()
{
assemblyLookup.LookupTable.Add(new MethodStub()
{
Declaration = $"Library_{_project}_{className}::{NativeMethodsCrc.GetMethodName(m)}"
Declaration = $"Library_{_safeProjectName}_{className}::{NativeMethodsCrc.GetMethodName(m)}"
});
}
else
Expand All @@ -312,7 +343,7 @@ private void GenerateAssemblyLookup()
assemblyLookup.LookupTable.Add(new MethodStub()
{
Declaration = "NULL"
//Declaration = $"**Library_{_project}_{NativeMethodsCrc.GetClassName(c)}::{NativeMethodsCrc.GetMethodName(m)}"
//Declaration = $"**Library_{_safeProjectName}_{NativeMethodsCrc.GetClassName(c)}::{NativeMethodsCrc.GetMethodName(m)}"
});
}
}
Expand All @@ -332,7 +363,7 @@ private void GenerateAssemblyLookup()
assemblyLookup.LookupTable.Add(new MethodStub()
{
Declaration = "NULL"
//Declaration = $"**Library_{_project}_{NativeMethodsCrc.GetClassName(c)}::{NativeMethodsCrc.GetMethodName(m)}"
//Declaration = $"**Library_{_safeProjectName}_{NativeMethodsCrc.GetClassName(c)}::{NativeMethodsCrc.GetMethodName(m)}"
});
}
}
Expand All @@ -347,12 +378,12 @@ private void GenerateAssemblyLookup()
if (!_withoutInteropCode)
{
// Interop code needs to use the root namespace
filePath = Path.Combine(_path, $"{_assemblyName}_{_project}.cpp");
filePath = Path.Combine(_path, $"{_assemblyName}_{_safeProjectName}.cpp");
}
else
{
// projects with Interop can use a simplified naming
filePath = Path.Combine(_path, $"{_project}.cpp");
filePath = Path.Combine(_path, $"{_safeProjectName}.cpp");
}

using (var headerFile = File.CreateText(filePath))
Expand All @@ -368,9 +399,9 @@ private void GenerateAssemblyHeader()

var assemblyData = new AssemblyDeclaration()
{
Name = _name.Replace('.', '_'),
ShortName = _project,
ShortNameUpper = _project.ToUpperInvariant(),
Name = _assemblyName,
ShortName = _safeProjectName,
ShortNameUpper = _safeProjectName.ToUpperInvariant(),
IsCoreLib = _isCoreLib
};

Expand All @@ -381,7 +412,7 @@ private void GenerateAssemblyHeader()
{
var classData = new Class()
{
AssemblyName = _project,
AssemblyName = _safeProjectName,
Name = NativeMethodsCrc.GetClassName(c)
};

Expand Down Expand Up @@ -480,12 +511,12 @@ private void GenerateAssemblyHeader()
if (!_withoutInteropCode)
{
// Interop code needs to use the root namespace
filePath = Path.Combine(_path, $"{_assemblyName}_{_project}.h");
filePath = Path.Combine(_path, $"{_assemblyName}_{_safeProjectName}.h");
}
else
{
// projects with Interop can use a simplified naming
filePath = Path.Combine(_path, $"{_project}.h");
filePath = Path.Combine(_path, $"{_safeProjectName}.h");
}

using (var headerFile = File.CreateText(filePath))
Expand Down