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.borland;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.Vector;
25  
26  import org.apache.tools.ant.BuildException;
27  
28  import com.github.maven_nar.cpptasks.CCTask;
29  import com.github.maven_nar.cpptasks.CUtil;
30  import com.github.maven_nar.cpptasks.compiler.CommandLineLinker;
31  import com.github.maven_nar.cpptasks.compiler.CommandLineLinkerConfiguration;
32  import com.github.maven_nar.cpptasks.compiler.LinkType;
33  import com.github.maven_nar.cpptasks.compiler.Linker;
34  import com.github.maven_nar.cpptasks.types.LibraryTypeEnum;
35  
36  /**
37   * Adapter for the Borland(r) tlib Librarian
38   *
39   * @author Curt Arnold
40   */
41  public class BorlandLibrarian extends CommandLineLinker {
42    private static final BorlandLibrarian instance = new BorlandLibrarian();
43  
44    public static BorlandLibrarian getInstance() {
45      return instance;
46    }
47  
48    private BorlandLibrarian() {
49      super("tlib", "--version", new String[] {
50        ".obj"
51      }, new String[0], ".lib", false, null);
52    }
53  
54    @Override
55    protected String getCommandFileSwitch(final String cmdFile) {
56      //
57      // tlib requires quotes around paths containing -
58      // ilink32 doesn't like them
59      final StringBuffer buf = new StringBuffer("@");
60      BorlandProcessor.quoteFile(buf, cmdFile);
61      return buf.toString();
62    }
63  
64    /**
65     * Gets identifier for the linker.
66     * 
67     * TLIB will lockup when attempting to get version
68     * information. Since the Librarian version isn't critical
69     * just return a stock response.
70     */
71    @Override
72    public String getIdentifier() {
73      return "TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation";
74    }
75  
76    @Override
77    public File[] getLibraryPath() {
78      return CUtil.getPathFromEnvironment("LIB", ";");
79    }
80  
81    @Override
82    public String[] getLibraryPatterns(final String[] libnames, final LibraryTypeEnum libType) {
83      return BorlandProcessor.getLibraryPatterns(libnames, libType);
84    }
85  
86    @Override
87    public Linker getLinker(final LinkType type) {
88      return BorlandLinker.getInstance().getLinker(type);
89    }
90  
91    @Override
92    public int getMaximumCommandLength() {
93      return 1024;
94    }
95  
96    @Override
97    public String[] getOutputFileSwitch(final String outFile) {
98      return BorlandProcessor.getOutputFileSwitch(outFile);
99    }
100 
101   @Override
102   public boolean isCaseSensitive() {
103     return BorlandProcessor.isCaseSensitive();
104   }
105 
106   /**
107    * Builds a library
108    *
109    */
110   @Override
111   public void link(final CCTask task, final File outputFile, final String[] sourceFiles,
112       final CommandLineLinkerConfiguration config) throws BuildException {
113     //
114     // delete any existing library
115     outputFile.delete();
116     //
117     // build a new library
118     super.link(task, outputFile, sourceFiles, config);
119   }
120 
121   /**
122    * Prepares argument list for exec command.
123    * 
124    * @param outputDir
125    *          linker output directory
126    * @param outputName
127    *          linker output name
128    * @param sourceFiles
129    *          linker input files (.obj, .o, .res)
130    * @param config
131    *          linker configuration
132    * @return arguments for runTask
133    */
134   @Override
135   protected String[] prepareArguments(final CCTask task, final String outputDir, final String outputName,
136       final String[] sourceFiles, final CommandLineLinkerConfiguration config) {
137     final String[] preargs = config.getPreArguments();
138     final String[] endargs = config.getEndArguments();
139     final StringBuffer buf = new StringBuffer();
140     final Vector<String> execArgs = new Vector<>(preargs.length + endargs.length + 10 + sourceFiles.length);
141 
142     execArgs.addElement(this.getCommand());
143     final String outputFileName = new File(outputDir, outputName).toString();
144     execArgs.addElement(quoteFilename(buf, outputFileName));
145 
146     for (final String prearg : preargs) {
147       execArgs.addElement(prearg);
148     }
149 
150     //
151     // add a place-holder for page size
152     //
153     final int pageSizeIndex = execArgs.size();
154     execArgs.addElement(null);
155 
156     int objBytes = 0;
157 
158     for (final String sourceFile : sourceFiles) {
159       final String last4 = sourceFile.substring(sourceFile.length() - 4).toLowerCase();
160       if (last4.equals(".def")) {
161       } else {
162         if (last4.equals(".res")) {
163         } else {
164           if (last4.equals(".lib")) {
165           } else {
166             execArgs.addElement("+" + quoteFilename(buf, sourceFile));
167             objBytes += new File(sourceFile).length();
168           }
169         }
170       }
171     }
172 
173     for (final String endarg : endargs) {
174       execArgs.addElement(endarg);
175     }
176 
177     final String[] execArguments = new String[execArgs.size()];
178     execArgs.copyInto(execArguments);
179 
180     final int minPageSize = objBytes >> 16;
181     int pageSize = 0;
182     for (int i = 4; i <= 15; i++) {
183       pageSize = 1 << i;
184       if (pageSize > minPageSize) {
185         break;
186       }
187     }
188     execArguments[pageSizeIndex] = "/P" + Integer.toString(pageSize);
189 
190     return execArguments;
191   }
192 
193   /**
194    * Prepares argument list to execute the linker using a response file.
195    * 
196    * @param outputFile
197    *          linker output file
198    * @param args
199    *          output of prepareArguments
200    * @return arguments for runTask
201    */
202   @Override
203   protected String[] prepareResponseFile(final File outputFile, final String[] args) throws IOException {
204     final String[] cmdargs = BorlandProcessor.prepareResponseFile(outputFile, args, " & \n");
205     cmdargs[cmdargs.length - 1] = getCommandFileSwitch(cmdargs[cmdargs.length - 1]);
206     return cmdargs;
207   }
208 
209   /**
210    * Encloses problematic file names within quotes.
211    * 
212    * @param buf
213    *          string buffer
214    * @param filename
215    *          source file name
216    * @return filename potentially enclosed in quotes.
217    */
218   @Override
219   protected String quoteFilename(final StringBuffer buf, final String filename) {
220     buf.setLength(0);
221     BorlandProcessor.quoteFile(buf, filename);
222     return buf.toString();
223   }
224 
225 }