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
;
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
.compiler
.CaptureStreamHandler
;
24 import net
.sf
.antcontrib
.cpptasks
.compiler
.LinkType
;
25 import net
.sf
.antcontrib
.cpptasks
.compiler
.Linker
;
26 import net
.sf
.antcontrib
.cpptasks
.types
.LibrarySet
;
28 * Adapter for the g++ variant of the GCC linker
30 * @author Stephen M. Webb <stephen.webb@bregmasoft.com>
32 public class GppLinker
extends AbstractLdLinker
{
33 protected static final String
[] discardFiles
= new String
[0];
34 protected static final String
[] objFiles
= new String
[]{".o", ".a", ".lib",
35 ".dll", ".so", ".sl"};
36 private static final GppLinker dllLinker
= new GppLinker("gcc", objFiles
,
37 discardFiles
, "lib", ".so", false, new GppLinker("gcc", objFiles
,
38 discardFiles
, "lib", ".so", true, null));
39 private final static String libPrefix
= "libraries: =";
40 protected static final String
[] libtoolObjFiles
= new String
[]{".fo", ".a",
41 ".lib", ".dll", ".so", ".sl"};
42 private static String
[] linkerOptions
= new String
[]{"-bundle", "-dylib",
43 "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib",
44 "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"};
45 private static final GppLinker instance
= new GppLinker("gcc", objFiles
,
46 discardFiles
, "", "", false, null);
47 private static final GppLinker machDllLinker
= new GppLinker("gcc",
48 objFiles
, discardFiles
, "lib", ".dylib", false, null);
49 private static final GppLinker machPluginLinker
= new GppLinker("gcc",
50 objFiles
, discardFiles
, "lib", ".bundle", false, null);
51 public static GppLinker
getInstance() {
54 private File
[] libDirs
;
55 private String runtimeLibrary
;
56 protected GppLinker(String command
, String
[] extensions
,
57 String
[] ignoredExtensions
, String outputPrefix
,
58 String outputSuffix
, boolean isLibtool
, GppLinker 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");
72 if (linkType
.isStaticRuntime()) {
73 String
[] cmdin
= new String
[]{"g++", "-print-file-name=libstdc++.a"};
74 String
[] cmdout
= CaptureStreamHandler
.run(cmdin
);
75 if (cmdout
.length
> 0) {
76 runtimeLibrary
= cmdout
[0];
78 runtimeLibrary
= null;
81 runtimeLibrary
= "-lstdc++";
84 public String
[] addLibrarySets(CCTask task
, LibrarySet
[] libsets
,
85 Vector preargs
, Vector midargs
, Vector endargs
) {
86 String
[] rs
= super.addLibrarySets(task
, libsets
, preargs
, midargs
,
88 if (runtimeLibrary
!= null) {
89 endargs
.addElement(runtimeLibrary
);
94 * Allows drived linker to decorate linker option. Override by GppLinker to
95 * prepend a "-Wl," to pass option to through gcc to linker.
98 * buffer that may be used and abused in the decoration process,
103 public String
decorateLinkerOption(StringBuffer buf
, String arg
) {
104 String decoratedArg
= arg
;
105 if (arg
.length() > 1 && arg
.charAt(0) == '-') {
106 switch (arg
.charAt(1)) {
108 // passed automatically by GCC
122 boolean known
= false;
123 for (int i
= 0; i
< linkerOptions
.length
; i
++) {
124 if (linkerOptions
[i
].equals(arg
)) {
133 decoratedArg
= buf
.toString();
141 * Returns library path.
144 public File
[] getLibraryPath() {
145 if (libDirs
== null) {
146 Vector dirs
= new Vector();
147 // Ask GCC where it will look for its libraries.
148 String
[] args
= new String
[]{"g++", "-print-search-dirs"};
149 String
[] cmdout
= CaptureStreamHandler
.run(args
);
150 for (int i
= 0; i
< cmdout
.length
; ++i
) {
151 int prefixIndex
= cmdout
[i
].indexOf(libPrefix
);
152 if (prefixIndex
>= 0) {
153 // Special case DOS-type GCCs like MinGW or Cygwin
154 int s
= prefixIndex
+ libPrefix
.length();
155 int t
= cmdout
[i
].indexOf(';', s
);
157 dirs
.addElement(cmdout
[i
].substring(s
, t
));
159 t
= cmdout
[i
].indexOf(';', s
);
161 dirs
.addElement(cmdout
[i
].substring(s
));
163 for (; i
< cmdout
.length
; ++i
) {
164 dirs
.addElement(cmdout
[i
]);
168 // Eliminate all but actual directories.
169 String
[] libpath
= new String
[dirs
.size()];
170 dirs
.copyInto(libpath
);
171 int count
= CUtil
.checkDirectoryArray(libpath
);
172 // Build return array.
173 libDirs
= new File
[count
];
175 for (int i
= 0; i
< libpath
.length
; ++i
) {
176 if (libpath
[i
] != null) {
177 libDirs
[index
++] = new File(libpath
[i
]);
183 public Linker
getLinker(LinkType type
) {
184 if (type
.isStaticLibrary()) {
185 return GccLibrarian
.getInstance();
187 if (type
.isPluginModule()) {
188 if (GccProcessor
.getMachine().indexOf("darwin") >= 0) {
189 return machPluginLinker
;
194 if (type
.isSharedLibrary()) {
195 if (GccProcessor
.getMachine().indexOf("darwin") >= 0) {
196 return machDllLinker
;