diff --git a/docs/en/makers/exe.md b/docs/en/makers/exe.md index c60599b4..9ea9263c 100644 --- a/docs/en/makers/exe.md +++ b/docs/en/makers/exe.md @@ -20,6 +20,8 @@ create_desktop_icon: true # install_dir_name: "D:\\HELLO-WORLD" # This path is relative to the root directory of your project; The format of icon file must be ico, can not be png or others # setup_icon_file: windows\runner\resources\app_icon.ico +# Custom Inno Setup installation path (optional, defaults to "C:\Program Files (x86)\Inno Setup 6") +# inno_setup_path: "C:\Program Files (x86)\Inno Setup 6" locales: - en - zh @@ -33,6 +35,15 @@ fastforge package --platform windows --targets exe ## Advanced usage +### Custom Inno Setup path + +By default, `fastforge` looks for Inno Setup 6 at `C:\Program Files (x86)\Inno Setup 6`. If you have installed Inno Setup in a different location, you can specify the custom path using the `inno_setup_path` option in your `make_config.yaml`: + +```yaml +# Custom Inno Setup installation path +inno_setup_path: "D:\Tools\Inno Setup 6" +``` + ### Custom Inno Setup template By default, `fastforge` will generate an Inno Setup configuration (`.iss`) based on an internal template on build time, and populate it with the values provided in `make_config.yaml`. If you need more control over the Inno Setup configuration, you can provide a custom template using the `script_template` option. diff --git a/docs/zh/makers/exe.md b/docs/zh/makers/exe.md index 338a205f..f0dc7e58 100644 --- a/docs/zh/makers/exe.md +++ b/docs/zh/makers/exe.md @@ -20,6 +20,8 @@ create_desktop_icon: true # install_dir_name: "D:\\HELLO-WORLD" # 这里的路径是相对于项目根目录的路径; 图标格式必须是ico格式,不能是png或其它 # setup_icon_file: windows\runner\resources\app_icon.ico +# 自定义 Inno Setup 安装路径(可选,默认为 "C:\Program Files (x86)\Inno Setup 6") +# inno_setup_path: "C:\Program Files (x86)\Inno Setup 6" locales: - en - zh @@ -33,6 +35,15 @@ fastforge package --platform windows --targets exe ## 高级用法 +### 自定义 Inno Setup 路径 + +默认情况下,`fastforge` 在 `C:\Program Files (x86)\Inno Setup 6` 路径查找 Inno Setup 6。如果你将 Inno Setup 安装在其他位置,可以在 `make_config.yaml` 中使用 `inno_setup_path` 选项指定自定义路径: + +```yaml +# 自定义 Inno Setup 安装路径 +inno_setup_path: "D:\Tools\Inno Setup 6" +``` + ### 自定义 Inno Setup 模板 默认情况下,`fastforge` 会在构建时基于内部模板生成一个 Inno Setup 配置(`.iss`),并将其填充到 `make_config.yaml` 中提供的值。如果你需要对 Inno Setup 配置进行更多控制,你可以使用 `script_template` 选项提供一个自定义模板。 diff --git a/examples/custom_inno_setup_path.md b/examples/custom_inno_setup_path.md new file mode 100644 index 00000000..b35a7ee8 --- /dev/null +++ b/examples/custom_inno_setup_path.md @@ -0,0 +1,39 @@ +# Example: Using Custom Inno Setup Path + +This example demonstrates how to configure fastforge to use a custom Inno Setup installation path. + +## Configuration + +Add the following to your `windows/packaging/exe/make_config.yaml`: + +```yaml +# Basic app information +app_id: 5B599538-42B1-4826-A479-AF079F21A65D +publisher: LeanFlutter +publisher_url: https://github.com/fastforgedev/fastforge +display_name: Hello 世界 +create_desktop_icon: true + +# Custom Inno Setup path +inno_setup_path: "D:\Tools\Inno Setup 6" + +locales: + - en + - zh +``` + +## Use Cases + +This feature is useful when: + +1. **Non-standard Installation**: You installed Inno Setup in a custom directory +2. **Portable Installation**: You're using a portable version of Inno Setup +3. **Multiple Versions**: You have multiple versions of Inno Setup and want to use a specific one +4. **CI/CD Environments**: You have Inno Setup installed in a specific location in your build agents + +## Fallback Behavior + +If `inno_setup_path` is not specified or is `null`, fastforge will use the default path: +`C:\Program Files (x86)\Inno Setup 6` + +This ensures backward compatibility with existing configurations. \ No newline at end of file diff --git a/examples/hello_world/windows/packaging/exe/make_config.yaml b/examples/hello_world/windows/packaging/exe/make_config.yaml index 089d8111..bf04e47d 100644 --- a/examples/hello_world/windows/packaging/exe/make_config.yaml +++ b/examples/hello_world/windows/packaging/exe/make_config.yaml @@ -6,5 +6,7 @@ display_name: Hello 世界 create_desktop_icon: true launch_at_startup: true # install_dir_name: "D:\\HELLO-WORLD" +# Custom Inno Setup path (optional, defaults to "C:\Program Files (x86)\Inno Setup 6") +# inno_setup_path: "D:\Tools\Inno Setup 6" locales: - zh diff --git a/packages/flutter_app_packager/lib/src/makers/exe/app_package_maker_exe.dart b/packages/flutter_app_packager/lib/src/makers/exe/app_package_maker_exe.dart index db174f32..5c09ef7a 100644 --- a/packages/flutter_app_packager/lib/src/makers/exe/app_package_maker_exe.dart +++ b/packages/flutter_app_packager/lib/src/makers/exe/app_package_maker_exe.dart @@ -43,7 +43,7 @@ class AppPackageMakerExe extends AppPackageMaker { InnoSetupScript script = InnoSetupScript.fromMakeConfig(makeConfig); InnoSetupCompiler compiler = InnoSetupCompiler(); - bool compiled = await compiler.compile(script); + bool compiled = await compiler.compile(script, customPath: makeConfig.innoSetupPath); if (!compiled) { throw MakeError(); diff --git a/packages/flutter_app_packager/lib/src/makers/exe/inno_setup/inno_setup_compiler.dart b/packages/flutter_app_packager/lib/src/makers/exe/inno_setup/inno_setup_compiler.dart index 4ae4f637..840acdc1 100644 --- a/packages/flutter_app_packager/lib/src/makers/exe/inno_setup/inno_setup_compiler.dart +++ b/packages/flutter_app_packager/lib/src/makers/exe/inno_setup/inno_setup_compiler.dart @@ -5,12 +5,12 @@ import 'package:path/path.dart' as p; import 'package:shell_executor/shell_executor.dart'; class InnoSetupCompiler { - Future compile(InnoSetupScript script) async { - Directory innoSetupDirectory = - Directory('C:\\Program Files (x86)\\Inno Setup 6'); + Future compile(InnoSetupScript script, {String? customPath}) async { + String innoSetupPath = customPath ?? 'C:\\Program Files (x86)\\Inno Setup 6'; + Directory innoSetupDirectory = Directory(innoSetupPath); if (!innoSetupDirectory.existsSync()) { - throw Exception('`Inno Setup 6` was not installed.'); + throw Exception('`Inno Setup 6` was not found at: $innoSetupPath'); } File file = await script.createFile(); diff --git a/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart b/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart index ddcde617..5ccdad3c 100644 --- a/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart +++ b/packages/flutter_app_packager/lib/src/makers/exe/make_exe_config.dart @@ -6,6 +6,7 @@ import 'package:path/path.dart' as p; class MakeExeConfig extends MakeConfig { MakeExeConfig({ this.scriptTemplate, + this.innoSetupPath, required this.appId, this.executableName, this.displayName, @@ -33,6 +34,7 @@ class MakeExeConfig extends MakeConfig { MakeExeConfig makeExeConfig = MakeExeConfig( scriptTemplate: json['script_template'], + innoSetupPath: json['inno_setup_path'], appId: json['app_id'] ?? json['appId'], executableName: json['executable_name'], displayName: json['display_name'], @@ -49,6 +51,7 @@ class MakeExeConfig extends MakeConfig { } String? scriptTemplate; + String? innoSetupPath; final String appId; String? executableName; String? displayName; @@ -80,6 +83,7 @@ class MakeExeConfig extends MakeConfig { Map toJson() { return { 'script_template': scriptTemplate, + 'inno_setup_path': innoSetupPath, 'app_id': appId, 'app_name': appName, 'app_version': appVersion.toString(), diff --git a/packages/flutter_app_packager/test/src/makers/exe/make_exe_config_test.dart b/packages/flutter_app_packager/test/src/makers/exe/make_exe_config_test.dart new file mode 100644 index 00000000..36d59ade --- /dev/null +++ b/packages/flutter_app_packager/test/src/makers/exe/make_exe_config_test.dart @@ -0,0 +1,95 @@ +import 'dart:io'; + +import 'package:flutter_app_packager/src/makers/exe/make_exe_config.dart'; +import 'package:pub_semver/pub_semver.dart'; +import 'package:pubspec_parse/pubspec_parse.dart'; +import 'package:test/test.dart'; + +void main() { + group('MakeExeConfig', () { + test('fromJson should parse inno_setup_path correctly', () { + final json = { + 'app_id': 'test-app-id', + 'inno_setup_path': 'D:\\CustomPath\\Inno Setup 6', + 'display_name': 'Test App', + 'publisher_name': 'Test Publisher', + 'locales': ['en', 'zh'], + }; + + final config = MakeExeConfig.fromJson(json); + + expect(config.appId, equals('test-app-id')); + expect(config.innoSetupPath, equals('D:\\CustomPath\\Inno Setup 6')); + expect(config.displayName, equals('Test App')); + expect(config.publisherName, equals('Test Publisher')); + expect(config.locales, equals(['en', 'zh'])); + }); + + test('fromJson should handle missing inno_setup_path', () { + final json = { + 'app_id': 'test-app-id', + 'display_name': 'Test App', + 'locales': ['en'], + }; + + final config = MakeExeConfig.fromJson(json); + + expect(config.appId, equals('test-app-id')); + expect(config.innoSetupPath, isNull); + expect(config.displayName, equals('Test App')); + }); + + test('toJson should include inno_setup_path when present', () { + final config = MakeExeConfig( + appId: 'test-app-id', + innoSetupPath: 'D:\\CustomPath\\Inno Setup 6', + displayName: 'Test App', + publisherName: 'Test Publisher', + locales: ['en'], + ); + + // Set required fields for the base config + config.buildOutputDirectory = Directory('build'); + config.buildOutputFiles = []; + config.platform = 'windows'; + config.packageFormat = 'exe'; + config.outputDirectory = Directory('dist/'); + config.pubspec = Pubspec( + 'test_app', + version: Version.parse('1.0.0'), + ); + + final json = config.toJson(); + + expect(json['app_id'], equals('test-app-id')); + expect(json['inno_setup_path'], equals('D:\\CustomPath\\Inno Setup 6')); + expect(json['display_name'], equals('Test App')); + expect(json['publisher_name'], equals('Test Publisher')); + }); + + test('toJson should exclude null inno_setup_path', () { + final config = MakeExeConfig( + appId: 'test-app-id', + displayName: 'Test App', + locales: ['en'], + ); + + // Set required fields for the base config + config.buildOutputDirectory = Directory('build'); + config.buildOutputFiles = []; + config.platform = 'windows'; + config.packageFormat = 'exe'; + config.outputDirectory = Directory('dist/'); + config.pubspec = Pubspec( + 'test_app', + version: Version.parse('1.0.0'), + ); + + final json = config.toJson(); + + expect(json['app_id'], equals('test-app-id')); + expect(json.containsKey('inno_setup_path'), isFalse); + expect(json['display_name'], equals('Test App')); + }); + }); +} \ No newline at end of file