1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.github.maven_nar.cpptasks.gcc.cross;
21
22 import java.io.File;
23 import java.util.Vector;
24
25 import org.apache.tools.ant.BuildException;
26
27 import com.github.maven_nar.cpptasks.CCTask;
28 import com.github.maven_nar.cpptasks.CUtil;
29 import com.github.maven_nar.cpptasks.LinkerParam;
30 import com.github.maven_nar.cpptasks.compiler.CaptureStreamHandler;
31 import com.github.maven_nar.cpptasks.compiler.CommandLineLinkerConfiguration;
32 import com.github.maven_nar.cpptasks.compiler.LinkType;
33 import com.github.maven_nar.cpptasks.compiler.Linker;
34 import com.github.maven_nar.cpptasks.gcc.AbstractLdLinker;
35 import com.github.maven_nar.cpptasks.types.LibrarySet;
36
37
38
39
40
41
42 public class GppLinker extends AbstractLdLinker {
43 protected static final String[] discardFiles = new String[0];
44 protected static final String[] objFiles = new String[] {
45 ".o", ".a", ".lib", ".dll", ".so", ".sl"
46 };
47 private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, discardFiles, "lib", ".so", false,
48 new GppLinker("gcc", objFiles, discardFiles, "lib", ".so", true, null));
49 private final static String libPrefix = "libraries: =";
50 protected static final String[] libtoolObjFiles = new String[] {
51 ".fo", ".a", ".lib", ".dll", ".so", ".sl"
52 };
53 private static String[] linkerOptions = new String[] {
54 "-bundle", "-dylib", "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", "-static",
55 "-shared", "-symbolic", "-Xlinker"
56 };
57 private static final GppLinker instance = new GppLinker("gcc", objFiles, discardFiles, "", "", false, null);
58 private static final GppLinker machDllLinker = new GppLinker("gcc", objFiles, discardFiles, "lib", ".dylib", false,
59 null);
60 private static final GppLinker machPluginLinker = new GppLinker("gcc", objFiles, discardFiles, "lib", ".bundle",
61 false, null);
62
63 public static GppLinker getInstance() {
64 return instance;
65 }
66
67 private File[] libDirs;
68 private String runtimeLibrary;
69
70 protected GppLinker(final String command, final String[] extensions, final String[] ignoredExtensions,
71 final String outputPrefix, final String outputSuffix, final boolean isLibtool, final GppLinker libtoolLinker) {
72 super(command, "-dumpversion", extensions, ignoredExtensions, outputPrefix, outputSuffix, isLibtool, libtoolLinker);
73 }
74
75 @Override
76 protected void addImpliedArgs(final CCTask task, final boolean debug, final LinkType linkType,
77 final Vector<String> args) {
78 super.addImpliedArgs(task, debug, linkType, args);
79 if (getIdentifier().contains("mingw")) {
80 if (linkType.isSubsystemConsole()) {
81 args.addElement("-mconsole");
82 }
83 if (linkType.isSubsystemGUI()) {
84 args.addElement("-mwindows");
85 }
86 }
87 if (linkType.isStaticRuntime()) {
88 final String[] cmdin = new String[] {
89 "g++", "-print-file-name=libstdc++.a"
90 };
91 final String[] cmdout = CaptureStreamHandler.run(cmdin);
92 if (cmdout.length > 0) {
93 this.runtimeLibrary = cmdout[0];
94 } else {
95 this.runtimeLibrary = null;
96 }
97 } else {
98 this.runtimeLibrary = "-lstdc++";
99 }
100 }
101
102 @Override
103 public String[] addLibrarySets(final CCTask task, final LibrarySet[] libsets, final Vector<String> preargs,
104 final Vector<String> midargs, final Vector<String> endargs) {
105 final String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, endargs);
106 if (this.runtimeLibrary != null) {
107 endargs.addElement(this.runtimeLibrary);
108 }
109 return rs;
110 }
111
112 @Override
113 protected Object clone() throws CloneNotSupportedException {
114 final GppLinker clone = (GppLinker) super.clone();
115 return clone;
116 }
117
118
119
120
121
122
123
124
125
126
127
128 @Override
129 public String decorateLinkerOption(final StringBuffer buf, final String arg) {
130 String decoratedArg = arg;
131 if (arg.length() > 1 && arg.charAt(0) == '-') {
132 switch (arg.charAt(1)) {
133
134
135
136 case 'g':
137 case 'f':
138 case 'F':
139
140 case 'm':
141 case 'O':
142 case 'W':
143 case 'l':
144 case 'L':
145 case 'u':
146 break;
147 default:
148 boolean known = false;
149 for (final String linkerOption : linkerOptions) {
150 if (linkerOption.equals(arg)) {
151 known = true;
152 break;
153 }
154 }
155 if (!known) {
156 buf.setLength(0);
157 buf.append("-Wl,");
158 buf.append(arg);
159 decoratedArg = buf.toString();
160 }
161 break;
162 }
163 }
164 return decoratedArg;
165 }
166
167
168
169
170
171 @Override
172 public File[] getLibraryPath() {
173 if (this.libDirs == null) {
174 final Vector<String> dirs = new Vector<>();
175
176 final String[] args = new String[] {
177 "g++", "-print-search-dirs"
178 };
179 final String[] cmdout = CaptureStreamHandler.run(args);
180 for (int i = 0; i < cmdout.length; ++i) {
181 final int prefixIndex = cmdout[i].indexOf(libPrefix);
182 if (prefixIndex >= 0) {
183
184 int s = prefixIndex + libPrefix.length();
185 int t = cmdout[i].indexOf(';', s);
186 while (t > 0) {
187 dirs.addElement(cmdout[i].substring(s, t));
188 s = t + 1;
189 t = cmdout[i].indexOf(';', s);
190 }
191 dirs.addElement(cmdout[i].substring(s));
192 ++i;
193 for (; i < cmdout.length; ++i) {
194 dirs.addElement(cmdout[i]);
195 }
196 }
197 }
198
199 final String[] libpath = new String[dirs.size()];
200 dirs.copyInto(libpath);
201 final int count = CUtil.checkDirectoryArray(libpath);
202
203 this.libDirs = new File[count];
204 int index = 0;
205 for (final String element : libpath) {
206 if (element != null) {
207 this.libDirs[index++] = new File(element);
208 }
209 }
210 }
211 return this.libDirs;
212 }
213
214 @Override
215 public Linker getLinker(final LinkType type) {
216 if (type.isStaticLibrary()) {
217 return GccLibrarian.getInstance();
218 }
219 if (type.isPluginModule()) {
220 if (GccProcessor.getMachine().contains("darwin")) {
221 return machPluginLinker;
222 } else {
223 return dllLinker;
224 }
225 }
226 if (type.isSharedLibrary()) {
227 if (GccProcessor.getMachine().contains("darwin")) {
228 return machDllLinker;
229 } else {
230 return dllLinker;
231 }
232 }
233 return instance;
234 }
235
236 @Override
237 public void link(final CCTask task, final File outputFile, final String[] sourceFiles,
238 final CommandLineLinkerConfiguration config) throws BuildException {
239 try {
240 final GppLinker clone = (GppLinker) this.clone();
241 final LinkerParam param = config.getParam("target");
242 if (param != null) {
243 clone.setCommand(param.getValue() + "-" + this.getCommand());
244 }
245 clone.superlink(task, outputFile, sourceFiles, config);
246 } catch (final CloneNotSupportedException e) {
247 superlink(task, outputFile, sourceFiles, config);
248 }
249 }
250
251 private void superlink(final CCTask task, final File outputFile, final String[] sourceFiles,
252 final CommandLineLinkerConfiguration config) throws BuildException {
253 super.link(task, outputFile, sourceFiles, config);
254 }
255 }