Skip to content

Commit

Permalink
[exe maker] Add display_name, create_desktop_icon, install_dir_name, …
Browse files Browse the repository at this point in the history
…fields #25 #57
  • Loading branch information
lijy91 committed Apr 3, 2022
1 parent c8c7460 commit 39461dc
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 123 deletions.
11 changes: 8 additions & 3 deletions examples/hello_world/windows/packaging/exe/make_config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
appId: C52EDEB4-E345-4C95-BF90-E2BF83CF2B30
appPublisher: LeanFlutter
appPublisherUrl: https://github.com/leanflutter/flutter_distributor
app_id: C52EDEB4-E345-4C95-BF90-E2BF83CF2B30
publisher_name: LeanFlutter
publisher_url: https://github.com/leanflutter/flutter_distributor
display_name: 你好世界
create_desktop_icon: true
install_dir_name: HELLO-WORLD
locales:
- zh
31 changes: 10 additions & 21 deletions packages/app_package_maker_exe/lib/src/app_package_maker_exe.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'dart:io';

import 'package:app_package_maker/app_package_maker.dart';
import 'package:path/path.dart' as p;
import 'package:io/io.dart';

import 'inno_setup/inno_setup_compiler.dart';
import 'inno_setup/inno_setup_script.dart';
import 'make_exe_config.dart';
import 'create_setup_script_file.dart';

class AppPackageMakerExe extends AppPackageMaker {
String get name => 'exe';
Expand All @@ -31,36 +31,25 @@ class AppPackageMakerExe extends AppPackageMaker {
void Function(List<int> data)? onProcessStdOut,
void Function(List<int> data)? onProcessStdErr,
}) async {
MakeConfig makeConfig = await loadMakeConfig()
MakeExeConfig makeConfig = await loadMakeConfig() as MakeExeConfig
..outputDirectory = outputDirectory;
Directory packagingDirectory = makeConfig.packagingDirectory;

Directory innoSetupDirectory =
Directory('C:\\Program Files (x86)\\Inno Setup 6');

if (!innoSetupDirectory.existsSync()) {
throw Exception('`Inno Setup 6` was not installed.');
}

copyPathSync(appDirectory.path, packagingDirectory.path);

File setupScriptFile =
await createSetupScriptFile(makeConfig as MakeExeConfig);
InnoSetupScript script = InnoSetupScript.fromMakeConfig(makeConfig);
InnoSetupCompiler compiler = InnoSetupCompiler();

Process process = await Process.start(
p.join(innoSetupDirectory.path, 'ISCC.exe'),
[setupScriptFile.path],
bool compiled = await compiler.compile(
script,
onProcessStdErr: onProcessStdErr,
onProcessStdOut: onProcessStdOut,
);
process.stdout.listen(onProcessStdOut);
process.stderr.listen(onProcessStdErr);

int exitCode = await process.exitCode;
if (exitCode != 0) {
if (!compiled) {
throw MakeError();
}

packagingDirectory.deleteSync(recursive: true);
setupScriptFile.deleteSync(recursive: true);

return MakeResult(makeConfig);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'dart:io';
import 'package:path/path.dart' as p;

import './inno_setup_script.dart';

class InnoSetupCompiler {
Future<bool> compile(
InnoSetupScript script, {
void Function(List<int> data)? onProcessStdOut,
void Function(List<int> data)? onProcessStdErr,
}) async {
Directory innoSetupDirectory =
Directory('C:\\Program Files (x86)\\Inno Setup 6');

if (!innoSetupDirectory.existsSync()) {
throw Exception('`Inno Setup 6` was not installed.');
}

File file = await script.createFile();

Process process = await Process.start(
p.join(innoSetupDirectory.path, 'ISCC.exe'),
[file.path],
);
process.stdout.listen(onProcessStdOut);
process.stderr.listen(onProcessStdErr);

int exitCode = await process.exitCode;
if (exitCode != 0) {
return false;
}

file.deleteSync(recursive: true);
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import 'dart:io';

import 'package:liquid_engine/liquid_engine.dart';

import '../make_exe_config.dart';

const String _template = """
[Setup]
AppId={{APP_ID}}
AppVersion={{APP_VERSION}}
AppName={{DISPLAY_NAME}}
AppPublisher={{PUBLISHER_NAME}}
AppPublisherURL={{PUBLISHER_URL}}
AppSupportURL={{PUBLISHER_URL}}
AppUpdatesURL={{PUBLISHER_URL}}
DefaultDirName={autopf}\\{{INSTALL_DIR_NAME}}
DisableProgramGroupPage=yes
OutputDir=.
OutputBaseFilename={{OUTPUT_BASE_FILENAME}}
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
{% for locale in LOCALES %}
{% if locale == 'en' %}Name: "english"; MessagesFile: "compiler:Default.isl"{% endif %}
{% if locale == 'zh' %}Name: "chinesesimplified"; MessagesFile: "compiler:Languages\\ChineseSimplified.isl"{% endif %}
{% endfor %}
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: {% if CREATE_DESKTOP_ICON != true %}unchecked{% else %}checkedonce{% endif %}
[Files]
Source: "{{SOURCE_DIR}}\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{autoprograms}\\{{APP_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"
Name: "{autodesktop}\\{{APP_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"; Tasks: desktopicon
[Run]
Filename: "{app}\\{{EXECUTABLE_NAME}}"; Description: "{cm:LaunchProgram,{{DISPLAY_NAME}}}"; Flags: nowait postinstall skipifsilent
""";

class InnoSetupScript {
final MakeExeConfig makeConfig;

InnoSetupScript({
required this.makeConfig,
});

factory InnoSetupScript.fromMakeConfig(MakeExeConfig makeConfig) {
return InnoSetupScript(
makeConfig: makeConfig,
);
}

Future<File> createFile() async {
Map<String, dynamic> variables = {
'APP_ID': makeConfig.appId,
'APP_NAME': makeConfig.appName,
'APP_VERSION': makeConfig.appVersion.toString(),
'EXECUTABLE_NAME':
makeConfig.executableName ?? makeConfig.defaultExecutableName,
'DISPLAY_NAME': makeConfig.displayName,
'PUBLISHER_NAME': makeConfig.publisherName,
'PUBLISHER_URL': makeConfig.publisherUrl,
'CREATE_DESKTOP_ICON': makeConfig.createDesktopIcon,
'INSTALL_DIR_NAME':
makeConfig.installDirName ?? makeConfig.defaultInstallDirName,
'SOURCE_DIR': makeConfig.sourceDir,
'OUTPUT_BASE_FILENAME': makeConfig.outputBaseFileName,
'LOCALES': makeConfig.locales,
}..removeWhere((key, value) => value == null);

Context context = Context.create();
context.variables = variables;

Template template = Template.parse(
context,
Source.fromString(_template),
);

String content = await template.render(context);
File file = File('${makeConfig.packagingDirectory.path}.iss');

file.writeAsStringSync(content);
return file;
}
}
67 changes: 56 additions & 11 deletions packages/app_package_maker_exe/lib/src/make_exe_config.dart
Original file line number Diff line number Diff line change
@@ -1,29 +1,74 @@
import 'dart:io';
import 'package:path/path.dart' as p;

import 'package:app_package_maker/app_package_maker.dart';

class MakeExeConfig extends MakeConfig {
final String appId;
String? appPublisher;
String? appPublisherUrl;
String? executableName;
String? displayName;
String? publisherName;
String? publisherUrl;
bool? createDesktopIcon;
String? installDirName;
List<String>? locales;

String get defaultExecutableName {
File executableFile = packagingDirectory
.listSync()
.where((e) => e.path.endsWith('.exe'))
.map((e) => File(e.path))
.first;
return p.basename(executableFile.path);
}

String get defaultInstallDirName => appName;

String get sourceDir => p.basename(packagingDirectory.path);
String get outputBaseFileName =>
p.basename(outputFile.path).replaceAll('.exe', '');

MakeExeConfig({
required this.appId,
this.appPublisher,
this.appPublisherUrl,
this.executableName,
this.displayName,
this.publisherName,
this.publisherUrl,
this.createDesktopIcon,
this.installDirName,
this.locales,
});

factory MakeExeConfig.fromJson(Map<String, dynamic> json) {
return MakeExeConfig(
appId: json['appId'],
appPublisher: json['appPublisher'],
appPublisherUrl: json['appPublisherUrl'],
List<String>? locales =
json['locales'] != null ? List<String>.from(json['locales']) : null;
if (locales == null || locales.isEmpty) locales = ['en'];

MakeExeConfig makeExeConfig = MakeExeConfig(
appId: json['app_id'] ?? json['appId'],
executableName: json['executable_name'],
displayName: json['display_name'],
publisherName: json['publisher_name'] ?? json['appPublisher'],
publisherUrl: json['publisher_url'] ?? json['appPublisherUrl'],
createDesktopIcon: json['create_desktop_icon'],
installDirName: json['install_dir_name'],
locales: locales,
);
return makeExeConfig;
}

Map<String, dynamic> toJson() {
return {
'appId': appId,
'appPublisher': appPublisher,
'appPublisherUrl': appPublisherUrl,
'app_id': appId,
'app_name': appName,
'app_version': appVersion.toString(),
'executable_name': executableName,
'display_name': displayName,
'publisher_name': publisherName,
'publisher_url': publisherUrl,
'create_desktop_icon': createDesktopIcon,
'install_dir_name': installDirName,
'locales': locales,
}..removeWhere((key, value) => value == null);
}
}
7 changes: 7 additions & 0 deletions packages/app_package_maker_exe/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
liquid_engine:
dependency: "direct main"
description:
name: liquid_engine
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.2"
meta:
dependency: transitive
description:
Expand Down
5 changes: 1 addition & 4 deletions packages/app_package_maker_exe/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,5 @@ environment:
dependencies:
app_package_maker: ^0.1.3
io: ^1.0.3
liquid_engine: ^0.2.2
path: ^1.8.1

# dependency_overrides:
# app_package_maker:
# path: ../app_package_maker
Loading

0 comments on commit 39461dc

Please sign in to comment.