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