Improve the C# API projects generation
- Now there is only one solution that contains both GodotSharp and GodotSharpEditor project. Previously we had one solution for each project - GodotSharpEditor reference GodotShatp with a 'ProjectReference'. Previously it was a 'Reference' to the assembly - This also simplifies the command line option to generate this solution: 'godot --generate-cs-api <OutputDir>'
This commit is contained in:
parent
2cf02f302f
commit
02d5ff4cd0
15 changed files with 238 additions and 208 deletions
|
@ -2770,7 +2770,8 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
|
||||||
"Compile",
|
"Compile",
|
||||||
ProjectSettings::get_singleton()->globalize_path(p_path));
|
ProjectSettings::get_singleton()->globalize_path(p_path));
|
||||||
} else {
|
} else {
|
||||||
ERR_PRINTS("Cannot add " + p_path + " to the C# project because it could not be created.");
|
ERR_PRINTS("Failed to create C# project");
|
||||||
|
ERR_PRINTS("Cannot add " + p_path + " to the C# project");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,22 +6,24 @@ namespace GodotSharpTools.Project
|
||||||
{
|
{
|
||||||
public static class ProjectGenerator
|
public static class ProjectGenerator
|
||||||
{
|
{
|
||||||
|
public const string CoreApiProjectName = "GodotSharp";
|
||||||
|
public const string EditorApiProjectName = "GodotSharpEditor";
|
||||||
const string CoreApiProjectGuid = "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}";
|
const string CoreApiProjectGuid = "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}";
|
||||||
const string EditorApiProjectGuid = "{8FBEC238-D944-4074-8548-B3B524305905}";
|
const string EditorApiProjectGuid = "{8FBEC238-D944-4074-8548-B3B524305905}";
|
||||||
|
|
||||||
public static string GenCoreApiProject(string dir, string[] compileItems)
|
public static string GenCoreApiProject(string dir, string[] compileItems)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(dir, CoreApiProject + ".csproj");
|
string path = Path.Combine(dir, CoreApiProjectName + ".csproj");
|
||||||
|
|
||||||
ProjectPropertyGroupElement mainGroup;
|
ProjectPropertyGroupElement mainGroup;
|
||||||
var root = CreateLibraryProject(CoreApiProject, out mainGroup);
|
var root = CreateLibraryProject(CoreApiProjectName, out mainGroup);
|
||||||
|
|
||||||
mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
|
mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
|
||||||
mainGroup.SetProperty("RootNamespace", "Godot");
|
mainGroup.SetProperty("RootNamespace", "Godot");
|
||||||
mainGroup.SetProperty("ProjectGuid", CoreApiProjectGuid);
|
mainGroup.SetProperty("ProjectGuid", CoreApiProjectGuid);
|
||||||
|
|
||||||
GenAssemblyInfoFile(root, dir, CoreApiProject,
|
GenAssemblyInfoFile(root, dir, CoreApiProjectName,
|
||||||
new string[] { "[assembly: InternalsVisibleTo(\"" + EditorApiProject + "\")]" },
|
new string[] { "[assembly: InternalsVisibleTo(\"" + EditorApiProjectName + "\")]" },
|
||||||
new string[] { "System.Runtime.CompilerServices" });
|
new string[] { "System.Runtime.CompilerServices" });
|
||||||
|
|
||||||
foreach (var item in compileItems)
|
foreach (var item in compileItems)
|
||||||
|
@ -31,34 +33,33 @@ namespace GodotSharpTools.Project
|
||||||
|
|
||||||
root.Save(path);
|
root.Save(path);
|
||||||
|
|
||||||
return root.GetGuid().ToString().ToUpper();
|
return CoreApiProjectGuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GenEditorApiProject(string dir, string coreApiHintPath, string[] compileItems)
|
public static string GenEditorApiProject(string dir, string coreApiProjPath, string[] compileItems)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(dir, EditorApiProject + ".csproj");
|
string path = Path.Combine(dir, EditorApiProjectName + ".csproj");
|
||||||
|
|
||||||
ProjectPropertyGroupElement mainGroup;
|
ProjectPropertyGroupElement mainGroup;
|
||||||
var root = CreateLibraryProject(EditorApiProject, out mainGroup);
|
var root = CreateLibraryProject(EditorApiProjectName, out mainGroup);
|
||||||
|
|
||||||
mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
|
mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
|
||||||
mainGroup.SetProperty("RootNamespace", "Godot");
|
mainGroup.SetProperty("RootNamespace", "Godot");
|
||||||
mainGroup.SetProperty("ProjectGuid", EditorApiProjectGuid);
|
mainGroup.SetProperty("ProjectGuid", EditorApiProjectGuid);
|
||||||
|
|
||||||
GenAssemblyInfoFile(root, dir, EditorApiProject);
|
GenAssemblyInfoFile(root, dir, EditorApiProjectName);
|
||||||
|
|
||||||
foreach (var item in compileItems)
|
foreach (var item in compileItems)
|
||||||
{
|
{
|
||||||
root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
|
root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var coreApiRef = root.AddItem("Reference", CoreApiProject);
|
var coreApiRef = root.AddItem("ProjectReference", coreApiProjPath.Replace("/", "\\"));
|
||||||
coreApiRef.AddMetadata("HintPath", coreApiHintPath);
|
|
||||||
coreApiRef.AddMetadata("Private", "False");
|
coreApiRef.AddMetadata("Private", "False");
|
||||||
|
|
||||||
root.Save(path);
|
root.Save(path);
|
||||||
|
|
||||||
return root.GetGuid().ToString().ToUpper();
|
return EditorApiProjectGuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GenGameProject(string dir, string name, string[] compileItems)
|
public static string GenGameProject(string dir, string name, string[] compileItems)
|
||||||
|
@ -82,13 +83,13 @@ namespace GodotSharpTools.Project
|
||||||
toolsGroup.AddProperty("WarningLevel", "4");
|
toolsGroup.AddProperty("WarningLevel", "4");
|
||||||
toolsGroup.AddProperty("ConsolePause", "false");
|
toolsGroup.AddProperty("ConsolePause", "false");
|
||||||
|
|
||||||
var coreApiRef = root.AddItem("Reference", CoreApiProject);
|
var coreApiRef = root.AddItem("Reference", CoreApiProjectName);
|
||||||
coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProject + ".dll"));
|
coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProjectName + ".dll"));
|
||||||
coreApiRef.AddMetadata("Private", "False");
|
coreApiRef.AddMetadata("Private", "False");
|
||||||
|
|
||||||
var editorApiRef = root.AddItem("Reference", EditorApiProject);
|
var editorApiRef = root.AddItem("Reference", EditorApiProjectName);
|
||||||
editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
|
editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
|
||||||
editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProject + ".dll"));
|
editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProjectName + ".dll"));
|
||||||
editorApiRef.AddMetadata("Private", "False");
|
editorApiRef.AddMetadata("Private", "False");
|
||||||
|
|
||||||
GenAssemblyInfoFile(root, dir, name);
|
GenAssemblyInfoFile(root, dir, name);
|
||||||
|
@ -187,9 +188,6 @@ namespace GodotSharpTools.Project
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public const string CoreApiProject = "GodotSharp";
|
|
||||||
public const string EditorApiProject = "GodotSharpEditor";
|
|
||||||
|
|
||||||
private const string assemblyInfoTemplate =
|
private const string assemblyInfoTemplate =
|
||||||
@"using System.Reflection;{0}
|
@"using System.Reflection;{0}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include "../utils/path_utils.h"
|
#include "../utils/path_utils.h"
|
||||||
#include "../utils/string_utils.h"
|
#include "../utils/string_utils.h"
|
||||||
#include "csharp_project.h"
|
#include "csharp_project.h"
|
||||||
#include "net_solution.h"
|
|
||||||
|
|
||||||
#define CS_INDENT " " // 4 whitespaces
|
#define CS_INDENT " " // 4 whitespaces
|
||||||
|
|
||||||
|
@ -401,32 +400,29 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
|
||||||
p_output.push_back(CLOSE_BLOCK); // end of namespace
|
p_output.push_back(CLOSE_BLOCK); // end of namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bool p_verbose_output) {
|
Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
|
||||||
|
|
||||||
verbose_output = p_verbose_output;
|
verbose_output = p_verbose_output;
|
||||||
|
|
||||||
|
String proj_dir = p_solution_dir.plus_file(CORE_API_ASSEMBLY_NAME);
|
||||||
|
|
||||||
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||||
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
|
||||||
|
|
||||||
if (!DirAccess::exists(p_output_dir)) {
|
if (!DirAccess::exists(proj_dir)) {
|
||||||
Error err = da->make_dir_recursive(p_output_dir);
|
Error err = da->make_dir_recursive(proj_dir);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
da->change_dir(p_output_dir);
|
da->change_dir(proj_dir);
|
||||||
da->make_dir("Core");
|
da->make_dir("Core");
|
||||||
da->make_dir("ObjectType");
|
da->make_dir("ObjectType");
|
||||||
|
|
||||||
String core_dir = path_join(p_output_dir, "Core");
|
String core_dir = path_join(proj_dir, "Core");
|
||||||
String obj_type_dir = path_join(p_output_dir, "ObjectType");
|
String obj_type_dir = path_join(proj_dir, "ObjectType");
|
||||||
|
|
||||||
Vector<String> compile_items;
|
Vector<String> compile_items;
|
||||||
|
|
||||||
NETSolution solution(API_ASSEMBLY_NAME);
|
|
||||||
|
|
||||||
if (!solution.set_path(p_output_dir))
|
|
||||||
return ERR_FILE_NOT_FOUND;
|
|
||||||
|
|
||||||
// Generate source file for global scope constants and enums
|
// Generate source file for global scope constants and enums
|
||||||
{
|
{
|
||||||
List<String> constants_source;
|
List<String> constants_source;
|
||||||
|
@ -530,15 +526,15 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
|
||||||
|
|
||||||
compile_items.push_back(internal_methods_file);
|
compile_items.push_back(internal_methods_file);
|
||||||
|
|
||||||
String guid = CSharpProject::generate_core_api_project(p_output_dir, compile_items);
|
String guid = CSharpProject::generate_core_api_project(proj_dir, compile_items);
|
||||||
|
|
||||||
solution.add_new_project(API_ASSEMBLY_NAME, guid);
|
DotNetSolution::ProjectInfo proj_info;
|
||||||
|
proj_info.guid = guid;
|
||||||
|
proj_info.relpath = String(CORE_API_ASSEMBLY_NAME).plus_file(CORE_API_ASSEMBLY_NAME ".csproj");
|
||||||
|
proj_info.configs.push_back("Debug");
|
||||||
|
proj_info.configs.push_back("Release");
|
||||||
|
|
||||||
Error sln_error = solution.save();
|
r_solution.add_new_project(CORE_API_ASSEMBLY_NAME, proj_info);
|
||||||
if (sln_error != OK) {
|
|
||||||
ERR_PRINT("Could not to save .NET solution.");
|
|
||||||
return sln_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose_output)
|
if (verbose_output)
|
||||||
OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n");
|
OS::get_singleton()->print("The solution and C# project for the Core API was generated successfully\n");
|
||||||
|
@ -546,32 +542,29 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output) {
|
Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
|
||||||
|
|
||||||
verbose_output = p_verbose_output;
|
verbose_output = p_verbose_output;
|
||||||
|
|
||||||
|
String proj_dir = p_solution_dir.plus_file(EDITOR_API_ASSEMBLY_NAME);
|
||||||
|
|
||||||
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||||
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
|
||||||
|
|
||||||
if (!DirAccess::exists(p_output_dir)) {
|
if (!DirAccess::exists(proj_dir)) {
|
||||||
Error err = da->make_dir_recursive(p_output_dir);
|
Error err = da->make_dir_recursive(proj_dir);
|
||||||
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
da->change_dir(p_output_dir);
|
da->change_dir(proj_dir);
|
||||||
da->make_dir("Core");
|
da->make_dir("Core");
|
||||||
da->make_dir("ObjectType");
|
da->make_dir("ObjectType");
|
||||||
|
|
||||||
String core_dir = path_join(p_output_dir, "Core");
|
String core_dir = path_join(proj_dir, "Core");
|
||||||
String obj_type_dir = path_join(p_output_dir, "ObjectType");
|
String obj_type_dir = path_join(proj_dir, "ObjectType");
|
||||||
|
|
||||||
Vector<String> compile_items;
|
Vector<String> compile_items;
|
||||||
|
|
||||||
NETSolution solution(EDITOR_API_ASSEMBLY_NAME);
|
|
||||||
|
|
||||||
if (!solution.set_path(p_output_dir))
|
|
||||||
return ERR_FILE_NOT_FOUND;
|
|
||||||
|
|
||||||
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
|
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) {
|
||||||
const TypeInterface &itype = E.get();
|
const TypeInterface &itype = E.get();
|
||||||
|
|
||||||
|
@ -632,15 +625,15 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
|
||||||
|
|
||||||
compile_items.push_back(internal_methods_file);
|
compile_items.push_back(internal_methods_file);
|
||||||
|
|
||||||
String guid = CSharpProject::generate_editor_api_project(p_output_dir, p_core_dll_path, compile_items);
|
String guid = CSharpProject::generate_editor_api_project(proj_dir, "../" CORE_API_ASSEMBLY_NAME "/" CORE_API_ASSEMBLY_NAME ".csproj", compile_items);
|
||||||
|
|
||||||
solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, guid);
|
DotNetSolution::ProjectInfo proj_info;
|
||||||
|
proj_info.guid = guid;
|
||||||
|
proj_info.relpath = String(EDITOR_API_ASSEMBLY_NAME).plus_file(EDITOR_API_ASSEMBLY_NAME ".csproj");
|
||||||
|
proj_info.configs.push_back("Debug");
|
||||||
|
proj_info.configs.push_back("Release");
|
||||||
|
|
||||||
Error sln_error = solution.save();
|
r_solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, proj_info);
|
||||||
if (sln_error != OK) {
|
|
||||||
ERR_PRINT("Could not to save .NET solution.");
|
|
||||||
return sln_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose_output)
|
if (verbose_output)
|
||||||
OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n");
|
OS::get_singleton()->print("The solution and C# project for the Editor API was generated successfully\n");
|
||||||
|
@ -648,6 +641,44 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error BindingsGenerator::generate_cs_api(const String &p_output_dir, bool p_verbose_output) {
|
||||||
|
|
||||||
|
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||||
|
ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
|
||||||
|
|
||||||
|
if (!DirAccess::exists(p_output_dir)) {
|
||||||
|
Error err = da->make_dir_recursive(p_output_dir);
|
||||||
|
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
DotNetSolution solution(API_SOLUTION_NAME);
|
||||||
|
|
||||||
|
if (!solution.set_path(p_output_dir))
|
||||||
|
return ERR_FILE_NOT_FOUND;
|
||||||
|
|
||||||
|
Error proj_err;
|
||||||
|
|
||||||
|
proj_err = generate_cs_core_project(p_output_dir, solution, p_verbose_output);
|
||||||
|
if (proj_err != OK) {
|
||||||
|
ERR_PRINT("Generation of the Core API C# project failed");
|
||||||
|
return proj_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
proj_err = generate_cs_editor_project(p_output_dir, solution, p_verbose_output);
|
||||||
|
if (proj_err != OK) {
|
||||||
|
ERR_PRINT("Generation of the Editor API C# project failed");
|
||||||
|
return proj_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error sln_error = solution.save();
|
||||||
|
if (sln_error != OK) {
|
||||||
|
ERR_PRINT("Failed to save API solution");
|
||||||
|
return sln_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: There are some members that hide other inherited members.
|
// FIXME: There are some members that hide other inherited members.
|
||||||
// - In the case of both members being the same kind, the new one must be declared
|
// - In the case of both members being the same kind, the new one must be declared
|
||||||
// explicitly as `new` to avoid the warning (and we must print a message about it).
|
// explicitly as `new` to avoid the warning (and we must print a message about it).
|
||||||
|
@ -2368,12 +2399,11 @@ void BindingsGenerator::initialize() {
|
||||||
|
|
||||||
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
|
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
|
||||||
|
|
||||||
const int NUM_OPTIONS = 3;
|
const int NUM_OPTIONS = 2;
|
||||||
int options_left = NUM_OPTIONS;
|
int options_left = NUM_OPTIONS;
|
||||||
|
|
||||||
String mono_glue_option = "--generate-mono-glue";
|
String mono_glue_option = "--generate-mono-glue";
|
||||||
String cs_core_api_option = "--generate-cs-core-api";
|
String cs_api_option = "--generate-cs-api";
|
||||||
String cs_editor_api_option = "--generate-cs-editor-api";
|
|
||||||
|
|
||||||
verbose_output = true;
|
verbose_output = true;
|
||||||
|
|
||||||
|
@ -2387,42 +2417,24 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
|
||||||
|
|
||||||
if (path_elem) {
|
if (path_elem) {
|
||||||
if (get_singleton()->generate_glue(path_elem->get()) != OK)
|
if (get_singleton()->generate_glue(path_elem->get()) != OK)
|
||||||
ERR_PRINT("Mono glue generation failed");
|
ERR_PRINTS(mono_glue_option + ": Failed to generate mono glue");
|
||||||
elem = elem->next();
|
elem = elem->next();
|
||||||
} else {
|
} else {
|
||||||
ERR_PRINTS("--generate-mono-glue: No output directory specified");
|
ERR_PRINTS(mono_glue_option + ": No output directory specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
--options_left;
|
--options_left;
|
||||||
|
|
||||||
} else if (elem->get() == cs_core_api_option) {
|
} else if (elem->get() == cs_api_option) {
|
||||||
|
|
||||||
const List<String>::Element *path_elem = elem->next();
|
const List<String>::Element *path_elem = elem->next();
|
||||||
|
|
||||||
if (path_elem) {
|
if (path_elem) {
|
||||||
if (get_singleton()->generate_cs_core_project(path_elem->get()) != OK)
|
if (get_singleton()->generate_cs_api(path_elem->get()) != OK)
|
||||||
ERR_PRINT("Generation of solution and C# project for the Core API failed");
|
ERR_PRINTS(cs_api_option + ": Failed to generate the C# API");
|
||||||
elem = elem->next();
|
elem = elem->next();
|
||||||
} else {
|
} else {
|
||||||
ERR_PRINTS(cs_core_api_option + ": No output directory specified");
|
ERR_PRINTS(cs_api_option + ": No output directory specified");
|
||||||
}
|
|
||||||
|
|
||||||
--options_left;
|
|
||||||
|
|
||||||
} else if (elem->get() == cs_editor_api_option) {
|
|
||||||
|
|
||||||
const List<String>::Element *path_elem = elem->next();
|
|
||||||
|
|
||||||
if (path_elem) {
|
|
||||||
if (path_elem->next()) {
|
|
||||||
if (get_singleton()->generate_cs_editor_project(path_elem->get(), path_elem->next()->get()) != OK)
|
|
||||||
ERR_PRINT("Generation of solution and C# project for the Editor API failed");
|
|
||||||
elem = path_elem->next();
|
|
||||||
} else {
|
|
||||||
ERR_PRINTS(cs_editor_api_option + ": No hint path for the Core API dll specified");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ERR_PRINTS(cs_editor_api_option + ": No output directory specified");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--options_left;
|
--options_left;
|
||||||
|
@ -2434,7 +2446,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
|
||||||
verbose_output = false;
|
verbose_output = false;
|
||||||
|
|
||||||
if (options_left != NUM_OPTIONS)
|
if (options_left != NUM_OPTIONS)
|
||||||
exit(0);
|
::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define BINDINGS_GENERATOR_H
|
#define BINDINGS_GENERATOR_H
|
||||||
|
|
||||||
#include "core/class_db.h"
|
#include "core/class_db.h"
|
||||||
|
#include "dotnet_solution.h"
|
||||||
#include "editor/doc/doc_data.h"
|
#include "editor/doc/doc_data.h"
|
||||||
#include "editor/editor_help.h"
|
#include "editor/editor_help.h"
|
||||||
|
|
||||||
|
@ -556,8 +557,9 @@ class BindingsGenerator {
|
||||||
static BindingsGenerator *singleton;
|
static BindingsGenerator *singleton;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Error generate_cs_core_project(const String &p_output_dir, bool p_verbose_output = true);
|
Error generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true);
|
||||||
Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true);
|
Error generate_cs_editor_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output = true);
|
||||||
|
Error generate_cs_api(const String &p_output_dir, bool p_verbose_output = true);
|
||||||
Error generate_glue(const String &p_output_dir);
|
Error generate_glue(const String &p_output_dir);
|
||||||
|
|
||||||
static uint32_t get_version();
|
static uint32_t get_version();
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include "csharp_project.h"
|
#include "csharp_project.h"
|
||||||
|
|
||||||
#include "core/io/json.h"
|
#include "core/io/json.h"
|
||||||
|
#include "core/os/dir_access.h"
|
||||||
|
#include "core/os/file_access.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/project_settings.h"
|
#include "core/project_settings.h"
|
||||||
|
|
||||||
|
@ -62,16 +64,16 @@ String generate_core_api_project(const String &p_dir, const Vector<String> &p_fi
|
||||||
return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
|
return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files) {
|
String generate_editor_api_project(const String &p_dir, const String &p_core_proj_path, const Vector<String> &p_files) {
|
||||||
|
|
||||||
_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
|
_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
|
||||||
|
|
||||||
GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
|
GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
|
||||||
|
|
||||||
Variant dir = p_dir;
|
Variant dir = p_dir;
|
||||||
Variant core_dll_path = p_core_dll_path;
|
Variant core_proj_path = p_core_proj_path;
|
||||||
Variant compile_items = p_files;
|
Variant compile_items = p_files;
|
||||||
const Variant *args[3] = { &dir, &core_dll_path, &compile_items };
|
const Variant *args[3] = { &dir, &core_proj_path, &compile_items };
|
||||||
MonoException *exc = NULL;
|
MonoException *exc = NULL;
|
||||||
MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &exc);
|
MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &exc);
|
||||||
|
|
||||||
|
@ -127,6 +129,14 @@ Error generate_scripts_metadata(const String &p_project_path, const String &p_ou
|
||||||
|
|
||||||
_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
|
_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
|
||||||
|
|
||||||
|
if (FileAccess::exists(p_output_path)) {
|
||||||
|
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||||
|
Error rm_err = da->remove(p_output_path);
|
||||||
|
|
||||||
|
ERR_EXPLAIN("Failed to remove old scripts metadata file");
|
||||||
|
ERR_FAIL_COND_V(rm_err != OK, rm_err);
|
||||||
|
}
|
||||||
|
|
||||||
GDMonoClass *project_utils = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectUtils");
|
GDMonoClass *project_utils = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectUtils");
|
||||||
|
|
||||||
void *args[2] = {
|
void *args[2] = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* net_solution.cpp */
|
/* dotnet_solution.cpp */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* This file is part of: */
|
/* This file is part of: */
|
||||||
/* GODOT ENGINE */
|
/* GODOT ENGINE */
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "net_solution.h"
|
#include "dotnet_solution.h"
|
||||||
|
|
||||||
#include "core/os/dir_access.h"
|
#include "core/os/dir_access.h"
|
||||||
#include "core/os/file_access.h"
|
#include "core/os/file_access.h"
|
||||||
|
@ -58,27 +58,26 @@
|
||||||
"\t\t{%0}.%1|Any CPU.ActiveCfg = %1|Any CPU\n" \
|
"\t\t{%0}.%1|Any CPU.ActiveCfg = %1|Any CPU\n" \
|
||||||
"\t\t{%0}.%1|Any CPU.Build.0 = %1|Any CPU"
|
"\t\t{%0}.%1|Any CPU.Build.0 = %1|Any CPU"
|
||||||
|
|
||||||
void NETSolution::add_new_project(const String &p_name, const String &p_guid, const Vector<String> &p_extra_configs) {
|
void DotNetSolution::add_new_project(const String &p_name, const ProjectInfo &p_project_info) {
|
||||||
if (projects.has(p_name))
|
projects[p_name] = p_project_info;
|
||||||
WARN_PRINT("Overriding existing project.");
|
|
||||||
|
|
||||||
ProjectInfo procinfo;
|
|
||||||
procinfo.guid = p_guid;
|
|
||||||
|
|
||||||
procinfo.configs.push_back("Debug");
|
|
||||||
procinfo.configs.push_back("Release");
|
|
||||||
|
|
||||||
for (int i = 0; i < p_extra_configs.size(); i++) {
|
|
||||||
procinfo.configs.push_back(p_extra_configs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
projects[p_name] = procinfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error NETSolution::save() {
|
bool DotNetSolution::has_project(const String &p_name) const {
|
||||||
|
return projects.find(p_name) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DotNetSolution::ProjectInfo &DotNetSolution::get_project_info(const String &p_name) const {
|
||||||
|
return projects[p_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DotNetSolution::remove_project(const String &p_name) {
|
||||||
|
return projects.erase(p_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error DotNetSolution::save() {
|
||||||
bool dir_exists = DirAccess::exists(path);
|
bool dir_exists = DirAccess::exists(path);
|
||||||
ERR_EXPLAIN("The directory does not exist.");
|
ERR_EXPLAIN("The directory does not exist.");
|
||||||
ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
|
ERR_FAIL_COND_V(!dir_exists, ERR_FILE_NOT_FOUND);
|
||||||
|
|
||||||
String projs_decl;
|
String projs_decl;
|
||||||
String sln_platform_cfg;
|
String sln_platform_cfg;
|
||||||
|
@ -86,34 +85,40 @@ Error NETSolution::save() {
|
||||||
|
|
||||||
for (Map<String, ProjectInfo>::Element *E = projects.front(); E; E = E->next()) {
|
for (Map<String, ProjectInfo>::Element *E = projects.front(); E; E = E->next()) {
|
||||||
const String &name = E->key();
|
const String &name = E->key();
|
||||||
const ProjectInfo &procinfo = E->value();
|
const ProjectInfo &proj_info = E->value();
|
||||||
|
|
||||||
projs_decl += sformat(PROJECT_DECLARATION, name, name + ".csproj", procinfo.guid);
|
bool is_front = E == projects.front();
|
||||||
|
|
||||||
for (int i = 0; i < procinfo.configs.size(); i++) {
|
if (!is_front)
|
||||||
const String &config = procinfo.configs[i];
|
projs_decl += "\n";
|
||||||
|
|
||||||
if (i != 0) {
|
projs_decl += sformat(PROJECT_DECLARATION, name, proj_info.relpath.replace("/", "\\"), proj_info.guid);
|
||||||
|
|
||||||
|
for (int i = 0; i < proj_info.configs.size(); i++) {
|
||||||
|
const String &config = proj_info.configs[i];
|
||||||
|
|
||||||
|
if (i != 0 || !is_front) {
|
||||||
sln_platform_cfg += "\n";
|
sln_platform_cfg += "\n";
|
||||||
proj_platform_cfg += "\n";
|
proj_platform_cfg += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
sln_platform_cfg += sformat(SOLUTION_PLATFORMS_CONFIG, config);
|
sln_platform_cfg += sformat(SOLUTION_PLATFORMS_CONFIG, config);
|
||||||
proj_platform_cfg += sformat(PROJECT_PLATFORMS_CONFIG, procinfo.guid, config);
|
proj_platform_cfg += sformat(PROJECT_PLATFORMS_CONFIG, proj_info.guid, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String content = sformat(SOLUTION_TEMPLATE, projs_decl, sln_platform_cfg, proj_platform_cfg);
|
String content = sformat(SOLUTION_TEMPLATE, projs_decl, sln_platform_cfg, proj_platform_cfg);
|
||||||
|
|
||||||
FileAccessRef file = FileAccess::open(path_join(path, name + ".sln"), FileAccess::WRITE);
|
FileAccess *file = FileAccess::open(path_join(path, name + ".sln"), FileAccess::WRITE);
|
||||||
ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
|
ERR_FAIL_NULL_V(file, ERR_FILE_CANT_WRITE);
|
||||||
file->store_string(content);
|
file->store_string(content);
|
||||||
file->close();
|
file->close();
|
||||||
|
memdelete(file);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NETSolution::set_path(const String &p_existing_path) {
|
bool DotNetSolution::set_path(const String &p_existing_path) {
|
||||||
if (p_existing_path.is_abs_path()) {
|
if (p_existing_path.is_abs_path()) {
|
||||||
path = p_existing_path;
|
path = p_existing_path;
|
||||||
} else {
|
} else {
|
||||||
|
@ -126,6 +131,10 @@ bool NETSolution::set_path(const String &p_existing_path) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NETSolution::NETSolution(const String &p_name) {
|
String DotNetSolution::get_path() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
DotNetSolution::DotNetSolution(const String &p_name) {
|
||||||
name = p_name;
|
name = p_name;
|
||||||
}
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* net_solution.h */
|
/* dotnet_solution.h */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* This file is part of: */
|
/* This file is part of: */
|
||||||
/* GODOT ENGINE */
|
/* GODOT ENGINE */
|
||||||
|
@ -34,23 +34,28 @@
|
||||||
#include "core/map.h"
|
#include "core/map.h"
|
||||||
#include "core/ustring.h"
|
#include "core/ustring.h"
|
||||||
|
|
||||||
struct NETSolution {
|
struct DotNetSolution {
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
void add_new_project(const String &p_name, const String &p_guid, const Vector<String> &p_extra_configs = Vector<String>());
|
struct ProjectInfo {
|
||||||
|
String guid;
|
||||||
|
String relpath; // Must be relative to the solution directory
|
||||||
|
Vector<String> configs;
|
||||||
|
};
|
||||||
|
|
||||||
|
void add_new_project(const String &p_name, const ProjectInfo &p_project_info);
|
||||||
|
bool has_project(const String &p_name) const;
|
||||||
|
const ProjectInfo &get_project_info(const String &p_name) const;
|
||||||
|
bool remove_project(const String &p_name);
|
||||||
|
|
||||||
Error save();
|
Error save();
|
||||||
|
|
||||||
bool set_path(const String &p_existing_path);
|
bool set_path(const String &p_existing_path);
|
||||||
|
String get_path();
|
||||||
|
|
||||||
NETSolution(const String &p_name);
|
DotNetSolution(const String &p_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ProjectInfo {
|
|
||||||
String guid;
|
|
||||||
Vector<String> configs;
|
|
||||||
};
|
|
||||||
|
|
||||||
String path;
|
String path;
|
||||||
Map<String, ProjectInfo> projects;
|
Map<String, ProjectInfo> projects;
|
||||||
};
|
};
|
|
@ -227,20 +227,24 @@ void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
|
||||||
MonoBottomPanel::get_singleton()->show_build_tab();
|
MonoBottomPanel::get_singleton()->show_build_tab();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config) {
|
bool GodotSharpBuilds::build_api_sln(const String &p_api_sln_dir, const String &p_config) {
|
||||||
|
|
||||||
String api_sln_file = p_api_sln_dir.plus_file(p_name + ".sln");
|
String api_sln_file = p_api_sln_dir.plus_file(API_SOLUTION_NAME ".sln");
|
||||||
String api_assembly_dir = p_api_sln_dir.plus_file("bin").plus_file(p_config);
|
|
||||||
String api_assembly_file = api_assembly_dir.plus_file(p_name + ".dll");
|
|
||||||
|
|
||||||
if (!FileAccess::exists(api_assembly_file)) {
|
String core_api_assembly_dir = p_api_sln_dir.plus_file(CORE_API_ASSEMBLY_NAME).plus_file("bin").plus_file(p_config);
|
||||||
|
String core_api_assembly_file = core_api_assembly_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
|
||||||
|
|
||||||
|
String editor_api_assembly_dir = p_api_sln_dir.plus_file(EDITOR_API_ASSEMBLY_NAME).plus_file("bin").plus_file(p_config);
|
||||||
|
String editor_api_assembly_file = editor_api_assembly_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
|
||||||
|
|
||||||
|
if (!FileAccess::exists(core_api_assembly_file) || !FileAccess::exists(editor_api_assembly_file)) {
|
||||||
MonoBuildInfo api_build_info(api_sln_file, p_config);
|
MonoBuildInfo api_build_info(api_sln_file, p_config);
|
||||||
// TODO Replace this global NoWarn with '#pragma warning' directives on generated files,
|
// TODO Replace this global NoWarn with '#pragma warning' directives on generated files,
|
||||||
// once we start to actively document manually maintained C# classes
|
// once we start to actively document manually maintained C# classes
|
||||||
api_build_info.custom_props.push_back("NoWarn=1591"); // Ignore missing documentation warnings
|
api_build_info.custom_props.push_back("NoWarn=1591"); // Ignore missing documentation warnings
|
||||||
|
|
||||||
if (!GodotSharpBuilds::get_singleton()->build(api_build_info)) {
|
if (!GodotSharpBuilds::get_singleton()->build(api_build_info)) {
|
||||||
show_build_error_dialog("Failed to build " + p_name + " solution.");
|
show_build_error_dialog("Failed to build " API_SOLUTION_NAME " solution.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,9 +306,9 @@ String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) {
|
||||||
"_" + String::num_uint64(CS_GLUE_VERSION);
|
"_" + String::num_uint64(CS_GLUE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
|
bool GodotSharpBuilds::make_api_assembly(APIAssembly::Type p_api_type) {
|
||||||
|
|
||||||
String api_name = p_api_type == APIAssembly::API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
|
String api_name = p_api_type == APIAssembly::API_CORE ? CORE_API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
|
||||||
|
|
||||||
String editor_prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir();
|
String editor_prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir();
|
||||||
String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
|
String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
|
||||||
|
@ -317,55 +321,35 @@ bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
|
||||||
|
|
||||||
String api_build_config = "Release";
|
String api_build_config = "Release";
|
||||||
|
|
||||||
EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 3);
|
EditorProgress pr("mono_build_release_" API_SOLUTION_NAME, "Building " API_SOLUTION_NAME " solution...", 3);
|
||||||
|
|
||||||
pr.step("Generating " + api_name + " solution", 0);
|
pr.step("Generating " API_SOLUTION_NAME " solution", 0);
|
||||||
|
|
||||||
String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
|
String api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
|
||||||
.plus_file(_api_folder_name(APIAssembly::API_CORE))
|
.plus_file(_api_folder_name(APIAssembly::API_CORE));
|
||||||
.plus_file(API_ASSEMBLY_NAME);
|
|
||||||
String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir()
|
|
||||||
.plus_file(_api_folder_name(APIAssembly::API_EDITOR))
|
|
||||||
.plus_file(EDITOR_API_ASSEMBLY_NAME);
|
|
||||||
|
|
||||||
String api_sln_dir = p_api_type == APIAssembly::API_CORE ? core_api_sln_dir : editor_api_sln_dir;
|
String api_sln_file = api_sln_dir.plus_file(API_SOLUTION_NAME ".sln");
|
||||||
String api_sln_file = api_sln_dir.plus_file(api_name + ".sln");
|
|
||||||
|
|
||||||
if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) {
|
if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) {
|
||||||
String core_api_assembly;
|
|
||||||
|
|
||||||
if (p_api_type == APIAssembly::API_EDITOR) {
|
|
||||||
core_api_assembly = core_api_sln_dir.plus_file("bin")
|
|
||||||
.plus_file(api_build_config)
|
|
||||||
.plus_file(API_ASSEMBLY_NAME ".dll");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DEBUG_METHODS_ENABLED
|
|
||||||
#error "How am I supposed to generate the bindings?"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BindingsGenerator *gen = BindingsGenerator::get_singleton();
|
BindingsGenerator *gen = BindingsGenerator::get_singleton();
|
||||||
bool gen_verbose = OS::get_singleton()->is_stdout_verbose();
|
bool gen_verbose = OS::get_singleton()->is_stdout_verbose();
|
||||||
|
|
||||||
Error err = p_api_type == APIAssembly::API_CORE ?
|
Error err = gen->generate_cs_api(api_sln_dir, gen_verbose);
|
||||||
gen->generate_cs_core_project(api_sln_dir, gen_verbose) :
|
|
||||||
gen->generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose);
|
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
show_build_error_dialog("Failed to generate " + api_name + " solution. Error: " + itos(err));
|
show_build_error_dialog("Failed to generate " API_SOLUTION_NAME " solution. Error: " + itos(err));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr.step("Building " + api_name + " solution", 1);
|
pr.step("Building " API_SOLUTION_NAME " solution", 1);
|
||||||
|
|
||||||
if (!GodotSharpBuilds::build_api_sln(api_name, api_sln_dir, api_build_config))
|
if (!GodotSharpBuilds::build_api_sln(api_sln_dir, api_build_config))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pr.step("Copying " + api_name + " assembly", 2);
|
pr.step("Copying " + api_name + " assembly", 2);
|
||||||
|
|
||||||
// Copy the built assembly to the assemblies directory
|
// Copy the built assembly to the assemblies directory
|
||||||
String api_assembly_dir = api_sln_dir.plus_file("bin").plus_file(api_build_config);
|
String api_assembly_dir = api_sln_dir.plus_file(api_name).plus_file("bin").plus_file(api_build_config);
|
||||||
if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type))
|
if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name, p_api_type))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -377,10 +361,10 @@ bool GodotSharpBuilds::build_project_blocking(const String &p_config) {
|
||||||
if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path()))
|
if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path()))
|
||||||
return true; // No solution to build
|
return true; // No solution to build
|
||||||
|
|
||||||
if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
|
if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
|
if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
EditorProgress pr("mono_project_debug_build", "Building project solution...", 1);
|
EditorProgress pr("mono_project_debug_build", "Building project solution...", 1);
|
||||||
|
@ -403,11 +387,13 @@ bool GodotSharpBuilds::editor_build_callback() {
|
||||||
Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path_editor);
|
Error metadata_err = CSharpProject::generate_scripts_metadata(GodotSharpDirs::get_project_csproj_path(), scripts_metadata_path_editor);
|
||||||
ERR_FAIL_COND_V(metadata_err != OK, false);
|
ERR_FAIL_COND_V(metadata_err != OK, false);
|
||||||
|
|
||||||
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
if (FileAccess::exists(scripts_metadata_path_editor)) {
|
||||||
Error copy_err = da->copy(scripts_metadata_path_editor, scripts_metadata_path_player);
|
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||||
|
Error copy_err = da->copy(scripts_metadata_path_editor, scripts_metadata_path_player);
|
||||||
|
|
||||||
ERR_EXPLAIN("Failed to copy scripts metadata file");
|
ERR_EXPLAIN("Failed to copy scripts metadata file");
|
||||||
ERR_FAIL_COND_V(copy_err != OK, false);
|
ERR_FAIL_COND_V(copy_err != OK, false);
|
||||||
|
}
|
||||||
|
|
||||||
return build_project_blocking("Tools");
|
return build_project_blocking("Tools");
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,10 +84,10 @@ public:
|
||||||
bool build(const MonoBuildInfo &p_build_info);
|
bool build(const MonoBuildInfo &p_build_info);
|
||||||
bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL);
|
bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL);
|
||||||
|
|
||||||
static bool build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config);
|
static bool build_api_sln(const String &p_api_sln_dir, const String &p_config);
|
||||||
static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type);
|
static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type);
|
||||||
|
|
||||||
static bool make_api_sln(APIAssembly::Type p_api_type);
|
static bool make_api_assembly(APIAssembly::Type p_api_type);
|
||||||
|
|
||||||
static bool build_project_blocking(const String &p_config);
|
static bool build_project_blocking(const String &p_config);
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
#include "../utils/path_utils.h"
|
#include "../utils/path_utils.h"
|
||||||
#include "bindings_generator.h"
|
#include "bindings_generator.h"
|
||||||
#include "csharp_project.h"
|
#include "csharp_project.h"
|
||||||
|
#include "dotnet_solution.h"
|
||||||
#include "godotsharp_export.h"
|
#include "godotsharp_export.h"
|
||||||
#include "net_solution.h"
|
|
||||||
|
|
||||||
#ifdef OSX_ENABLED
|
#ifdef OSX_ENABLED
|
||||||
#include "../utils/osx_utils.h"
|
#include "../utils/osx_utils.h"
|
||||||
|
@ -71,17 +71,21 @@ bool GodotSharpEditor::_create_project_solution() {
|
||||||
|
|
||||||
if (guid.length()) {
|
if (guid.length()) {
|
||||||
|
|
||||||
NETSolution solution(name);
|
DotNetSolution solution(name);
|
||||||
|
|
||||||
if (!solution.set_path(path)) {
|
if (!solution.set_path(path)) {
|
||||||
show_error_dialog(TTR("Failed to create solution."));
|
show_error_dialog(TTR("Failed to create solution."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String> extra_configs;
|
DotNetSolution::ProjectInfo proj_info;
|
||||||
extra_configs.push_back("Tools");
|
proj_info.guid = guid;
|
||||||
|
proj_info.relpath = name + ".csproj";
|
||||||
|
proj_info.configs.push_back("Debug");
|
||||||
|
proj_info.configs.push_back("Release");
|
||||||
|
proj_info.configs.push_back("Tools");
|
||||||
|
|
||||||
solution.add_new_project(name, guid, extra_configs);
|
solution.add_new_project(name, proj_info);
|
||||||
|
|
||||||
Error sln_error = solution.save();
|
Error sln_error = solution.save();
|
||||||
|
|
||||||
|
@ -90,10 +94,10 @@ bool GodotSharpEditor::_create_project_solution() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
|
if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
|
if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pr.step(TTR("Done"));
|
pr.step(TTR("Done"));
|
||||||
|
@ -122,15 +126,15 @@ void GodotSharpEditor::_make_api_solutions_if_needed_impl() {
|
||||||
// If the project has a solution and C# project make sure the API assemblies are present and up to date
|
// If the project has a solution and C# project make sure the API assemblies are present and up to date
|
||||||
String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
|
String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
|
||||||
|
|
||||||
if (!FileAccess::exists(res_assemblies_dir.plus_file(API_ASSEMBLY_NAME ".dll")) ||
|
if (!FileAccess::exists(res_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll")) ||
|
||||||
GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) {
|
GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) {
|
||||||
if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_CORE))
|
if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_CORE))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FileAccess::exists(res_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll")) ||
|
if (!FileAccess::exists(res_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll")) ||
|
||||||
GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
|
GDMono::get_singleton()->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
|
||||||
if (!GodotSharpBuilds::make_api_sln(APIAssembly::API_EDITOR))
|
if (!GodotSharpBuilds::make_api_assembly(APIAssembly::API_EDITOR))
|
||||||
return; // Redundant? I don't think so
|
return; // Redundant? I don't think so
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@
|
||||||
#define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
|
#define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
|
||||||
#define BINDINGS_PTR_FIELD "ptr"
|
#define BINDINGS_PTR_FIELD "ptr"
|
||||||
#define BINDINGS_NATIVE_NAME_FIELD "nativeName"
|
#define BINDINGS_NATIVE_NAME_FIELD "nativeName"
|
||||||
#define API_ASSEMBLY_NAME "GodotSharp"
|
#define API_SOLUTION_NAME "GodotSharp"
|
||||||
|
#define CORE_API_ASSEMBLY_NAME "GodotSharp"
|
||||||
#define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor"
|
#define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor"
|
||||||
#define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools"
|
#define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools"
|
||||||
|
|
||||||
|
|
|
@ -496,12 +496,12 @@ bool GDMono::_load_core_api_assembly() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(API_ASSEMBLY_NAME ".dll");
|
String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(CORE_API_ASSEMBLY_NAME ".dll");
|
||||||
|
|
||||||
if (!FileAccess::exists(assembly_path))
|
if (!FileAccess::exists(assembly_path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool success = load_assembly_from(API_ASSEMBLY_NAME,
|
bool success = load_assembly_from(CORE_API_ASSEMBLY_NAME,
|
||||||
assembly_path,
|
assembly_path,
|
||||||
&core_api_assembly);
|
&core_api_assembly);
|
||||||
|
|
||||||
|
@ -635,7 +635,7 @@ void GDMono::metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type,
|
||||||
|
|
||||||
String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
|
String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
|
||||||
.plus_file(p_api_type == APIAssembly::API_CORE ?
|
.plus_file(p_api_type == APIAssembly::API_CORE ?
|
||||||
API_ASSEMBLY_NAME ".dll" :
|
CORE_API_ASSEMBLY_NAME ".dll" :
|
||||||
EDITOR_API_ASSEMBLY_NAME ".dll");
|
EDITOR_API_ASSEMBLY_NAME ".dll");
|
||||||
|
|
||||||
ERR_FAIL_COND(!FileAccess::exists(assembly_path));
|
ERR_FAIL_COND(!FileAccess::exists(assembly_path));
|
||||||
|
@ -666,7 +666,7 @@ bool GDMono::metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type)
|
||||||
|
|
||||||
String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
|
String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
|
||||||
.plus_file(p_api_type == APIAssembly::API_CORE ?
|
.plus_file(p_api_type == APIAssembly::API_CORE ?
|
||||||
API_ASSEMBLY_NAME ".dll" :
|
CORE_API_ASSEMBLY_NAME ".dll" :
|
||||||
EDITOR_API_ASSEMBLY_NAME ".dll");
|
EDITOR_API_ASSEMBLY_NAME ".dll");
|
||||||
|
|
||||||
if (!FileAccess::exists(assembly_path))
|
if (!FileAccess::exists(assembly_path))
|
||||||
|
|
|
@ -631,36 +631,36 @@ void set_pending_exception(MonoException *p_exc) {
|
||||||
_THREAD_LOCAL_(int)
|
_THREAD_LOCAL_(int)
|
||||||
current_invoke_count = 0;
|
current_invoke_count = 0;
|
||||||
|
|
||||||
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **p_exc) {
|
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc) {
|
||||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||||
MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)p_exc);
|
MonoObject *ret = mono_runtime_invoke(p_method, p_obj, p_params, (MonoObject **)r_exc);
|
||||||
GD_MONO_END_RUNTIME_INVOKE;
|
GD_MONO_END_RUNTIME_INVOKE;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **p_exc) {
|
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
|
||||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||||
MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)p_exc);
|
MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
|
||||||
GD_MONO_END_RUNTIME_INVOKE;
|
GD_MONO_END_RUNTIME_INVOKE;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoString *object_to_string(MonoObject *p_obj, MonoException **p_exc) {
|
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
|
||||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||||
MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)p_exc);
|
MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);
|
||||||
GD_MONO_END_RUNTIME_INVOKE;
|
GD_MONO_END_RUNTIME_INVOKE;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc) {
|
void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
|
||||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||||
mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)p_exc);
|
mono_property_set_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
|
||||||
GD_MONO_END_RUNTIME_INVOKE;
|
GD_MONO_END_RUNTIME_INVOKE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc) {
|
MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc) {
|
||||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||||
MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)p_exc);
|
MonoObject *ret = mono_property_get_value(p_prop, p_obj, p_params, (MonoObject **)r_exc);
|
||||||
GD_MONO_END_RUNTIME_INVOKE;
|
GD_MONO_END_RUNTIME_INVOKE;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,13 +233,13 @@ _FORCE_INLINE_ int &get_runtime_invoke_count_ref() {
|
||||||
return current_invoke_count;
|
return current_invoke_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **p_exc);
|
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc);
|
||||||
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **p_exc);
|
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc);
|
||||||
|
|
||||||
MonoString *object_to_string(MonoObject *p_obj, MonoException **p_exc);
|
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc);
|
||||||
|
|
||||||
void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc);
|
void property_set_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc);
|
||||||
MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **p_exc);
|
MonoObject *property_get_value(MonoProperty *p_prop, void *p_obj, void **p_params, MonoException **r_exc);
|
||||||
|
|
||||||
uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error);
|
uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &r_error);
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ void fix_path(const String &p_path, String &r_out) {
|
||||||
bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
|
bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
|
||||||
#ifdef WINDOWS_ENABLED
|
#ifdef WINDOWS_ENABLED
|
||||||
CharType ret[_MAX_PATH];
|
CharType ret[_MAX_PATH];
|
||||||
if (_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
|
if (::_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
|
||||||
String abspath = String(ret).replace("\\", "/");
|
String abspath = String(ret).replace("\\", "/");
|
||||||
int pos = abspath.find(":/");
|
int pos = abspath.find(":/");
|
||||||
if (pos != -1) {
|
if (pos != -1) {
|
||||||
|
@ -99,10 +99,12 @@ bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
char ret[PATH_MAX];
|
char *resolved_path = ::realpath(p_existing_path.utf8().get_data(), NULL);
|
||||||
if (realpath(p_existing_path.utf8().get_data(), ret)) {
|
if (resolved_path) {
|
||||||
String retstr;
|
String retstr;
|
||||||
if (!retstr.parse_utf8(ret)) {
|
bool success = !retstr.parse_utf8(resolved_path);
|
||||||
|
::free(resolved_path);
|
||||||
|
if (success) {
|
||||||
r_abs_path = retstr;
|
r_abs_path = retstr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue