for 0.27.0 iOS packaging improved (#39)

* Override serious_python

* Fix yaml

* Manual signing and provisioning profile

* Introduce bundle_id and project_name

* Fix dict checks

* exportOptions.plist

* Output all vars

* Move .vars

* Fix expor options template

* Format template

* Pyodide 0.27.2

* Add teamid

* Added "ios_signing_certificate" var

* serious_python:main

* Fake run script to sign iOS bundle frameworks

* Updated sign script

* Explicitly sign .py files

* Remove custom code signing

* Use serious_python:resources branch

* return to main

* resources branch

* Add build_arch for Android

* Rename build_arch to target_arch

* Fix target_arch def value

* Hide target_arch inside options

* serious_python:main

* .plist to support arrays

* Add closing if

* fix template

* Another template fix

* Remove comments

* macOS plist to support arrays
This commit is contained in:
Feodor Fitsner 2025-02-18 15:38:30 -08:00 committed by GitHub
parent c99bd8f120
commit 2043b4a1cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 172 additions and 41 deletions

View File

@ -5,14 +5,20 @@
"project_name_slug": "", "project_name_slug": "",
"project_description": "", "project_description": "",
"product_name": "{{ cookiecutter.project_name }}", "product_name": "{{ cookiecutter.project_name }}",
"org_name": "com.flet", "org_name": "{{ cookiecutter.org_name if 'org_name' in cookiecutter else cookiecutter.bundle_id.rsplit('.', 1)[0] if 'bundle_id' in cookiecutter else 'com.flet' }}",
"company_name": "Your Company", "company_name": "Your Company",
"copyright": "Copyright (c) 2023 Your Company", "copyright": "Copyright (c) 2023 Your Company",
"flutter": null, "flutter": null,
"sep": "/", "sep": "/",
"kotlin_dir": "{{ cookiecutter.org_name.replace('.', cookiecutter.sep) }}{{ cookiecutter.sep }}{{ cookiecutter.project_name }}{{ cookiecutter.sep }}",
"hide_loading_animation": true, "hide_loading_animation": true,
"team_id": "", "bundle_id": "{{ cookiecutter.bundle_id if 'bundle_id' in cookiecutter else cookiecutter.org_name + '.' + cookiecutter.project_name }}",
"ios_provisioning_profile": "",
"ios_export_method": "",
"ios_signing_certificate": "",
"ios_export_options": {},
"ios_team_id": "",
"package_name": "{{ cookiecutter.bundle_id.rsplit('.', 1)[-1].replace('-', '_') if 'bundle_id' in cookiecutter else cookiecutter.project_name }}",
"kotlin_dir": "{{ cookiecutter.org_name.replace('.', cookiecutter.sep) }}{{ cookiecutter.sep }}{{ cookiecutter.package_name }}{{ cookiecutter.sep }}",
"base_url": "/", "base_url": "/",
"route_url_strategy": "path", "route_url_strategy": "path",
"web_renderer": "canvaskit", "web_renderer": "canvaskit",

View File

@ -0,0 +1,3 @@
{% for key, value in cookiecutter.items() -%}
{{ key }}: {{ value }}
{% endfor %}

View File

@ -50,7 +50,7 @@ android {
} }
defaultConfig { defaultConfig {
applicationId "{{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}" applicationId "{{ cookiecutter.bundle_id }}"
minSdkVersion flutter.minSdkVersion minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()

View File

@ -1,4 +1,4 @@
package {{ cookiecutter.org_name }}.{{ cookiecutter.project_name }} package {{ cookiecutter.org_name }}.{{ cookiecutter.package_name }}
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity

View File

@ -360,9 +360,16 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
{% if cookiecutter.team_id %} {% if cookiecutter.ios_team_id %}
DEVELOPMENT_TEAM = {{ cookiecutter.team_id }}; DEVELOPMENT_TEAM = "{{ cookiecutter.ios_team_id }}";
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
CODE_SIGN_IDENTITY = "{{ cookiecutter.ios_signing_certificate }}";
{% endif %}
{% if cookiecutter.ios_provisioning_profile %}
PROVISIONING_PROFILE_SPECIFIER = "{{ cookiecutter.ios_provisioning_profile }}";
{% endif %} {% endif %}
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -370,7 +377,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }};
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@ -387,7 +394,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -405,7 +412,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -421,7 +428,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@ -541,9 +548,16 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
{% if cookiecutter.team_id %} {% if cookiecutter.ios_team_id %}
DEVELOPMENT_TEAM = {{ cookiecutter.team_id }}; DEVELOPMENT_TEAM = "{{ cookiecutter.ios_team_id }}";
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
CODE_SIGN_IDENTITY = "{{ cookiecutter.ios_signing_certificate }}";
{% endif %}
{% if cookiecutter.ios_provisioning_profile %}
PROVISIONING_PROFILE_SPECIFIER = "{{ cookiecutter.ios_provisioning_profile }}";
{% endif %} {% endif %}
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -551,7 +565,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }};
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@ -566,9 +580,16 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
{% if cookiecutter.team_id %} {% if cookiecutter.ios_team_id %}
DEVELOPMENT_TEAM = {{ cookiecutter.team_id }}; DEVELOPMENT_TEAM = "{{ cookiecutter.ios_team_id }}";
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
CODE_SIGN_IDENTITY = "{{ cookiecutter.ios_signing_certificate }}";
{% endif %}
{% if cookiecutter.ios_provisioning_profile %}
PROVISIONING_PROFILE_SPECIFIER = "{{ cookiecutter.ios_provisioning_profile }}";
{% endif %} {% endif %}
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@ -576,7 +597,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }};
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;

View File

@ -67,14 +67,35 @@
</dict> </dict>
</array> </array>
<!-- flet: end of deep linking {% endif %} --> <!-- flet: end of deep linking {% endif %} -->
<!-- flet: prop {% for k, v in cookiecutter.options.info_plist.items() %} -->
<key>{{ k }}</key> {% macro render_dict(d) -%}
<!-- flet: True {% if v == True %} --> {% for key, value in d.items() -%}
<true /> <key>{{ key }}</key>
<!-- flet: False {% elif v == False %} --> {% if value is string -%}
<false /> <string>{{ value }}</string>
<!-- flet: string value {% else %} --> {% elif value is boolean -%}
<string>{{ v }}</string> <{{ "true" if value else "false" }}/>
<!-- flet: end of prop {% endif %} {% endfor %} --> {% elif value is mapping -%}
<dict>
{{ render_dict(value) }}
</dict>
{% elif value is sequence -%} {# Support for lists/arrays #}
<array>
{% for item in value -%}
{% if item is string -%}
<string>{{ item }}</string>
{% elif item is boolean -%}
<{{ "true" if item else "false" }}/>
{% elif item is mapping -%}
<dict>
{{ render_dict(item) }}
</dict>
{% endif -%}
{% endfor -%}
</array>
{% endif -%}
{% endfor -%}
{% endmacro -%}
{{ render_dict(cookiecutter.options.info_plist) }}
</dict> </dict>
</plist> </plist>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>{{ cookiecutter.ios_export_method }}</string>
<key>provisioningProfiles</key>
<dict>
<key>{{ cookiecutter.bundle_id }}</key>
<string>{{ cookiecutter.ios_provisioning_profile }}</string>
</dict>
{% if cookiecutter.ios_team_id %}
<key>teamID</key>
<string>{{ cookiecutter.ios_team_id }}</string>
{% endif %}
{% if cookiecutter.ios_signing_certificate %}
<key>signingCertificate</key>
<string>{{ cookiecutter.ios_signing_certificate }}</string>
{% endif %}
{% macro render_dict(d) -%}
{% for key, value in d.items() -%}
<key>{{ key }}</key>
{% if value is string -%}
<string>{{ value }}</string>
{% elif value is boolean -%}
<{{ "true" if value else "false" }}/>
{% elif value is mapping -%}
<dict>
{{ render_dict(value) }}
</dict>
{% elif value is sequence -%} {# Support for lists/arrays #}
<array>
{% for item in value -%}
{% if item is string -%}
<string>{{ item }}</string>
{% elif item is boolean -%}
<{{ "true" if item else "false" }}/>
{% elif item is mapping -%}
<dict>
{{ render_dict(item) }}
</dict>
{% endif -%}
{% endfor -%}
</array>
{% endif -%}
{% endfor -%}
{% endmacro -%}
{{ render_dict(cookiecutter.ios_export_options) }}
</dict>
</plist>

View File

@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
set(BINARY_NAME "{{ cookiecutter.project_name }}") set(BINARY_NAME "{{ cookiecutter.project_name }}")
# The unique GTK application identifier for this application. See: # The unique GTK application identifier for this application. See:
# https://wiki.gnome.org/HowDoI/ChooseApplicationID # https://wiki.gnome.org/HowDoI/ChooseApplicationID
set(APPLICATION_ID "{{ cookiecutter.org_name }}.{{ cookiecutter.project_name }}") set(APPLICATION_ID "{{ cookiecutter.bundle_id }}")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake. # versions of CMake.

View File

@ -384,7 +384,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}";
@ -398,7 +398,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}";
@ -412,7 +412,7 @@
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }}.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/{{ cookiecutter.project_name }}.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/{{ cookiecutter.project_name }}";

View File

@ -8,7 +8,7 @@
PRODUCT_NAME = {{ cookiecutter.product_name }} PRODUCT_NAME = {{ cookiecutter.product_name }}
// The application's bundle identifier // The application's bundle identifier
PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.org_name }}.{{ cookiecutter.project_name_slug }} PRODUCT_BUNDLE_IDENTIFIER = {{ cookiecutter.bundle_id }}
// The copyright displayed in application information // The copyright displayed in application information
PRODUCT_COPYRIGHT = {{ cookiecutter.copyright }}. All rights reserved. PRODUCT_COPYRIGHT = {{ cookiecutter.copyright }}. All rights reserved.

View File

@ -28,14 +28,35 @@
<string>MainMenu</string> <string>MainMenu</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<!-- flet: prop {% for k, v in cookiecutter.options.info_plist.items() %} -->
<key>{{ k }}</key> {% macro render_dict(d) -%}
<!-- flet: True {% if v == True %} --> {% for key, value in d.items() -%}
<true /> <key>{{ key }}</key>
<!-- flet: False {% elif v == False %} --> {% if value is string -%}
<false /> <string>{{ value }}</string>
<!-- flet: string value {% else %} --> {% elif value is boolean -%}
<string>{{ v }}</string> <{{ "true" if value else "false" }}/>
<!-- flet: end of prop {% endif %} {% endfor %} --> {% elif value is mapping -%}
<dict>
{{ render_dict(value) }}
</dict>
{% elif value is sequence -%} {# Support for lists/arrays #}
<array>
{% for item in value -%}
{% if item is string -%}
<string>{{ item }}</string>
{% elif item is boolean -%}
<{{ "true" if item else "false" }}/>
{% elif item is mapping -%}
<dict>
{{ render_dict(item) }}
</dict>
{% endif -%}
{% endfor -%}
</array>
{% endif -%}
{% endfor -%}
{% endmacro -%}
{{ render_dict(cookiecutter.options.info_plist) }}
</dict> </dict>
</plist> </plist>

View File

@ -28,6 +28,12 @@ dependency_overrides:
# ref: main # ref: main
# url: https://github.com/flet-dev/flet.git # url: https://github.com/flet-dev/flet.git
serious_python:
git:
url: https://github.com/flet-dev/serious-python.git
ref: main
path: src/serious_python
wakelock_plus: ^1.2.10 wakelock_plus: ^1.2.10
web: ^1.0.0 web: ^1.0.0
window_manager: ^0.4.3 window_manager: ^0.4.3

View File

@ -1,4 +1,4 @@
importScripts("https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js"); importScripts("https://cdn.jsdelivr.net/pyodide/v0.27.2/full/pyodide.js");
self.pythonModuleName = null; self.pythonModuleName = null;
self.initialized = false; self.initialized = false;