Skip to content

Automatically package OpenSSL inside the framework #668

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions ObjectiveGitFramework.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@
F8D1BDEF1B31FE7C00CDEC90 /* GTRepository+Pull.h in Headers */ = {isa = PBXBuildFile; fileRef = F8D1BDEC1B31FE7C00CDEC90 /* GTRepository+Pull.h */; settings = {ATTRIBUTES = (Public, ); }; };
F8D1BDF01B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; };
F8D1BDF11B31FE7C00CDEC90 /* GTRepository+Pull.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D1BDED1B31FE7C00CDEC90 /* GTRepository+Pull.m */; };
F8D6384B207A618D00D1FD32 /* script in Resources */ = {isa = PBXBuildFile; fileRef = F8D6384A207A618D00D1FD32 /* script */; };
F8D6385C207AC74A00D1FD32 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F8D6385B207AC74A00D1FD32 /* libiconv.tbd */; };
F8D6385D207AC75100D1FD32 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 23BB67BB1C7DF45300A37A66 /* libz.tbd */; };
F8D6385F207ACAE600D1FD32 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F8D6385E207ACAE600D1FD32 /* libz.tbd */; };
Expand Down Expand Up @@ -1226,6 +1225,7 @@
79262F0F13C697BE00A4B1EA /* Copy git2 Headers */,
BEF7E4DF1A3A47450035BB8E /* Copy git2 Headers again */,
8DC2EF500486A6940098B216 /* Headers */,
4D751E9D215D765D003CD3CE /* Package external libraries */,
);
buildRules = (
);
Expand Down Expand Up @@ -1343,7 +1343,6 @@
buildActionMask = 2147483647;
files = (
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
F8D6384B207A618D00D1FD32 /* script in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -1358,6 +1357,20 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
4D751E9D215D765D003CD3CE /* Package external libraries */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Package external libraries";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "./script/repackage-dylibs.rb";
};
6A28265317C69CB400C6A948 /* OpenSSL-iOS */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down
124 changes: 124 additions & 0 deletions script/repackage-dylibs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/ruby

# This script looks up an executable's list of shared libraries, copies
# non-standard ones (ie. anything not under /usr or /System/) into the target's
# bundle and updates the executable install_name to point to the "packaged"
# version.

# Usage:
# Add the script as a Run Script build phase in the target using Xcode.

# FIXMEs:
# - only handles dylibs
# - only tested against a framework target
# - doesn't care about codesigning


require 'fileutils'
require 'ostruct'

def err(msg)
puts "error: " + msg
exit 1
end

def warn(msg)
puts "warning: " + msg
end

def note(msg)
puts "note: " + msg
end

envvars = %w(
TARGET_BUILD_DIR
EXECUTABLE_PATH
FRAMEWORKS_FOLDER_PATH
)

envvars.each do |var|
raise "Must be run in an Xcode Run Phase" unless ENV[var]
Kernel.const_set var, ENV[var]
end

TARGET_EXECUTABLE_PATH = File.join(TARGET_BUILD_DIR, EXECUTABLE_PATH)
TARGET_FRAMEWORKS_PATH = File.join(TARGET_BUILD_DIR, FRAMEWORKS_FOLDER_PATH)

def extract_link_dependencies(executable)
deps = `otool -L #{executable}`

lines = deps.split("\n").map(&:strip)
lines.shift
# lines.shift
lines.map do |dep|
path, compat, current = /^(.*) \(compatibility version (.*), current version (.*)\)$/.match(dep)[1..3]
err "Failed to parse #{dep}" if path.nil?

dep = OpenStruct.new
dep.is_self = (File.basename(path) == File.basename(executable))
dep.executable = executable
dep.install_name = path
dep.current_version = current
dep.compat_version = compat
dep.type = File.extname(path)
dep.name = File.basename(path)
dep.is_packaged = !!(dep.install_name =~ /^@rpath/)
dep.path = if dep.install_name =~ /^@rpath/
File.join(TARGET_FRAMEWORKS_PATH, dep.name)
else
dep.install_name
end

dep
end
end

def repackage_dependency(dep)
return if dep.is_self or dep.is_packaged or dep.path =~ /^(\/usr\/lib|\/System\/Library)/

note "Packaging #{dep.name}…"

FileUtils.mkdir(TARGET_FRAMEWORKS_PATH) unless Dir.exist?(TARGET_FRAMEWORKS_PATH)
packaged_path = File.join(TARGET_FRAMEWORKS_PATH, dep.name)

case dep.type
when ".dylib"
if File.exist? packaged_path
warn "#{dep.path} already in Frameworks directory, removing"
FileUtils.rm packaged_path
end

note "Copying #{dep[:path]} to TARGET_FRAMEWORKS_PATH"
FileUtils.cp dep[:path], TARGET_FRAMEWORKS_PATH
FileUtils.chmod "u=rw", packaged_path

out = `install_name_tool -change #{dep.path} "@rpath/#{dep.name}" #{dep.executable}`
if $? != 0
err "install_name_tool failed with error #{$?}:\n#{out}"
end

dep.path = packaged_path
dep.install_name = "@rpath/#{dep.name}"
dep.is_packaged = true
else
warn "Unhandled type #{dep.type} for #{dep.path}, ignoring"
end
end

def fix_install_id(dep)
note "Fixing #{dep.name} install_name id…"
out = `install_name_tool -id @rpath/#{dep.name} #{dep.executable}`
if $? != 0
err "install_name_tool failed with error #{$?}:\n#{out}"
end
end

deps = extract_link_dependencies(TARGET_EXECUTABLE_PATH)
while (dep = deps.shift) do
repackage_dependency dep
fix_install_id dep if dep.is_self and dep.executable != TARGET_EXECUTABLE_PATH
deps += extract_link_dependencies(dep[:path]) if dep.is_packaged and not dep.is_self
end

note "Packaging done"
exit 0