View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar.cpptasks.gcc.cross.sparc_sun_solaris2;
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.compiler.CaptureStreamHandler;
28  import com.github.maven_nar.cpptasks.compiler.LinkType;
29  import com.github.maven_nar.cpptasks.compiler.Linker;
30  import com.github.maven_nar.cpptasks.gcc.AbstractLdLinker;
31  import com.github.maven_nar.cpptasks.types.LibrarySet;
32  
33  /**
34   * Adapter for the g++ variant of the GCC linker
35   *
36   * @author Stephen M. Webb <stephen.webb@bregmasoft.com>
37   */
38  public class GppLinker extends AbstractLdLinker {
39    protected static final String[] discardFiles = new String[0];
40    protected static final String[] objFiles = new String[] {
41        ".o", ".a", ".lib", ".dll", ".so", ".sl"
42    };
43    private final static String libPrefix = "libraries: =";
44    protected static final String[] libtoolObjFiles = new String[] {
45        ".fo", ".a", ".lib", ".dll", ".so", ".sl"
46    };
47    private static String[] linkerOptions = new String[] {
48        "-bundle", "-dylib", "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", "-static",
49        "-shared", "-symbolic", "-Xlinker"
50    };
51    private static final GppLinker dllLinker = new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles,
52        "lib", ".so", false, new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", ".so", true,
53            null));
54    private static final GppLinker instance = new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "",
55        "", false, null);
56    private static final GppLinker machDllLinker = new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles,
57        "lib", ".dylib", false, null);
58    private static final GppLinker machPluginLinker = new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles,
59        discardFiles, "lib", ".bundle", false, null);
60  
61    public static GppLinker getInstance() {
62      return instance;
63    }
64  
65    private File[] libDirs;
66    private String runtimeLibrary;
67  
68    protected GppLinker(final String command, final String[] extensions, final String[] ignoredExtensions,
69        final String outputPrefix, final String outputSuffix, final boolean isLibtool, final GppLinker libtoolLinker) {
70      super(command, "-dumpversion", extensions, ignoredExtensions, outputPrefix, outputSuffix, isLibtool, libtoolLinker);
71    }
72  
73    @Override
74    protected void addImpliedArgs(final CCTask task, final boolean debug, final LinkType linkType,
75        final Vector<String> args) {
76      super.addImpliedArgs(task, debug, linkType, args);
77      if (getIdentifier().contains("mingw")) {
78        if (linkType.isSubsystemConsole()) {
79          args.addElement("-mconsole");
80        }
81        if (linkType.isSubsystemGUI()) {
82          args.addElement("-mwindows");
83        }
84      }
85      if (linkType.isStaticRuntime()) {
86        final String[] cmdin = new String[] {
87            GccCCompiler.CMD_PREFIX + "g++", "-print-file-name=libstdc++.a"
88        };
89        final String[] cmdout = CaptureStreamHandler.run(cmdin);
90        if (cmdout.length > 0) {
91          this.runtimeLibrary = cmdout[0];
92        } else {
93          this.runtimeLibrary = null;
94        }
95      } else {
96        this.runtimeLibrary = "-lstdc++";
97      }
98    }
99  
100   @Override
101   public String[] addLibrarySets(final CCTask task, final LibrarySet[] libsets, final Vector<String> preargs,
102       final Vector<String> midargs, final Vector<String> endargs) {
103     final String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, endargs);
104     if (this.runtimeLibrary != null) {
105       endargs.addElement(this.runtimeLibrary);
106     }
107     return rs;
108   }
109 
110   /**
111    * Allows drived linker to decorate linker option. Override by GppLinker to
112    * prepend a "-Wl," to pass option to through gcc to linker.
113    * 
114    * @param buf
115    *          buffer that may be used and abused in the decoration process,
116    *          must not be null.
117    * @param arg
118    *          linker argument
119    */
120   @Override
121   public String decorateLinkerOption(final StringBuffer buf, final String arg) {
122     String decoratedArg = arg;
123     if (arg.length() > 1 && arg.charAt(0) == '-') {
124       switch (arg.charAt(1)) {
125       //
126       // passed automatically by GCC
127       //
128         case 'g':
129         case 'f':
130         case 'F':
131           /* Darwin */
132         case 'm':
133         case 'O':
134         case 'W':
135         case 'l':
136         case 'L':
137         case 'u':
138           break;
139         default:
140           boolean known = false;
141           for (final String linkerOption : linkerOptions) {
142             if (linkerOption.equals(arg)) {
143               known = true;
144               break;
145             }
146           }
147           if (!known) {
148             buf.setLength(0);
149             buf.append("-Wl,");
150             buf.append(arg);
151             decoratedArg = buf.toString();
152           }
153           break;
154       }
155     }
156     return decoratedArg;
157   }
158 
159   /**
160    * Returns library path.
161    * 
162    */
163   @Override
164   public File[] getLibraryPath() {
165     if (this.libDirs == null) {
166       final Vector<String> dirs = new Vector<>();
167       // Ask GCC where it will look for its libraries.
168       final String[] args = new String[] {
169           GccCCompiler.CMD_PREFIX + "g++", "-print-search-dirs"
170       };
171       final String[] cmdout = CaptureStreamHandler.run(args);
172       for (int i = 0; i < cmdout.length; ++i) {
173         final int prefixIndex = cmdout[i].indexOf(libPrefix);
174         if (prefixIndex >= 0) {
175           // Special case DOS-type GCCs like MinGW or Cygwin
176           int s = prefixIndex + libPrefix.length();
177           int t = cmdout[i].indexOf(';', s);
178           while (t > 0) {
179             dirs.addElement(cmdout[i].substring(s, t));
180             s = t + 1;
181             t = cmdout[i].indexOf(';', s);
182           }
183           dirs.addElement(cmdout[i].substring(s));
184           ++i;
185           for (; i < cmdout.length; ++i) {
186             dirs.addElement(cmdout[i]);
187           }
188         }
189       }
190       // Eliminate all but actual directories.
191       final String[] libpath = new String[dirs.size()];
192       dirs.copyInto(libpath);
193       final int count = CUtil.checkDirectoryArray(libpath);
194       // Build return array.
195       this.libDirs = new File[count];
196       int index = 0;
197       for (final String element : libpath) {
198         if (element != null) {
199           this.libDirs[index++] = new File(element);
200         }
201       }
202     }
203     return this.libDirs;
204   }
205 
206   @Override
207   public Linker getLinker(final LinkType type) {
208     if (type.isStaticLibrary()) {
209       return GccLibrarian.getInstance();
210     }
211     if (type.isPluginModule()) {
212       if (GccProcessor.getMachine().contains("darwin")) {
213         return machPluginLinker;
214       } else {
215         return dllLinker;
216       }
217     }
218     if (type.isSharedLibrary()) {
219       if (GccProcessor.getMachine().contains("darwin")) {
220         return machDllLinker;
221       } else {
222         return dllLinker;
223       }
224     }
225     return instance;
226   }
227 }