153 lines
5.9 KiB
Ruby
153 lines
5.9 KiB
Ruby
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
require 'xcodeproj'
|
|
|
|
ROOT = File.expand_path('..', __dir__)
|
|
PROJECT_PATH = File.join(ROOT, 'QuickLocation.xcodeproj')
|
|
project = Xcodeproj::Project.open(PROJECT_PATH)
|
|
|
|
main_target = project.targets.find { |t| t.name == 'QuickLocation' }
|
|
raise 'QuickLocation target not found' unless main_target
|
|
|
|
def ensure_group(project, path_components)
|
|
group = project.main_group
|
|
path_components.each do |name|
|
|
next_group = group.children.find { |c| c.respond_to?(:name) && (c.name == name || c.path == name) }
|
|
group = next_group || group.new_group(name)
|
|
end
|
|
group
|
|
end
|
|
|
|
def add_file(project, target, group, relative_path, root:, resources: false)
|
|
abs = File.join(root, relative_path)
|
|
raise "Missing file: #{abs}" unless File.exist?(abs)
|
|
|
|
ref = group.files.find { |f| f.real_path.to_s == abs || f.path == File.basename(relative_path) }
|
|
ref ||= group.new_file(abs)
|
|
|
|
if resources
|
|
unless target.resources_build_phase.files_references.include?(ref)
|
|
target.add_resources([ref])
|
|
end
|
|
else
|
|
unless target.source_build_phase.files_references.include?(ref)
|
|
target.source_build_phase.add_file_reference(ref)
|
|
end
|
|
end
|
|
ref
|
|
end
|
|
|
|
def configure_extension_target(target, bundle_id, entitlements, info_plist)
|
|
target.build_configurations.each do |config|
|
|
bs = config.build_settings
|
|
bs['PRODUCT_BUNDLE_IDENTIFIER'] = bundle_id
|
|
bs['PRODUCT_NAME'] = target.name
|
|
bs['PRODUCT_MODULE_NAME'] = target.name
|
|
bs['CODE_SIGN_ENTITLEMENTS'] = entitlements
|
|
bs['INFOPLIST_FILE'] = info_plist
|
|
bs['GENERATE_INFOPLIST_FILE'] = 'NO'
|
|
bs['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
|
|
bs['TARGETED_DEVICE_FAMILY'] = '1'
|
|
bs['SKIP_INSTALL'] = 'YES'
|
|
bs['LD_RUNPATH_SEARCH_PATHS'] = '$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks'
|
|
bs['DEVELOPMENT_TEAM'] = 'LRDLWZ2Y83'
|
|
bs['SWIFT_DEFAULT_ACTOR_ISOLATION'] = 'nonisolated'
|
|
bs['SWIFT_VERSION'] = '5.0'
|
|
bs['CODE_SIGN_STYLE'] = 'Automatic'
|
|
bs['CURRENT_PROJECT_VERSION'] = '1'
|
|
bs['MARKETING_VERSION'] = '1.0'
|
|
end
|
|
end
|
|
|
|
def find_or_create_extension(project, name)
|
|
existing = project.targets.find { |t| t.name == name }
|
|
return existing if existing
|
|
|
|
project.new_target(:app_extension, name, :ios, '15.0')
|
|
end
|
|
|
|
def link_system_framework(target, name)
|
|
frameworks = project = target.project
|
|
frameworks_group = project.frameworks_group
|
|
path = "System/Library/Frameworks/#{name}.framework"
|
|
ref = frameworks_group.files.find { |f| f.path == "#{name}.framework" || f.name == "#{name}.framework" }
|
|
ref ||= frameworks_group.new_file(path)
|
|
ref.name = "#{name}.framework"
|
|
ref.source_tree = 'SDKROOT'
|
|
unless target.frameworks_build_phase.files_references.include?(ref)
|
|
target.frameworks_build_phase.add_file_reference(ref)
|
|
end
|
|
end
|
|
|
|
# Shared
|
|
shared_group = ensure_group(project, ['AppRestrictShared'])
|
|
add_file(project, main_target, shared_group, 'AppRestrictShared/AppRestrictShared.swift', root: ROOT)
|
|
|
|
# Main app
|
|
mgr_group = ensure_group(project, ['QuickLocation', 'Manager', 'AppRestrict'])
|
|
add_file(project, main_target, mgr_group, 'QuickLocation/Manager/AppRestrict/AppRestrictManager.swift', root: ROOT)
|
|
|
|
section_group = ensure_group(project, ['QuickLocation', 'Section', 'AppRestrict'])
|
|
%w[
|
|
AppCatalogStore.swift
|
|
AppRestrictCell.swift
|
|
AppRestrictVC.swift
|
|
AppRestrictView.swift
|
|
AppRestrictShieldSettingsVC.swift
|
|
FamilyActivityPickerHost.swift
|
|
SelectActivityVC.swift
|
|
].each do |name|
|
|
add_file(project, main_target, section_group, "QuickLocation/Section/AppRestrict/#{name}", root: ROOT)
|
|
end
|
|
add_file(project, main_target, section_group, 'QuickLocation/Section/AppRestrict/app_catalog.json', root: ROOT, resources: true)
|
|
|
|
%w[FamilyControls ManagedSettings DeviceActivity ManagedSettingsUI].each do |fw|
|
|
link_system_framework(main_target, fw)
|
|
end
|
|
|
|
# Monitor extension
|
|
monitor = find_or_create_extension(project, 'DeviceActivityMonitorExtension')
|
|
monitor_group = ensure_group(project, ['DeviceActivityMonitorExtension'])
|
|
add_file(project, monitor, monitor_group, 'DeviceActivityMonitorExtension/DeviceActivityMonitorExtension.swift', root: ROOT)
|
|
add_file(project, monitor, shared_group, 'AppRestrictShared/AppRestrictShared.swift', root: ROOT)
|
|
configure_extension_target(
|
|
monitor,
|
|
'cn.zuomeng.jisuloca.DeviceActivityMonitor',
|
|
'DeviceActivityMonitorExtension/DeviceActivityMonitorExtension.entitlements',
|
|
'DeviceActivityMonitorExtension/Info.plist'
|
|
)
|
|
%w[DeviceActivity FamilyControls ManagedSettings].each { |fw| link_system_framework(monitor, fw) }
|
|
|
|
# Shield extension
|
|
shield = find_or_create_extension(project, 'ShieldConfigurationExtension')
|
|
shield_group = ensure_group(project, ['ShieldConfigurationExtension'])
|
|
add_file(project, shield, shield_group, 'ShieldConfigurationExtension/ShieldConfigurationExtension.swift', root: ROOT)
|
|
add_file(project, shield, shared_group, 'AppRestrictShared/AppRestrictShared.swift', root: ROOT)
|
|
configure_extension_target(
|
|
shield,
|
|
'cn.zuomeng.jisuloca.ShieldConfiguration',
|
|
'ShieldConfigurationExtension/ShieldConfigurationExtension.entitlements',
|
|
'ShieldConfigurationExtension/Info.plist'
|
|
)
|
|
%w[ManagedSettings ManagedSettingsUI FamilyControls UIKit].each { |fw| link_system_framework(shield, fw) }
|
|
|
|
# Embed
|
|
embed_phase = main_target.copy_files_build_phases.find { |p| p.dst_subfolder_spec == '13' || p.name == 'Embed Foundation Extensions' }
|
|
unless embed_phase
|
|
embed_phase = main_target.new_copy_files_build_phase('Embed Foundation Extensions')
|
|
embed_phase.symbol_dst_subfolder_spec = :plug_ins
|
|
end
|
|
|
|
[monitor, shield].each do |ext|
|
|
main_target.add_dependency(ext) unless main_target.dependencies.any? { |d| d.target == ext }
|
|
product = ext.product_reference
|
|
unless embed_phase.files.any? { |f| f.file_ref == product }
|
|
bf = embed_phase.add_file_reference(product)
|
|
bf.settings = { 'ATTRIBUTES' => ['RemoveHeadersOnCopy'] }
|
|
end
|
|
end
|
|
|
|
project.save
|
|
puts 'OK: App Restrict targets wired into QuickLocation.xcodeproj'
|