summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-12-12 07:29:07 +0100
committerSven Gothel <[email protected]>2019-12-12 07:29:07 +0100
commit07aeed47e484bfec85e749ea721756b8a2571e00 (patch)
treeb77ce918b3ee90349ec4e72de5893664e1b27097
parent79a8fed9fddab5429a3457c3077ee5012b405a51 (diff)
Bug 1417 (JogAmp): New CCTask parameter 'writesoname': Adds GnuLinker and clang linker '-h name' options, writing SONAME for shares libraries
Setting the SONAME via general options simplifies the adoption of SONAME, as the individual linker configurations must not change in the user projects. This is new option for conveninience and scaling. Feature is currently enabled for the GnuLinker (GccLinker 'gcc' + GppLinker 'gpp') as well as for clang (clang). The SONAME must be set on Android API level >= 23, see gluegen commit 51ef5eadd9db020412d3a3716b4ab5a25b0522fb.
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/CCTask.java54
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java12
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java45
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java83
4 files changed, 131 insertions, 63 deletions
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java b/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java
index 3197080..0701ba1 100644
--- a/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java
+++ b/src/main/java/net/sf/antcontrib/cpptasks/CCTask.java
@@ -21,6 +21,7 @@ import java.util.Enumeration;
import java.util.Hashtable;
import java.util.*;
+import net.sf.antcontrib.cpptasks.compiler.AbstractLinker;
import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration;
import net.sf.antcontrib.cpptasks.compiler.LinkType;
import net.sf.antcontrib.cpptasks.compiler.Linker;
@@ -622,7 +623,7 @@ public class CCTask extends Task {
// Assemble hashtable of all files
// that we know how to compile (keyed by output file name)
//
- final Hashtable targets = getTargets(linkerConfig, objectFiles, versionInfo, _outfile);
+ final Hashtable targets = getTargets(linkerConfig, objectFiles, versionInfo, _outfile); // getTargets(..) -> createConfiguration(..) -> addImpliedArgs(..)
TargetInfo linkTarget = null;
//
// if output file is not specified,
@@ -804,7 +805,7 @@ public class CCTask extends Task {
final LinkerConfiguration linkConfig = (LinkerConfiguration) linkTarget
.getConfiguration();
if (failOnError) {
- linkConfig.link(this, linkTarget);
+ linkConfig.link(this, linkTarget); // link(..) -> prepareArguments(..) -> decorateLinkerOption(..) + getOutputFileSwitch(..)
} else {
try {
linkConfig.link(this, linkTarget);
@@ -1297,11 +1298,7 @@ public class CCTask extends Task {
}
/**
- * User preference whether to use a high-level-tool for
- * linker operations, e.g. gcc instead of ar to build static libraries.
- * <p>
- * Default is false.
- * </p>
+ * See {@link #getUseHighlevelTool()}.
* @param useHighlevelTool user preference, default is false
*/
public void setUseHighlevelTool(final boolean useHighlevelTool) {
@@ -1309,7 +1306,11 @@ public class CCTask extends Task {
}
/**
- * Gets the usehighleveltool flag.
+ * User preference whether to use a high-level-tool for
+ * linker operations, e.g. gcc instead of ar to build static libraries.
+ * <p>
+ * Default is false.
+ * </p>
* @return the usehighleveltool flag
* @see #setUseHighlevelTool(boolean)
*/
@@ -1318,6 +1319,43 @@ public class CCTask extends Task {
}
/**
+ * See {@link #getWriteSONAME()}
+ * @param v user preference, default is false
+ */
+ public void setWriteSONAME(final boolean v) {
+ linkType.setWriteSONAME(v);
+ }
+
+ /**
+ * User preference whether to write the {@code DT_SONAME} in a {@link #isSharedLibrary() shared library}
+ * using the {@link AbstractLinker#getOutputFileName(String, net.sf.antcontrib.cpptasks.VersionInfo)}.
+ * <p>
+ * This will set the linker options {@code -h name}, which is compatible with GNU ld and clang's ld,
+ * decorated as {@code -Wl,-h,name}.
+ * </p>
+ * <p>
+ * Feature is currently enabled for the GnuLinker (GccLinker 'gcc' + GppLinker 'gpp') as well as for clang (clang).
+ * </p>
+ * <p>
+ * Default is false.
+ * </p>
+ *
+ * @return the setSONAME flag
+ */
+ public boolean getWriteSONAME() {
+ return linkType.getWriteSONAME();
+ }
+
+ /**
+ * Gets whether the link should produce a shared library.
+ *
+ * @return boolean
+ */
+ public boolean isSharedLibrary() {
+ return linkType.isSharedLibrary();
+ }
+
+ /**
* Sets the project.
*/
@Override
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java
index d7b30cd..8ed0b2f 100644
--- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java
+++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java
@@ -31,6 +31,7 @@ import net.sf.antcontrib.cpptasks.types.CommandLineArgument;
import net.sf.antcontrib.cpptasks.types.LibrarySet;
import net.sf.antcontrib.cpptasks.TargetDef;
import net.sf.antcontrib.cpptasks.VersionInfo;
+import net.sf.antcontrib.cpptasks.gcc.GccProcessor;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.Environment;
@@ -328,13 +329,17 @@ public abstract class CommandLineLinker extends AbstractLinker
final String outputDir,
final String outputFile,
final String[] sourceFiles,
- final CommandLineLinkerConfiguration config) {
+ final CommandLineLinkerConfiguration config)
+ {
final String[] preargs = config.getPreArguments();
final String[] endargs = config.getEndArguments();
final String outputSwitch[] = getOutputFileSwitch(task, outputFile);
+ final boolean writeSONAME = task.getWriteSONAME() && task.isSharedLibrary() && ( isGCC || isCLANG );
int allArgsCount = preargs.length + 1 + outputSwitch.length +
- sourceFiles.length + endargs.length;
+ sourceFiles.length + endargs.length +
+ ( writeSONAME ? 1 : 0 );
+
if (isLibtool) {
allArgsCount++;
}
@@ -354,6 +359,9 @@ public abstract class CommandLineLinker extends AbstractLinker
for (int i = 0; i < preargs.length; i++) {
allArgs[index++] = decorateLinkerOption(buf, preargs[i]);
}
+ if( writeSONAME ) {
+ allArgs[index++] = "-Wl,-h,"+GccProcessor.getEscapedOutputFile(outputFile);
+ }
for (int i = 0; i < outputSwitch.length; i++) {
allArgs[index++] = outputSwitch[i];
}
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java b/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java
index c74f314..d650de7 100644
--- a/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java
+++ b/src/main/java/net/sf/antcontrib/cpptasks/compiler/LinkType.java
@@ -27,14 +27,8 @@ public class LinkType {
private OutputTypeEnum outputType = new OutputTypeEnum();
private boolean staticRuntime = false;
private SubsystemEnum subsystem = new SubsystemEnum();
- /**
- * User preference whether to use a high-level-tool for
- * linker operations, e.g. gcc instead of ar to build static libraries.
- * <p>
- * Default is false.
- * </p>
- */
private boolean useHighlevelTool = false;
+ private boolean writeSONAME = false;
/**
* Constructor
@@ -158,11 +152,7 @@ public class LinkType {
}
/**
- * User preference whether to use a high-level-tool for
- * linker operations, e.g. gcc instead of ar to build static libraries.
- * <p>
- * Default is false.
- * </p>
+ * See {@link #getUseHighlevelTool()}.
* @param useHighlevelTool user preference, default is false
*/
public void setUseHighlevelTool(final boolean useHighlevelTool) {
@@ -170,11 +160,40 @@ public class LinkType {
}
/**
- * Gets the usehighleveltool flag.
+ * User preference whether to use a high-level-tool for
+ * linker operations, e.g. gcc instead of ar to build static libraries.
+ * <p>
+ * Default is false.
+ * </p>
* @return the usehighleveltool flag
* @see #setUseHighlevelTool(boolean)
*/
public boolean getUseHighlevelTool() {
return useHighlevelTool;
}
+
+ /**
+ * See {@link #getWriteSONAME()}
+ * @param v user preference, default is false
+ */
+ public void setWriteSONAME(final boolean v) {
+ writeSONAME=v;
+ }
+
+ /**
+ * User preference whether to write the {@code DT_SONAME} in a {@link #isSharedLibrary() shared library}
+ * using the {@link AbstractLinker#getOutputFileName(String, net.sf.antcontrib.cpptasks.VersionInfo)}.
+ * <p>
+ * This will set the linker options {@code -h name}, which is compatible with GNU ld and clang's ld,
+ * decorated as {@code -Wl,-h,name}.
+ * </p>
+ * <p>
+ * Default is false.
+ * </p>
+ *
+ * @return the setSONAME flag
+ */
+ public boolean getWriteSONAME() {
+ return writeSONAME;
+ }
}
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java
index 988848d..e02054d 100644
--- a/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java
+++ b/src/main/java/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java
@@ -1,5 +1,5 @@
/*
- *
+ *
* Copyright 2002-2004 The Ant-Contrib project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,8 +25,8 @@ import net.sf.antcontrib.cpptasks.CUtil;
import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler;
/**
* A add-in class for Gcc processors
- *
- *
+ *
+ *
*/
public class GccProcessor {
// the results from gcc -dumpmachine
@@ -34,8 +34,8 @@ public class GccProcessor {
private static String[] specs;
// the results from gcc -dumpversion
private static String version;
- private static int addLibraryPatterns(String[] libnames, StringBuffer buf,
- String prefix, String extension, String[] patterns, int offset) {
+ private static int addLibraryPatterns(final String[] libnames, final StringBuffer buf,
+ final String prefix, final String extension, final String[] patterns, final int offset) {
for (int i = 0; i < libnames.length; i++) {
buf.setLength(0);
buf.append(prefix);
@@ -48,21 +48,21 @@ public class GccProcessor {
/**
* Converts absolute Cygwin file or directory names to the corresponding
* Win32 name.
- *
+ *
* @param names
* array of names, some elements may be null, will be changed in
* place.
*/
- public static void convertCygwinFilenames(String[] names) {
+ public static void convertCygwinFilenames(final String[] names) {
if (names == null) {
throw new NullPointerException("names");
}
- File gccDir = CUtil.getExecutableLocation("gcc.exe");
+ final File gccDir = CUtil.getExecutableLocation("gcc.exe");
if (gccDir != null) {
- String prefix = gccDir.getAbsolutePath() + "/..";
- StringBuffer buf = new StringBuffer();
+ final String prefix = gccDir.getAbsolutePath() + "/..";
+ final StringBuffer buf = new StringBuffer();
for (int i = 0; i < names.length; i++) {
- String name = names[i];
+ final String name = names[i];
if (name != null && name.length() > 1 && name.charAt(0) == '/') {
buf.setLength(0);
buf.append(prefix);
@@ -72,9 +72,9 @@ public class GccProcessor {
}
}
}
- public static String[] getLibraryPatterns(String[] libnames) {
- StringBuffer buf = new StringBuffer();
- String[] patterns = new String[libnames.length * 2];
+ public static String[] getLibraryPatterns(final String[] libnames) {
+ final StringBuffer buf = new StringBuffer();
+ final String[] patterns = new String[libnames.length * 2];
int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0);
if (isHPUX()) {
offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns,
@@ -87,8 +87,8 @@ public class GccProcessor {
}
public static String getMachine() {
if (machine == null) {
- String[] args = new String[]{"gcc", "-dumpmachine"};
- String[] cmdout = CaptureStreamHandler.run(args);
+ final String[] args = new String[]{"gcc", "-dumpmachine"};
+ final String[] cmdout = CaptureStreamHandler.run(args);
if (cmdout.length == 0) {
machine = "nomachine";
} else {
@@ -97,8 +97,8 @@ public class GccProcessor {
}
return machine;
}
- public static String[] getOutputFileSwitch(String letter, String outputFile) {
- StringBuffer buf = new StringBuffer();
+ public static String getEscapedOutputFile(final String outputFile) {
+ final StringBuffer buf = new StringBuffer();
if (outputFile.indexOf(' ') >= 0) {
buf.append('"');
buf.append(outputFile.replace('\\', '/'));
@@ -106,28 +106,31 @@ public class GccProcessor {
} else {
buf.append(outputFile.replace('\\', '/'));
}
- String[] retval = new String[]{letter, buf.toString()};
+ return buf.toString();
+ }
+ public static String[] getOutputFileSwitch(final String letter, final String outputFile) {
+ final String[] retval = new String[]{letter, getEscapedOutputFile(outputFile)};
return retval;
}
/**
* Returns the contents of the gcc specs file.
- *
+ *
* The implementation locates gcc.exe in the executable path and then
* builds a relative path name from the results of -dumpmachine and
* -dumpversion. Attempts to use gcc -dumpspecs to provide this information
* resulted in stalling on the Execute.run
- *
+ *
* @return contents of the specs file
*/
public static String[] getSpecs() {
if (specs == null) {
- File gccParent = CUtil.getExecutableLocation("gcc.exe");
+ final File gccParent = CUtil.getExecutableLocation("gcc.exe");
if (gccParent != null) {
//
// build a relative path like
// ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs
//
- StringBuffer buf = new StringBuffer("../lib/gcc-lib/");
+ final StringBuffer buf = new StringBuffer("../lib/gcc-lib/");
buf.append(getMachine());
buf.append('/');
buf.append(getVersion());
@@ -135,8 +138,8 @@ public class GccProcessor {
//
// resolve it relative to the location of gcc.exe
//
- String relativePath = buf.toString();
- File specsFile = new File(gccParent, relativePath);
+ final String relativePath = buf.toString();
+ final File specsFile = new File(gccParent, relativePath);
//
// found the specs file
//
@@ -144,9 +147,9 @@ public class GccProcessor {
//
// read the lines in the file
//
- BufferedReader reader = new BufferedReader(new FileReader(
+ final BufferedReader reader = new BufferedReader(new FileReader(
specsFile));
- Vector lines = new Vector(100);
+ final Vector lines = new Vector(100);
String line = reader.readLine();
while (line != null) {
lines.addElement(line);
@@ -154,7 +157,7 @@ public class GccProcessor {
}
specs = new String[lines.size()];
lines.copyInto(specs);
- } catch (IOException ex) {
+ } catch (final IOException ex) {
}
}
}
@@ -165,8 +168,8 @@ public class GccProcessor {
}
public static String getVersion() {
if (version == null) {
- String[] args = new String[]{"gcc", "-dumpversion"};
- String[] cmdout = CaptureStreamHandler.run(args);
+ final String[] args = new String[]{"gcc", "-dumpversion"};
+ final String[] cmdout = CaptureStreamHandler.run(args);
if (cmdout.length == 0) {
version = "noversion";
} else {
@@ -180,24 +183,24 @@ public class GccProcessor {
}
/**
* Determines if task is running with cygwin
- *
+ *
* @return true if cygwin was detected
*/
public static boolean isCygwin() {
return getMachine().indexOf("cygwin") > 0;
}
private static boolean isHPUX() {
- String osname = System.getProperty("os.name").toLowerCase();
+ final String osname = System.getProperty("os.name").toLowerCase();
if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) {
return true;
}
return false;
}
/**
- *
+ *
* Parses the results of the specs file for a specific processor and
* options
- *
+ *
* @param specsContent
* Contents of specs file as returned from getSpecs
* @param specSectionStart
@@ -205,8 +208,8 @@ public class GccProcessor {
* @param options
* command line switches such as "-istart"
*/
- public static String[][] parseSpecs(String[] specsContent,
- String specSectionStart, String[] options) {
+ public static String[][] parseSpecs(final String[] specsContent,
+ final String specSectionStart, final String[] options) {
if (specsContent == null) {
throw new NullPointerException("specsContent");
}
@@ -216,15 +219,15 @@ public class GccProcessor {
if (options == null) {
throw new NullPointerException("option");
}
- String[][] optionValues = new String[options.length][];
- StringBuffer optionValue = new StringBuffer(40);
+ final String[][] optionValues = new String[options.length][];
+ final StringBuffer optionValue = new StringBuffer(40);
for (int i = 0; i < specsContent.length; i++) {
String specLine = specsContent[i];
//
// if start of section then start paying attention
//
if (specLine.startsWith(specSectionStart)) {
- Vector[] optionVectors = new Vector[options.length];
+ final Vector[] optionVectors = new Vector[options.length];
for (int j = 0; j < options.length; j++) {
optionVectors[j] = new Vector(10);
}
@@ -287,7 +290,7 @@ public class GccProcessor {
// fill in any missing option values with
// a zero-length string array
for (int i = 0; i < optionValues.length; i++) {
- String[] zeroLenArray = new String[0];
+ final String[] zeroLenArray = new String[0];
if (optionValues[i] == null) {
optionValues[i] = zeroLenArray;
}