瀏覽代碼

[macOS/iOS export] Add option to set custom Info.plist data.

bruvzg 1 年之前
父節點
當前提交
491077239c

+ 37 - 17
platform/macos/export/plist.cpp → core/io/plist.cpp

@@ -448,7 +448,9 @@ PList::PList() {
 }
 
 PList::PList(const String &p_string) {
-	load_string(p_string);
+	String err_str;
+	bool ok = load_string(p_string, err_str);
+	ERR_FAIL_COND_MSG(!ok, "PList: " + err_str);
 }
 
 uint64_t PList::read_bplist_var_size_int(Ref<FileAccess> p_file, uint8_t p_size) {
@@ -642,11 +644,15 @@ bool PList::load_file(const String &p_filename) {
 
 		String ret;
 		ret.parse_utf8((const char *)array.ptr(), array.size());
-		return load_string(ret);
+		String err_str;
+		bool ok = load_string(ret, err_str);
+		ERR_FAIL_COND_V_MSG(!ok, false, "PList: " + err_str);
+
+		return true;
 	}
 }
 
-bool PList::load_string(const String &p_string) {
+bool PList::load_string(const String &p_string, String &r_err_out) {
 	root = Ref<PListNode>();
 
 	int pos = 0;
@@ -657,14 +663,16 @@ bool PList::load_string(const String &p_string) {
 	while (pos >= 0) {
 		int open_token_s = p_string.find("<", pos);
 		if (open_token_s == -1) {
-			ERR_FAIL_V_MSG(false, "PList: Unexpected end of data. No tags found.");
+			r_err_out = "Unexpected end of data. No tags found.";
+			return false;
 		}
 		int open_token_e = p_string.find(">", open_token_s);
 		pos = open_token_e;
 
 		String token = p_string.substr(open_token_s + 1, open_token_e - open_token_s - 1);
 		if (token.is_empty()) {
-			ERR_FAIL_V_MSG(false, "PList: Invalid token name.");
+			r_err_out = "Invalid token name.";
+			return false;
 		}
 		String value;
 		if (token[0] == '?' || token[0] == '!') { // Skip <?xml ... ?> and <!DOCTYPE ... >
@@ -684,7 +692,8 @@ bool PList::load_string(const String &p_string) {
 		}
 
 		if (!in_plist) {
-			ERR_FAIL_V_MSG(false, "PList: Node outside of <plist> tag.");
+			r_err_out = "Node outside of <plist> tag.";
+			return false;
 		}
 
 		if (token == "dict") {
@@ -693,13 +702,15 @@ bool PList::load_string(const String &p_string) {
 				Ref<PListNode> dict = PListNode::new_dict();
 				dict->data_type = PList::PLNodeType::PL_NODE_TYPE_DICT;
 				if (!stack.back()->get()->push_subnode(dict, key)) {
-					ERR_FAIL_V_MSG(false, "PList: Can't push subnode, invalid parent type.");
+					r_err_out = "Can't push subnode, invalid parent type.";
+					return false;
 				}
 				stack.push_back(dict);
 			} else {
 				// Add root node.
 				if (!root.is_null()) {
-					ERR_FAIL_V_MSG(false, "PList: Root node already set.");
+					r_err_out = "Root node already set.";
+					return false;
 				}
 				Ref<PListNode> dict = PListNode::new_dict();
 				stack.push_back(dict);
@@ -711,7 +722,8 @@ bool PList::load_string(const String &p_string) {
 		if (token == "/dict") {
 			// Exit current dict.
 			if (stack.is_empty() || stack.back()->get()->data_type != PList::PLNodeType::PL_NODE_TYPE_DICT) {
-				ERR_FAIL_V_MSG(false, "PList: Mismatched </dict> tag.");
+				r_err_out = "Mismatched </dict> tag.";
+				return false;
 			}
 			stack.pop_back();
 			continue;
@@ -722,13 +734,15 @@ bool PList::load_string(const String &p_string) {
 				// Add subnode end enter it.
 				Ref<PListNode> arr = PListNode::new_array();
 				if (!stack.back()->get()->push_subnode(arr, key)) {
-					ERR_FAIL_V_MSG(false, "PList: Can't push subnode, invalid parent type.");
+					r_err_out = "Can't push subnode, invalid parent type.";
+					return false;
 				}
 				stack.push_back(arr);
 			} else {
 				// Add root node.
 				if (!root.is_null()) {
-					ERR_FAIL_V_MSG(false, "PList: Root node already set.");
+					r_err_out = "Root node already set.";
+					return false;
 				}
 				Ref<PListNode> arr = PListNode::new_array();
 				stack.push_back(arr);
@@ -740,7 +754,8 @@ bool PList::load_string(const String &p_string) {
 		if (token == "/array") {
 			// Exit current array.
 			if (stack.is_empty() || stack.back()->get()->data_type != PList::PLNodeType::PL_NODE_TYPE_ARRAY) {
-				ERR_FAIL_V_MSG(false, "PList: Mismatched </array> tag.");
+				r_err_out = "Mismatched </array> tag.";
+				return false;
 			}
 			stack.pop_back();
 			continue;
@@ -751,13 +766,15 @@ bool PList::load_string(const String &p_string) {
 		} else {
 			int end_token_s = p_string.find("</", pos);
 			if (end_token_s == -1) {
-				ERR_FAIL_V_MSG(false, vformat("PList: Mismatched <%s> tag.", token));
+				r_err_out = vformat("Mismatched <%s> tag.", token);
+				return false;
 			}
 			int end_token_e = p_string.find(">", end_token_s);
 			pos = end_token_e;
 			String end_token = p_string.substr(end_token_s + 2, end_token_e - end_token_s - 2);
 			if (end_token != token) {
-				ERR_FAIL_V_MSG(false, vformat("PList: Mismatched <%s> and <%s> token pair.", token, end_token));
+				r_err_out = vformat("Mismatched <%s> and <%s> token pair.", token, end_token);
+				return false;
 			}
 			value = p_string.substr(open_token_e + 1, end_token_s - open_token_e - 1);
 		}
@@ -780,15 +797,18 @@ bool PList::load_string(const String &p_string) {
 			} else if (token == "date") {
 				var = PListNode::new_date(value);
 			} else {
-				ERR_FAIL_V_MSG(false, "PList: Invalid value type.");
+				r_err_out = vformat("Invalid value type: %s.", token);
+				return false;
 			}
 			if (stack.is_empty() || !stack.back()->get()->push_subnode(var, key)) {
-				ERR_FAIL_V_MSG(false, "PList: Can't push subnode, invalid parent type.");
+				r_err_out = "Can't push subnode, invalid parent type.";
+				return false;
 			}
 		}
 	}
 	if (!stack.is_empty() || !done_plist) {
-		ERR_FAIL_V_MSG(false, "PList: Unexpected end of data. Root node is not closed.");
+		r_err_out = "Unexpected end of data. Root node is not closed.";
+		return false;
 	}
 	return true;
 }

+ 4 - 4
platform/macos/export/plist.h → core/io/plist.h

@@ -28,8 +28,8 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */
 /**************************************************************************/
 
-#ifndef MACOS_PLIST_H
-#define MACOS_PLIST_H
+#ifndef PLIST_H
+#define PLIST_H
 
 // Property list file format (application/x-plist) parser, property list ASN-1 serialization.
 
@@ -75,7 +75,7 @@ public:
 	PList(const String &p_string);
 
 	bool load_file(const String &p_filename);
-	bool load_string(const String &p_string);
+	bool load_string(const String &p_string, String &r_err_out);
 
 	PackedByteArray save_asn1() const;
 	String save_text() const;
@@ -125,4 +125,4 @@ public:
 	~PListNode() {}
 };
 
-#endif // MACOS_PLIST_H
+#endif // PLIST_H

+ 1 - 0
misc/dist/macos_template.app/Contents/Info.plist

@@ -58,5 +58,6 @@ $usage_descriptions
 	</dict>
 	<key>NSHighResolutionCapable</key>
 $highres
+$additional_plist_content
 </dict>
 </plist>

+ 7 - 0
platform/ios/doc_classes/EditorExportPlatformIOS.xml

@@ -10,6 +10,13 @@
 		<link title="iOS plugins documentation index">$DOCS_URL/tutorials/platform/ios/index.html</link>
 	</tutorials>
 	<members>
+		<member name="application/additional_plist_content" type="String" setter="" getter="">
+			Additional data added to the root [code]&lt;dict&gt;[/code] section of the [url=https://developer.apple.com/documentation/bundleresources/information_property_list]Info.plist[/url] file. The value should be an XML section with pairs of key-value elements, e.g.:
+			[codeblock]
+			&lt;key&gt;key_name&lt;/key&gt;
+			&lt;string&gt;value&lt;/string&gt;
+			[/codeblock]
+		</member>
 		<member name="application/app_store_team_id" type="String" setter="" getter="">
 			Apple Team ID, unique 10-character string. To locate your Team ID check "Membership details" section in your Apple developer account dashboard, or "Organizational Unit" of your code signing certificate. See [url=https://developer.apple.com/help/account/manage-your-team/locate-your-team-id]Locate your Team ID[/url].
 		</member>

+ 25 - 0
platform/ios/export/export_plugin.cpp

@@ -34,6 +34,7 @@
 #include "run_icon_svg.gen.h"
 
 #include "core/io/json.h"
+#include "core/io/plist.h"
 #include "core/string/translation.h"
 #include "editor/editor_node.h"
 #include "editor/editor_paths.h"
@@ -154,6 +155,8 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
 
 	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/min_ios_version"), "12.0"));
 
+	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/additional_plist_content", PROPERTY_HINT_MULTILINE_TEXT), ""));
+
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/icon_interpolation", PROPERTY_HINT_ENUM, "Nearest neighbor,Bilinear,Cubic,Trilinear,Lanczos"), 4));
 
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "application/export_project_only"), false));
@@ -1498,6 +1501,8 @@ Error EditorExportPlatformIOS::_export_project_helper(const Ref<EditorExportPres
 		false
 	};
 
+	config_data.plist_content += p_preset->get("application/additional_plist_content").operator String() + "\n";
+
 	Vector<IOSExportAsset> assets;
 
 	Ref<DirAccess> tmp_app_path = DirAccess::create_for_path(dest_dir);
@@ -1867,6 +1872,26 @@ bool EditorExportPlatformIOS::has_valid_export_configuration(const Ref<EditorExp
 	valid = dvalid || rvalid;
 	r_missing_templates = !valid;
 
+	const String &additional_plist_content = p_preset->get("application/additional_plist_content");
+	if (!additional_plist_content.is_empty()) {
+		const String &plist = vformat("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+									  "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
+									  "<plist version=\"1.0\">"
+									  "<dict>\n"
+									  "%s\n"
+									  "</dict>\n"
+									  "</plist>\n",
+				additional_plist_content);
+
+		String plist_err;
+		Ref<PList> plist_parser;
+		plist_parser.instantiate();
+		if (!plist_parser->load_string(plist, plist_err)) {
+			err += TTR("Invalid additional PList content: ") + plist_err + "\n";
+			valid = false;
+		}
+	}
+
 	if (!err.is_empty()) {
 		r_error = err;
 	}

+ 7 - 0
platform/macos/doc_classes/EditorExportPlatformMacOS.xml

@@ -10,6 +10,13 @@
 		<link title="Running Godot apps on macOS">$DOCS_URL/tutorials//export/running_on_macos.html</link>
 	</tutorials>
 	<members>
+		<member name="application/additional_plist_content" type="String" setter="" getter="">
+			Additional data added to the root [code]&lt;dict&gt;[/code] section of the [url=https://developer.apple.com/documentation/bundleresources/information_property_list]Info.plist[/url] file. The value should be an XML section with pairs of key-value elements, e.g.:
+			[codeblock]
+			&lt;key&gt;key_name&lt;/key&gt;
+			&lt;string&gt;value&lt;/string&gt;
+			[/codeblock]
+		</member>
 		<member name="application/app_category" type="String" setter="" getter="">
 			Application category for the App Store.
 		</member>

+ 1 - 1
platform/macos/export/codesign.cpp

@@ -32,8 +32,8 @@
 
 #include "lipo.h"
 #include "macho.h"
-#include "plist.h"
 
+#include "core/io/plist.h"
 #include "core/os/os.h"
 #include "editor/editor_paths.h"
 #include "editor/editor_settings.h"

+ 1 - 2
platform/macos/export/codesign.h

@@ -41,11 +41,10 @@
 //  - Requirements code generator is not implemented (only hard-coded requirements for the ad-hoc signing is supported).
 //  - RFC5652/CMS blob generation is not implemented, supports ad-hoc signing only.
 
-#include "plist.h"
-
 #include "core/crypto/crypto_core.h"
 #include "core/io/dir_access.h"
 #include "core/io/file_access.h"
+#include "core/io/plist.h"
 #include "core/object/ref_counted.h"
 
 #include "modules/modules_enabled.gen.h" // For regex.

+ 25 - 0
platform/macos/export/export_plugin.cpp

@@ -37,6 +37,7 @@
 #include "run_icon_svg.gen.h"
 
 #include "core/io/image_loader.h"
+#include "core/io/plist.h"
 #include "core/string/translation.h"
 #include "drivers/png/png_driver_common.h"
 #include "editor/editor_node.h"
@@ -388,6 +389,8 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_angle", PROPERTY_HINT_ENUM, "Auto,Yes,No"), 0, true));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), true));
 
+	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/additional_plist_content", PROPERTY_HINT_MULTILINE_TEXT), ""));
+
 	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/platform_build"), "14C18"));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_version"), "13.1"));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "xcode/sdk_build"), "22C55"));
@@ -672,6 +675,8 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres
 			strnew += lines[i].replace("$min_version", p_preset->get("application/min_macos_version")) + "\n";
 		} else if (lines[i].find("$highres") != -1) {
 			strnew += lines[i].replace("$highres", p_preset->get("display/high_res") ? "\t<true/>" : "\t<false/>") + "\n";
+		} else if (lines[i].find("$additional_plist_content") != -1) {
+			strnew += lines[i].replace("$additional_plist_content", p_preset->get("application/additional_plist_content")) + "\n";
 		} else if (lines[i].find("$platfbuild") != -1) {
 			strnew += lines[i].replace("$platfbuild", p_preset->get("xcode/platform_build")) + "\n";
 		} else if (lines[i].find("$sdkver") != -1) {
@@ -2095,6 +2100,26 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor
 		};
 	}
 
+	const String &additional_plist_content = p_preset->get("application/additional_plist_content");
+	if (!additional_plist_content.is_empty()) {
+		const String &plist = vformat("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+									  "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
+									  "<plist version=\"1.0\">"
+									  "<dict>\n"
+									  "%s\n"
+									  "</dict>\n"
+									  "</plist>\n",
+				additional_plist_content);
+
+		String plist_err;
+		Ref<PList> plist_parser;
+		plist_parser.instantiate();
+		if (!plist_parser->load_string(plist, plist_err)) {
+			err += TTR("Invalid additional PList content: ") + plist_err + "\n";
+			valid = false;
+		}
+	}
+
 	List<ExportOption> options;
 	get_export_options(&options);
 	for (const EditorExportPlatform::ExportOption &E : options) {