summaryrefslogtreecommitdiff
path: root/src/main/java/net/sf/antcontrib/cpptasks/borland/CBuilderXProjectWriter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/net/sf/antcontrib/cpptasks/borland/CBuilderXProjectWriter.java')
-rw-r--r--src/main/java/net/sf/antcontrib/cpptasks/borland/CBuilderXProjectWriter.java542
1 files changed, 542 insertions, 0 deletions
diff --git a/src/main/java/net/sf/antcontrib/cpptasks/borland/CBuilderXProjectWriter.java b/src/main/java/net/sf/antcontrib/cpptasks/borland/CBuilderXProjectWriter.java
new file mode 100644
index 0000000..dfe5ec6
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/cpptasks/borland/CBuilderXProjectWriter.java
@@ -0,0 +1,542 @@
+/*
+ *
+ * Copyright 2004-2005 The Ant-Contrib project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package net.sf.antcontrib.cpptasks.borland;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import net.sf.antcontrib.cpptasks.CCTask;
+import net.sf.antcontrib.cpptasks.CUtil;
+import net.sf.antcontrib.cpptasks.TargetInfo;
+import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration;
+import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration;
+import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration;
+import net.sf.antcontrib.cpptasks.gcc.GccCCompiler;
+import net.sf.antcontrib.cpptasks.ide.ProjectDef;
+import net.sf.antcontrib.cpptasks.ide.ProjectWriter;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.Serializer;
+import org.apache.xml.serialize.XMLSerializer;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Writes a CBuilderX 1.0 project file.
+ *
+ * @author curta
+ *
+ */
+public final class CBuilderXProjectWriter
+ implements ProjectWriter {
+ /**
+ * Constructor.
+ */
+ public CBuilderXProjectWriter() {
+ }
+
+ /**
+ * Writes a project definition file.
+ *
+ * @param fileName
+ * project name for file, should has .cbx extension
+ * @param task
+ * cc task for which to write project
+ * @param projectDef
+ * project element
+ * @param sources source files
+ * @param targets compilation targets
+ * @param linkTarget link target
+ * @throws IOException if I/O error
+ * @throws SAXException if XML serialization error
+ */
+ public void writeProject(final File fileName,
+ final CCTask task,
+ final ProjectDef projectDef,
+ final List sources,
+ final Hashtable targets,
+ final TargetInfo linkTarget) throws
+ IOException,
+ SAXException {
+
+ String projectName = projectDef.getName();
+ if (projectName == null) {
+ projectName = fileName.getName();
+ }
+ final String basePath = fileName.getAbsoluteFile().getParent();
+
+ File projectFile = new File(fileName + ".cbx");
+ if (!projectDef.getOverwrite() && projectFile.exists()) {
+ throw new BuildException("Not allowed to overwrite project file "
+ + projectFile.toString());
+ }
+
+ CommandLineCompilerConfiguration compilerConfig =
+ getBaseCompilerConfiguration(targets);
+ if (compilerConfig == null) {
+ throw new BuildException(
+ "Unable to generate C++ BuilderX project when gcc or bcc is not used.");
+ }
+
+ OutputStream outStream = new FileOutputStream(projectFile);
+ OutputFormat format = new OutputFormat("xml", "UTF-8", true);
+ Serializer serializer = new XMLSerializer(outStream, format);
+ ContentHandler content = serializer.asContentHandler();
+ content.startDocument();
+ AttributesImpl emptyAttrs = new AttributesImpl();
+ content.startElement(null, "project", "project", emptyAttrs);
+ PropertyWriter propertyWriter = new PropertyWriter(content);
+ propertyWriter.write("build.config", "active", "0");
+ propertyWriter.write("build.config", "count", "0");
+ propertyWriter.write("build.config", "excludedefaultforzero", "0");
+ propertyWriter.write("build.config.0", "builddir", "Debug");
+ propertyWriter.write("build.config.0", "key", "Debug_Build");
+ propertyWriter.write("build.config.0", "linux.builddir",
+ "linux/Debug_Build");
+ propertyWriter.write("build.config.0", "settings.MinGW",
+ "default;debug");
+ propertyWriter.write("build.config.0", "settings.gnuc++",
+ "default;debug");
+ propertyWriter.write("build.config.0", "settings.intellinia32",
+ "default;debug");
+ propertyWriter.write("build.config.0", "settings.mswin32",
+ "default;debug");
+ propertyWriter.write("build.config.0", "type", "Toolset");
+ propertyWriter.write("build.config.0", "win32.builddir",
+ "windows/Debug_Build");
+ propertyWriter.write("build.node", "name", projectDef.getName());
+ final String buildType = getBuildType(task);
+ propertyWriter.write("build.node", "type", buildType);
+ propertyWriter.write("build.platform", "active",
+ getActivePlatform(task));
+ propertyWriter.write("build.platform", "linux.Debug_Build.toolset",
+ "gnuc++");
+ propertyWriter.write("build.platform", "linux.Release_Build.toolset",
+ "gnuc++");
+ propertyWriter.write("build.platform", "linux.default", "gnuc++");
+ propertyWriter.write("build.platform", "linux.gnuc++.enabled", "1");
+ propertyWriter.write("build.platform", "linux.mswin32.enabled", "1");
+ propertyWriter.write("build.platform", "linux.win32b.enabled", "1");
+ propertyWriter.write("build.platform", "solaris.default", "gnuc++");
+ propertyWriter.write("build.platform", "solaris.enabled", "1");
+ String toolset = getWin32Toolset(compilerConfig);
+ propertyWriter.write("build.platform", "win32.default", toolset);
+ propertyWriter.write("build.platform", "win32." + toolset + ".enabled", "1");
+
+ propertyWriter.write("cbproject", "version", "X.1.0");
+ if ("dllproject".equals(buildType)) {
+ propertyWriter.write("gnuc++.g++compile",
+ "option.fpic_using_GOT.enabled", "1");
+ propertyWriter.write("gnuc++.g++link", "option.shared.enabled", "1");
+ propertyWriter.write("intellinia32.icc", "option.minus_Kpic.enabled",
+ "1");
+ propertyWriter.write("intellinia32.icclink",
+ "option.minus_shared.enabled", "1");
+ }
+ //
+ // assume the first target is representative of all compilation tasks
+ //
+ writeCompileOptions(basePath, propertyWriter, compilerConfig);
+ writeLinkOptions(basePath, propertyWriter, linkTarget);
+ propertyWriter.write("linux.gnuc++.Debug_Build", "saved", "1");
+ if ("dllproject".equals(buildType)) {
+ propertyWriter.write("runtime", "ExcludeDefaultForZero", "1");
+ //propertyWriter.write("unique", "id", "852");
+ } else if ("exeproject".equals(buildType)) {
+ propertyWriter.write("runtime.0", "BuildTargetOnRun",
+ "com.borland.cbuilder.build."
+ + "CBProjectBuilder$ProjectBuildAction;make");
+ propertyWriter.write("runtime.0", "ConfigurationName",
+ projectDef.getName());
+ propertyWriter.write("runtime.0", "RunnableType",
+ "com.borland.cbuilder.runtime.ExecutableRunner");
+ }
+ AttributesImpl fileAttributes = new AttributesImpl();
+ fileAttributes.addAttribute(null, "path", "path", "#PCDATA", "");
+ AttributesImpl gccAttributes = null;
+ if (!"g++".equals(compilerConfig.getCommand())) {
+ gccAttributes = new AttributesImpl();
+ gccAttributes.addAttribute(null, "category", "category", "#PCDATA",
+ "build.basecmd");
+ gccAttributes.addAttribute(null, "name", "name", "#PCDATA",
+ "linux.gnuc++.Debug_Build.g++_key");
+ gccAttributes.addAttribute(null, "value", "value", "#PCDATA",
+ compilerConfig.getCommand());
+ }
+
+ Iterator targetIter = targets.values().iterator();
+ while (targetIter.hasNext()) {
+ TargetInfo info = (TargetInfo) targetIter.next();
+ File[] targetsources = info.getSources();
+ for (int i = 0; i < targetsources.length; i++) {
+ String relativePath = CUtil.getRelativePath(basePath,
+ targetsources[i]);
+ fileAttributes.setValue(0, relativePath);
+ content.startElement(null, "file", "file", fileAttributes);
+
+ //
+ // if file ends with .c, use gcc instead of g++
+ //
+ if (gccAttributes != null) {
+ content.startElement(null, "property", "property", gccAttributes);
+ content.endElement(null, "property", "property");
+ }
+ content.endElement(null, "file", "file");
+ }
+ }
+ content.endElement(null, "project", "project");
+ content.endDocument();
+ }
+
+ /**
+ * Gets build type from link target.
+ * @param task CCTask current task
+ * @return String build type
+ */
+ private String getBuildType(final CCTask task) {
+ String outType = task.getOuttype();
+ if ("executable".equals(outType)) {
+ return "exeproject";
+ } else if ("static".equals(outType)) {
+ return "libraryproject";
+ }
+ return "dllproject";
+ }
+
+ /**
+ * Gets active platform.
+ * @param task CCTask cc task
+ * @return String platform identifier
+ */
+ private String getActivePlatform(final CCTask task) {
+ String osName = System.getProperty("os.name").toLowerCase(Locale.US);
+ if (osName.indexOf("windows") >= 0) {
+ return "win32";
+ }
+ return "linux";
+ }
+
+ private String getWin32Toolset(final CommandLineCompilerConfiguration compilerConfig) {
+ if (compilerConfig != null && compilerConfig.getCompiler() instanceof BorlandCCompiler) {
+ return "win32b";
+ }
+ return "MinGW";
+ }
+
+ /**
+ * Utility class to generate property elements.
+ */
+ private static class PropertyWriter {
+ /**
+ * Content handler.
+ */
+ private ContentHandler content;
+
+ /**
+ * Attributes list.
+ */
+ private AttributesImpl propertyAttributes;
+
+ /**
+ * Constructor.
+ *
+ * @param contentHandler ContentHandler content handler
+ */
+ public PropertyWriter(final ContentHandler contentHandler) {
+ content = contentHandler;
+ propertyAttributes = new AttributesImpl();
+ propertyAttributes.addAttribute(null, "category", "category",
+ "#PCDATA", "");
+ propertyAttributes
+ .addAttribute(null, "name", "name", "#PCDATA", "");
+ propertyAttributes.addAttribute(null, "value", "value", "#PCDATA",
+ "");
+ }
+
+ /**
+ * Write property element.
+ *
+ * @param category String category
+ * @param name String property name
+ * @param value String property value
+ * @throws SAXException if I/O error or illegal content
+ */
+ public final void write(final String category,
+ final String name,
+ final String value) throws SAXException {
+ propertyAttributes.setValue(0, category);
+ propertyAttributes.setValue(1, name);
+ propertyAttributes.setValue(2, value);
+ content.startElement(null, "property", "property",
+ propertyAttributes);
+ content.endElement(null, "property", "property");
+ }
+ }
+
+ /**
+ * Gets the first recognized compiler from the
+ * compilation targets.
+ * @param targets compilation targets
+ * @return representative (hopefully) compiler configuration
+ */
+ private CommandLineCompilerConfiguration
+ getBaseCompilerConfiguration(final Hashtable targets) {
+ //
+ // find first target with an gcc or bcc compilation
+ //
+ CommandLineCompilerConfiguration compilerConfig = null;
+ //
+ // get the first target and assume that it is representative
+ //
+ Iterator targetIter = targets.values().iterator();
+ while (targetIter.hasNext()) {
+ TargetInfo targetInfo = (TargetInfo) targetIter.next();
+ ProcessorConfiguration config = targetInfo.getConfiguration();
+ String identifier = config.getIdentifier();
+ //
+ // for the first gcc or bcc compiler
+ //
+ if (config instanceof CommandLineCompilerConfiguration) {
+ compilerConfig = (CommandLineCompilerConfiguration) config;
+ if (compilerConfig.getCompiler() instanceof GccCCompiler ||
+ compilerConfig.getCompiler() instanceof BorlandCCompiler) {
+ return compilerConfig;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Writes elements corresponding to compilation options.
+ *
+ * @param baseDir String base directory
+ * @param writer PropertyWriter property writer
+ * @param compilerConfig representative configuration
+ * @throws SAXException if I/O error or illegal content
+ */
+ private void writeCompileOptions(final String baseDir,
+ final PropertyWriter writer,
+ final CommandLineCompilerConfiguration
+ compilerConfig) throws SAXException {
+ boolean isBcc = false;
+ boolean isUnix = true;
+ String compileID = "linux.Debug_Build.gnuc++.g++compile";
+ if (compilerConfig.getCompiler() instanceof BorlandCCompiler) {
+ compileID = "win32.Debug_Build.win32b.bcc32";
+ isUnix = false;
+ isBcc = true;
+ }
+
+ File[] includePath = compilerConfig.getIncludePath();
+ int includeIndex = 1;
+ if (isUnix) {
+ writer.write(compileID,
+ "option.I.arg." + (includeIndex++),
+ "/usr/include");
+ writer.write(compileID,
+ "option.I.arg." + (includeIndex++),
+ "/usr/include/g++-3");
+ }
+ for (int i = 0; i < includePath.length; i++) {
+ String relPath = CUtil.getRelativePath(baseDir, includePath[i]);
+ writer.write(compileID,
+ "option.I.arg." + (includeIndex++),
+ relPath);
+ }
+ if (includePath.length > 0) {
+ writer.write(compileID,
+ "option.I.enabled",
+ "1");
+ }
+
+ String defineBase = "option.D_MACRO_VALUE";
+ if (isBcc) {
+ defineBase = "option.D";
+ }
+ String defineOption = defineBase + ".arg.";
+ int defineIndex = 1;
+ int undefineIndex = 1;
+ String[] preArgs = compilerConfig.getPreArguments();
+ for (int i = 0; i < preArgs.length; i++) {
+ if (preArgs[i].startsWith("-D")) {
+ writer.write(compileID,
+ defineOption + (defineIndex++),
+ preArgs[i].substring(2));
+ } else if (preArgs[i].startsWith("-U")) {
+ writer.write(compileID,
+ "option.U.arg."
+ + (undefineIndex++), preArgs[i]
+ .substring(2));
+ } else if (!(preArgs[i].startsWith("-I")
+ || preArgs[i].startsWith("-o"))) {
+ //
+ // any others (-g, -fno-rtti, -w, -Wall, etc)
+ //
+ writer.write(compileID,
+ "option." + preArgs[i].substring(1) + ".enabled",
+ "1");
+ }
+ }
+ if (defineIndex > 1) {
+ writer.write(compileID,
+ defineBase + ".enabled",
+ "1");
+ }
+ if (undefineIndex > 1) {
+ writer.write(compileID,
+ "option.U.enabled",
+ "1");
+ }
+ }
+
+ /**
+ * Writes elements corresponding to link options.
+ *
+ * @param baseDir String base directory
+ * @param writer PropertyWriter property writer
+ * @param linkTarget TargetInfo link target
+ * @throws SAXException if I/O error or illegal content
+ */
+ private void
+ writeLinkOptions(final String baseDir,
+ final PropertyWriter writer,
+ final TargetInfo linkTarget) throws SAXException {
+ if (linkTarget != null) {
+ ProcessorConfiguration config = linkTarget.getConfiguration();
+ if (config instanceof CommandLineLinkerConfiguration) {
+ CommandLineLinkerConfiguration linkConfig =
+ (CommandLineLinkerConfiguration) config;
+
+ if (linkConfig.getLinker() instanceof BorlandLinker) {
+ String linkID = "win32.Debug_Build.win32b.ilink32";
+ writeIlinkArgs(writer, linkID, linkConfig.getPreArguments());
+ writeIlinkArgs(writer, linkID, linkConfig.getEndArguments());
+ writer.write(linkID, "param.libfiles.1", "cw32mt.lib");
+ writer.write(linkID, "param.libfiles.2", "import32.lib");
+ int libIndex = 3;
+ String[] libNames = linkConfig.getLibraryNames();
+ for(int i = 0; i < libNames.length; i++) {
+ writer.write(linkID, "param.libfiles." + (libIndex++),
+ libNames[i]);
+ }
+ String startup = linkConfig.getStartupObject();
+ if (startup != null) {
+ writer.write(linkID, "param.objfiles.1", startup);
+ }
+ } else {
+ String linkID = "linux.Debug_Build.gnuc++.g++link";
+ writeLdArgs(writer, linkID, linkConfig.getPreArguments());
+ writeLdArgs(writer, linkID, linkConfig.getEndArguments());
+ }
+ }
+ }
+ }
+
+ /**
+ * Writes ld linker options to project file.
+ *
+ * @param writer PropertyWriter property writer
+ * @param linkID String linker identifier
+ * @param preArgs String[] linker arguments
+ * @throws SAXException thrown if unable to write option
+ */
+ private void writeLdArgs(final PropertyWriter writer,
+ final String linkID,
+ final String[] preArgs) throws SAXException {
+ int objnameIndex = 1;
+ int libnameIndex = 1;
+ int libpathIndex = 1;
+ for (int i = 0; i < preArgs.length; i++) {
+ if (preArgs[i].startsWith("-o")) {
+ writer.write(linkID,
+ "option.o.arg."
+ + (objnameIndex++), preArgs[i]
+ .substring(2));
+ } else if (preArgs[i].startsWith("-l")) {
+ writer.write(linkID,
+ "option.l.arg."
+ + (libnameIndex++), preArgs[i]
+ .substring(2));
+ } else if (preArgs[i].startsWith("-L")) {
+ writer.write(linkID,
+ "option.L.arg."
+ + (libpathIndex++), preArgs[i]
+ .substring(2));
+ } else {
+ //
+ // any others
+ //
+ writer.write(linkID, "option." + preArgs[i].substring(1) + ".enabled",
+ "1");
+ }
+ }
+ if (objnameIndex > 1) {
+ writer.write(linkID,
+ "option.o.enabled",
+ "1");
+ }
+ if (libnameIndex > 1) {
+ writer.write(linkID,
+ "option.l.enabled",
+ "1");
+ }
+ if (libpathIndex > 1) {
+ writer.write(linkID,
+ "option.L.enabled",
+ "1");
+ }
+ }
+
+ /**
+ * Writes ilink32 linker options to project file.
+ *
+ * @param writer PropertyWriter property writer
+ * @param linkID String linker identifier
+ * @param preArgs String[] linker arguments
+ * @throws SAXException thrown if unable to write option
+ */
+ private void writeIlinkArgs(final PropertyWriter writer,
+ final String linkID,
+ final String[] args) throws SAXException {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].charAt(0) == '/' || args[i].charAt(0) == '-') {
+ int equalsPos = args[i].indexOf('=');
+ if (equalsPos > 0) {
+ String option = "option." + args[i].substring(0, equalsPos -1);
+ writer.write(linkID,
+ option + ".enabled",
+ "1");
+ writer.write(linkID,
+ option + ".value",
+ args[i].substring(equalsPos + 1));
+ } else {
+ writer.write(linkID, "option." + args[i].substring(1) + ".enabled", "1");
+ }
+ }
+ }
+ }
+
+}