Merge pull request #1205 from dsnopek/4.1-cherrypicks-1
Cherry-picks for the godot-cpp 4.1 branch - 1st batchpull/1244/head
commit
28494f0bd5
39
SConstruct
39
SConstruct
|
@ -20,14 +20,19 @@ def normalize_path(val):
|
||||||
return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val)
|
return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val)
|
||||||
|
|
||||||
|
|
||||||
def validate_api_file(key, val, env):
|
def validate_file(key, val, env):
|
||||||
if not os.path.isfile(normalize_path(val)):
|
if not os.path.isfile(normalize_path(val)):
|
||||||
raise UserError("GDExtension API file ('%s') does not exist: %s" % (key, val))
|
raise UserError("'%s' is not a file: %s" % (key, val))
|
||||||
|
|
||||||
|
|
||||||
def validate_gdextension_dir(key, val, env):
|
def validate_dir(key, val, env):
|
||||||
if not os.path.isdir(normalize_path(val)):
|
if not os.path.isdir(normalize_path(val)):
|
||||||
raise UserError("GDExtension directory ('%s') does not exist: %s" % (key, val))
|
raise UserError("'%s' is not a directory: %s" % (key, val))
|
||||||
|
|
||||||
|
|
||||||
|
def validate_parent_dir(key, val, env):
|
||||||
|
if not os.path.isdir(normalize_path(os.path.dirname(val))):
|
||||||
|
raise UserError("'%s' is not a directory: %s" % (key, os.path.dirname(val)))
|
||||||
|
|
||||||
|
|
||||||
def get_gdextension_dir(env):
|
def get_gdextension_dir(env):
|
||||||
|
@ -115,7 +120,7 @@ opts.Add(
|
||||||
key="gdextension_dir",
|
key="gdextension_dir",
|
||||||
help="Path to a custom directory containing GDExtension interface header and API JSON file",
|
help="Path to a custom directory containing GDExtension interface header and API JSON file",
|
||||||
default=env.get("gdextension_dir", None),
|
default=env.get("gdextension_dir", None),
|
||||||
validator=validate_gdextension_dir,
|
validator=validate_dir,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
opts.Add(
|
opts.Add(
|
||||||
|
@ -123,7 +128,7 @@ opts.Add(
|
||||||
key="custom_api_file",
|
key="custom_api_file",
|
||||||
help="Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)",
|
help="Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)",
|
||||||
default=env.get("custom_api_file", None),
|
default=env.get("custom_api_file", None),
|
||||||
validator=validate_api_file,
|
validator=validate_file,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
opts.Add(
|
opts.Add(
|
||||||
|
@ -151,6 +156,23 @@ opts.Add(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# compiledb
|
||||||
|
opts.Add(
|
||||||
|
BoolVariable(
|
||||||
|
key="compiledb",
|
||||||
|
help="Generate compilation DB (`compile_commands.json`) for external tools",
|
||||||
|
default=env.get("compiledb", False),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
opts.Add(
|
||||||
|
PathVariable(
|
||||||
|
key="compiledb_file",
|
||||||
|
help="Path to a custom `compile_commands.json` file",
|
||||||
|
default=env.get("compiledb_file", "compile_commands.json"),
|
||||||
|
validator=validate_parent_dir,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Add platform options
|
# Add platform options
|
||||||
tools = {}
|
tools = {}
|
||||||
for pl in platforms:
|
for pl in platforms:
|
||||||
|
@ -242,6 +264,11 @@ else:
|
||||||
if env["precision"] == "double":
|
if env["precision"] == "double":
|
||||||
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
|
||||||
|
|
||||||
|
# compile_commands.json
|
||||||
|
if env.get("compiledb", False):
|
||||||
|
env.Tool("compilation_db")
|
||||||
|
env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"])))
|
||||||
|
|
||||||
# Generate bindings
|
# Generate bindings
|
||||||
env.Append(BUILDERS={"GenerateBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
|
env.Append(BUILDERS={"GenerateBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)})
|
||||||
|
|
||||||
|
|
|
@ -1453,16 +1453,22 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
|
||||||
|
|
||||||
if is_singleton:
|
if is_singleton:
|
||||||
result.append(f"{class_name} *{class_name}::get_singleton() {{")
|
result.append(f"{class_name} *{class_name}::get_singleton() {{")
|
||||||
result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();")
|
# We assume multi-threaded access is OK because each assignment will assign the same value every time
|
||||||
|
result.append(f"\tstatic {class_name} *singleton = nullptr;")
|
||||||
|
result.append("\tif (unlikely(singleton == nullptr)) {")
|
||||||
result.append(
|
result.append(
|
||||||
"\tstatic GDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton(_gde_class_name._native_ptr());"
|
f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());"
|
||||||
)
|
)
|
||||||
result.append("#ifdef DEBUG_ENABLED")
|
result.append("#ifdef DEBUG_ENABLED")
|
||||||
result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
|
result.append("\t\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);")
|
||||||
result.append("#endif // DEBUG_ENABLED")
|
result.append("#endif // DEBUG_ENABLED")
|
||||||
result.append(
|
result.append(
|
||||||
f"\tstatic {class_name} *singleton = reinterpret_cast<{class_name} *>(internal::gdextension_interface_object_get_instance_binding(singleton_obj, internal::token, &{class_name}::_gde_binding_callbacks));"
|
f"\t\tsingleton = reinterpret_cast<{class_name} *>(internal::gdextension_interface_object_get_instance_binding(singleton_obj, internal::token, &{class_name}::_gde_binding_callbacks));"
|
||||||
)
|
)
|
||||||
|
result.append("#ifdef DEBUG_ENABLED")
|
||||||
|
result.append("\t\tERR_FAIL_COND_V(singleton == nullptr, nullptr);")
|
||||||
|
result.append("#endif // DEBUG_ENABLED")
|
||||||
|
result.append("\t}")
|
||||||
result.append("\treturn singleton;")
|
result.append("\treturn singleton;")
|
||||||
result.append("}")
|
result.append("}")
|
||||||
result.append("")
|
result.append("")
|
||||||
|
@ -1480,10 +1486,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
|
||||||
result.append(method_signature + " {")
|
result.append(method_signature + " {")
|
||||||
|
|
||||||
# Method body.
|
# Method body.
|
||||||
result.append(f"\tconst StringName _gde_class_name = {class_name}::get_class_static();")
|
|
||||||
result.append(f'\tconst StringName _gde_method_name = "{method["name"]}";')
|
|
||||||
result.append(
|
result.append(
|
||||||
f'\tstatic GDExtensionMethodBindPtr _gde_method_bind = internal::gdextension_interface_classdb_get_method_bind(_gde_class_name._native_ptr(), _gde_method_name._native_ptr(), {method["hash"]});'
|
f'\tstatic GDExtensionMethodBindPtr _gde_method_bind = internal::gdextension_interface_classdb_get_method_bind({class_name}::get_class_static()._native_ptr(), StringName("{method["name"]}")._native_ptr(), {method["hash"]});'
|
||||||
)
|
)
|
||||||
method_call = "\t"
|
method_call = "\t"
|
||||||
has_return = "return_value" in method and method["return_value"]["type"] != "void"
|
has_return = "return_value" in method and method["return_value"]["type"] != "void"
|
||||||
|
@ -1773,9 +1777,8 @@ def generate_utility_functions(api, output_dir):
|
||||||
|
|
||||||
# Function body.
|
# Function body.
|
||||||
|
|
||||||
source.append(f'\tconst StringName _gde_function_name = "{function["name"]}";')
|
|
||||||
source.append(
|
source.append(
|
||||||
f'\tstatic GDExtensionPtrUtilityFunction _gde_function = internal::gdextension_interface_variant_get_ptr_utility_function(_gde_function_name._native_ptr(), {function["hash"]});'
|
f'\tstatic GDExtensionPtrUtilityFunction _gde_function = internal::gdextension_interface_variant_get_ptr_utility_function(StringName("{function["name"]}")._native_ptr(), {function["hash"]});'
|
||||||
)
|
)
|
||||||
has_return = "return_type" in function and function["return_type"] != "void"
|
has_return = "return_type" in function and function["return_type"] != "void"
|
||||||
if has_return:
|
if has_return:
|
||||||
|
|
|
@ -32,13 +32,13 @@
|
||||||
#define GODOT_COWDATA_HPP
|
#define GODOT_COWDATA_HPP
|
||||||
|
|
||||||
#include <godot_cpp/classes/global_constants.hpp>
|
#include <godot_cpp/classes/global_constants.hpp>
|
||||||
#include <godot_cpp/core/class_db.hpp>
|
|
||||||
#include <godot_cpp/core/error_macros.hpp>
|
#include <godot_cpp/core/error_macros.hpp>
|
||||||
#include <godot_cpp/core/math.hpp>
|
#include <godot_cpp/core/math.hpp>
|
||||||
#include <godot_cpp/core/memory.hpp>
|
#include <godot_cpp/core/memory.hpp>
|
||||||
#include <godot_cpp/templates/safe_refcount.hpp>
|
#include <godot_cpp/templates/safe_refcount.hpp>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
|
@ -48,6 +48,9 @@ class Vector;
|
||||||
template <class T, class V>
|
template <class T, class V>
|
||||||
class VMap;
|
class VMap;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class CharStringT;
|
||||||
|
|
||||||
// Silence a false positive warning (see GH-52119).
|
// Silence a false positive warning (see GH-52119).
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
|
@ -62,6 +65,9 @@ class CowData {
|
||||||
template <class TV, class VV>
|
template <class TV, class VV>
|
||||||
friend class VMap;
|
friend class VMap;
|
||||||
|
|
||||||
|
template <class TS>
|
||||||
|
friend class CharStringT;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable T *_ptr = nullptr;
|
mutable T *_ptr = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -31,82 +31,99 @@
|
||||||
#ifndef GODOT_CHAR_STRING_HPP
|
#ifndef GODOT_CHAR_STRING_HPP
|
||||||
#define GODOT_CHAR_STRING_HPP
|
#define GODOT_CHAR_STRING_HPP
|
||||||
|
|
||||||
|
#include <godot_cpp/templates/cowdata.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
class CharString {
|
template <class T>
|
||||||
friend class String;
|
class CharStringT;
|
||||||
|
|
||||||
const char *_data = nullptr;
|
template <class T>
|
||||||
int _length = 0;
|
class CharProxy {
|
||||||
|
template <class TS>
|
||||||
|
friend class CharStringT;
|
||||||
|
|
||||||
CharString(const char *str, int length);
|
const int _index;
|
||||||
|
CowData<T> &_cowdata;
|
||||||
|
static inline const T _null = 0;
|
||||||
|
|
||||||
|
_FORCE_INLINE_ CharProxy(const int &p_index, CowData<T> &p_cowdata) :
|
||||||
|
_index(p_index),
|
||||||
|
_cowdata(p_cowdata) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int length() const;
|
_FORCE_INLINE_ CharProxy(const CharProxy<T> &p_other) :
|
||||||
const char *get_data() const;
|
_index(p_other._index),
|
||||||
|
_cowdata(p_other._cowdata) {}
|
||||||
|
|
||||||
CharString(CharString &&p_str);
|
_FORCE_INLINE_ operator T() const {
|
||||||
void operator=(CharString &&p_str);
|
if (unlikely(_index == _cowdata.size())) {
|
||||||
CharString() {}
|
return _null;
|
||||||
~CharString();
|
}
|
||||||
|
|
||||||
|
return _cowdata.get(_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ const T *operator&() const {
|
||||||
|
return _cowdata.ptr() + _index;
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void operator=(const T &p_other) const {
|
||||||
|
_cowdata.set(_index, p_other);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ void operator=(const CharProxy<T> &p_other) const {
|
||||||
|
_cowdata.set(_index, p_other.operator T());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Char16String {
|
template <class T>
|
||||||
|
class CharStringT {
|
||||||
friend class String;
|
friend class String;
|
||||||
|
|
||||||
const char16_t *_data = nullptr;
|
CowData<T> _cowdata;
|
||||||
int _length = 0;
|
static inline const T _null = 0;
|
||||||
|
|
||||||
Char16String(const char16_t *str, int length);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int length() const;
|
_FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); }
|
||||||
const char16_t *get_data() const;
|
_FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); }
|
||||||
|
_FORCE_INLINE_ int size() const { return _cowdata.size(); }
|
||||||
|
Error resize(int p_size) { return _cowdata.resize(p_size); }
|
||||||
|
|
||||||
Char16String(Char16String &&p_str);
|
_FORCE_INLINE_ T get(int p_index) const { return _cowdata.get(p_index); }
|
||||||
void operator=(Char16String &&p_str);
|
_FORCE_INLINE_ void set(int p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); }
|
||||||
Char16String() {}
|
_FORCE_INLINE_ const T &operator[](int p_index) const {
|
||||||
~Char16String();
|
if (unlikely(p_index == _cowdata.size())) {
|
||||||
|
return _null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cowdata.get(p_index);
|
||||||
|
}
|
||||||
|
_FORCE_INLINE_ CharProxy<T> operator[](int p_index) { return CharProxy<T>(p_index, _cowdata); }
|
||||||
|
|
||||||
|
_FORCE_INLINE_ CharStringT() {}
|
||||||
|
_FORCE_INLINE_ CharStringT(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
|
||||||
|
_FORCE_INLINE_ void operator=(const CharStringT<T> &p_str) { _cowdata._ref(p_str._cowdata); }
|
||||||
|
_FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); }
|
||||||
|
|
||||||
|
void operator=(const T *p_cstr);
|
||||||
|
bool operator<(const CharStringT<T> &p_right) const;
|
||||||
|
CharStringT<T> &operator+=(T p_char);
|
||||||
|
int length() const { return size() ? size() - 1 : 0; }
|
||||||
|
const T *get_data() const;
|
||||||
|
operator const T *() const { return get_data(); };
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void copy_from(const T *p_cstr);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Char32String {
|
typedef CharStringT<char> CharString;
|
||||||
friend class String;
|
typedef CharStringT<char16_t> Char16String;
|
||||||
|
typedef CharStringT<char32_t> Char32String;
|
||||||
const char32_t *_data = nullptr;
|
typedef CharStringT<wchar_t> CharWideString;
|
||||||
int _length = 0;
|
|
||||||
|
|
||||||
Char32String(const char32_t *str, int length);
|
|
||||||
|
|
||||||
public:
|
|
||||||
int length() const;
|
|
||||||
const char32_t *get_data() const;
|
|
||||||
|
|
||||||
Char32String(Char32String &&p_str);
|
|
||||||
void operator=(Char32String &&p_str);
|
|
||||||
Char32String() {}
|
|
||||||
~Char32String();
|
|
||||||
};
|
|
||||||
|
|
||||||
class CharWideString {
|
|
||||||
friend class String;
|
|
||||||
|
|
||||||
const wchar_t *_data = nullptr;
|
|
||||||
int _length = 0;
|
|
||||||
|
|
||||||
CharWideString(const wchar_t *str, int length);
|
|
||||||
|
|
||||||
public:
|
|
||||||
int length() const;
|
|
||||||
const wchar_t *get_data() const;
|
|
||||||
|
|
||||||
CharWideString(CharWideString &&p_str);
|
|
||||||
void operator=(CharWideString &&p_str);
|
|
||||||
CharWideString() {}
|
|
||||||
~CharWideString();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace godot
|
} // namespace godot
|
||||||
|
|
||||||
|
|
|
@ -38,117 +38,121 @@
|
||||||
#include <godot_cpp/godot.hpp>
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace godot {
|
namespace godot {
|
||||||
|
|
||||||
int CharString::length() const {
|
template <typename L, typename R>
|
||||||
return _length;
|
_FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) {
|
||||||
|
while (true) {
|
||||||
|
const char32_t l = *l_ptr;
|
||||||
|
const char32_t r = *r_ptr;
|
||||||
|
|
||||||
|
if (l == 0 && r == 0) {
|
||||||
|
return false;
|
||||||
|
} else if (l == 0) {
|
||||||
|
return true;
|
||||||
|
} else if (r == 0) {
|
||||||
|
return false;
|
||||||
|
} else if (l < r) {
|
||||||
|
return true;
|
||||||
|
} else if (l > r) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CharString::get_data() const {
|
l_ptr++;
|
||||||
return _data;
|
r_ptr++;
|
||||||
}
|
|
||||||
|
|
||||||
CharString::CharString(CharString &&p_str) {
|
|
||||||
SWAP(_length, p_str._length);
|
|
||||||
SWAP(_data, p_str._data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CharString::operator=(CharString &&p_str) {
|
|
||||||
SWAP(_length, p_str._length);
|
|
||||||
SWAP(_data, p_str._data);
|
|
||||||
}
|
|
||||||
|
|
||||||
CharString::CharString(const char *str, int length) :
|
|
||||||
_data(str), _length(length) {}
|
|
||||||
|
|
||||||
CharString::~CharString() {
|
|
||||||
if (_data != nullptr) {
|
|
||||||
memdelete_arr(_data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Char16String::length() const {
|
template <class T>
|
||||||
return _length;
|
bool CharStringT<T>::operator<(const CharStringT<T> &p_right) const {
|
||||||
|
if (length() == 0) {
|
||||||
|
return p_right.length() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char16_t *Char16String::get_data() const {
|
return is_str_less(get_data(), p_right.get_data());
|
||||||
return _data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Char16String::Char16String(Char16String &&p_str) {
|
template <class T>
|
||||||
SWAP(_length, p_str._length);
|
CharStringT<T> &CharStringT<T>::operator+=(T p_char) {
|
||||||
SWAP(_data, p_str._data);
|
const int lhs_len = length();
|
||||||
|
resize(lhs_len + 2);
|
||||||
|
|
||||||
|
T *dst = ptrw();
|
||||||
|
dst[lhs_len] = p_char;
|
||||||
|
dst[lhs_len + 1] = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Char16String::operator=(Char16String &&p_str) {
|
template <class T>
|
||||||
SWAP(_length, p_str._length);
|
void CharStringT<T>::operator=(const T *p_cstr) {
|
||||||
SWAP(_data, p_str._data);
|
copy_from(p_cstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Char16String::Char16String(const char16_t *str, int length) :
|
template <>
|
||||||
_data(str), _length(length) {}
|
const char *CharStringT<char>::get_data() const {
|
||||||
|
if (size()) {
|
||||||
Char16String::~Char16String() {
|
return &operator[](0);
|
||||||
if (_data != nullptr) {
|
} else {
|
||||||
memdelete_arr(_data);
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Char32String::length() const {
|
template <>
|
||||||
return _length;
|
const char16_t *CharStringT<char16_t>::get_data() const {
|
||||||
}
|
if (size()) {
|
||||||
|
return &operator[](0);
|
||||||
const char32_t *Char32String::get_data() const {
|
} else {
|
||||||
return _data;
|
return u"";
|
||||||
}
|
|
||||||
|
|
||||||
Char32String::Char32String(Char32String &&p_str) {
|
|
||||||
SWAP(_length, p_str._length);
|
|
||||||
SWAP(_data, p_str._data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Char32String::operator=(Char32String &&p_str) {
|
|
||||||
SWAP(_length, p_str._length);
|
|
||||||
SWAP(_data, p_str._data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Char32String::Char32String(const char32_t *str, int length) :
|
|
||||||
_data(str), _length(length) {}
|
|
||||||
|
|
||||||
Char32String::~Char32String() {
|
|
||||||
if (_data != nullptr) {
|
|
||||||
memdelete_arr(_data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CharWideString::length() const {
|
template <>
|
||||||
return _length;
|
const char32_t *CharStringT<char32_t>::get_data() const {
|
||||||
|
if (size()) {
|
||||||
|
return &operator[](0);
|
||||||
|
} else {
|
||||||
|
return U"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t *CharWideString::get_data() const {
|
template <>
|
||||||
return _data;
|
const wchar_t *CharStringT<wchar_t>::get_data() const {
|
||||||
|
if (size()) {
|
||||||
|
return &operator[](0);
|
||||||
|
} else {
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CharWideString::CharWideString(CharWideString &&p_str) {
|
template <class T>
|
||||||
SWAP(_length, p_str._length);
|
void CharStringT<T>::copy_from(const T *p_cstr) {
|
||||||
SWAP(_data, p_str._data);
|
if (!p_cstr) {
|
||||||
|
resize(0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharWideString::operator=(CharWideString &&p_str) {
|
size_t len = std::char_traits<T>::length(p_cstr);
|
||||||
SWAP(_length, p_str._length);
|
|
||||||
SWAP(_data, p_str._data);
|
if (len == 0) {
|
||||||
|
resize(0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharWideString::CharWideString(const wchar_t *str, int length) :
|
Error err = resize(++len); // include terminating null char
|
||||||
_data(str), _length(length) {}
|
|
||||||
|
|
||||||
CharWideString::~CharWideString() {
|
ERR_FAIL_COND_MSG(err != OK, "Failed to copy C-string.");
|
||||||
if (_data != nullptr) {
|
|
||||||
memdelete_arr(_data);
|
memcpy(ptrw(), p_cstr, len);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template class CharStringT<char>;
|
||||||
|
template class CharStringT<char16_t>;
|
||||||
|
template class CharStringT<char32_t>;
|
||||||
|
template class CharStringT<wchar_t>;
|
||||||
|
|
||||||
// Custom String functions that are not part of bound API.
|
// Custom String functions that are not part of bound API.
|
||||||
// It's easier to have them written in C++ directly than in a Python script that generates them.
|
// It's easier to have them written in C++ directly than in a Python script that generates them.
|
||||||
|
|
||||||
|
@ -228,56 +232,61 @@ String rtoss(double p_val) {
|
||||||
CharString String::utf8() const {
|
CharString String::utf8() const {
|
||||||
int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
|
int length = internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), nullptr, 0);
|
||||||
int size = length + 1;
|
int size = length + 1;
|
||||||
char *cstr = memnew_arr(char, size);
|
CharString str;
|
||||||
internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), cstr, length);
|
str.resize(size);
|
||||||
|
internal::gdextension_interface_string_to_utf8_chars(_native_ptr(), str.ptrw(), length);
|
||||||
|
|
||||||
cstr[length] = '\0';
|
str[length] = '\0';
|
||||||
|
|
||||||
return CharString(cstr, length);
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharString String::ascii() const {
|
CharString String::ascii() const {
|
||||||
int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
|
int length = internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), nullptr, 0);
|
||||||
int size = length + 1;
|
int size = length + 1;
|
||||||
char *cstr = memnew_arr(char, size);
|
CharString str;
|
||||||
internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), cstr, length);
|
str.resize(size);
|
||||||
|
internal::gdextension_interface_string_to_latin1_chars(_native_ptr(), str.ptrw(), length);
|
||||||
|
|
||||||
cstr[length] = '\0';
|
str[length] = '\0';
|
||||||
|
|
||||||
return CharString(cstr, length);
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
Char16String String::utf16() const {
|
Char16String String::utf16() const {
|
||||||
int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
|
int length = internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), nullptr, 0);
|
||||||
int size = length + 1;
|
int size = length + 1;
|
||||||
char16_t *cstr = memnew_arr(char16_t, size);
|
Char16String str;
|
||||||
internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), cstr, length);
|
str.resize(size);
|
||||||
|
internal::gdextension_interface_string_to_utf16_chars(_native_ptr(), str.ptrw(), length);
|
||||||
|
|
||||||
cstr[length] = '\0';
|
str[length] = '\0';
|
||||||
|
|
||||||
return Char16String(cstr, length);
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
Char32String String::utf32() const {
|
Char32String String::utf32() const {
|
||||||
int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
|
int length = internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), nullptr, 0);
|
||||||
int size = length + 1;
|
int size = length + 1;
|
||||||
char32_t *cstr = memnew_arr(char32_t, size);
|
Char32String str;
|
||||||
internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), cstr, length);
|
str.resize(size);
|
||||||
|
internal::gdextension_interface_string_to_utf32_chars(_native_ptr(), str.ptrw(), length);
|
||||||
|
|
||||||
cstr[length] = '\0';
|
str[length] = '\0';
|
||||||
|
|
||||||
return Char32String(cstr, length);
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
CharWideString String::wide_string() const {
|
CharWideString String::wide_string() const {
|
||||||
int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
|
int length = internal::gdextension_interface_string_to_wide_chars(_native_ptr(), nullptr, 0);
|
||||||
int size = length + 1;
|
int size = length + 1;
|
||||||
wchar_t *cstr = memnew_arr(wchar_t, size);
|
CharWideString str;
|
||||||
internal::gdextension_interface_string_to_wide_chars(_native_ptr(), cstr, length);
|
str.resize(size);
|
||||||
|
internal::gdextension_interface_string_to_wide_chars(_native_ptr(), str.ptrw(), length);
|
||||||
|
|
||||||
cstr[length] = '\0';
|
str[length] = '\0';
|
||||||
|
|
||||||
return CharWideString(cstr, length);
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
String &String::operator=(const char *p_str) {
|
String &String::operator=(const char *p_str) {
|
||||||
|
|
|
@ -82,6 +82,10 @@ func _ready():
|
||||||
# UtilityFunctions::str()
|
# UtilityFunctions::str()
|
||||||
assert_equal(example.test_str_utility(), "Hello, World! The answer is 42")
|
assert_equal(example.test_str_utility(), "Hello, World! The answer is 42")
|
||||||
|
|
||||||
|
# Test converting string to char* and doing comparison.
|
||||||
|
assert_equal(example.test_string_is_fourty_two("blah"), false)
|
||||||
|
assert_equal(example.test_string_is_fourty_two("fourty two"), true)
|
||||||
|
|
||||||
# PackedArray iterators
|
# PackedArray iterators
|
||||||
assert_equal(example.test_vector_ops(), 105)
|
assert_equal(example.test_vector_ops(), 105)
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,7 @@ void Example::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
|
ClassDB::bind_method(D_METHOD("test_node_argument"), &Example::test_node_argument);
|
||||||
ClassDB::bind_method(D_METHOD("test_string_ops"), &Example::test_string_ops);
|
ClassDB::bind_method(D_METHOD("test_string_ops"), &Example::test_string_ops);
|
||||||
ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility);
|
ClassDB::bind_method(D_METHOD("test_str_utility"), &Example::test_str_utility);
|
||||||
|
ClassDB::bind_method(D_METHOD("test_string_is_fourty_two"), &Example::test_string_is_fourty_two);
|
||||||
ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops);
|
ClassDB::bind_method(D_METHOD("test_vector_ops"), &Example::test_vector_ops);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
|
ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield);
|
||||||
|
@ -299,6 +300,10 @@ String Example::test_str_utility() const {
|
||||||
return UtilityFunctions::str("Hello, ", "World", "! The answer is ", 42);
|
return UtilityFunctions::str("Hello, ", "World", "! The answer is ", 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Example::test_string_is_fourty_two(const String &p_string) const {
|
||||||
|
return strcmp(p_string.utf8().ptr(), "fourty two") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
int Example::test_vector_ops() const {
|
int Example::test_vector_ops() const {
|
||||||
PackedInt32Array arr;
|
PackedInt32Array arr;
|
||||||
arr.push_back(10);
|
arr.push_back(10);
|
||||||
|
|
|
@ -117,6 +117,7 @@ public:
|
||||||
Example *test_node_argument(Example *p_node) const;
|
Example *test_node_argument(Example *p_node) const;
|
||||||
String test_string_ops() const;
|
String test_string_ops() const;
|
||||||
String test_str_utility() const;
|
String test_str_utility() const;
|
||||||
|
bool test_string_is_fourty_two(const String &p_str) const;
|
||||||
int test_vector_ops() const;
|
int test_vector_ops() const;
|
||||||
|
|
||||||
BitField<Flags> test_bitfield(BitField<Flags> flags);
|
BitField<Flags> test_bitfield(BitField<Flags> flags);
|
||||||
|
|
|
@ -100,3 +100,5 @@ def generate(env):
|
||||||
)
|
)
|
||||||
env.Append(CCFLAGS=arch_info["ccflags"])
|
env.Append(CCFLAGS=arch_info["ccflags"])
|
||||||
env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
|
env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"])
|
||||||
|
|
37
tools/ios.py
37
tools/ios.py
|
@ -1,7 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import ios_osxcross
|
|
||||||
from SCons.Variables import *
|
from SCons.Variables import *
|
||||||
|
|
||||||
if sys.version_info < (3,):
|
if sys.version_info < (3,):
|
||||||
|
@ -16,6 +15,10 @@ else:
|
||||||
return codecs.utf_8_decode(x)[0]
|
return codecs.utf_8_decode(x)[0]
|
||||||
|
|
||||||
|
|
||||||
|
def has_ios_osxcross():
|
||||||
|
return "OSXCROSS_IOS" in os.environ
|
||||||
|
|
||||||
|
|
||||||
def options(opts):
|
def options(opts):
|
||||||
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
|
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
|
||||||
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "10.0")
|
opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "10.0")
|
||||||
|
@ -25,17 +28,18 @@ def options(opts):
|
||||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
|
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
|
||||||
)
|
)
|
||||||
opts.Add("IOS_SDK_PATH", "Path to the iOS SDK", "")
|
opts.Add("IOS_SDK_PATH", "Path to the iOS SDK", "")
|
||||||
ios_osxcross.options(opts)
|
|
||||||
|
if has_ios_osxcross():
|
||||||
|
opts.Add("ios_triple", "Triple for ios toolchain", "")
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
def exists(env):
|
||||||
return sys.platform == "darwin" or ios_osxcross.exists(env)
|
return sys.platform == "darwin" or has_ios_osxcross()
|
||||||
|
|
||||||
|
|
||||||
def generate(env):
|
def generate(env):
|
||||||
if env["arch"] not in ("universal", "arm64", "x86_64"):
|
if env["arch"] not in ("universal", "arm64", "x86_64"):
|
||||||
print("Only universal, arm64, and x86_64 are supported on iOS. Exiting.")
|
raise ValueError("Only universal, arm64, and x86_64 are supported on iOS. Exiting.")
|
||||||
Exit()
|
|
||||||
|
|
||||||
if env["ios_simulator"]:
|
if env["ios_simulator"]:
|
||||||
sdk_name = "iphonesimulator"
|
sdk_name = "iphonesimulator"
|
||||||
|
@ -64,7 +68,26 @@ def generate(env):
|
||||||
env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
|
env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ios_osxcross.generate(env)
|
# OSXCross
|
||||||
|
compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}"
|
||||||
|
env["CC"] = compiler_path + "clang"
|
||||||
|
env["CXX"] = compiler_path + "clang++"
|
||||||
|
env["AR"] = compiler_path + "ar"
|
||||||
|
env["RANLIB"] = compiler_path + "ranlib"
|
||||||
|
env["SHLIBSUFFIX"] = ".dylib"
|
||||||
|
|
||||||
|
env.Prepend(
|
||||||
|
CPPPATH=[
|
||||||
|
"$IOS_SDK_PATH/usr/include",
|
||||||
|
"$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
env.Append(CCFLAGS=["-stdlib=libc++"])
|
||||||
|
|
||||||
|
binpath = os.path.join(env["IOS_TOOLCHAIN_PATH"], "usr", "bin")
|
||||||
|
if binpath not in env["ENV"]["PATH"]:
|
||||||
|
env.PrependENVPath("PATH", binpath)
|
||||||
|
|
||||||
if env["arch"] == "universal":
|
if env["arch"] == "universal":
|
||||||
if env["ios_simulator"]:
|
if env["ios_simulator"]:
|
||||||
|
@ -79,3 +102,5 @@ def generate(env):
|
||||||
|
|
||||||
env.Append(CCFLAGS=["-isysroot", env["IOS_SDK_PATH"]])
|
env.Append(CCFLAGS=["-isysroot", env["IOS_SDK_PATH"]])
|
||||||
env.Append(LINKFLAGS=["-isysroot", env["IOS_SDK_PATH"], "-F" + env["IOS_SDK_PATH"]])
|
env.Append(LINKFLAGS=["-isysroot", env["IOS_SDK_PATH"], "-F" + env["IOS_SDK_PATH"]])
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"])
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def options(opts):
|
|
||||||
opts.Add("ios_triple", "Triple for ios toolchain", "")
|
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return "OSXCROSS_IOS" in os.environ
|
|
||||||
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}"
|
|
||||||
env["CC"] = compiler_path + "clang"
|
|
||||||
env["CXX"] = compiler_path + "clang++"
|
|
||||||
env["AR"] = compiler_path + "ar"
|
|
||||||
env["RANLIB"] = compiler_path + "ranlib"
|
|
||||||
env["SHLIBSUFFIX"] = ".dylib"
|
|
||||||
|
|
||||||
env.Prepend(
|
|
||||||
CPPPATH=[
|
|
||||||
"$IOS_SDK_PATH/usr/include",
|
|
||||||
"$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
env.Append(CCFLAGS=["-stdlib=libc++"])
|
|
|
@ -43,3 +43,5 @@ def generate(env):
|
||||||
env.Append(CCFLAGS=["-O0", "-g"])
|
env.Append(CCFLAGS=["-O0", "-g"])
|
||||||
elif env["target"] == "release":
|
elif env["target"] == "release":
|
||||||
env.Append(CCFLAGS=["-O3"])
|
env.Append(CCFLAGS=["-O3"])
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"])
|
||||||
|
|
|
@ -32,3 +32,5 @@ def generate(env):
|
||||||
elif env["arch"] == "rv64":
|
elif env["arch"] == "rv64":
|
||||||
env.Append(CCFLAGS=["-march=rv64gc"])
|
env.Append(CCFLAGS=["-march=rv64gc"])
|
||||||
env.Append(LINKFLAGS=["-march=rv64gc"])
|
env.Append(LINKFLAGS=["-march=rv64gc"])
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"])
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import macos_osxcross
|
|
||||||
|
|
||||||
|
def has_osxcross():
|
||||||
|
return "OSXCROSS_ROOT" in os.environ
|
||||||
|
|
||||||
|
|
||||||
def options(opts):
|
def options(opts):
|
||||||
opts.Add("macos_deployment_target", "macOS deployment target", "default")
|
opts.Add("macos_deployment_target", "macOS deployment target", "default")
|
||||||
opts.Add("macos_sdk_path", "macOS SDK path", "")
|
opts.Add("macos_sdk_path", "macOS SDK path", "")
|
||||||
macos_osxcross.options(opts)
|
if has_osxcross():
|
||||||
|
opts.Add("osxcross_sdk", "OSXCross SDK version", "darwin16")
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
def exists(env):
|
||||||
return sys.platform == "darwin" or macos_osxcross.exists(env)
|
return sys.platform == "darwin" or has_osxcross()
|
||||||
|
|
||||||
|
|
||||||
def generate(env):
|
def generate(env):
|
||||||
|
@ -23,9 +27,25 @@ def generate(env):
|
||||||
env["CXX"] = "clang++"
|
env["CXX"] = "clang++"
|
||||||
env["CC"] = "clang"
|
env["CC"] = "clang"
|
||||||
else:
|
else:
|
||||||
# Use osxcross
|
# OSXCross
|
||||||
macos_osxcross.generate(env)
|
root = os.environ.get("OSXCROSS_ROOT", "")
|
||||||
|
if env["arch"] == "arm64":
|
||||||
|
basecmd = root + "/target/bin/arm64-apple-" + env["osxcross_sdk"] + "-"
|
||||||
|
else:
|
||||||
|
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
|
||||||
|
|
||||||
|
env["CC"] = basecmd + "clang"
|
||||||
|
env["CXX"] = basecmd + "clang++"
|
||||||
|
env["AR"] = basecmd + "ar"
|
||||||
|
env["RANLIB"] = basecmd + "ranlib"
|
||||||
|
env["AS"] = basecmd + "as"
|
||||||
|
|
||||||
|
binpath = os.path.join(root, "target", "bin")
|
||||||
|
if binpath not in env["ENV"]["PATH"]:
|
||||||
|
# Add OSXCROSS bin folder to PATH (required for linking).
|
||||||
|
env.PrependENVPath("PATH", binpath)
|
||||||
|
|
||||||
|
# Common flags
|
||||||
if env["arch"] == "universal":
|
if env["arch"] == "universal":
|
||||||
env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
|
env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
|
||||||
env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
|
env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
|
||||||
|
@ -48,3 +68,5 @@ def generate(env):
|
||||||
"-Wl,-undefined,dynamic_lookup",
|
"-Wl,-undefined,dynamic_lookup",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"])
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
def options(opts):
|
|
||||||
opts.Add("osxcross_sdk", "OSXCross SDK version", "darwin16")
|
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return "OSXCROSS_ROOT" in os.environ
|
|
||||||
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
root = os.environ.get("OSXCROSS_ROOT", "")
|
|
||||||
if env["arch"] == "arm64":
|
|
||||||
basecmd = root + "/target/bin/arm64-apple-" + env["osxcross_sdk"] + "-"
|
|
||||||
else:
|
|
||||||
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
|
|
||||||
|
|
||||||
env["CC"] = basecmd + "clang"
|
|
||||||
env["CXX"] = basecmd + "clang++"
|
|
||||||
env["AR"] = basecmd + "ar"
|
|
||||||
env["RANLIB"] = basecmd + "ranlib"
|
|
||||||
env["AS"] = basecmd + "as"
|
|
||||||
|
|
||||||
binpath = os.path.join(root, "target", "bin")
|
|
||||||
if binpath not in env["ENV"]["PATH"]:
|
|
||||||
# Add OSXCROSS bin folder to PATH (required for linking).
|
|
||||||
env["ENV"]["PATH"] = "%s:%s" % (binpath, env["ENV"]["PATH"])
|
|
|
@ -60,17 +60,17 @@ def generate(env):
|
||||||
env.Append(CCFLAGS=["/Zi", "/FS"])
|
env.Append(CCFLAGS=["/Zi", "/FS"])
|
||||||
env.Append(LINKFLAGS=["/DEBUG:FULL"])
|
env.Append(LINKFLAGS=["/DEBUG:FULL"])
|
||||||
|
|
||||||
if env["optimize"] == "speed" or env["optimize"] == "speed_trace":
|
if env["optimize"] == "speed":
|
||||||
env.Append(CCFLAGS=["/O2"])
|
env.Append(CCFLAGS=["/O2"])
|
||||||
env.Append(LINKFLAGS=["/OPT:REF"])
|
env.Append(LINKFLAGS=["/OPT:REF"])
|
||||||
|
elif env["optimize"] == "speed_trace":
|
||||||
|
env.Append(CCFLAGS=["/O2"])
|
||||||
|
env.Append(LINKFLAGS=["/OPT:REF", "/OPT:NOICF"])
|
||||||
elif env["optimize"] == "size":
|
elif env["optimize"] == "size":
|
||||||
env.Append(CCFLAGS=["/O1"])
|
env.Append(CCFLAGS=["/O1"])
|
||||||
env.Append(LINKFLAGS=["/OPT:REF"])
|
env.Append(LINKFLAGS=["/OPT:REF"])
|
||||||
|
elif env["optimize"] == "debug" or env["optimize"] == "none":
|
||||||
if env["optimize"] == "debug" or env["optimize"] == "none":
|
env.Append(CCFLAGS=["/Od"])
|
||||||
env.Append(CCFLAGS=["/MDd", "/Od"])
|
|
||||||
else:
|
|
||||||
env.Append(CCFLAGS=["/MD"])
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if env["debug_symbols"]:
|
if env["debug_symbols"]:
|
||||||
|
|
|
@ -9,6 +9,7 @@ from SCons.Variables import *
|
||||||
def options(opts):
|
def options(opts):
|
||||||
opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False))
|
opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False))
|
||||||
opts.Add(BoolVariable("use_clang_cl", "Use the clang driver instead of MSVC - only effective on Windows", False))
|
opts.Add(BoolVariable("use_clang_cl", "Use the clang driver instead of MSVC - only effective on Windows", False))
|
||||||
|
opts.Add(BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True))
|
||||||
|
|
||||||
|
|
||||||
def exists(env):
|
def exists(env):
|
||||||
|
@ -37,6 +38,11 @@ def generate(env):
|
||||||
env["CC"] = "clang-cl"
|
env["CC"] = "clang-cl"
|
||||||
env["CXX"] = "clang-cl"
|
env["CXX"] = "clang-cl"
|
||||||
|
|
||||||
|
if env["use_static_cpp"]:
|
||||||
|
env.Append(CCFLAGS=["/MT"])
|
||||||
|
else:
|
||||||
|
env.Append(CCFLAGS=["/MD"])
|
||||||
|
|
||||||
elif sys.platform == "win32" or sys.platform == "msys":
|
elif sys.platform == "win32" or sys.platform == "msys":
|
||||||
env["use_mingw"] = True
|
env["use_mingw"] = True
|
||||||
mingw.generate(env)
|
mingw.generate(env)
|
||||||
|
@ -45,6 +51,18 @@ def generate(env):
|
||||||
env["SHLIBPREFIX"] = ""
|
env["SHLIBPREFIX"] = ""
|
||||||
# Want dll suffix
|
# Want dll suffix
|
||||||
env["SHLIBSUFFIX"] = ".dll"
|
env["SHLIBSUFFIX"] = ".dll"
|
||||||
|
|
||||||
|
env.Append(CCFLAGS=["-Wwrite-strings"])
|
||||||
|
env.Append(LINKFLAGS=["-Wl,--no-undefined"])
|
||||||
|
if env["use_static_cpp"]:
|
||||||
|
env.Append(
|
||||||
|
LINKFLAGS=[
|
||||||
|
"-static",
|
||||||
|
"-static-libgcc",
|
||||||
|
"-static-libstdc++",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other).
|
# Long line hack. Use custom spawn, quick AR append (to avoid files with the same names to override each other).
|
||||||
my_spawn.configure(env)
|
my_spawn.configure(env)
|
||||||
|
|
||||||
|
@ -60,13 +78,15 @@ def generate(env):
|
||||||
# Want dll suffix
|
# Want dll suffix
|
||||||
env["SHLIBSUFFIX"] = ".dll"
|
env["SHLIBSUFFIX"] = ".dll"
|
||||||
|
|
||||||
# These options are for a release build even using target=debug
|
env.Append(CCFLAGS=["-Wwrite-strings"])
|
||||||
env.Append(CCFLAGS=["-O3", "-Wwrite-strings"])
|
env.Append(LINKFLAGS=["-Wl,--no-undefined"])
|
||||||
|
if env["use_static_cpp"]:
|
||||||
env.Append(
|
env.Append(
|
||||||
LINKFLAGS=[
|
LINKFLAGS=[
|
||||||
"--static",
|
"-static",
|
||||||
"-Wl,--no-undefined",
|
|
||||||
"-static-libgcc",
|
"-static-libgcc",
|
||||||
"-static-libstdc++",
|
"-static-libstdc++",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
env.Append(CPPDEFINES=["WINDOWS_ENABLED"])
|
||||||
|
|
Loading…
Reference in New Issue