Skip to content

Commit 61051a5

Browse files
committed
Package non-system libraries inside the framework
This automatically copies libssl & libcrypto inside our framework bundle.
1 parent bbb5e11 commit 61051a5

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

ObjectiveGitFramework.xcodeproj/project.pbxproj

+15
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,7 @@
12251225
79262F0F13C697BE00A4B1EA /* Copy git2 Headers */,
12261226
BEF7E4DF1A3A47450035BB8E /* Copy git2 Headers again */,
12271227
8DC2EF500486A6940098B216 /* Headers */,
1228+
4D751E9D215D765D003CD3CE /* Package external libraries */,
12281229
);
12291230
buildRules = (
12301231
);
@@ -1356,6 +1357,20 @@
13561357
/* End PBXResourcesBuildPhase section */
13571358

13581359
/* Begin PBXShellScriptBuildPhase section */
1360+
4D751E9D215D765D003CD3CE /* Package external libraries */ = {
1361+
isa = PBXShellScriptBuildPhase;
1362+
buildActionMask = 2147483647;
1363+
files = (
1364+
);
1365+
inputPaths = (
1366+
);
1367+
name = "Package external libraries";
1368+
outputPaths = (
1369+
);
1370+
runOnlyForDeploymentPostprocessing = 0;
1371+
shellPath = /bin/sh;
1372+
shellScript = "./script/repackage-dylibs.rb";
1373+
};
13591374
6A28265317C69CB400C6A948 /* OpenSSL-iOS */ = {
13601375
isa = PBXShellScriptBuildPhase;
13611376
buildActionMask = 2147483647;

script/repackage-dylibs.rb

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/usr/bin/ruby
2+
3+
# This script looks up an executable's list of shared libraries, copies
4+
# non-standard ones (ie. anything not under /usr or /System/) into the target's
5+
# bundle and updates the executable install_name to point to the "packaged"
6+
# version.
7+
8+
# Usage:
9+
# Add the script as a Run Script build phase in the target using Xcode.
10+
11+
# FIXMEs:
12+
# - only handles dylibs
13+
# - only tested against a framework target
14+
# - doesn't care about codesigning
15+
16+
17+
require 'fileutils'
18+
require 'ostruct'
19+
20+
def err(msg)
21+
puts "error: " + msg
22+
exit 1
23+
end
24+
25+
def warn(msg)
26+
puts "warning: " + msg
27+
end
28+
29+
def note(msg)
30+
puts "note: " + msg
31+
end
32+
33+
envvars = %w(
34+
TARGET_BUILD_DIR
35+
EXECUTABLE_PATH
36+
FRAMEWORKS_FOLDER_PATH
37+
)
38+
39+
envvars.each do |var|
40+
raise "Must be run in an Xcode Run Phase" unless ENV[var]
41+
Kernel.const_set var, ENV[var]
42+
end
43+
44+
TARGET_EXECUTABLE_PATH = File.join(TARGET_BUILD_DIR, EXECUTABLE_PATH)
45+
TARGET_FRAMEWORKS_PATH = File.join(TARGET_BUILD_DIR, FRAMEWORKS_FOLDER_PATH)
46+
47+
def extract_link_dependencies
48+
deps = `otool -L #{TARGET_EXECUTABLE_PATH}`
49+
50+
lines = deps.split("\n").map(&:strip)
51+
lines.shift
52+
lines.shift
53+
lines.map do |dep|
54+
path, compat, current = /^(.*) \(compatibility version (.*), current version (.*)\)$/.match(dep)[1..3]
55+
err "Failed to parse #{dep}" if path.nil?
56+
57+
dep = OpenStruct.new
58+
dep.install_name = path
59+
dep.current_version = current
60+
dep.compat_version = compat
61+
dep.type = File.extname(path)
62+
dep.name = File.basename(path)
63+
dep.is_packaged = (dep.install_name =~ /^@rpath/)
64+
dep.path = if dep.install_name =~ /^@rpath/
65+
File.join(TARGET_FRAMEWORKS_PATH, dep.name)
66+
else
67+
dep.install_name
68+
end
69+
70+
dep
71+
end
72+
end
73+
74+
def repackage_dependency(dep)
75+
return if dep.is_packaged or dep.path =~ /^(\/usr\/lib|\/System\/Library)/
76+
77+
note "Packaging #{dep.name}…"
78+
79+
FileUtils.mkdir(TARGET_FRAMEWORKS_PATH) unless Dir.exist?(TARGET_FRAMEWORKS_PATH)
80+
81+
case dep.type
82+
when ".dylib"
83+
if File.exist?(File.join(TARGET_FRAMEWORKS_PATH, dep.name))
84+
warn "#{dep.path} already in Frameworks directory, removing"
85+
FileUtils.rm File.join(TARGET_FRAMEWORKS_PATH, dep.name)
86+
end
87+
88+
note "Copying #{dep[:path]} to TARGET_FRAMEWORKS_PATH"
89+
FileUtils.cp dep[:path], TARGET_FRAMEWORKS_PATH
90+
91+
out = `install_name_tool -change #{dep.path} "@rpath/#{dep.name}" #{TARGET_EXECUTABLE_PATH}`
92+
if $? != 0
93+
err "install_name_tool failed with error #{$?}:\n#{out}"
94+
end
95+
96+
dep.path = File.join(TARGET_FRAMEWORKS_PATH, dep.name)
97+
dep.install_name = "@rpath/#{dep.name}"
98+
dep.is_packaged = true
99+
100+
else
101+
warn "Unhandled type #{dep.type} for #{dep.path}, ignoring"
102+
end
103+
end
104+
105+
extract_link_dependencies.each do |dep|
106+
repackage_dependency dep
107+
end
108+
109+
note "Packaging done"
110+
exit 0

0 commit comments

Comments
 (0)