SF.net SVN: ant-contrib: [135] cpptasks/trunk/src/main/java/net/sf/ antcontrib/cpptasks/apple

[email protected] Thu, 02 Aug 2007 15:46:46 -0700
Newsgroups gmane.comp.java.ant-contrib.devel
Message-ID <[email protected]>
Revision: 135
          http://ant-contrib.svn.sourceforge.net/ant-contrib/?rev=135&view=rev
Author:   carnold
Date:     2007-08-02 15:46:45 -0700 (Thu, 02 Aug 2007)

Log Message:
-----------
Bug 980130: Rework XCodeProjectWriter for XCode 2.1 and later

Modified Paths:
--------------
    cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java

Added Paths:
-----------
    cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java

Added: cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java
===================================================================
--- cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java	                        (rev 0)
+++ cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/PropertyListSerialization.java	2007-08-02 22:46:45 UTC (rev 135)
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Ant-Contrib Project under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The Ant-Contrib licenses this file to You 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.apple;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Static class that provides methods to serialize
+ * a Map to a Cocoa XML Property List.  Does not currently support
+ * date or data elements.
+ */
+public final class PropertyListSerialization {
+    /**
+     * Private constructor.
+     */
+    private PropertyListSerialization() {
+
+    }
+
+    /**
+     * Serializes a property list into a Cocoa XML Property List document.
+     * @param propertyList property list.
+     * @param result destination.
+     * @throws SAXException if exception during serialization.
+     * @throws TransformerConfigurationException if exception creating serializer.
+     */
+    public static void serialize(final Map propertyList,
+                                 final Result result)
+           throws SAXException, TransformerConfigurationException {
+        SAXTransformerFactory sf = (SAXTransformerFactory)
+                SAXTransformerFactory.newInstance();
+        TransformerHandler handler = sf.newTransformerHandler();
+        handler.setResult(result);
+
+        handler.startDocument();
+        AttributesImpl attributes = new AttributesImpl();
+        handler.startElement(null, "plist", "plist", attributes);
+        serializeMap(propertyList, handler);
+        handler.endElement(null, "plist", "plist");
+
+        handler.endDocument();
+    }
+
+    /**
+     * Serialize a map as a dict element.
+     * @param map map to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeMap(final Map map,
+                                     final ContentHandler handler)
+         throws SAXException {
+        AttributesImpl attributes = new AttributesImpl();
+        handler.startElement(null, "dict", "dict", attributes);
+
+        if (map.size() > 0) {
+            //
+            //   need to output with sorted keys to maintain
+            //     reproducability
+            //
+            Object[] keys = map.keySet().toArray();
+            Arrays.sort(keys);
+            for(int i = 0; i < keys.length; i++) {
+                String key = String.valueOf(keys[i]);
+                handler.startElement(null, "key", "key", attributes);
+                handler.characters(key.toCharArray(), 0, key.length());
+                handler.endElement(null, "key", "key");
+                serializeObject(map.get(keys[i]), handler);
+            }
+        }
+        handler.endElement(null, "dict", "dict");
+    }
+
+    /**
+     * Serialize a list as an array element.
+     * @param list list to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeList(final List list,
+                                      final ContentHandler handler)
+         throws SAXException {
+        AttributesImpl attributes = new AttributesImpl();
+        handler.startElement(null, "array", "array", attributes);
+        for(Iterator iter = list.iterator();iter.hasNext();) {
+            serializeObject(iter.next(), handler);
+        }
+        handler.endElement(null, "array", "array");
+    }
+
+    /**
+     * Creates an element with the specified tag name and character content.
+     * @param tag tag name.
+     * @param content character content.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeElement(final String tag,
+                                  final String content,
+                                  final ContentHandler handler)
+         throws SAXException {
+        AttributesImpl attributes = new AttributesImpl();
+        handler.startElement(null, tag, tag, attributes);
+        handler.characters(content.toCharArray(), 0, content.length());
+        handler.endElement(null, tag, tag);
+    }
+
+
+    /**
+     * Serialize a Number as an integer element.
+     * @param integer number to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeInteger(final Number integer,
+                                         final ContentHandler handler)
+         throws SAXException {
+        serializeElement("integer", String.valueOf(integer.longValue()),
+                handler);
+    }
+
+    /**
+     * Serialize a Number as a real element.
+     * @param real number to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeReal(final Number real,
+                                      final ContentHandler handler)
+         throws SAXException {
+        serializeElement("real",
+                String.valueOf(real.doubleValue()),
+                handler);
+    }
+
+
+    /**
+     * Serialize a Boolean as a true or false element.
+     * @param val boolean to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeBoolean(final Boolean val,
+                                         final ContentHandler handler)
+         throws SAXException {
+        String tag = "false";
+        if (val.booleanValue()) {
+            tag = "true";
+        }
+        AttributesImpl attributes = new AttributesImpl();
+        handler.startElement(null, tag, tag, attributes);
+        handler.endElement(null, tag, tag);
+    }
+
+    /**
+     * Serialize a string as a string element.
+     * @param val string to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeString(final String val,
+                                        final ContentHandler handler)
+         throws SAXException {
+        serializeElement("string",
+                val,
+                handler);
+    }
+
+
+    /**
+     * Serialize an object using the best available element.
+     * @param obj object to serialize.
+     * @param handler destination of serialization events.
+     * @throws SAXException if exception during serialization.
+     */
+    private static void serializeObject(final Object obj,
+                                        final ContentHandler handler)
+        throws SAXException {
+        if (obj instanceof Map) {
+            serializeMap((Map) obj, handler);
+        } else if (obj instanceof List) {
+            serializeList((List) obj, handler);      
+        } else if (obj instanceof Number) {
+            if(obj instanceof Double
+                ||obj instanceof Float) {
+                serializeReal((Number) obj, handler);
+            } else {
+                serializeInteger((Number) obj, handler);
+            }
+        } else if (obj instanceof Boolean) {
+            serializeBoolean((Boolean) obj, handler);
+        } else {
+            serializeString(String.valueOf(obj), handler);
+        }
+    }
+}

Modified: cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java
===================================================================
--- cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java	2007-07-31 21:02:52 UTC (rev 134)
+++ cpptasks/trunk/src/main/java/net/sf/antcontrib/cpptasks/apple/XcodeProjectWriter.java	2007-08-02 22:46:45 UTC (rev 135)
@@ -16,559 +16,724 @@
  */
 package net.sf.antcontrib.cpptasks.apple;
 
-import java.io.BufferedWriter;
+import net.sf.antcontrib.cpptasks.CCTask;
+import net.sf.antcontrib.cpptasks.TargetInfo;
+import net.sf.antcontrib.cpptasks.CUtil;
+import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration;
+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.xml.sax.SAXException;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.stream.StreamResult;
 import java.io.File;
-import java.io.FileWriter;
 import java.io.IOException;
-import java.io.Writer;
+import java.text.NumberFormat;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
-import java.util.Vector;
 import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 
-import org.apache.tools.ant.BuildException;
 
-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;
-
 /**
- * Writes a Apple Xcode project directory.
- *
- * Status: Collects file list but does not pick up libraries and settings from
- * project.
- *
- * @author curta
+ * Writes a Apple Xcode 2.1+ project directory.  XCode stores project
+ * configuration as a PropertyList.  Though it will always write the project
+ * as a Cocoa Old-Style ASCII property list, it will read projects
+ * stored using Cocoa's XML Property List format.
  */
 public final class XcodeProjectWriter
-    implements ProjectWriter {
+        implements ProjectWriter {
 
-  /**
-   * Next object identifier for project file.
-   */
-  private int nextID = 0x08FB7796;
+    /**
+     * Constructor.
+     */
+    public XcodeProjectWriter() {
+    }
 
-  /**
-   * Constructor.
-   *
-   */
-  public XcodeProjectWriter() {
-  }
+    /**
+     * Writes a project definition file.
+     *
+     * @param fileName   File name base, writer may append appropriate extension
+     * @param task       cc task for which to write project
+     * @param projectDef project element
+     * @param targets    compilation targets
+     * @param linkTarget link target
+     * @throws IOException if error writing project file
+     */
+    public void writeProject(final File fileName,
+                             final CCTask task,
+                             final ProjectDef projectDef,
+                             final List sources,
+                             final Hashtable targets,
+                             final TargetInfo linkTarget) throws IOException {
 
-  /**
-   * Get next unique ID.
-   * @return unique ID
-   */
-  private String getUniqueID() {
-    return Integer.toString(nextID++, 16) + "FE84155DC02AAC07";
-  }
+        File xcodeDir = new File(fileName + ".xcodeproj");
+        if (!projectDef.getOverwrite() && xcodeDir.exists()) {
+            throw new BuildException("Not allowed to overwrite project file "
+                    + xcodeDir.toString());
+        }
 
-  /**
-   * Writes a project definition file.
-   *
-   * @param fileName
-   *            File name base, writer may append appropriate extension
-   * @param task
-   *            cc task for which to write project
-   * @param projectDef
-   *            project element
-   * @param targets
-   *            compilation targets
-   * @param linkTarget
-   *            link target
-   * @throws IOException
-   *             if error writing project file
-   */
-  public void writeProject(final File fileName, 
-  		                   final CCTask task,
-                           final ProjectDef projectDef,
-						   final List sources,
-						   final Hashtable targets,
-                           final TargetInfo linkTarget) throws IOException {
+        CommandLineCompilerConfiguration compilerConfig =
+                getBaseCompilerConfiguration(targets);
+        if (compilerConfig == null) {
+            throw new BuildException(
+                    "Unable to find compilation target using GNU C++ compiler");
+        }
 
-    File xcodeDir = new File(fileName + ".xcode");
-    if (!projectDef.getOverwrite() && xcodeDir.exists()) {
-      throw new BuildException("Not allowed to overwrite project file "
-                               + xcodeDir.toString());
+        String projectName = projectDef.getName();
+        if (projectName == null) {
+            projectName = fileName.getName();
+        }
+        final String basePath = fileName.getAbsoluteFile().getParent();
+
+        xcodeDir.mkdir();
+
+        File xcodeProj = new File(xcodeDir, "project.pbxproj");
+
+        //
+        //   create property list
+        //
+        Map propertyList = new HashMap();
+        propertyList.put("archiveVersion", "1");
+        propertyList.put("classes", new HashMap());
+        propertyList.put("objectVersion", "42");
+        Map objects = new HashMap();
+
+        final String sourceTree = "<source>";
+
+        //
+        //   add source files and source group to property list
+        //
+        List sourceGroupChildren =
+                addSources(objects, "SOURCE_ROOT", basePath, targets);
+        PBXObjectRef sourceGroup =
+                createPBXGroup("Source", sourceTree, sourceGroupChildren);
+        objects.put(sourceGroup.getID(), sourceGroup.getProperties());
+
+        //
+        //    add product to property list
+        //
+        PBXObjectRef product = addProduct(objects, linkTarget);
+        List productsList = new ArrayList();
+        productsList.add(product);
+        PBXObjectRef productsGroup =
+                createPBXGroup("Products", sourceTree, productsList);
+        objects.put(productsGroup.getID(), productsGroup.getProperties());
+
+        //
+        //    add documentation group to property list
+        //
+        PBXObjectRef documentationGroup = addDocumentationGroup(objects, sourceTree);
+
+        //
+        //    add main group containing source, products and documentation group
+        //
+        ArrayList groups = new ArrayList(3);
+        groups.add(sourceGroup);
+        groups.add(documentationGroup);
+        groups.add(productsGroup);
+        PBXObjectRef mainGroup = createPBXGroup(projectName, sourceTree, groups);
+        objects.put(mainGroup.getID(), mainGroup.getProperties());
+
+        //
+        //   add project configurations
+        //
+        PBXObjectRef projectConfigurations = addProjectConfigurationList(objects);
+
+        String projectDirPath = "";
+        List projectTargets = new ArrayList();
+
+        //
+        //   add description of native target (that is the executable or
+        //      shared library)
+        //
+        PBXObjectRef nativeTarget =
+                addNativeTarget(objects, linkTarget, product, sourceGroupChildren);
+        projectTargets.add(nativeTarget);
+
+
+        //
+        //    add project to property list
+        //
+        PBXObjectRef project = createPBXProject(projectConfigurations, mainGroup,
+                projectDirPath, projectTargets);
+        objects.put(project.getID(), project.getProperties());
+
+
+        //
+        //    finish up overall property list
+        //
+        propertyList.put("objects", objects);
+        propertyList.put("rootObject", project.getID());
+
+
+        //
+        //    write property list out to XML file
+        //
+        Result result = new StreamResult(xcodeProj);
+
+        try {
+            PropertyListSerialization.serialize(propertyList, result);
+        } catch (TransformerConfigurationException ex) {
+            throw new IOException(ex.toString());
+        } catch (SAXException ex) {
+            if (ex.getException() instanceof IOException) {
+                throw (IOException) ex.getException();
+            }
+            throw new IOException(ex.toString());
+        }
     }
 
-    CommandLineCompilerConfiguration compilerConfig =
-        getBaseCompilerConfiguration(targets);
-    if (compilerConfig == null) {
-      throw new BuildException(
-          "Unable to find compilation target using GNU C++ compiler");
+
+    /**
+     * Add documentation group to map of objects.
+     * @param objects object map.
+     * @param sourceTree source tree description.
+     * @return documentation group.
+     */
+    private PBXObjectRef addDocumentationGroup(final Map objects,
+                                            final String sourceTree) {
+        List productsList = new ArrayList();
+        PBXObjectRef products =
+                createPBXGroup("Documentation", sourceTree, productsList);
+        objects.put(products.getID(), products.getProperties());
+        return products;
     }
 
-    String projectName = projectDef.getName();
-    if (projectName == null) {
-    	projectName = fileName.getName();
+    /**
+     * Add file reference of product to map of objects.
+     * @param objects object map.
+     * @param linkTarget build description for executable or shared library.
+     * @return file reference to generated executable or shared library.
+     */
+    private PBXObjectRef addProduct(final Map objects,
+                                 final TargetInfo linkTarget) {
+
+        //
+        //   create file reference for executable file
+        //     forget Ant's location, just place in XCode's default location
+        PBXObjectRef executable = createPBXFileReference("BUILD_PRODUCTS_DIR",
+                linkTarget.getOutput().getParent(),
+                linkTarget.getOutput());
+        Map executableProperties = executable.getProperties();
+        executableProperties.put("explicitFileType", "compiled.mach-o.executable");
+        executableProperties.put("includeInIndex", "0");
+        objects.put(executable.getID(), executableProperties);
+
+        return executable;
     }
-    final String basePath = fileName.getAbsoluteFile().getParent();
 
-    xcodeDir.mkdir();
 
-    File xcodeProj = new File(xcodeDir, "project.pbxproj");
+    /**
+     * Add file references for all source files to map of objects.
+     * @param objects map of objects.
+     * @param sourceTree source tree.
+     * @param basePath parent of XCode project dir
+     * @param targets build targets.
+     * @return list containing file references of source files.
+     */
+    private List addSources(final Map objects,
+                            final String sourceTree,
+                            final String basePath,
+                            final Hashtable targets) {
+        List sourceGroupChildren = new ArrayList();
 
-    //
-    //   assume that all C++ compiles can use the
-    //    same settings
-    //
-    CommandLineCompilerConfiguration gccConfig = null;
+        ArrayList sourceList = new ArrayList(targets.size());
+        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++) {
+                sourceList.add(targetsources[i]);
+            }
+        }
+        Object[] sortedSources = sourceList.toArray();
+        Arrays.sort(sortedSources, new Comparator() {
+            public int compare(final Object o1, final Object o2) {
+                return (((File) o1).getName().compareTo(
+                        ((File) o2).getName()));
+            }
+        });
+        for (int i = 0; i < sortedSources.length; i++) {
+            PBXObjectRef fileRef = createPBXFileReference(sourceTree,
+                    basePath, (File) sortedSources[i]);
+            sourceGroupChildren.add(fileRef);
+            objects.put(fileRef.getID(), fileRef.getProperties());
+        }
 
-    Vector sourceList = new Vector(targets.size());
-    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++) {
-        sourceList.addElement(new SourceEntry(targetsources[i],
-                                              getUniqueID(), getUniqueID()));
-      }
-      ProcessorConfiguration procConfig = info.getConfiguration();
-      if (procConfig instanceof CommandLineCompilerConfiguration
-          && gccConfig == null) {
-        gccConfig = (CommandLineCompilerConfiguration) procConfig;
-      }
+        return sourceGroupChildren;
     }
-    SourceEntry[] sortedSources = new SourceEntry[sourceList.size()];
-    sourceList.copyInto(sortedSources);
-    Arrays.sort(sortedSources, new Comparator() {
-      public int compare(final Object o1, final Object o2) {
-        return ( (SourceEntry) o1).getFile().getName().compareTo( ( (
-            SourceEntry) o2).getFile().getName());
-      }
-    });
-    File outFile = task.getOutfile();
 
-    Writer writer = new BufferedWriter(new FileWriter(xcodeProj));
+    /**
+     * Add native target configuration list.
+     * @param objects map of objects.
+     * @param projectName project name.
+     * @return build configurations for native target.
+     */
+    private PBXObjectRef addNativeTargetConfigurationList(final Map objects,
+                                                       final String projectName) {
+        //
+        //   Create a configuration list with
+        //     two stock configurations: Debug and Release
+        //
+        List configurations = new ArrayList();
+        Map debugSettings = new HashMap();
+        debugSettings.put("COPY_PHASE_STRIP", "NO");
+        debugSettings.put("GCC_DYNAMIC_NO_PIC", "NO");
+        debugSettings.put("GCC_ENABLE_FIX_AND_CONTINUE", "YES");
+        debugSettings.put("GCC_MODEL_TUNING", "G5");
+        debugSettings.put("GCC_OPTIMIZATION_LEVEL", "0");
+        debugSettings.put("INSTALL_PATH", "$(HOME)/bin");
+        debugSettings.put("PRODUCT_NAME", projectName);
+        debugSettings.put("ZERO_LINK", "YES");
+        PBXObjectRef debugConfig = createXCBuildConfiguration("Debug",
+                debugSettings);
+        objects.put(debugConfig.getID(), debugConfig.getProperties());
+        configurations.add(debugConfig);
 
-    writer.write("// !$*UTF8*$!\n");
-    writer.write("   {\n");
-    writer.write("   	archiveVersion = 1;\n");
-    writer.write("   	classes = {\n");
-    writer.write("   	};\n");
-    writer.write("   	objectVersion = 39;\n");
-    writer.write("   	objects = {\n");
-    writer.write("   		014CEA520018CE5811CA2923 = {\n");
-    writer.write("   			buildRules = (\n");
-    writer.write("   			);\n");
-    writer.write("   			buildSettings = {\n");
-    writer.write("   				COPY_PHASE_STRIP = NO;\n");
-    writer.write("   				DEBUGGING_SYMBOLS = YES;\n");
-    writer.write("   				GCC_DYNAMIC_NO_PIC = NO;\n");
-    writer.write("   				GCC_ENABLE_FIX_AND_CONTINUE = YES;\n");
-    writer.write("   				GCC_GENERATE_DEBUGGING_SYMBOLS = YES;\n");
-    writer.write("   				GCC_OPTIMIZATION_LEVEL = 0;\n");
-    writer.write("   				OPTIMIZATION_CFLAGS = \"-O0\";\n");
-    writer.write("   				ZERO_LINK = YES;\n");
-    writer.write("   			};\n");
-    writer.write("   			isa = PBXBuildStyle;\n");
-    writer.write("   			name = Development;\n");
-    writer.write("   		};\n");
-    writer.write("   		014CEA530018CE5811CA2923 = {\n");
-    writer.write("   			buildRules = (\n");
-    writer.write("   			);\n");
-    writer.write("   			buildSettings = {\n");
-    writer.write("   				COPY_PHASE_STRIP = YES;\n");
-    writer.write("   				GCC_ENABLE_FIX_AND_CONTINUE = NO;\n");
-    writer.write("   				ZERO_LINK = NO;\n");
-    writer.write("   			};\n");
-    writer.write("   			isa = PBXBuildStyle;\n");
-    writer.write("   			name = Deployment;\n");
-    writer.write("   		};\n");
-    writer.write("//   010\n");
-    writer.write("//   011\n");
-    writer.write("//   012\n");
-    writer.write("//   013\n");
-    writer.write("//   014\n");
-    writer.write("//   080\n");
-    writer.write("//   081\n");
-    writer.write("//   082\n");
-    writer.write("//   083\n");
-    writer.write("//   084\n");
-    writer.write("   		08FB7793FE84155DC02AAC07 = {\n");
-    writer.write("   			buildSettings = {\n");
-    writer.write("   			};\n");
-    writer.write("   			buildStyles = (\n");
-    writer.write("   				014CEA520018CE5811CA2923,\n");
-    writer.write("   				014CEA530018CE5811CA2923,\n");
-    writer.write("   			);\n");
-    writer.write("   			hasScannedForEncodings = 1;\n");
-    writer.write("   			isa = PBXProject;\n");
-    writer.write("   			mainGroup = 08FB7794FE84155DC02AAC07;\n");
-    writer.write("   			projectDirPath = \"\";\n");
-    writer.write("   			targets = (\n");
-    writer.write("   				D2AAC0620554660B00DB518D,\n");
-    writer.write("   			);\n");
-    writer.write("   		};\n");
-    writer.write("   		08FB7794FE84155DC02AAC07 = {\n");
-    writer.write("   			children = (\n");
-    writer.write("   				08FB7795FE84155DC02AAC07,\n");
-    writer.write("   				1AB674ADFE9D54B511CA2CBB,\n");
-    writer.write("   			);\n");
-    writer.write("   			isa = PBXGroup;\n");
-    writer.write("   			name = ");
-    writer.write(outFile.getName());
-    writer.write(";\n");
-    writer.write("   			refType = 4;\n");
-    writer.write("   			sourceTree = \"<group>\";\n");
-    writer.write("   		};\n");
-    writer.write("   		08FB7795FE84155DC02AAC07 = {\n");
-    writer.write("   			children = (\n");
+        Map releaseSettings = new HashMap();
+        List archs = new ArrayList();
+        archs.add("ppc");
+        archs.add("i386");
+        releaseSettings.put("ARCHS", archs);
+        releaseSettings.put("GCC_GENERATE_DEBUGGING_SYMBOLS", "NO");
+        releaseSettings.put("GCC_MODEL_TUNING", "G5");
+        releaseSettings.put("INSTALL_PATH", "$(HOME)/bin");
+        releaseSettings.put("PRODUCT_NAME", projectName);
+        PBXObjectRef releaseConfig = createXCBuildConfiguration("Release",
+                releaseSettings);
+        objects.put(releaseConfig.getID(), releaseConfig.getProperties());
+        configurations.add(releaseConfig);
 
-    //
-    //   source ID's go here
-    //
-    for (int i = 0; i < sortedSources.length; i++) {
-      writer.write("   				");
-      writer.write(sortedSources[i].getSourceID());
-      writer.write(",\n");
+        PBXObjectRef configurationList = createXCConfigurationList(configurations);
+        objects.put(configurationList.getID(), configurationList.getProperties());
+        return configurationList;
     }
 
-    writer.write("   			);\n");
-    writer.write("   			isa = PBXGroup;\n");
-    writer.write("   			name = Source;\n");
-    writer.write("   			refType = 4;\n");
-    writer.write("   			sourceTree = \"<group>\";\n");
-    writer.write("   		};\n");
+    /**
+     * Add project configuration list.
+     * @param objects map of objects.
+     * @return project configuration object.
+     */
+    private PBXObjectRef addProjectConfigurationList(final Map objects) {
+        //
+        //   Create a configuration list with
+        //     two stock configurations: Debug and Release
+        //
+        List configurations = new ArrayList();
+        Map debugSettings = new HashMap();
+        debugSettings.put("GCC_WARN_ABOUT_RETURN_TYPE", "YES");
+        debugSettings.put("GCC_WARN_UNUSED_VARIABLE", "YES");
+        debugSettings.put("PREBINDING", "NO");
+        debugSettings.put("SDKROOT", "/Developer/SDKs/MacOSX10.4u.sdk");
+        PBXObjectRef debugConfig = createXCBuildConfiguration("Debug", debugSettings);
+        objects.put(debugConfig.getID(), debugConfig.getProperties());
+        configurations.add(debugConfig);
 
-    for (int i = 0; i < sortedSources.length; i++) {
-      //
-      //   source definition
-      //
-      SourceEntry entry = sortedSources[i];
-      writer.write("   		");
-      writer.write(entry.getSourceID());
-      writer.write(" = {\n");
-      writer.write("   			fileEncoding = 4;\n");
-      writer.write("   			isa = PBXFileReference;\n");
-      String sourceName = entry.getFile().getName();
-      if (sourceName.endsWith(".c")) {
-        writer.write("   			lastKnownFileType = sourcecode.c.c;\n");
-      } else {
-        writer.write("   			lastKnownFileType = sourcecode.cpp.cpp;\n");
-      }
+        Map releaseSettings = new HashMap();
+        releaseSettings.put("GCC_WARN_ABOUT_RETURN_TYPE", "YES");
+        releaseSettings.put("GCC_WARN_UNUSED_VARIABLE", "YES");
+        releaseSettings.put("PREBINDING", "NO");
+        releaseSettings.put("SDKROOT", "/Developer/SDKs/MacOSX10.4u.sdk");
+        PBXObjectRef releaseConfig =
+                createXCBuildConfiguration("Release", releaseSettings);
+        objects.put(releaseConfig.getID(), releaseConfig.getProperties());
+        configurations.add(releaseConfig);
+        PBXObjectRef configurationList = createXCConfigurationList(configurations);
+        Map projectConfigurationListProperties = configurationList.getProperties();
+        projectConfigurationListProperties.put("defaultConfigurationIsVisible", "0");
+        projectConfigurationListProperties.put("defaultConfigurationName", "Release");
+        objects.put(configurationList.getID(), configurationList.getProperties());
+        return configurationList;
+    }
 
-      String relativePath = CUtil.getRelativePath(basePath, entry.getFile());
-      if (!relativePath.equals(sourceName)) {
-        writer.write("              name = ");
-        writer.write(sourceName);
-        writer.write(";\n");
-      }
-      writer.write("   			path = ");
-      writer.write(relativePath);
-      writer.write(";\n");
-      writer.write("   			refType = 4;\n");
-      writer.write("   			sourceTree = \"<group>\";\n");
-      writer.write("   		};\n");
+    /**
+     * Add native target to map of objects.
+     * @param objects map of objects.
+     * @param linkTarget description of executable or shared library.
+     * @param product product.
+     * @param sourceGroupChildren source files needed to build product.
+     * @return native target.
+     */
+    private PBXObjectRef addNativeTarget(final Map objects,
+                                      final TargetInfo linkTarget,
+                                      final PBXObjectRef product,
+                                      final List sourceGroupChildren) {
 
-      //
-      //   build definition
-      //
-      writer.write("   		");
-      writer.write(entry.getBuildID());
-      writer.write(" = {\n");
-      writer.write("   			fileRef = ");
-      writer.write(entry.getSourceID());
-      writer.write(";\n");
-      writer.write("   			isa = PBXBuildFile;\n");
-      writer.write("   			settings = {\n");
-      writer.write("   			};\n");
-      writer.write("   		};\n");
+        PBXObjectRef buildConfigurations = this.addNativeTargetConfigurationList(objects,
+                linkTarget.getOutput().getName());
 
-    }
-    writer.write("//   080\n");
-    writer.write("//   081\n");
-    writer.write("//   082\n");
-    writer.write("//   083\n");
-    writer.write("//   084\n");
-    writer.write("//   1A0\n");
-    writer.write("//   1A1\n");
-    writer.write("//   1A2\n");
-    writer.write("//   1A3\n");
-    writer.write("//   1A4\n");
-    writer.write("   		1AB674ADFE9D54B511CA2CBB = {\n");
-    writer.write("   			children = (\n");
-    writer.write("   				D2AAC0630554660B00DB518D,\n");
-    writer.write("   			);\n");
-    writer.write("   			isa = PBXGroup;\n");
-    writer.write("   			name = Products;\n");
-    writer.write("   			refType = 4;\n");
-    writer.write("   			sourceTree = \"<group>\";\n");
-    writer.write("   		};\n");
-    writer.write("//   1A0\n");
-    writer.write("//   1A1\n");
-    writer.write("//   1A2\n");
-    writer.write("//   1A3\n");
-    writer.write("//   1A4\n");
-    writer.write("//   D20\n");
-    writer.write("//   D21\n");
-    writer.write("//   D22\n");
-    writer.write("//   D23\n");
-    writer.write("//   D24\n");
-    writer.write("   		D2AAC0600554660B00DB518D = {\n");
-    writer.write("   			buildActionMask = 2147483647;\n");
-    writer.write("   			files = (\n");
-    writer.write("   			);\n");
-    writer.write("   			isa = PBXHeadersBuildPhase;\n");
-    writer.write("   			runOnlyForDeploymentPostprocessing = 0;\n");
-    writer.write("   		};\n");
-    writer.write("   		D2AAC0610554660B00DB518D = {\n");
-    writer.write("   			buildActionMask = 2147483647;\n");
-    writer.write("   			files = (\n");
+        int buildActionMask = 2147483647;
+        List buildPhases = new ArrayList();
 
-    //
-    //   build ID's
-    //
-    for (int i = 0; i < sortedSources.length; i++) {
-      writer.write("   				");
-      writer.write(sortedSources[i].getBuildID());
-      writer.write(",\n");
-    }
-    writer.write("   			);\n");
-    writer.write("   			isa = PBXSourcesBuildPhase;\n");
-    writer.write("   			runOnlyForDeploymentPostprocessing = 0;\n");
-    writer.write("   		};\n");
-    writer.write("   		D2AAC0620554660B00DB518D = {\n");
-    writer.write("   			buildPhases = (\n");
-    writer.write("   				D2AAC0600554660B00DB518D,\n");
-    writer.write("   				D2AAC0610554660B00DB518D,\n");
-    writer.write("   			);\n");
-    writer.write("   			buildRules = (\n");
-    writer.write("   			);\n");
-    writer.write("   			buildSettings = {\n");
-    writer.write("   				DYLIB_COMPATIBILITY_VERSION = 1;\n");
-    writer.write("   				DYLIB_CURRENT_VERSION = 1;\n");
-    //
-    //   write preprocessor macros
-    //
-    if (gccConfig != null) {
-      String[] options = gccConfig.getPreArguments();
-      boolean hasD = false;
-      for (int i = 0; i < options.length; i++) {
-        if (options[i].startsWith("-D")) {
-          if (!hasD) {
-            writer.write("   				GCC_PREPROCESSOR_DEFINITIONS = \"");
-            hasD = true;
-          } else {
-            writer.write(" ");
-          }
-          writer.write(options[i].substring(2));
+        Map settings = new HashMap();
+        settings.put("ATTRIBUTES", new ArrayList());
+        List buildFiles = new ArrayList();
+        for (Iterator iter = sourceGroupChildren.iterator();
+             iter.hasNext();) {
+            PBXObjectRef sourceFile = (PBXObjectRef) iter.next();
+            PBXObjectRef buildFile = createPBXBuildFile(sourceFile, settings);
+            buildFiles.add(buildFile);
+            objects.put(buildFile.getID(), buildFile.getProperties());
         }
-      }
-      if (hasD) {
-        writer.write("\";\n");
-      }
+
+
+        PBXObjectRef sourcesBuildPhase = createPBXSourcesBuildPhase(buildActionMask,
+                buildFiles, false);
+        objects.put(sourcesBuildPhase.getID(), sourcesBuildPhase.getProperties());
+        buildPhases.add(sourcesBuildPhase);
+
+
+        PBXObjectRef frameworksBuildPhase =
+                createPBXFrameworksBuildPhase(buildActionMask,
+                new ArrayList(), false);
+        objects.put(frameworksBuildPhase.getID(), frameworksBuildPhase.getProperties());
+        buildPhases.add(frameworksBuildPhase);
+
+        PBXObjectRef copyFilesBuildPhase = createPBXCopyFilesBuildPhase(8,
+                "/usr/share/man/man1", "0", new ArrayList(), true);
+        objects.put(copyFilesBuildPhase.getID(), copyFilesBuildPhase.getProperties());
+        buildPhases.add(copyFilesBuildPhase);
+
+        List buildRules = new ArrayList();
+
+        List dependencies = new ArrayList();
+
+        String productInstallPath = "$(HOME)/bin";
+
+        String productType = "com.apple.product-type.tool";
+
+        PBXObjectRef nativeTarget = createPBXNativeTarget("hello",
+                buildConfigurations, buildPhases, buildRules, dependencies,
+                productInstallPath, "hello", product, productType);
+        objects.put(nativeTarget.getID(), nativeTarget.getProperties());
+
+        return nativeTarget;
     }
-    writer.write("   				GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;\n");
-    writer.write("   				GCC_WARN_UNKNOWN_PRAGMAS = NO;\n");
-    if (gccConfig != null) {
-      File[] includes = gccConfig.getIncludePath();
-      if (includes.length > 0) {
-        writer.write("   				HEADER_SEARCH_PATHS = \"");
-        for (int i = 0; i < includes.length; i++) {
-          if (i > 0) {
-            writer.write(" ");
-          }
-          writer.write(CUtil.getRelativePath(basePath, includes[i]));
+
+
+    /**
+     * Create PBXFileReference.
+     * @param sourceTree source tree.
+     * @param baseDir base directory.
+     * @param file file.
+     * @return PBXFileReference object.
+     */
+    private static PBXObjectRef createPBXFileReference(final String sourceTree,
+                                             final String baseDir,
+                                             final File file) {
+        Map map = new HashMap();
+        map.put("isa", "PBXFileReference");
+
+        String relPath = CUtil.getRelativePath(baseDir, file);
+        String name = file.getName();
+
+        if (!name.equals(relPath)) {
+            map.put("name", name);
         }
-        writer.write("\";\n");
-      }
+        map.put("path", relPath);
+        map.put("sourceTree", sourceTree);
+        return new PBXObjectRef(map);
     }
-    
-    
-    String[] linkerArgs = null;
-    ProcessorConfiguration linkConfig = linkTarget.getConfiguration();
-    if (linkConfig instanceof CommandLineLinkerConfiguration) {
-      linkerArgs = ((CommandLineLinkerConfiguration) linkConfig).getPreArguments();
+
+    /**
+     * Create PBXGroup.
+     * @param name group name.
+     * @param sourceTree source tree.
+     * @param children list of PBXFileReferences.
+     * @return group.
+     */
+    private static PBXObjectRef createPBXGroup(final String name,
+                                     final String sourceTree,
+                                     final List children) {
+        Map map = new HashMap();
+        map.put("isa", "PBXGroup");
+        map.put("name", name);
+        map.put("sourceTree", sourceTree);
+        map.put("children", children);
+        return new PBXObjectRef(map);
     }
 
-    
-    writer.write("   				INSTALL_PATH = /usr/local/lib;\n");
-    if (linkerArgs != null) {
-        boolean hasLibPath = false;
-        for (int i = 0; i < linkerArgs.length; i++) {
-            if (linkerArgs[i].startsWith("-L")) {
-                if (!hasLibPath) {
-        		   writer.write("   				LIBRARY_SEARCH_PATHS = \"");
-        		   hasLibPath = true;
-        		} else {
-        		   writer.write(" ");
-        		}
-        		writer.write(linkerArgs[i].substring(2));
-            }
-        }
-        if (hasLibPath) {
-            writer.write("\";\n");
-        }
-    } 
-    writer.write("   				LIBRARY_STYLE = DYNAMIC;\n");
-    writer.write("   				OTHER_CFLAGS = \"\";\n");
-    writer.write("   				OTHER_LDFLAGS = \"");
-    if (linkerArgs != null) {
-    	 String prepend = "";
-    	 for (int i = 0; i < linkerArgs.length; i++) {
-    	     if (!linkerArgs[i].startsWith("-L")) {
-    	         writer.write(prepend);
-    	         writer.write(linkerArgs[i]);
-    	         prepend = "  ";
-    	     }
-    	}
+    /**
+     * Create PBXProject.
+     * @param buildConfigurationList build configuration list.
+     * @param mainGroup main group.
+     * @param projectDirPath project directory path.
+     * @param targets targets.
+     * @return project.
+     */
+    private static PBXObjectRef createPBXProject(final PBXObjectRef buildConfigurationList,
+                                       final PBXObjectRef mainGroup,
+                                       final String projectDirPath,
+                                       final List targets) {
+        Map map = new HashMap();
+        map.put("isa", "PBXProject");
+        map.put("buildConfigurationList", buildConfigurationList.getID());
+        map.put("hasScannedForEncodings", "0");
+        map.put("mainGroup", mainGroup.getID());
+        map.put("projectDirPath", projectDirPath);
+        map.put("targets", targets);
+        return new PBXObjectRef(map);
     }
-    writer.write("\";\n");
-    writer.write("   				OTHER_REZFLAGS = \"\";\n");
-    writer.write("   				PRODUCT_NAME = testbsd;\n");
-    writer.write("   				SECTORDER_FLAGS = \"\";\n");
-    writer.write("   				WARNING_CFLAGS = \"-Wmost\";\n");
-    writer.write("   			};\n");
-    writer.write("   			dependencies = (\n");
-    writer.write("   			);\n");
-    writer.write("   			isa = PBXNativeTarget;\n");
 
-    writer.write("   			name = ");
-    writer.write(outFile.getName());
-    writer.write(";\n");
-    writer.write("   			productName = ");
-    writer.write(outFile.getName());
-    writer.write(";\n");
-    writer.write("   			productReference = D2AAC0630554660B00DB518D;\n");
-
-    String productType = "com.apple.product-type.library.dynamic";
-    String prefix = "lib";
-    String suffix = ".dylib";
-    String explicitFileType = "compiled.mach-o.dylib";
-    String outType = task.getOuttype();
-    if ("executable".equals(outType)) {
-      productType = "com.apple.product-type.tool";
-      prefix = "";
-      suffix = "";
-      explicitFileType = "compiled.mach-o.executable";
-    } else if ("static".equals(outType)) {
-      productType = "com.apple.product-type.library.static";
-      suffix = ".a";
-      explicitFileType = "archive.ar";
+    /**
+     * Create XCConfigurationList.
+     * @param buildConfigurations build configurations.
+     * @return configuration list.
+     */
+    private static PBXObjectRef createXCConfigurationList(final List buildConfigurations) {
+        Map map = new HashMap();
+        map.put("isa", "XCConfigurationList");
+        map.put("buildConfigurations", buildConfigurations);
+        return new PBXObjectRef(map);
     }
-    writer.write("   			productType = \"");
-    writer.write(productType);
-    writer.write("\";\n");
-    writer.write("   		};\n");
-    writer.write("   		D2AAC0630554660B00DB518D = {\n");
 
-    writer.write("   			explicitFileType = \"");
-    writer.write(explicitFileType);
-    writer.write("\";\n");
-    writer.write("   			includeInIndex = 0;\n");
-    writer.write("   			isa = PBXFileReference;\n");
-    writer.write("   			path = ");
-    writer.write(outFile.getName());
-    writer.write(suffix);
-    writer.write(";\n");
-    writer.write("   			refType = 3;\n");
-    writer.write("   			sourceTree = BUILT_PRODUCTS_DIR;\n");
-    writer.write("   		};\n");
-    writer.write("   	};\n");
-    writer.write("   	rootObject = 08FB7793FE84155DC02AAC07;\n");
-    writer.write("   }\n");
 
-    writer.close();
-  }
+    /**
+     * Create XCBuildConfiguration.
+     * @param name name.
+     * @param buildSettings build settings.
+     * @return build configuration.
+     */
+    private static PBXObjectRef createXCBuildConfiguration(final String name,
+                                                 final Map buildSettings) {
+        Map map = new HashMap();
+        map.put("isa", "XCBuildConfiguration");
+        map.put("buildSettings", buildSettings);
+        map.put("name", name);
+        return new PBXObjectRef(map);
+    }
 
-  /**
-   * Gets the first recognized compiler from the
-   * compilation targets.
-   * @param targets compilation targets
-   * @return representative (hopefully) compiler configuration
-   */
-  private CommandLineCompilerConfiguration
-      getBaseCompilerConfiguration(Hashtable targets) {
-    //
-    //   find first target with an GNU C++ 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 cl compiler
-      //
-      if (config instanceof CommandLineCompilerConfiguration) {
-        compilerConfig = (CommandLineCompilerConfiguration) config;
-        if (compilerConfig.getCompiler() instanceof GccCCompiler) {
-          return compilerConfig;
-        }
-      }
+    /**
+     * Create PBXNativeTarget.
+     * @param name name.
+     * @param buildConfigurationList build configuration list.
+     * @param buildPhases build phases.
+     * @param buildRules build rules.
+     * @param dependencies dependencies.
+     * @param productInstallPath product install path.
+     * @param productName product name.
+     * @param productReference file reference for product.
+     * @param productType product type.
+     * @return native target.
+     */
+    private static PBXObjectRef createPBXNativeTarget(final String name,
+                                            final PBXObjectRef buildConfigurationList,
+                                            final List buildPhases,
+                                            final List buildRules,
+                                            final List dependencies,
+                                            final String productInstallPath,
+                                            final String productName,
+                                            final PBXObjectRef productReference,
+                                            final String productType) {
+        Map map = new HashMap();
+        map.put("isa", "PBXNativeTarget");
+        map.put("buildConfigurationList", buildConfigurationList);
+        map.put("buildPhases", buildPhases);
+        map.put("buildRules", buildRules);
+        map.put("dependencies", dependencies);
+        map.put("name", name);
+        map.put("productInstallPath", productInstallPath);
+        map.put("productName", productName);
+        map.put("productReference", productReference);
+        map.put("productType", productType);
+        return new PBXObjectRef(map);
     }
-    return null;
-  }
 
-  /**
-   * Source file with 96-bit source and build ID's.
-   */
-  private static final class SourceEntry {
     /**
-     * Source file.
+     * Create PBXSourcesBuildPhase.
+     * @param buildActionMask build action mask.
+     * @param files source files.
+     * @param runOnly if true, phase should only be run on deployment.
+     * @return PBXSourcesBuildPhase.
      */
-    private final File file;
+    private static PBXObjectRef createPBXSourcesBuildPhase(int buildActionMask,
+                                                 List files,
+                                                 boolean runOnly) {
+        Map map = new HashMap();
+        map.put("buildActionMask",
+                String.valueOf(buildActionMask));
+        map.put("files", files);
+        map.put("isa", "PBXSourcesBuildPhase");
+        map.put("runOnlyForDeploymentPostprocessing", toString(runOnly));
+        return new PBXObjectRef(map);
+    }
 
     /**
-     * Source ID.
+     * Create PBXBuildFile.
+     * @param fileRef source file.
+     * @param settings build settings.
+     * @return PBXBuildFile.
      */
-    private final String sourceID;
+    private static PBXObjectRef createPBXBuildFile(PBXObjectRef fileRef,
+                                         Map settings) {
+        Map map = new HashMap();
+        map.put("fileRef", fileRef);
+        map.put("isa", "PBXBuildFile");
+        if (settings != null) {
+            map.put("settings", settings);
+        }
+        return new PBXObjectRef(map);
+    }
 
     /**
-     * Build step ID.
+     * Create PBXFrameworksBuildPhase.
+     * @param buildActionMask build action mask.
+     * @param files files.
+     * @param runOnly if true, phase should only be run on deployment.
+     * @return PBXFrameworkBuildPhase.
      */
-    private final String buildID;
+    private static PBXObjectRef createPBXFrameworksBuildPhase(
+            final int buildActionMask,
+            final List files,
+            final boolean runOnly) {
+        Map map = new HashMap();
+        map.put("isa", "PBXFrameworksBuildPhase");
+        map.put("buildActionMask", NumberFormat.getIntegerInstance(Locale.US).format(buildActionMask));
+        map.put("files", files);
+        map.put("runOnlyForDeploymentPostprocessing", toString(runOnly));
+        return new PBXObjectRef(map);
+    }
 
     /**
-     * Constructor.
-     * @param fileArg source file
-     * @param sourceIDArg source ID
-     * @param buildIDArg build step ID
+     * Create a build phase that copies files to a destination.
+     * @param buildActionMask build action mask.
+     * @param dstPath destination path.
+     * @param dstSubfolderSpec subfolder spec.
+     * @param files files.
+     * @param runOnly if true, phase should only be run on deployment.
+     * @return PBXCopyFileBuildPhase.
      */
-    public SourceEntry(final File fileArg,
-                       final String sourceIDArg,
-                       final String buildIDArg) {
-      file = fileArg;
-      sourceID = sourceIDArg;
-      buildID = buildIDArg;
+    private static PBXObjectRef createPBXCopyFilesBuildPhase(
+            final int buildActionMask,
+            final String dstPath,
+            final String dstSubfolderSpec,
+            final List files,
+            final boolean runOnly) {
+        Map map = new HashMap();
+        map.put("isa", "PBXCopyFilesBuildPhase");
+        map.put("buildActionMask", NumberFormat.getIntegerInstance(Locale.US).format(buildActionMask));
+        map.put("dstPath", dstPath);
+        map.put("dstSubfolderSpec", dstSubfolderSpec);
+        map.put("files", files);
+        map.put("runOnlyForDeploymentPostprocessing", toString(runOnly));
+        return new PBXObjectRef(map);
     }
 
     /**
-     * Get source file.
-     * @return source file
+     * Method returns "1" for true, "0" for false.
+     * @param b boolean value.
+     * @return "1" for true, "0" for false.
      */
-    public File getFile() {
-      return file;
+    private static String toString(boolean b) {
+        if (b) {
+            return "1";
+        } else {
+            return "0";
+        }
     }
 
     /**
-     * Get source ID.
-     * @return source ID
+     * Represents a property map with an 96 bit identity.
+     * When placed in a property list, this object will
+     * output the string representation of the identity
+     * which XCode uses to find the corresponding property
+     * bag in the "objects" property of the top-level property list.
      */
-    public String getSourceID() {
-      return sourceID;
+    private static final class PBXObjectRef {
+        /**
+         * Identifier.
+         */
+        private final String id;
+        /**
+         * Properties.
+         */
+        private final Map properties;
+        /**
+         * Next available identifier.
+         */
+        private static int nextID = 0;
+
+        /**
+         * Create reference.
+         * @param props properties.
+         */
+        public PBXObjectRef(final Map props) {
+            if (props == null) {
+                throw new NullPointerException("props");
+            }
+            StringBuffer buf = new StringBuffer("000000000000000000000000");
+            String idStr = Integer.toHexString(nextID++);
+            buf.replace(buf.length() - idStr.length(), buf.length(), idStr);
+            id = buf.toString();
+            properties = props;
+        }
+
+        /**
+         * Get object identifier.
+         * @return identifier.
+         */
+        public String toString() {
+            return id;
+        }
+
+        /**
+         * Get object identifier.
+         * @return object identifier.
+         */
+        public String getID() {
+            return id;
+        }
+
+        /**
+         * Get properties.
+         * @return properties.
+         */
+        public Map getProperties() {
+            return properties;
+        }
     }
 
     /**
-     * Get build step ID.
-     * @return build step ID
+     * Gets the first recognized compiler from the
+     * compilation targets.
+     *
+     * @param targets compilation targets
+     * @return representative (hopefully) compiler configuration
      */
-    public String getBuildID() {
-      return buildID;
+    private CommandLineCompilerConfiguration
+    getBaseCompilerConfiguration(Hashtable targets) {
+        //
+        //   find first target with an GNU C++ compilation
+        //
+        CommandLineCompilerConfiguration compilerConfig;
+        //
+        //   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();
+            //
+            //   for the first cl compiler
+            //
+            if (config instanceof CommandLineCompilerConfiguration) {
+                compilerConfig = (CommandLineCompilerConfiguration) config;
+                if (compilerConfig.getCompiler() instanceof GccCCompiler) {
+                    return compilerConfig;
+                }
+            }
+        }
+        return null;
     }
-  }
+
 }


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/