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;
21
22 import java.io.File;
23 import java.util.Vector;
24
25 import com.github.maven_nar.cpptasks.CCTask;
26 import com.github.maven_nar.cpptasks.CUtil;
27 import com.github.maven_nar.cpptasks.VersionInfo;
28 import com.github.maven_nar.cpptasks.compiler.CommandLineLinker;
29 import com.github.maven_nar.cpptasks.compiler.CommandLineLinkerConfiguration;
30 import com.github.maven_nar.cpptasks.compiler.LinkType;
31 import com.github.maven_nar.cpptasks.types.LibrarySet;
32 import com.github.maven_nar.cpptasks.types.LibraryTypeEnum;
33
34
35
36
37
38
39 public abstract class AbstractLdLinker extends CommandLineLinker {
40 private final String outputPrefix;
41
42 protected AbstractLdLinker(final String command, final String identifierArg, final String[] extensions,
43 final String[] ignoredExtensions, final String outputPrefix, final String outputSuffix, final boolean isLibtool,
44 final AbstractLdLinker libtoolLinker) {
45 super(command, identifierArg, extensions, ignoredExtensions, outputSuffix, isLibtool, libtoolLinker);
46 this.outputPrefix = outputPrefix;
47 }
48
49 @Override
50 protected void addBase(final CCTask task, final long base, final Vector<String> args) {
51 if (base >= 0) {
52 args.addElement("--image-base");
53 args.addElement(Long.toHexString(base));
54 }
55 }
56
57 @Override
58 protected void addEntry(final CCTask task, final String entry, final Vector<String> args) {
59 if (entry != null) {
60 args.addElement("-e");
61 args.addElement(entry);
62 }
63 }
64
65 @Override
66 protected void addImpliedArgs(final CCTask task, final boolean debug, final LinkType linkType,
67 final Vector<String> args) {
68 if (debug) {
69 args.addElement("-g");
70 }
71 if (isDarwin()) {
72 if (linkType.isPluginModule()) {
73 args.addElement("-bundle");
74
75 } else if (linkType.isJNIModule()) {
76 args.addElement("-dynamic");
77 args.addElement("-bundle");
78
79 } else {
80 if (linkType.isSharedLibrary()) {
81
82
83 args.addElement("-dynamiclib");
84 }
85 }
86 } else {
87 if (linkType.isStaticRuntime()) {
88 args.addElement("-static");
89 }
90 if (linkType.isPluginModule()) {
91 args.addElement("-shared");
92 } else {
93 if (linkType.isSharedLibrary()) {
94 args.addElement("-shared");
95 }
96 }
97 }
98 }
99
100 @Override
101 protected void addIncremental(final CCTask task, final boolean incremental, final Vector<String> args) {
102 if (incremental) {
103 args.addElement("-i");
104 }
105 }
106
107 @Override
108 protected void addLibraryPath(final Vector<String> preargs, final String path) {
109 preargs.addElement("-L" + path);
110 }
111
112 protected int addLibraryPatterns(final String[] libnames, final StringBuffer buf, final String prefix,
113 final String extension, final String[] patterns, final int offset) {
114 for (int i = 0; i < libnames.length; i++) {
115 buf.setLength(0);
116 buf.append(prefix);
117 buf.append(libnames[i]);
118 buf.append(extension);
119 patterns[offset + i] = buf.toString();
120 }
121 return offset + libnames.length;
122 }
123
124 @Override
125 protected String[] addLibrarySets(final CCTask task, final LibrarySet[] libsets, final Vector<String> preargs,
126 final Vector<String> midargs, final Vector<String> endargs) {
127 final Vector<String> libnames = new Vector<>();
128 super.addLibrarySets(task, libsets, preargs, midargs, endargs);
129 LibraryTypeEnum previousLibraryType = null;
130 for (final LibrarySet libset : libsets) {
131 final LibrarySet set = libset;
132 final File libdir = set.getDir(null);
133 final String[] libs = set.getLibs();
134 if (libdir != null) {
135 String relPath = libdir.getAbsolutePath();
136
137 final File currentDir = new File(".");
138 if (currentDir.getParentFile() != null) {
139 relPath = CUtil.getRelativePath(currentDir.getParentFile().getAbsolutePath(), libdir);
140 }
141 if (set.getType() != null && "framework".equals(set.getType().getValue()) && isDarwin()) {
142 endargs.addElement("-F" + relPath);
143 } else {
144 endargs.addElement("-L" + relPath);
145 }
146 }
147
148
149
150 if (set.getType() != previousLibraryType) {
151 if (set.getType() != null && "static".equals(set.getType().getValue())) {
152
153 if (!isDarwin()) {
154 endargs.addElement(getStaticLibFlag());
155 previousLibraryType = set.getType();
156 }
157
158 } else {
159
160 if (set.getType() == null || !"framework".equals(set.getType().getValue()) && !isDarwin()) {
161 endargs.addElement(getDynamicLibFlag());
162 previousLibraryType = set.getType();
163 }
164 }
165 }
166 final StringBuffer buf = new StringBuffer("-l");
167 if (set.getType() != null && "framework".equals(set.getType().getValue()) && isDarwin()) {
168 buf.setLength(0);
169
170 endargs.addElement("-framework");
171 }
172 final int initialLength = buf.length();
173 for (final String lib : libs) {
174
175
176
177 buf.setLength(initialLength);
178
179
180 buf.append(lib);
181 libnames.addElement(lib);
182
183
184 endargs.addElement(buf.toString());
185 }
186 }
187
188
189
190 if (previousLibraryType != null && previousLibraryType.getValue().equals("static") && !isDarwin()) {
191 endargs.addElement(getDynamicLibFlag());
192 }
193
194
195 final String rc[] = new String[libnames.size()];
196 for (int i = 0; i < libnames.size(); i++) {
197 rc[i] = libnames.elementAt(i);
198 }
199 return rc;
200 }
201
202 @Override
203 protected void addMap(final CCTask task, final boolean map, final Vector<String> args) {
204 if (map) {
205 args.addElement("-M");
206 }
207 }
208
209 @Override
210 protected void addStack(final CCTask task, final int stack, final Vector<String> args) {
211 if (stack > 0) {
212 args.addElement("--stack");
213 args.addElement(Integer.toString(stack));
214 }
215 }
216
217 @Override
218 public String getCommandFileSwitch(final String commandFile) {
219 throw new IllegalStateException("ld does not support command files");
220 }
221
222 protected String getDynamicLibFlag() {
223 return "-Bdynamic";
224 }
225
226
227
228
229
230 protected File[] getEnvironmentIncludePath() {
231 return CUtil.getPathFromEnvironment("LIB", ":");
232 }
233
234 @Override
235 public String getLibraryKey(final File libfile) {
236 final String libname = libfile.getName();
237 final int lastDot = libname.lastIndexOf('.');
238 if (lastDot >= 0) {
239 return libname.substring(0, lastDot);
240 }
241 return libname;
242 }
243
244
245
246
247
248 @Override
249 public File[] getLibraryPath() {
250 return new File[0];
251 }
252
253 @Override
254 public String[] getLibraryPatterns(final String[] libnames, final LibraryTypeEnum libType) {
255 final StringBuffer buf = new StringBuffer();
256 int patternCount = libnames.length;
257 if (libType == null) {
258 patternCount *= 2;
259 }
260 final String[] patterns = new String[patternCount];
261 int offset = 0;
262 if (libType == null || "static".equals(libType.getValue())) {
263 offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0);
264 }
265 if (libType != null && "framework".equals(libType.getValue()) && isDarwin()) {
266 for (final String libname : libnames) {
267 buf.setLength(0);
268 buf.append(libname);
269 buf.append(".framework/");
270 buf.append(libname);
271 patterns[offset++] = buf.toString();
272 }
273 } else {
274 if (libType == null || !"static".equals(libType.getValue())) {
275 if (isHPUX()) {
276 offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, offset);
277 } else {
278 offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, offset);
279 }
280 }
281 }
282 return patterns;
283 }
284
285 @Override
286 public int getMaximumCommandLength() {
287
288 return isWindows() ? 20000 : Integer.MAX_VALUE;
289 }
290
291 @Override
292 public String[] getOutputFileNames(final String baseName, final VersionInfo versionInfo) {
293 final String[] baseNames = super.getOutputFileNames(baseName, versionInfo);
294 if (this.outputPrefix.length() > 0) {
295 for (int i = 0; i < baseNames.length; i++) {
296 baseNames[i] = this.outputPrefix + baseNames[i];
297 }
298 }
299 return baseNames;
300 }
301
302 @Override
303 public String[] getOutputFileSwitch(final String outputFile) {
304 return GccProcessor.getOutputFileSwitch("-o", outputFile);
305 }
306
307 protected String getStaticLibFlag() {
308 return "-Bstatic";
309 }
310
311 @Override
312 public boolean isCaseSensitive() {
313 return true;
314 }
315
316 protected boolean isHPUX() {
317 final String osname = System.getProperty("os.name").toLowerCase();
318 if (osname.contains("hp") && osname.contains("ux")) {
319 return true;
320 }
321 return false;
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336 @Override
337 public String[] prepareArguments(final CCTask task, final String outputDir, final String outputFile,
338 final String[] sourceFiles, final CommandLineLinkerConfiguration config) {
339
340
341
342
343 final String[] libnames = config.getLibraryNames();
344 if (libnames == null || libnames.length == 0) {
345 return super.prepareArguments(task, outputDir, outputFile, sourceFiles, config);
346 }
347
348
349
350
351 final String[] localSources = sourceFiles.clone();
352 int extra = 0;
353 for (final String libname : libnames) {
354 for (int j = 0; j < localSources.length; j++) {
355 if (localSources[j] != null && localSources[j].indexOf(libname) > 0 && localSources[j].indexOf("lib") > 0) {
356 final String filename = new File(localSources[j]).getName();
357 if (filename.startsWith("lib") && filename.substring(3).startsWith(libname)) {
358 final String extension = filename.substring(libname.length() + 3);
359 if (extension.equals(".a") || extension.equals(".so") || extension.equals(".sl")) {
360 localSources[j] = null;
361 extra++;
362 }
363 }
364 }
365 }
366 }
367 if (extra == 0) {
368 return super.prepareArguments(task, outputDir, outputFile, sourceFiles, config);
369 }
370 final String[] finalSources = new String[localSources.length - extra];
371 int index = 0;
372 for (final String localSource : localSources) {
373 if (localSource != null) {
374 finalSources[index++] = localSource;
375 }
376 }
377 return super.prepareArguments(task, outputDir, outputFile, finalSources, config);
378 }
379 }