diff --git a/lib/commands/autofixes/strip_binary_symbols.rb b/lib/commands/autofixes/strip_binary_symbols.rb new file mode 100644 index 0000000..5074291 --- /dev/null +++ b/lib/commands/autofixes/strip_binary_symbols.rb @@ -0,0 +1,116 @@ +require 'dry/cli' +require 'xcodeproj' + +module EmergeCLI + module Commands + module Autofixes + class StripBinarySymbols < EmergeCLI::Commands::GlobalOptions + desc 'Strip binary symbols from the app' + + option :path, type: :string, required: true, desc: 'Path to the xcarchive' + + # Constants + SCRIPT_NAME = 'EmergeTools Strip Binary Symbols'.freeze + ENABLE_USER_SCRIPT_SANDBOXING = 'ENABLE_USER_SCRIPT_SANDBOXING'.freeze + INPUT_FILE = '${DWARF_DSYM_FOLDER_PATH}/${EXECUTABLE_NAME}.app.dSYM/' \ + 'Contents/Resources/DWARF/${EXECUTABLE_NAME}'.freeze + SCRIPT_CONTENT = %{#!/bin/bash +set -e + +echo "Starting the symbol stripping process..." + +if [ "Release" = "$\{CONFIGURATION\}" ]; then + echo "Configuration is Release." + + # Path to the app directory + APP_DIR_PATH="$\{BUILT_PRODUCTS_DIR\}/$\{EXECUTABLE_FOLDER_PATH\}" + echo "App directory path: $\{APP_DIR_PATH\}" + + # Strip main binary + echo "Stripping main binary: $\{APP_DIR_PATH\}/$\{EXECUTABLE_NAME\}" + strip -rSTx "$\{APP_DIR_PATH\}/$\{EXECUTABLE_NAME\}" + if [ $? -eq 0 ]; then + echo "Successfully stripped main binary." + else + echo "Failed to strip main binary." >&2 + fi + + # Path to the Frameworks directory + APP_FRAMEWORKS_DIR="$\{APP_DIR_PATH\}/Frameworks" + echo "Frameworks directory path: $\{APP_FRAMEWORKS_DIR\}" + + # Strip symbols from frameworks, if Frameworks/ exists at all + # ... as long as the framework is NOT signed by Apple + if [ -d "$\{APP_FRAMEWORKS_DIR\}" ]; then + echo "Frameworks directory exists. Proceeding to strip symbols from frameworks." + find "$\{APP_FRAMEWORKS_DIR\}" -type f -perm +111 -maxdepth 2 -mindepth 2 -exec bash -c ' + codesign -v -R="anchor apple" "\{\}" &> /dev/null || + ( + echo "Stripping \{\}" && + if [ -w "\{\}" ]; then + strip -rSTx "\{\}" + if [ $? -eq 0 ]; then + echo "Successfully stripped \{\}" + else + echo "Failed to strip \{\}" >&2 + fi + else + echo "Warning: No write permission for \{\}" + fi + ) + ' \\; + if [ $? -eq 0 ]; then + echo "Successfully stripped symbols from frameworks." + else + echo "Failed to strip symbols from some frameworks." >&2 + fi + else + echo "Frameworks directory does not exist. Skipping framework stripping." + fi +else + echo "Configuration is not Release. Skipping symbol stripping." +fi + +echo "Symbol stripping process completed."}.freeze + + def call(**options) + @options = options + before(options) + + raise 'Path must be an xcodeproj' unless @options[:path].end_with?('.xcodeproj') + raise 'Path does not exist' unless File.exist?(@options[:path]) + + Sync do + project = Xcodeproj::Project.open(@options[:path]) + + project.targets.each do |target| + target.build_configurations.each do |config| + enable_user_script_sandboxing(config) + end + + add_run_script(target) + end + + project.save + end + end + + private + + def enable_user_script_sandboxing(config) + Logger.info "Enabling user script sandboxing for #{config.name}" + config.build_settings[ENABLE_USER_SCRIPT_SANDBOXING] = 'NO' + end + + def add_run_script(target) + phase = target.shell_script_build_phases.find { |item| item.name == SCRIPT_NAME } + return unless phase.nil? + Logger.info "Creating script '#{SCRIPT_NAME}'" + phase = target.new_shell_script_build_phase(SCRIPT_NAME) + phase.shell_script = SCRIPT_CONTENT + phase.input_paths = [INPUT_FILE] + end + end + end + end +end diff --git a/lib/emerge_cli.rb b/lib/emerge_cli.rb index 97fba8e..8890922 100644 --- a/lib/emerge_cli.rb +++ b/lib/emerge_cli.rb @@ -18,6 +18,7 @@ require_relative 'commands/build_distribution/validate_app' require_relative 'commands/build_distribution/download_and_install' require_relative 'commands/autofixes/minify_strings' +require_relative 'commands/autofixes/strip_binary_symbols' require_relative 'commands/autofixes/exported_symbols' require_relative 'reaper/ast_parser' @@ -73,6 +74,7 @@ module EmergeCLI register 'autofix' do |prefix| prefix.register 'minify-strings', Commands::Autofixes::MinifyStrings + prefix.register 'strip-binary-symbols', Commands::Autofixes::StripBinarySymbols prefix.register 'exported-symbols', Commands::Autofixes::ExportedSymbols end end diff --git a/test/commands/autofixes/strip_binary_symbols_test.rb b/test/commands/autofixes/strip_binary_symbols_test.rb new file mode 100644 index 0000000..dc7dbce --- /dev/null +++ b/test/commands/autofixes/strip_binary_symbols_test.rb @@ -0,0 +1,56 @@ +require 'test_helper' + +module EmergeCLI + module Commands + module Autofixes + class StripBinarySymbolsTest < Minitest::Test + SCRIPT_NAME = 'EmergeTools Strip Binary Symbols'.freeze + ENABLE_USER_SCRIPT_SANDBOXING = 'ENABLE_USER_SCRIPT_SANDBOXING'.freeze + INPUT_FILE = '${DWARF_DSYM_FOLDER_PATH}/${EXECUTABLE_NAME}.app.dSYM/' \ + 'Contents/Resources/DWARF/${EXECUTABLE_NAME}'.freeze + + def setup + @command = EmergeCLI::Commands::Autofixes::StripBinarySymbols.new + + FileUtils.mkdir_p('tmp/test_autofix_strip_binary_symbols') + FileUtils.cp_r('test/test_files/ExampleApp.xcodeproj', + 'tmp/test_autofix_strip_binary_symbols/ExampleApp.xcodeproj') + end + + def teardown + FileUtils.rm_rf('tmp/test_autofix_strip_binary_symbols') + end + + def test_script_is_created + options = { + path: 'tmp/test_autofix_strip_binary_symbols/ExampleApp.xcodeproj' + } + + @command.call(**options) + + project = Xcodeproj::Project.open('tmp/test_autofix_strip_binary_symbols/ExampleApp.xcodeproj') + + phase = project.targets[0].shell_script_build_phases.find do |item| + item.name == SCRIPT_NAME + end + assert_equal SCRIPT_NAME, phase.name + assert_equal INPUT_FILE, phase.input_paths[0] + end + + def test_user_script_sandboxing_is_disabled + options = { + path: 'tmp/test_autofix_strip_binary_symbols/ExampleApp.xcodeproj' + } + + @command.call(**options) + + project = Xcodeproj::Project.open('tmp/test_autofix_strip_binary_symbols/ExampleApp.xcodeproj') + + project.targets[0].build_configurations.each do |config| + assert_equal 'NO', config.build_settings[ENABLE_USER_SCRIPT_SANDBOXING] + end + end + end + end + end +end