diff --git a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj index fc052c9a..3d0591a8 100644 --- a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj +++ b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj @@ -90,6 +90,7 @@ + diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs index a4e89e6b..2666227b 100644 --- a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs +++ b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs @@ -21,6 +21,8 @@ public class AssemblyClassStubs public string ProjectName; + public string AssemblyName; + public List Functions = new List(); } } diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassTable.cs b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassTable.cs new file mode 100644 index 00000000..483edd34 --- /dev/null +++ b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassTable.cs @@ -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 Classes = new List(); + } +} diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs b/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs index 8a6172af..da36581d 100644 --- a/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs +++ b/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs @@ -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) +"; } } diff --git a/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs b/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs index ef02542c..75b04466 100644 --- a/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs +++ b/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs @@ -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, @@ -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 .h with the structs declarations GenerateAssemblyHeader(); @@ -59,6 +61,12 @@ 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() && @@ -66,31 +74,35 @@ private void GenerateStubs() { 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); @@ -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) @@ -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); @@ -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); @@ -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); @@ -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); @@ -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() @@ -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") }; @@ -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 @@ -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)}" }); } } @@ -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)}" }); } } @@ -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)) @@ -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 }; @@ -381,7 +412,7 @@ private void GenerateAssemblyHeader() { var classData = new Class() { - AssemblyName = _project, + AssemblyName = _safeProjectName, Name = NativeMethodsCrc.GetClassName(c) }; @@ -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))