3 * Copyright 2003-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
;
21 import net
.sf
.antcontrib
.cpptasks
.CCTask
;
22 import net
.sf
.antcontrib
.cpptasks
.CUtil
;
23 import net
.sf
.antcontrib
.cpptasks
.LinkerParam
;
24 import net
.sf
.antcontrib
.cpptasks
.compiler
.CaptureStreamHandler
;
25 import net
.sf
.antcontrib
.cpptasks
.compiler
.CommandLineLinkerConfiguration
;
26 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
27 import net
.sf
.antcontrib
.cpptasks
.compiler
.Linker
;
28 import net
.sf
.antcontrib
.cpptasks
.gcc
.AbstractLdLinker
;
29 import net
.sf
.antcontrib
.cpptasks
.types
.LibrarySet
;
31 import org
.apache
.tools
.ant
.BuildException
;
33 * Adapter for the g++ variant of the GCC linker
35 * @author Stephen M. Webb <stephen.webb@bregmasoft.com>
37 public class GppLinker
extends AbstractLdLinker
{
38 protected static final String
[] discardFiles
= new String
[0];
39 protected static final String
[] objFiles
= new String
[]{".o", ".a", ".lib",
40 ".dll", ".so", ".sl"};
41 private static final GppLinker dllLinker
= new GppLinker("gcc", objFiles
,
42 discardFiles
, "lib", ".so", false, new GppLinker("gcc", objFiles
,
43 discardFiles
, "lib", ".so", true, null));
44 private final static String libPrefix
= "libraries: =";
45 protected static final String
[] libtoolObjFiles
= new String
[]{".fo", ".a",
46 ".lib", ".dll", ".so", ".sl"};
47 private static String
[] linkerOptions
= new String
[]{"-bundle", "-dylib",
48 "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib",
49 "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"};
50 private static final GppLinker instance
= new GppLinker("gcc", objFiles
,
51 discardFiles
, "", "", false, null);
52 private static final GppLinker machDllLinker
= new GppLinker("gcc",
53 objFiles
, discardFiles
, "lib", ".dylib", false, null);
54 private static final GppLinker machPluginLinker
= new GppLinker("gcc",
55 objFiles
, discardFiles
, "lib", ".bundle", false, null);
56 public static GppLinker
getInstance() {
59 private File
[] libDirs
;
60 private String runtimeLibrary
;
61 protected GppLinker(String command
, String
[] extensions
,
62 String
[] ignoredExtensions
, String outputPrefix
,
63 String outputSuffix
, boolean isLibtool
, GppLinker libtoolLinker
) {
64 super(command
, "-dumpversion", extensions
, ignoredExtensions
,
65 outputPrefix
, outputSuffix
, isLibtool
, libtoolLinker
);
67 protected void addImpliedArgs(boolean debug
, LinkType linkType
, Vector args
, Boolean defaultflag
) {
68 super.addImpliedArgs(debug
, linkType
, args
, defaultflag
);
69 if (getIdentifier().indexOf("mingw") >= 0) {
70 if (linkType
.isSubsystemConsole()) {
71 args
.addElement("-mconsole");
73 if (linkType
.isSubsystemGUI()) {
74 args
.addElement("-mwindows");
77 if (linkType
.isStaticRuntime()) {
78 String
[] cmdin
= new String
[]{"g++", "-print-file-name=libstdc++.a"};
79 String
[] cmdout
= CaptureStreamHandler
.run(cmdin
);
80 if (cmdout
.length
> 0) {
81 runtimeLibrary
= cmdout
[0];
83 runtimeLibrary
= null;
86 runtimeLibrary
= "-lstdc++";
89 public String
[] addLibrarySets(CCTask task
, LibrarySet
[] libsets
,
90 Vector preargs
, Vector midargs
, Vector endargs
) {
91 String
[] rs
= super.addLibrarySets(task
, libsets
, preargs
, midargs
,
93 if (runtimeLibrary
!= null) {
94 endargs
.addElement(runtimeLibrary
);
98 protected Object
clone() throws CloneNotSupportedException
{
99 GppLinker clone
= (GppLinker
) super.clone();
103 * Allows drived linker to decorate linker option. Override by GppLinker to
104 * prepend a "-Wl," to pass option to through gcc to linker.
107 * buffer that may be used and abused in the decoration process,
112 public String
decorateLinkerOption(StringBuffer buf
, String arg
) {
113 String decoratedArg
= arg
;
114 if (arg
.length() > 1 && arg
.charAt(0) == '-') {
115 switch (arg
.charAt(1)) {
117 // passed automatically by GCC
131 boolean known
= false;
132 for (int i
= 0; i
< linkerOptions
.length
; i
++) {
133 if (linkerOptions
[i
].equals(arg
)) {
142 decoratedArg
= buf
.toString();
150 * Returns library path.
153 public File
[] getLibraryPath() {
154 if (libDirs
== null) {
155 Vector dirs
= new Vector();
156 // Ask GCC where it will look for its libraries.
157 String
[] args
= new String
[]{"g++", "-print-search-dirs"};
158 String
[] cmdout
= CaptureStreamHandler
.run(args
);
159 for (int i
= 0; i
< cmdout
.length
; ++i
) {
160 int prefixIndex
= cmdout
[i
].indexOf(libPrefix
);
161 if (prefixIndex
>= 0) {
162 // Special case DOS-type GCCs like MinGW or Cygwin
163 int s
= prefixIndex
+ libPrefix
.length();
164 int t
= cmdout
[i
].indexOf(';', s
);
166 dirs
.addElement(cmdout
[i
].substring(s
, t
));
168 t
= cmdout
[i
].indexOf(';', s
);
170 dirs
.addElement(cmdout
[i
].substring(s
));
172 for (; i
< cmdout
.length
; ++i
) {
173 dirs
.addElement(cmdout
[i
]);
177 // Eliminate all but actual directories.
178 String
[] libpath
= new String
[dirs
.size()];
179 dirs
.copyInto(libpath
);
180 int count
= CUtil
.checkDirectoryArray(libpath
);
181 // Build return array.
182 libDirs
= new File
[count
];
184 for (int i
= 0; i
< libpath
.length
; ++i
) {
185 if (libpath
[i
] != null) {
186 libDirs
[index
++] = new File(libpath
[i
]);
192 public Linker
getLinker(LinkType type
) {
193 if (type
.isStaticLibrary()) {
194 return GccLibrarian
.getInstance();
196 if (type
.isPluginModule()) {
197 if (GccProcessor
.getMachine().indexOf("darwin") >= 0) {
198 return machPluginLinker
;
203 if (type
.isSharedLibrary()) {
204 if (GccProcessor
.getMachine().indexOf("darwin") >= 0) {
205 return machDllLinker
;
212 public void link(CCTask task
, File outputFile
, String
[] sourceFiles
,
213 CommandLineLinkerConfiguration config
) throws BuildException
{
215 GppLinker clone
= (GppLinker
) this.clone();
216 LinkerParam param
= config
.getParam("target");
218 clone
.setCommand(param
.getValue() + "-" + this.getCommand());
219 clone
.superlink(task
, outputFile
, sourceFiles
, config
);
220 } catch (CloneNotSupportedException e
) {
221 superlink(task
, outputFile
, sourceFiles
, config
);
224 private void superlink(CCTask task
, File outputFile
, String
[] sourceFiles
,
225 CommandLineLinkerConfiguration config
) throws BuildException
{
226 super.link(task
, outputFile
, sourceFiles
, config
);