Fix --generate-mono-glue bug when directory doesn't exist

DirAccess::get_full_path(path) only works if the path exists. Implement our own abspath function.
This commit is contained in:
Ignacio Etcheverry 2019-07-08 15:16:35 +02:00
parent 2c83255013
commit 5ed3d34cd9
4 changed files with 132 additions and 65 deletions

View file

@ -875,14 +875,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
da->make_dir("Core"); da->make_dir("Core");
da->make_dir("ObjectType"); da->make_dir("ObjectType");
String core_dir = path_join(p_proj_dir, "Core"); String core_dir = path::join(p_proj_dir, "Core");
String obj_type_dir = path_join(p_proj_dir, "ObjectType"); String obj_type_dir = path::join(p_proj_dir, "ObjectType");
// Generate source file for global scope constants and enums // Generate source file for global scope constants and enums
{ {
StringBuilder constants_source; StringBuilder constants_source;
_generate_global_constants(constants_source); _generate_global_constants(constants_source);
String output_file = path_join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs"); String output_file = path::join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs");
Error save_err = _save_file(output_file, constants_source); Error save_err = _save_file(output_file, constants_source);
if (save_err != OK) if (save_err != OK)
return save_err; return save_err;
@ -896,7 +896,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
if (itype.api_type == ClassDB::API_EDITOR) if (itype.api_type == ClassDB::API_EDITOR)
continue; continue;
String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); String output_file = path::join(obj_type_dir, itype.proxy_name + ".cs");
Error err = _generate_cs_type(itype, output_file); Error err = _generate_cs_type(itype, output_file);
if (err == ERR_SKIP) if (err == ERR_SKIP)
@ -917,7 +917,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
const String &file_name = E->key(); const String &file_name = E->key();
const GodotCsCompressedFile &file_data = E->value(); const GodotCsCompressedFile &file_data = E->value();
String output_file = path_join(core_dir, file_name); String output_file = path::join(core_dir, file_name);
Vector<uint8_t> data; Vector<uint8_t> data;
data.resize(file_data.uncompressed_size); data.resize(file_data.uncompressed_size);
@ -971,7 +971,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect
cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); String internal_methods_file = path::join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs");
Error err = _save_file(internal_methods_file, cs_icalls_content); Error err = _save_file(internal_methods_file, cs_icalls_content);
if (err != OK) if (err != OK)
@ -996,8 +996,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
da->make_dir("Core"); da->make_dir("Core");
da->make_dir("ObjectType"); da->make_dir("ObjectType");
String core_dir = path_join(p_proj_dir, "Core"); String core_dir = path::join(p_proj_dir, "Core");
String obj_type_dir = path_join(p_proj_dir, "ObjectType"); String obj_type_dir = path::join(p_proj_dir, "ObjectType");
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();
@ -1005,7 +1005,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
if (itype.api_type != ClassDB::API_EDITOR) if (itype.api_type != ClassDB::API_EDITOR)
continue; continue;
String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); String output_file = path::join(obj_type_dir, itype.proxy_name + ".cs");
Error err = _generate_cs_type(itype, output_file); Error err = _generate_cs_type(itype, output_file);
if (err == ERR_SKIP) if (err == ERR_SKIP)
@ -1051,7 +1051,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs"); String internal_methods_file = path::join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs");
Error err = _save_file(internal_methods_file, cs_icalls_content); Error err = _save_file(internal_methods_file, cs_icalls_content);
if (err != OK) if (err != OK)
@ -1064,7 +1064,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve
Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { Error BindingsGenerator::generate_cs_api(const String &p_output_dir) {
String output_dir = DirAccess::get_full_path(p_output_dir, DirAccess::ACCESS_FILESYSTEM); String output_dir = path::abspath(path::realpath(p_output_dir));
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);
@ -1862,7 +1862,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.append("\n#endif // MONO_GLUE_ENABLED\n"); output.append("\n#endif // MONO_GLUE_ENABLED\n");
Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output); Error save_err = _save_file(path::join(p_output_dir, "mono_glue.gen.cpp"), output);
if (save_err != OK) if (save_err != OK)
return save_err; return save_err;

View file

@ -241,9 +241,9 @@ void GDMono::initialize() {
locations.push_back("/usr/local/var/homebrew/linked/mono/"); locations.push_back("/usr/local/var/homebrew/linked/mono/");
for (int i = 0; i < locations.size(); i++) { for (int i = 0; i < locations.size(); i++) {
String hint_assembly_rootdir = path_join(locations[i], "lib"); String hint_assembly_rootdir = path::join(locations[i], "lib");
String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll"); String hint_mscorlib_path = path::join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll");
String hint_config_dir = path_join(locations[i], "etc"); String hint_config_dir = path::join(locations[i], "etc");
if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) { if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) {
assembly_rootdir = hint_assembly_rootdir; assembly_rootdir = hint_assembly_rootdir;

View file

@ -36,16 +36,21 @@
#include "core/project_settings.h" #include "core/project_settings.h"
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
#include <windows.h>
#define ENV_PATH_SEP ";" #define ENV_PATH_SEP ";"
#else #else
#define ENV_PATH_SEP ":"
#include <limits.h> #include <limits.h>
#include <unistd.h>
#define ENV_PATH_SEP ":"
#endif #endif
#include <stdlib.h> #include <stdlib.h>
String path_which(const String &p_name) { namespace path {
String find_executable(const String &p_name) {
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
Vector<String> exts = OS::get_singleton()->get_environment("PATHEXT").split(ENV_PATH_SEP, false); Vector<String> exts = OS::get_singleton()->get_environment("PATHEXT").split(ENV_PATH_SEP, false);
#endif #endif
@ -55,7 +60,7 @@ String path_which(const String &p_name) {
return String(); return String();
for (int i = 0; i < env_path.size(); i++) { for (int i = 0; i < env_path.size(); i++) {
String p = path_join(env_path[i], p_name); String p = path::join(env_path[i], p_name);
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
for (int j = 0; j < exts.size(); j++) { for (int j = 0; j < exts.size(); j++) {
@ -73,42 +78,96 @@ String path_which(const String &p_name) {
return String(); return String();
} }
void fix_path(const String &p_path, String &r_out) { String cwd() {
r_out = p_path.replace("\\", "/");
while (true) { // in case of using 2 or more slash
String compare = r_out.replace("//", "/");
if (r_out == compare)
break;
else
r_out = compare;
}
}
bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
CharType ret[_MAX_PATH]; const DWORD expected_size = ::GetCurrentDirectoryW(0, NULL);
if (::_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
String abspath = String(ret).replace("\\", "/"); String buffer;
int pos = abspath.find(":/"); buffer.resize((int)expected_size);
if (pos != -1) { if (::GetCurrentDirectoryW(expected_size, buffer.ptrw()) == 0)
r_abs_path = abspath.substr(pos - 1, abspath.length()); return ".";
} else {
r_abs_path = abspath; return buffer.simplify_path();
}
return true;
}
#else #else
char *resolved_path = ::realpath(p_existing_path.utf8().get_data(), NULL); char buffer[PATH_MAX];
if (resolved_path) { if (::getcwd(buffer, sizeof(buffer)) == NULL)
String retstr; return ".";
bool success = !retstr.parse_utf8(resolved_path);
::free(resolved_path); String result;
if (success) { if (result.parse_utf8(buffer))
r_abs_path = retstr; return ".";
return true;
} return result.simplify_path();
}
#endif #endif
return false;
} }
String abspath(const String &p_path) {
if (p_path.is_abs_path()) {
return p_path.simplify_path();
} else {
return path::join(path::cwd(), p_path).simplify_path();
}
}
String realpath(const String &p_path) {
#ifdef WINDOWS_ENABLED
// Open file without read/write access
HANDLE hFile = ::CreateFileW(p_path.c_str(), 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return p_path;
const DWORD expected_size = ::GetFinalPathNameByHandleW(hFile, NULL, 0, FILE_NAME_NORMALIZED);
if (expected_size == 0) {
::CloseHandle(hFile);
return p_path;
}
String buffer;
buffer.resize((int)expected_size);
::GetFinalPathNameByHandleW(hFile, buffer.ptrw(), expected_size, FILE_NAME_NORMALIZED);
::CloseHandle(hFile);
return buffer.simplify_path();
#elif UNIX_ENABLED
char *resolved_path = ::realpath(p_path.utf8().get_data(), NULL);
if (!resolved_path)
return p_path;
String result;
bool parse_ok = result.parse_utf8(resolved_path);
::free(resolved_path);
if (parse_ok)
return p_path;
return result.simplify_path();
#endif
}
String join(const String &p_a, const String &p_b) {
if (p_a.empty())
return p_b;
const CharType a_last = p_a[p_a.length() - 1];
if ((a_last == '/' || a_last == '\\') ||
(p_b.size() > 0 && (p_b[0] == '/' || p_b[0] == '\\'))) {
return p_a + p_b;
}
return p_a + "/" + p_b;
}
String join(const String &p_a, const String &p_b, const String &p_c) {
return path::join(path::join(p_a, p_b), p_c);
}
String join(const String &p_a, const String &p_b, const String &p_c, const String &p_d) {
return path::join(path::join(path::join(p_a, p_b), p_c), p_d);
}
} // namespace path

View file

@ -31,24 +31,32 @@
#ifndef PATH_UTILS_H #ifndef PATH_UTILS_H
#define PATH_UTILS_H #define PATH_UTILS_H
#include "core/string_builder.h"
#include "core/ustring.h" #include "core/ustring.h"
_FORCE_INLINE_ String path_join(const String &e1, const String &e2) { namespace path {
return e1.plus_file(e2);
}
_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3) { String join(const String &p_a, const String &p_b);
return e1.plus_file(e2).plus_file(e3); String join(const String &p_a, const String &p_b, const String &p_c);
} String join(const String &p_a, const String &p_b, const String &p_c, const String &p_d);
_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3, const String &e4) { String find_executable(const String &p_name);
return e1.plus_file(e2).plus_file(e3).plus_file(e4);
}
String path_which(const String &p_name); /// Returns a normalized absolute path to the current working directory
String cwd();
void fix_path(const String &p_path, String &r_out); /**
* Obtains a normalized absolute path to p_path. Symbolic links are
* not resolved. The path p_path might not exist in the file system.
*/
String abspath(const String &p_path);
bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path); /**
* Obtains a normalized path to p_path with symbolic links resolved.
* The resulting path might be either a relative or an absolute path.
*/
String realpath(const String &p_path);
} // namespace path
#endif // PATH_UTILS_H #endif // PATH_UTILS_H