Skip to content

Commit 87ed872

Browse files
fwolffflorianf
authored andcommitted
Add the "framework" compiler target (issue #132) (#141)
1 parent a1aa180 commit 87ed872

File tree

5 files changed

+221
-9
lines changed

5 files changed

+221
-9
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@
55
.idea/
66
.DS_Store
77
dependency-reduced-pom.xml
8-
target/

compiler/compiler/src/main/java/org/robovm/compiler/config/Config.java

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.robovm.compiler.plugin.objc.ObjCProtocolProxyPlugin;
7676
import org.robovm.compiler.target.ConsoleTarget;
7777
import org.robovm.compiler.target.Target;
78+
import org.robovm.compiler.target.framework.FrameworkTarget;
7879
import org.robovm.compiler.target.ios.IOSTarget;
7980
import org.robovm.compiler.target.ios.ProvisioningProfile;
8081
import org.robovm.compiler.target.ios.SigningIdentity;
@@ -850,6 +851,8 @@ private Config build() throws IOException {
850851
target = new ConsoleTarget();
851852
} else if (IOSTarget.TYPE.equals(targetType)) {
852853
target = new IOSTarget();
854+
} else if (FrameworkTarget.TYPE.equals(targetType)) {
855+
target = new FrameworkTarget();
853856
} else {
854857
for (TargetPlugin plugin : getTargetPlugins()) {
855858
if (plugin.getTarget().getType().equals(targetType)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package org.robovm.compiler.target.framework;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
import java.util.ArrayList;
6+
import java.util.Arrays;
7+
import java.util.Collections;
8+
import java.util.List;
9+
10+
import org.apache.commons.io.FileUtils;
11+
import org.robovm.compiler.clazz.Path;
12+
import org.robovm.compiler.config.Arch;
13+
import org.robovm.compiler.config.Config;
14+
import org.robovm.compiler.config.OS;
15+
import org.robovm.compiler.log.Logger;
16+
import org.robovm.compiler.log.LoggerProxy;
17+
import org.robovm.compiler.target.AbstractTarget;
18+
import org.robovm.compiler.target.ios.SDK;
19+
import org.robovm.compiler.util.Executor;
20+
21+
import com.dd.plist.NSDictionary;
22+
import com.dd.plist.NSObject;
23+
import com.dd.plist.PropertyListParser;
24+
25+
public class FrameworkTarget extends AbstractTarget {
26+
27+
public static final String TYPE = "framework";
28+
29+
private OS os;
30+
private Arch arch;
31+
private SDK sdk;
32+
33+
public FrameworkTarget() {
34+
}
35+
36+
@Override
37+
public String getType() {
38+
return TYPE;
39+
}
40+
41+
@Override
42+
public OS getOs() {
43+
return os;
44+
}
45+
46+
@Override
47+
public Arch getArch() {
48+
return arch;
49+
}
50+
51+
@Override
52+
public boolean canLaunch() {
53+
return false;
54+
}
55+
56+
public static boolean isSimulatorArch(Arch arch) {
57+
return arch == Arch.x86 || arch == Arch.x86_64;
58+
}
59+
60+
public static boolean isDeviceArch(Arch arch) {
61+
return arch == Arch.thumbv7 || arch == Arch.arm64;
62+
}
63+
64+
65+
public List<SDK> getSDKs() {
66+
if (isSimulatorArch(arch)) {
67+
return SDK.listSimulatorSDKs();
68+
} else {
69+
return SDK.listDeviceSDKs();
70+
}
71+
}
72+
73+
public void init(Config paramConfig) {
74+
super.init(paramConfig);
75+
76+
os = config.getOs();
77+
if (os == null)
78+
os = OS.getDefaultOS();
79+
80+
arch = config.getArch();
81+
if (arch == null)
82+
arch = Arch.getDefaultArch();
83+
84+
if (os.getFamily() != OS.Family.darwin)
85+
throw new IllegalArgumentException("Frameworks can only be built for Darwin platforms");
86+
87+
if (paramConfig.getInfoPList() == null)
88+
throw new IllegalArgumentException("Frameworks must have a Info.plist file");
89+
paramConfig.getIosInfoPList().parse(paramConfig.getProperties());
90+
91+
String sdkVersion = config.getIosSdkVersion();
92+
93+
List<SDK> sdks = getSDKs();
94+
if (sdkVersion == null) {
95+
if (sdks.isEmpty()) {
96+
throw new IllegalArgumentException("No " + (isDeviceArch(arch) ? "device" : "simulator")
97+
+ " SDKs installed");
98+
}
99+
Collections.sort(sdks);
100+
this.sdk = sdks.get(sdks.size() - 1);
101+
}
102+
else {
103+
for (SDK sdk : sdks) {
104+
if (sdk.getVersion().equals(sdkVersion)) {
105+
this.sdk = sdk;
106+
break;
107+
}
108+
}
109+
if (sdk == null) {
110+
throw new IllegalArgumentException("No SDK found matching version string " + sdkVersion);
111+
}
112+
}
113+
}
114+
115+
@Override
116+
public String getInstallRelativeArchivePath(Path path) {
117+
return config.getImageName() + ".bundle/Resources/" + super.getInstallRelativeArchivePath(path);
118+
}
119+
120+
@Override
121+
protected List<String> getTargetExportedSymbols() {
122+
return Arrays.asList(new String[] { "JNI_*" });
123+
}
124+
125+
private String getMinimumOSVersion() {
126+
NSObject minimumOSVersion = config.getInfoPList().getDictionary().objectForKey("MinimumOSVersion");
127+
if (minimumOSVersion != null)
128+
return minimumOSVersion.toString();
129+
return "8.0";
130+
}
131+
132+
@Override
133+
protected List<String> getTargetCcArgs() {
134+
List<String> ccArgs = new ArrayList<String>();
135+
136+
ccArgs.add("-stdlib=libc++");
137+
138+
if (isDeviceArch(arch))
139+
ccArgs.add("-miphoneos-version-min=" + getMinimumOSVersion());
140+
else
141+
ccArgs.add("-mios-simulator-version-min=" + getMinimumOSVersion());
142+
143+
ccArgs.add("-isysroot");
144+
ccArgs.add(sdk.getRoot().getAbsolutePath());
145+
146+
ccArgs.add("-dynamiclib");
147+
ccArgs.add("-single_module");
148+
ccArgs.add("-compatibility_version");
149+
ccArgs.add("1");
150+
ccArgs.add("-current_version");
151+
ccArgs.add("1");
152+
153+
if (this.config.getArch() == Arch.x86) {
154+
ccArgs.add("-read_only_relocs");
155+
ccArgs.add("suppress");
156+
}
157+
158+
ccArgs.add("-install_name");
159+
ccArgs.add(String.format("@rpath/%s.framework/%s", config.getImageName(), config.getImageName()));
160+
161+
return ccArgs;
162+
}
163+
164+
@Override
165+
protected void doInstall(File installDir, String image, File resourcesDir) throws IOException {
166+
File frameworkDir = new File(installDir, image + ".framework");
167+
168+
config.getLogger().info("Creating framework: %s", frameworkDir);
169+
170+
if (frameworkDir.exists())
171+
FileUtils.deleteDirectory(frameworkDir);
172+
frameworkDir.mkdirs();
173+
174+
File bundleDir = new File(frameworkDir, image + ".bundle");
175+
bundleDir.mkdirs();
176+
177+
File bundleResourcesDir = new File(bundleDir, "Resources");
178+
bundleResourcesDir.mkdirs();
179+
180+
super.doInstall(frameworkDir, image, bundleResourcesDir);
181+
182+
File frameworkBinaryFile = new File(frameworkDir, image);
183+
File dsymDir = new File(installDir, image + ".dSYM");
184+
185+
config.getLogger().info("Creating framework symbol directory: %s", dsymDir);
186+
if (dsymDir.exists())
187+
FileUtils.deleteDirectory(dsymDir);
188+
dsymDir.mkdirs();
189+
new Executor(new FilterDSYMWarningsLogger(config.getLogger()), "xcrun").args("dsymutil", "-o", dsymDir, frameworkBinaryFile).exec();
190+
191+
if (!config.isDebug()) {
192+
config.getLogger().info("Striping framework binary: %s", frameworkBinaryFile);
193+
new Executor(config.getLogger(), "xcrun").args("strip", "-x", frameworkBinaryFile).exec();
194+
}
195+
196+
NSDictionary infoPlist = config.getInfoPList().getDictionary();
197+
if (infoPlist.objectForKey("MinimumOSVersion") == null)
198+
infoPlist.put("MinimumOSVersion", "8.0");
199+
200+
File infoPlistBin = new File(frameworkDir, "Info.plist");
201+
config.getLogger().info("Installing Info.plist to: %s", infoPlistBin);
202+
PropertyListParser.saveAsBinary(infoPlist, infoPlistBin);
203+
}
204+
205+
private static class FilterDSYMWarningsLogger extends LoggerProxy {
206+
207+
public FilterDSYMWarningsLogger(Logger target) {
208+
super(target);
209+
}
210+
211+
@Override
212+
public void warn(String format, Object... args) {
213+
if (!(format.startsWith("warning:") && format.contains("could not find object file symbol for symbol")))
214+
super.warn(format, args);
215+
}
216+
}
217+
}

compiler/vm/core/src/init.c

-8
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,6 @@ jboolean rvmInitOptions(int argc, char* argv[], Options* options, jboolean ignor
240240
if (i >= 0 && options->resourcesPath[i] == '/') {
241241
options->resourcesPath[i] = '\0';
242242
}
243-
if (argc == 0) {
244-
#if defined(DARWIN)
245-
// Called via JNI and on Darwin. Assume this is a framework. Use the
246-
// Resources folder next to the image.
247-
strncat(options->resourcesPath, "/Resources",
248-
sizeof(options->resourcesPath) - strlen(options->resourcesPath) - 1);
249-
#endif
250-
}
251243
}
252244

253245
// Look for a robovm.ini in the resources path

plugins/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target/

0 commit comments

Comments
 (0)