diff --git a/lib/src/pbx/build_phase.dart b/lib/src/pbx/build_phase.dart index 3666403..748a511 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; @@ -51,6 +57,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. diff --git a/lib/src/pbx/file_element.dart b/lib/src/pbx/file_element.dart index b55f2a9..09a015e 100644 --- a/lib/src/pbx/file_element.dart +++ b/lib/src/pbx/file_element.dart @@ -65,14 +65,41 @@ mixin PBXGroupMixin on PBXFileElement { /// A list of references to [PBXFileElement] elements List get children => getObjectList('children'); - PBXFileReference? addReference(String path, {String sourceTree = ''}) { + bool removeReferences(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 = '', String? name}) { var uuid = UuidGenerator().random(); + name = name ?? path_lib.basename(path); - project.set('objects/$uuid', - {'isa': 'PBXFileReference', 'path': 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 98a70df..3d0e420 100644 --- a/lib/src/pbx/target.dart +++ b/lib/src/pbx/target.dart @@ -16,6 +16,84 @@ 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 [], + String shellPath = '/bin/sh', + 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) + 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) + + var uuid = UuidGenerator().random(); + + project.set('objects/$uuid', { + 'isa': 'PBXShellScriptBuildPhase', + 'name': name, + 'alwaysOutOfDate': alwaysOutOfDate ? null : 1, // this is not an error, xCode set flag 1 if this value unchecked + 'buildActionMask': buildActionMask, + 'files': files, + 'inputFileListPaths': inputFileListPaths, + 'inputPaths': inputsPaths, + 'outputFileListPaths': outputFileListPaths, + 'outputPaths': outputPaths, + 'shellPath': shellPath, + 'shellScript': shellScript, + 'runOnlyForDeploymentPostprocessing': runOnlyForDeploymentPostprocessing, + 'showEnvVarsInLog': showEnvVarsInLog ? null : 0, // this is not an error, xCode set flag 0 if this value unchecked + 'dependencyFile': dependencyFile, + }); + + var p = 'objects/${this.uuid}/buildPhases'; + project.set(p, [...getList('buildPhases'), uuid]); + } + + /// 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).toList(); + + if (uuidToDeleted.isNotEmpty) { + isRemoved = true; + } + + // 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); + + 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;