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.LinkType;
28  import com.github.maven_nar.cpptasks.compiler.Linker;
29  import com.github.maven_nar.cpptasks.gcc.AbstractLdLinker;
30  
31  /**
32   * Adapter for the GCC linker
33   *
34   * @author Adam Murdoch
35   */
36  public class GccLinker extends AbstractLdLinker {
37    private static final String[] discardFiles = new String[0];
38    private static final String[] objFiles = new String[] {
39        ".o", ".a", ".lib", ".dll", ".so", ".sl"
40    };
41    private static final String[] libtoolObjFiles = new String[] {
42        ".fo", ".a", ".lib", ".dll", ".so", ".sl"
43    };
44    private static String[] linkerOptions = new String[] {
45        "-bundle", "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", "-static", "-shared", "-symbolic",
46        "-Xlinker", "--export-all-symbols", "-static-libgcc",
47    };
48    private static final GccLinker dllLinker = new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles,
49        "lib", ".so", false, new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", ".so", true,
50            null));
51    private static final GccLinker instance = new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "",
52        "", false, null);
53    private static final GccLinker machBundleLinker = new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles,
54        discardFiles, "lib", ".bundle", false, null);
55    private static final GccLinker machDllLinker = new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles,
56        "lib", ".dylib", false, null);
57  
58    public static GccLinker getInstance() {
59      return instance;
60    }
61  
62    private File[] libDirs;
63  
64    protected GccLinker(final String command, final String[] extensions, final String[] ignoredExtensions,
65        final String outputPrefix, final String outputSuffix, final boolean isLibtool, final GccLinker libtoolLinker) {
66      super(command, "-dumpversion", extensions, ignoredExtensions, outputPrefix, outputSuffix, isLibtool, libtoolLinker);
67    }
68  
69    @Override
70    protected void addImpliedArgs(final CCTask task, final boolean debug, final LinkType linkType,
71        final Vector<String> args) {
72      super.addImpliedArgs(task, debug, linkType, args);
73      if (getIdentifier().contains("mingw")) {
74        if (linkType.isSubsystemConsole()) {
75          args.addElement("-mconsole");
76        }
77        if (linkType.isSubsystemGUI()) {
78          args.addElement("-mwindows");
79        }
80      }
81    }
82  
83    /**
84     * Allows drived linker to decorate linker option. Override by GccLinker to
85     * prepend a "-Wl," to pass option to through gcc to linker.
86     * 
87     * @param buf
88     *          buffer that may be used and abused in the decoration process,
89     *          must not be null.
90     * @param arg
91     *          linker argument
92     */
93    @Override
94    public String decorateLinkerOption(final StringBuffer buf, final String arg) {
95      String decoratedArg = arg;
96      if (arg.length() > 1 && arg.charAt(0) == '-') {
97        switch (arg.charAt(1)) {
98        //
99        // passed automatically by GCC
100       //
101         case 'g':
102         case 'f':
103         case 'F':
104           /* Darwin */
105         case 'm':
106         case 'O':
107         case 'W':
108         case 'l':
109         case 'L':
110         case 'u':
111         case 'v':
112           break;
113         default:
114           boolean known = false;
115           for (final String linkerOption : linkerOptions) {
116             if (linkerOption.equals(arg)) {
117               known = true;
118               break;
119             }
120           }
121           if (!known) {
122             buf.setLength(0);
123             buf.append("-Wl,");
124             buf.append(arg);
125             decoratedArg = buf.toString();
126           }
127           break;
128       }
129     }
130     return decoratedArg;
131   }
132 
133   /**
134    * Returns library path.
135    * 
136    */
137   @Override
138   public File[] getLibraryPath() {
139     if (this.libDirs == null) {
140       //
141       // construct gcc lib path from machine and version
142       //
143       final StringBuffer buf = new StringBuffer("/lib/gcc-lib/");
144       buf.append(GccProcessor.getMachine());
145       buf.append('/');
146       buf.append(GccProcessor.getVersion());
147       //
148       // build default path from gcc and system /lib and /lib/w32api
149       //
150       final String[] impliedLibPath = new String[] {
151           buf.toString(), "/lib/w32api", "/lib"
152       };
153       //
154       // read gcc specs file for other library paths
155       //
156       final String[] specs = GccProcessor.getSpecs();
157       final String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", new String[] {
158         "%q"
159       });
160       String[] libpath;
161       if (libpaths[0].length > 0) {
162         libpath = new String[libpaths[0].length + 3];
163         int i = 0;
164         for (; i < libpaths[0].length; i++) {
165           libpath[i] = libpaths[0][i];
166         }
167         libpath[i++] = buf.toString();
168         libpath[i++] = "/lib/w32api";
169         libpath[i++] = "/lib";
170       } else {
171         //
172         // if a failure to find any matches then
173         // use some default values for lib path entries
174         libpath = new String[] {
175             "/usr/local/lib/mingw", "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", "/usr/lib", buf.toString(),
176             "/lib/w32api", "/lib"
177         };
178       }
179       for (int i = 0; i < libpath.length; i++) {
180         if (libpath[i].contains("mingw")) {
181           libpath[i] = null;
182         }
183       }
184       //
185       // if cygwin then
186       // we have to prepend location of gcc32
187       // and .. to start of absolute filenames to
188       // have something that will exist in the
189       // windows filesystem
190       if (GccProcessor.isCygwin()) {
191         GccProcessor.convertCygwinFilenames(libpath);
192       }
193       //
194       // check that remaining entries are actual directories
195       //
196       final int count = CUtil.checkDirectoryArray(libpath);
197       //
198       // populate return array with remaining entries
199       //
200       this.libDirs = new File[count];
201       int index = 0;
202       for (final String element : libpath) {
203         if (element != null) {
204           this.libDirs[index++] = new File(element);
205         }
206       }
207     }
208     return this.libDirs;
209   }
210 
211   @Override
212   public Linker getLinker(final LinkType type) {
213     if (type.isStaticLibrary()) {
214       return GccLibrarian.getInstance();
215     }
216     if (type.isPluginModule()) {
217       if (isDarwin()) {
218         return machBundleLinker;
219       } else {
220         return dllLinker;
221       }
222     }
223     if (type.isSharedLibrary()) {
224       if (isDarwin()) {
225         return machDllLinker;
226       } else {
227         return dllLinker;
228       }
229     }
230     return instance;
231   }
232 }