3 * Copyright 2001-2004 The Ant-Contrib project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package net
.sf
.antcontrib
.cpptasks
.gcc
.cross
;
19 import java
.util
.Vector
;
20 import net
.sf
.antcontrib
.cpptasks
.CCTask
;
21 import net
.sf
.antcontrib
.cpptasks
.CUtil
;
22 import net
.sf
.antcontrib
.cpptasks
.LinkerParam
;
23 import net
.sf
.antcontrib
.cpptasks
.compiler
.CommandLineLinkerConfiguration
;
24 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
25 import net
.sf
.antcontrib
.cpptasks
.compiler
.Linker
;
26 import net
.sf
.antcontrib
.cpptasks
.gcc
.AbstractLdLinker
;
27 import org
.apache
.tools
.ant
.BuildException
;
29 * Adapter for the GCC linker
31 * @author Adam Murdoch
33 public class GccLinker
extends AbstractLdLinker
{
34 private static final String
[] discardFiles
= new String
[0];
35 private static final String
[] objFiles
= new String
[]{".o", ".a", ".lib",
36 ".dll", ".so", ".sl"};
37 private static final GccLinker dllLinker
= new GccLinker("gcc", objFiles
,
38 discardFiles
, "lib", ".so", false, new GccLinker("gcc", objFiles
,
39 discardFiles
, "lib", ".so", true, null));
40 private static final GccLinker instance
= new GccLinker("gcc", objFiles
,
41 discardFiles
, "", "", false, null);
42 private static final String
[] libtoolObjFiles
= new String
[]{".fo", ".a",
43 ".lib", ".dll", ".so", ".sl"};
44 private static String
[] linkerOptions
= new String
[]{"-bundle",
45 "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s",
46 "-static", "-shared", "-symbolic", "-Xlinker",
47 "--export-all-symbols", "-static-libgcc",};
48 private static final GccLinker machBundleLinker
= new GccLinker("gcc",
49 objFiles
, discardFiles
, "lib", ".bundle", false, null);
50 private static final GccLinker machDllLinker
= new GccLinker("gcc",
51 objFiles
, discardFiles
, "lib", ".dylib", false, null);
52 public static GccLinker
getInstance() {
55 private File
[] libDirs
;
56 protected GccLinker(String command
, String
[] extensions
,
57 String
[] ignoredExtensions
, String outputPrefix
,
58 String outputSuffix
, boolean isLibtool
, GccLinker libtoolLinker
) {
59 super(command
, "-dumpversion", extensions
, ignoredExtensions
,
60 outputPrefix
, outputSuffix
, isLibtool
, libtoolLinker
);
62 protected void addImpliedArgs(boolean debug
, LinkType linkType
, Vector args
, Boolean defaultflag
) {
63 super.addImpliedArgs(debug
, linkType
, args
, defaultflag
);
64 if (getIdentifier().indexOf("mingw") >= 0) {
65 if (linkType
.isSubsystemConsole()) {
66 args
.addElement("-mconsole");
68 if (linkType
.isSubsystemGUI()) {
69 args
.addElement("-mwindows");
73 protected Object
clone() throws CloneNotSupportedException
{
74 GccLinker clone
= (GccLinker
) super.clone();
78 * Allows drived linker to decorate linker option. Override by GccLinker to
79 * prepend a "-Wl," to pass option to through gcc to linker.
82 * buffer that may be used and abused in the decoration process,
87 public String
decorateLinkerOption(StringBuffer buf
, String arg
) {
88 String decoratedArg
= arg
;
89 if (arg
.length() > 1 && arg
.charAt(0) == '-') {
90 switch (arg
.charAt(1)) {
92 // passed automatically by GCC
107 boolean known
= false;
108 for (int i
= 0; i
< linkerOptions
.length
; i
++) {
109 if (linkerOptions
[i
].equals(arg
)) {
118 decoratedArg
= buf
.toString();
126 * Returns library path.
129 public File
[] getLibraryPath() {
130 if (libDirs
== null) {
132 // construct gcc lib path from machine and version
134 StringBuffer buf
= new StringBuffer("/lib/gcc-lib/");
135 buf
.append(GccProcessor
.getMachine());
137 buf
.append(GccProcessor
.getVersion());
139 // build default path from gcc and system /lib and /lib/w32api
141 String
[] impliedLibPath
= new String
[]{buf
.toString(),
142 "/lib/w32api", "/lib"};
144 // read gcc specs file for other library paths
146 String
[] specs
= GccProcessor
.getSpecs();
147 String
[][] libpaths
= GccProcessor
.parseSpecs(specs
, "*link:",
150 if (libpaths
[0].length
> 0) {
151 libpath
= new String
[libpaths
[0].length
+ 3];
153 for (; i
< libpaths
[0].length
; i
++) {
154 libpath
[i
] = libpaths
[0][i
];
156 libpath
[i
++] = buf
.toString();
157 libpath
[i
++] = "/lib/w32api";
158 libpath
[i
++] = "/lib";
161 // if a failure to find any matches then
162 // use some default values for lib path entries
163 libpath
= new String
[]{"/usr/local/lib/mingw",
164 "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw",
165 "/usr/lib", buf
.toString(), "/lib/w32api", "/lib"};
167 for (int i
= 0; i
< libpath
.length
; i
++) {
168 if (libpath
[i
].indexOf("mingw") >= 0) {
174 // we have to prepend location of gcc32
175 // and .. to start of absolute filenames to
176 // have something that will exist in the
177 // windows filesystem
178 if (GccProcessor
.isCygwin()) {
179 GccProcessor
.convertCygwinFilenames(libpath
);
182 // check that remaining entries are actual directories
184 int count
= CUtil
.checkDirectoryArray(libpath
);
186 // populate return array with remaining entries
188 libDirs
= new File
[count
];
190 for (int i
= 0; i
< libpath
.length
; i
++) {
191 if (libpath
[i
] != null) {
192 libDirs
[index
++] = new File(libpath
[i
]);
198 public Linker
getLinker(LinkType type
) {
199 if (type
.isStaticLibrary()) {
200 return GccLibrarian
.getInstance();
202 if (type
.isPluginModule()) {
204 return machBundleLinker
;
209 if (type
.isSharedLibrary()) {
211 return machDllLinker
;
218 public void link(CCTask task
, File outputFile
, String
[] sourceFiles
,
219 CommandLineLinkerConfiguration config
) throws BuildException
{
221 GccLinker clone
= (GccLinker
) this.clone();
222 LinkerParam param
= config
.getParam("target");
224 clone
.setCommand(param
.getValue() + "-" + this.getCommand());
225 clone
.superlink(task
, outputFile
, sourceFiles
, config
);
226 } catch (CloneNotSupportedException e
) {
227 superlink(task
, outputFile
, sourceFiles
, config
);
230 private void superlink(CCTask task
, File outputFile
, String
[] sourceFiles
,
231 CommandLineLinkerConfiguration config
) throws BuildException
{
232 super.link(task
, outputFile
, sourceFiles
, config
);