From 23653407b799c753f3bd5dee438806791f0d829b Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Wed, 25 Oct 2023 11:20:52 +0200 Subject: [PATCH 01/11] #4170 Added addRunScript method into xcodeProj. --- lib/src/pbx/target.dart | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index 3c090f8..425787f 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -16,6 +16,45 @@ mixin PBXTargetMixin on PBXElement { /// The product name String get productName => get('productName'); + + /// Add Run script into Xcode "Build Phase". + void addRunScript({ + required String name, + required String shellScript, + List files = const [], + List inputFileListPaths = const [], + List inputsPaths = const [], + List outputPaths = const [], + List outputFileListPaths = const [], + int? showEnvVarsInLog, // 'Show environment variables in build log' default checked (null - not visible) + String? dependencyFile, // Default 'discovered dependency file' option unchecked (null - not visible) + int? alwaysOutOfDate, // 'Based on dependency analysis' default checked (null - not visible) + }) { + const buildActionMask = 2147483647; // buildActionMask is const (compatible) for this below parameter + const runOnlyForDeploymentPostprocessing = 0; // install build only = false (unchecked) + + var uuid = UuidGenerator().random(); + + project.set('objects/$uuid', { + 'isa': 'PBXShellScriptBuildPhase', + 'name': name, + 'alwaysOutOfDate': alwaysOutOfDate, + 'buildActionMask': buildActionMask, + 'files': files, + 'inputFileListPaths': inputFileListPaths, + 'inputPaths': inputsPaths, + 'outputFileListPaths': outputFileListPaths, + 'outputPaths': outputPaths, + 'shellPath': '/bin/sh;', + 'shellScript': shellScript, + 'runOnlyForDeploymentPostprocessing': runOnlyForDeploymentPostprocessing, + 'showEnvVarsInLog': showEnvVarsInLog, + 'dependencyFile': dependencyFile, + }); + + var p = 'objects/${this.uuid}/buildPhases'; + project.set(p, [...getList('buildPhases'), uuid]); + } } abstract class PBXTarget = PBXElement with PBXTargetMixin; From e3e8e8386d81ddf1a43b52d5c7fc07dd803affd7 Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Wed, 25 Oct 2023 14:30:30 +0200 Subject: [PATCH 02/11] #4170 Added optional shellPath parameter. Deleted wrong hardcoded parameter with ';'. --- lib/src/pbx/target.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index 425787f..96deef3 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -26,6 +26,7 @@ mixin PBXTargetMixin on PBXElement { List inputsPaths = const [], List outputPaths = const [], List outputFileListPaths = const [], + String shellPath = '/bin/sh', int? showEnvVarsInLog, // 'Show environment variables in build log' default checked (null - not visible) String? dependencyFile, // Default 'discovered dependency file' option unchecked (null - not visible) int? alwaysOutOfDate, // 'Based on dependency analysis' default checked (null - not visible) @@ -45,7 +46,7 @@ mixin PBXTargetMixin on PBXElement { 'inputPaths': inputsPaths, 'outputFileListPaths': outputFileListPaths, 'outputPaths': outputPaths, - 'shellPath': '/bin/sh;', + 'shellPath': shellPath, 'shellScript': shellScript, 'runOnlyForDeploymentPostprocessing': runOnlyForDeploymentPostprocessing, 'showEnvVarsInLog': showEnvVarsInLog, From 851138c5b794c0b7b6876b246bd6f2c0bab48411 Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Wed, 25 Oct 2023 14:33:08 +0200 Subject: [PATCH 03/11] #4170 Added 'name' parameter for PBXShellScriptBuildPhaseMixin. --- lib/src/pbx/build_phase.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/pbx/build_phase.dart b/lib/src/pbx/build_phase.dart index 0856c52..6c2c5de 100644 --- a/lib/src/pbx/build_phase.dart +++ b/lib/src/pbx/build_phase.dart @@ -51,6 +51,8 @@ mixin PBXShellScriptBuildPhaseMixin on PBXBuildPhaseMixin { /// The content of the script shell String get shellScript => get('shellScript'); + + String get name => get('name'); } /// Element for the resources copy build phase. From e7823110192c2ecce778062a6852d2af0796b8a5 Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Thu, 26 Oct 2023 13:20:23 +0200 Subject: [PATCH 04/11] #4170 Added removeRunScript method. --- lib/src/pbx/target.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index 96deef3..e33f145 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -56,6 +56,24 @@ mixin PBXTargetMixin on PBXElement { var p = 'objects/${this.uuid}/buildPhases'; project.set(p, [...getList('buildPhases'), uuid]); } + + /// Remove Run script from Xcode "Build Phase", also the reference. + void removeRunScript(String name) { + final buildPhasesListString = [...getList('buildPhases')]; + + // list uuid which is the same as 'name' parameter + final uuidToDeleted = buildPhases.whereType().where((element) => element.name == name).map((e) => e.uuid); + + // Remove run script object (with all parameters) + for (final uuid in uuidToDeleted) { + buildPhasesListString.removeWhere((element) => (element as String) == uuid); + project.set('objects/$uuid', null); + } + + // Remove UUIDs from buildPhases list (reference) + var p = 'objects/$uuid/buildPhases'; + project.set(p, buildPhasesListString); + } } abstract class PBXTarget = PBXElement with PBXTargetMixin; From a23dd1bffdf4941712da2b417c535407a8ffe2e1 Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Thu, 26 Oct 2023 13:36:12 +0200 Subject: [PATCH 05/11] #4170 Changed flags into boolean values in addRunScript(). --- lib/src/pbx/target.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index e33f145..61edd85 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -27,9 +27,9 @@ mixin PBXTargetMixin on PBXElement { List outputPaths = const [], List outputFileListPaths = const [], String shellPath = '/bin/sh', - int? showEnvVarsInLog, // 'Show environment variables in build log' default checked (null - not visible) + bool showEnvVarsInLog = true, // 'Show environment variables in build log' default checked (null - not visible) String? dependencyFile, // Default 'discovered dependency file' option unchecked (null - not visible) - int? alwaysOutOfDate, // 'Based on dependency analysis' default checked (null - not visible) + bool alwaysOutOfDate = true, // 'Based on dependency analysis' default checked (null - not visible) }) { const buildActionMask = 2147483647; // buildActionMask is const (compatible) for this below parameter const runOnlyForDeploymentPostprocessing = 0; // install build only = false (unchecked) @@ -39,7 +39,7 @@ mixin PBXTargetMixin on PBXElement { project.set('objects/$uuid', { 'isa': 'PBXShellScriptBuildPhase', 'name': name, - 'alwaysOutOfDate': alwaysOutOfDate, + 'alwaysOutOfDate': alwaysOutOfDate ? null : 1, // this is not an error, xCode set flag 1 if this value unchecked 'buildActionMask': buildActionMask, 'files': files, 'inputFileListPaths': inputFileListPaths, @@ -49,7 +49,7 @@ mixin PBXTargetMixin on PBXElement { 'shellPath': shellPath, 'shellScript': shellScript, 'runOnlyForDeploymentPostprocessing': runOnlyForDeploymentPostprocessing, - 'showEnvVarsInLog': showEnvVarsInLog, + 'showEnvVarsInLog': showEnvVarsInLog ? null : 0, // this is not an error, xCode set flag 0 if this value unchecked 'dependencyFile': dependencyFile, }); From 345836813a9d7966bc4928666ccc6fd8f6aebff6 Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Thu, 26 Oct 2023 14:04:00 +0200 Subject: [PATCH 06/11] #4170 Added bool for removeRunScript(). --- lib/src/pbx/target.dart | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index 61edd85..7cdc462 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -57,13 +57,20 @@ mixin PBXTargetMixin on PBXElement { project.set(p, [...getList('buildPhases'), uuid]); } - /// Remove Run script from Xcode "Build Phase", also the reference. - void removeRunScript(String name) { + /// Remove Run script with proper [name] from Xcode "Build Phase", and also the reference. + /// Return true if script existed and now it doesn't, otherwise false. + bool removeRunScript(String name) { + var isRemoved = false; + final buildPhasesListString = [...getList('buildPhases')]; // list uuid which is the same as 'name' parameter final uuidToDeleted = buildPhases.whereType().where((element) => element.name == name).map((e) => e.uuid); + if (uuidToDeleted.isNotEmpty) { + isRemoved = true; + } + // Remove run script object (with all parameters) for (final uuid in uuidToDeleted) { buildPhasesListString.removeWhere((element) => (element as String) == uuid); @@ -73,6 +80,8 @@ mixin PBXTargetMixin on PBXElement { // Remove UUIDs from buildPhases list (reference) var p = 'objects/$uuid/buildPhases'; project.set(p, buildPhasesListString); + + return isRemoved; } } From 8e5dbcebe98a9888cdc2a9ba4d788c3f886c5d98 Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Mon, 30 Oct 2023 17:39:26 +0100 Subject: [PATCH 07/11] #4191 Handled remove object in PBXGroupMixin. --- lib/src/pbx/file_element.dart | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/lib/src/pbx/file_element.dart b/lib/src/pbx/file_element.dart index 51da1e7..3557e7e 100644 --- a/lib/src/pbx/file_element.dart +++ b/lib/src/pbx/file_element.dart @@ -65,6 +65,33 @@ mixin PBXGroupMixin on PBXFileElement { /// A list of references to [PBXFileElement] elements List get children => getObjectList('children'); + bool removeReference(String path) { + var isRemoved = false; + + var children = [...this.children]; + + // list uuids which is the same as 'path' parameter + final uuidToDeleted = children.where((e) => e.path == path).map((e) => e.uuid).toList(); + + if (uuidToDeleted.isNotEmpty) { + isRemoved = true; + } + + // Remove object + children.removeWhere((childrenElement) => uuidToDeleted.any((element) => element == childrenElement.uuid)); + + for (var element in uuidToDeleted) { + project.set('objects/$element', null); + } + + // Remove reference (UUID) + final modifiedChildrenUUIDList = children.map((e) => e.uuid).toList(); + var p = '$_path/children'; + project.set(p, [...modifiedChildrenUUIDList]); + + return isRemoved; + } + PBXFileReference? addReference(String path, {String sourceTree = ''}) { var uuid = UuidGenerator().random(); From cde92cd1cb07c4b65ecae741a22520466f1c686a Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Mon, 30 Oct 2023 17:53:08 +0100 Subject: [PATCH 08/11] #4191 Fixed typo. --- lib/src/pbx/file_element.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/pbx/file_element.dart b/lib/src/pbx/file_element.dart index 3557e7e..5036b31 100644 --- a/lib/src/pbx/file_element.dart +++ b/lib/src/pbx/file_element.dart @@ -65,7 +65,7 @@ mixin PBXGroupMixin on PBXFileElement { /// A list of references to [PBXFileElement] elements List get children => getObjectList('children'); - bool removeReference(String path) { + bool removeReferences(String path) { var isRemoved = false; var children = [...this.children]; From 1498983f4906e161567770b750957f25aa8fde2c Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Thu, 11 Apr 2024 11:10:46 +0200 Subject: [PATCH 09/11] #4997 Added path parameter to addReference(). --- lib/src/pbx/file_element.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/pbx/file_element.dart b/lib/src/pbx/file_element.dart index 5036b31..f1faddf 100644 --- a/lib/src/pbx/file_element.dart +++ b/lib/src/pbx/file_element.dart @@ -92,11 +92,11 @@ mixin PBXGroupMixin on PBXFileElement { return isRemoved; } - PBXFileReference? addReference(String path, {String sourceTree = ''}) { + PBXFileReference? addReference(String path, {String sourceTree = '', String? name}) { var uuid = UuidGenerator().random(); project.set('objects/$uuid', - {'isa': 'PBXFileReference', 'path': path, 'sourceTree': sourceTree}); + {'isa': 'PBXFileReference', 'path': path, 'name': name ?? path, 'sourceTree': sourceTree}); project.set('$_path/children', [...getList('children'), uuid]); return project.getObject(uuid) as PBXFileReference?; From ccb298d2d779e0ea924deac1afecbd5d9bb8fe30 Mon Sep 17 00:00:00 2001 From: czarny Date: Fri, 28 Mar 2025 15:21:25 +0100 Subject: [PATCH 10/11] #6717 Handled possibility to add framework to project target. --- lib/src/pbx/build_phase.dart | 8 +++++++- lib/src/pbx/file_element.dart | 8 ++++---- lib/src/pbx/target.dart | 11 +++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/src/pbx/build_phase.dart b/lib/src/pbx/build_phase.dart index 6c2c5de..49c6597 100644 --- a/lib/src/pbx/build_phase.dart +++ b/lib/src/pbx/build_phase.dart @@ -24,7 +24,13 @@ mixin PBXCopyFilesBuildPhaseMixin on PBXBuildPhaseMixin { /// Element for the copy file build phase. class PBXCopyFilesBuildPhase = PBXBuildPhase with PBXCopyFilesBuildPhaseMixin; -mixin PBXFrameworksBuildPhaseMixin on PBXBuildPhaseMixin {} +mixin PBXFrameworksBuildPhaseMixin on PBXBuildPhaseMixin { + void linkBinaryWithFile(PBXFileReference file) { + var uuid = UuidGenerator().random(); + project.set('objects/$uuid', {'isa': 'PBXBuildFile', 'fileRef': file.uuid}); + project.set('$_path/files', [...getList('files'), uuid]); + } +} /// Element for the framework link build phase. class PBXFrameworksBuildPhase = PBXBuildPhase with PBXFrameworksBuildPhaseMixin; diff --git a/lib/src/pbx/file_element.dart b/lib/src/pbx/file_element.dart index f1faddf..a6a84b1 100644 --- a/lib/src/pbx/file_element.dart +++ b/lib/src/pbx/file_element.dart @@ -92,14 +92,14 @@ mixin PBXGroupMixin on PBXFileElement { return isRemoved; } - PBXFileReference? addReference(String path, {String sourceTree = '', String? name}) { + PBXFileReference addReference(String path, {String sourceTree = '', String? name}) { var uuid = UuidGenerator().random(); + name = name ?? path_lib.basename(path); - project.set('objects/$uuid', - {'isa': 'PBXFileReference', 'path': path, 'name': name ?? path, 'sourceTree': sourceTree}); + project.set('objects/$uuid', {'isa': 'PBXFileReference', 'path': path, 'name': name, 'sourceTree': sourceTree}); project.set('$_path/children', [...getList('children'), uuid]); - return project.getObject(uuid) as PBXFileReference?; + return project.getObject(uuid) as PBXFileReference; } } diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index 7cdc462..2ff4021 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -83,6 +83,17 @@ mixin PBXTargetMixin on PBXElement { return isRemoved; } + + void addFramework(String path, String sourceTree) { + var frameworks = project.groups.where((group) => group.name == 'Frameworks').single; + + var reference = frameworks.children.where((file) => file.path == path); + if (reference.isEmpty) { + var file = frameworks.addReference(path, sourceTree: sourceTree); + var phase = buildPhases.where((phase) => phase.runtimeType == PBXFrameworksBuildPhase).single as PBXFrameworksBuildPhase; + phase.linkBinaryWithFile(file); + } + } } abstract class PBXTarget = PBXElement with PBXTargetMixin; From a06152d70e2415c62fff8e1144c2b20fbca9b2ae Mon Sep 17 00:00:00 2001 From: Maciej Slonina Date: Tue, 23 Sep 2025 12:23:13 +0200 Subject: [PATCH 11/11] #7379 Fixed modify iterable during iterating. --- lib/src/pbx/target.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/pbx/target.dart b/lib/src/pbx/target.dart index 2ff4021..be55286 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -65,7 +65,7 @@ mixin PBXTargetMixin on PBXElement { final buildPhasesListString = [...getList('buildPhases')]; // list uuid which is the same as 'name' parameter - final uuidToDeleted = buildPhases.whereType().where((element) => element.name == name).map((e) => e.uuid); + final uuidToDeleted = buildPhases.whereType().where((element) => element.name == name).map((e) => e.uuid).toList(); if (uuidToDeleted.isNotEmpty) { isRemoved = true;