Changeset 1230

Show
Ignore:
Timestamp:
07/14/08 04:58:09 (2 months ago)
Author:
fraserofthenight
Message:

Yet another approach here -- it appears dependency analysis is non-trivial with things like static ifs, etc., and may be slow, so I'll try parsing compiler output to get imports where possible, and maybe later add dependency analysis for compilers where this can't be done (GDC, I think).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/descent.building/src/descent/building/compiler/IBuildManager.java

    r1197 r1230  
    11package descent.building.compiler; 
    22 
     3/** 
     4 * Class representing the state of the internal builder, which the  
     5 * {@link ICompileManager} should use to gain information on the state of the 
     6 * build and to perform various tasks. 
     7 *  
     8 * <b>This class is not intended to be implemented by clients.</b> 
     9 *  
     10 * @see ICompileManager 
     11 * @author Robert Fraser 
     12 */ 
    313public interface IBuildManager 
    414{ 
  • trunk/descent.building/src/descent/building/compiler/ICompileManager.java

    r1197 r1230  
    11package descent.building.compiler; 
    22 
     3import org.eclipse.core.runtime.IProgressMonitor; 
     4 
     5/** 
     6 * The build process contains some processes that are compiler-ambivalent, and 
     7 * others that depend on the compiler being used. The compiler-ambivalent parts 
     8 * are managed internally by the builder, and an instance of this class is used 
     9 * to manage compiler-specific parts. The lifecycle of a build involves 
     10 * cooperation between this class and the builder (accessed via an 
     11 * {@link IBuildManager}), with multiple calls made back and forth between the 
     12 * two components. From the perspective of the compiler implementer, the 
     13 * lifecycle works roughly like this: 
     14 *  
     15 * <ol> 
     16 *     <li>For each build, this class will be constructed via the  
     17 *         {@link ICompilerInterface#getCompileManager(IBuildManager)} class.</li> 
     18 *          
     19 *     <li>When an object file needs to be compiled, the  
     20 *         {@link #compile(IObjectFile)} method will be called.</li> 
     21 *          
     22 *     <li>During the course of building, methods on the {@link IBuildManager} 
     23 *         should be called to handle things like executing specific commands, 
     24 *         reporting errors, or getting build information.</li> 
     25 *          
     26 *     <li>TODO linking</li> 
     27 * </ol> 
     28 *  
     29 * <b>This class should be implemented by clients providing a compiler interface.</b> 
     30 *  
     31 * @author Robert Fraser 
     32 */ 
    333public interface ICompileManager 
    434{ 
     35    /** 
     36     * Compiles the given object files. If multiple files are passed, they may 
     37     * be built together. If  
     38     * {@link ICompilerInterface#supportsInternalDependancyAnalysis()} returns 
     39     * <code>true</code> for this compiler type, this class should return a  
     40     * non-null array of the names of all modules imported by the given object 
     41     * files (whether or not these files need to be built should be decided by 
     42     * the builder). If supportsInternalDependancyAnalysis() is 
     43     * <code>false</code>, the return of this method will be ignored. 
     44     *  
     45     * @param objectFiles the object files to be built 
     46     * @param pm          a monitor to rack the progress of the operation 
     47     * @return            a list of files imported by the given targets 
     48     */ 
     49    public String[] compile(IObjectFile[] objectFiles, IProgressMonitor pm); 
    550} 
  • trunk/descent.building/src/descent/building/compiler/ICompilerInterface.java

    r1197 r1230  
    22 
    33import descent.building.compiler.ui.CompilerOption; 
    4  
    54 
    65/** 
     
    1716 * TODO document how it is used 
    1817 *  
     18 * <b>This class should be implemented by clients providing a compiler interface.</b> 
     19 *  
    1920 * @author Robert Fraser 
    2021 */ 
    2122public interface ICompilerInterface 
    22 { 
     23{    
    2324    /** 
    2425     * Gets the compiler options which should be presented in the UI. 
     
    2829    // TODO comment about what sorts of options should be included etc 
    2930    public CompilerOption[] getOptions(); 
     31     
     32    /** 
     33     * Checks whether this type of compiler supports internal compiler analysis. 
     34     * Internal dependency analysis means that during the compile step it is 
     35     * possible to retrieve a list of dependencies after building an object file. 
     36     * For example, DMD output can be parsed for imports. If this returns false, 
     37     * the descent builder will use internal dependency analysis. This method can 
     38     * be slower and could potentially have issues if the semantics are slightly 
     39     * different than the compiler, so if it is possible to support internal 
     40     * dependency analysis, it should be done. 
     41     *  
     42     * @return true if and only if this compiler supports internal dependency 
     43     *         analysis 
     44     */ 
     45    public boolean supportsInternalDependancyAnalysis(); 
     46     
     47    /** 
     48     * Gets a new instance of a compile manager that should cooperate with the 
     49     * given build manager. 
     50     *  
     51     * @param buildManager the build manager the compile manager should work 
     52     *                     with 
     53     * @return             an instance of a compiler manager to be used for a 
     54     *                     build 
     55     * @see                ICompileManager 
     56     */ 
     57    public ICompileManager getCompileManager(IBuildManager buildManager); 
    3058} 
  • trunk/descent.building/src/descent/building/compiler/IObjectFile.java

    r1216 r1230  
    33import java.io.File; 
    44 
     5/** 
     6 * Ties together an input file (a D module) and an output file (the target .obj 
     7 * file). Instances of this interface represent fully-qualified D modules with 
     8 * their target outputs from a build. 
     9 *  
     10 * There should be only one of this class for any given module in or referenced by 
     11 * a build. The {@link #equals(Object)} method should return <code>true</true> for 
     12 * two object file if they refer to the same module. 
     13 *  
     14 * <b>This class is not intended to be implemented by clients.</b> 
     15 *  
     16 * @author Robert Fraser 
     17 */ 
    518public interface IObjectFile 
    619{ 
     20    /** 
     21     * Gets the name of the D module to which this refers. 
     22     */ 
     23    public String getName(); 
     24     
     25    /** 
     26     * Gets the D file which is the module's source code. This file should 
     27     * exist, but be sure to check for existence before use. 
     28     */ 
    729    public File getInputFile(); 
     30     
     31    /** 
     32     * Gets the object file (which may or may not exist) which is the target 
     33     * output for a compile execution. 
     34     */ 
    835    public File getOutputFile(); 
     36     
     37    /** 
     38     * Checks whether this module is local to the project/workspace or is 
     39     * referenced from a source library. 
     40     */ 
    941    public boolean isLibraryFile(); 
    1042} 
  • trunk/descent.building/src/descent/internal/building/compiler/DmdCompilerInterface.java

    r1197 r1230  
    55import java.util.regex.Pattern; 
    66 
     7import descent.building.compiler.IBuildManager; 
     8import descent.building.compiler.ICompileManager; 
    79import descent.building.compiler.IResponseInterpreter; 
    810import descent.building.compiler.ui.CompilerOption; 
     
    1113 
    1214public final class DmdCompilerInterface extends DmdfeCompilerInterface 
    13 
    14     protected static final boolean DEBUG = true; 
    15      
    16     //-------------------------------------------------------------------------- 
    17     // Response interpreter 
    18     protected static class DmdResponseInterpreter implements IResponseInterpreter 
    19     { 
    20         private static final Pattern ERROR_WITH_FILENAME = Pattern.compile( 
    21                 "([^\\(\\:]*)" +          // Filename 
    22                 "(?:\\((\\d*)\\))?" +     // Line number 
    23                 "\\:\\s(.*)$"             // Message 
    24             ); 
    25          
    26         /* (non-Javadoc) 
    27          * @see descent.launching.compiler.IResponseInterpreter#interpret(java.lang.String) 
    28          */ 
    29         public void interpret(String line) 
    30         { 
    31             // TODO finish & test 
    32              
    33             if(DEBUG) 
    34                 System.out.println("OUT => " + line); 
    35              
    36             /* 
    37             Matcher m = ERROR_WITH_FILENAME.matcher(line); 
    38             if(m.find()) 
    39             { 
    40                 String file = m.group(1); 
    41                 String lineStr = m.group(2); 
    42                 String message = m.group(3); 
    43                 int lineNum = null != lineStr ? Integer.parseInt(lineStr) : -1; 
    44                 resp.addError(new BuildError(message, file, lineNum)); 
    45                 return; 
    46             } 
    47             */ 
    48         } 
    49          
    50         /* (non-Javadoc) 
    51          * @see descent.launching.compiler.IResponseInterpreter#interpretError(java.lang.String) 
    52          */ 
    53         public void interpretError(String line) 
    54         { 
    55             if(DEBUG) 
    56                 System.out.println("ERR => " + line); 
    57              
    58             // Keep all the interpretation in one method 
    59             // TODO interpret(line); 
    60         } 
    61     } 
    62      
     15{    
    6316    //-------------------------------------------------------------------------- 
    6417    // UI Options 
     
    9548        uiOptions = options.toArray(new CompilerOption[options.size()]); 
    9649    } 
     50 
     51    @Override 
     52    public ICompileManager getCompileManager(IBuildManager buildManager) 
     53    { 
     54        return new DmdCompileManager(); 
     55    } 
    9756} 
  • trunk/descent.building/src/descent/internal/building/compiler/DmdfeCompilerInterface.java

    r1197 r1230  
    11package descent.internal.building.compiler; 
    22 
     3import descent.building.compiler.IBuildManager; 
     4import descent.building.compiler.ICompileManager; 
    35import descent.building.compiler.ICompilerInterface; 
    46 
    57public abstract class DmdfeCompilerInterface implements ICompilerInterface 
    68{ 
     9    public ICompileManager getCompileManager(IBuildManager buildManager) 
     10    { 
     11        // TODO Auto-generated method stub 
     12        return null; 
     13    } 
     14 
     15    public boolean supportsInternalDependancyAnalysis() 
     16    { 
     17        return true; 
     18    } 
    719} 
  • trunk/descent.building/src/descent/internal/building/debuild/BuildRequest.java

    r1229 r1230  
    2020import descent.internal.building.BuilderUtil; 
    2121import descent.launching.IVMInstall; 
     22import descent.building.compiler.BuildException; 
    2223import descent.building.compiler.ICompilerInterface; 
    2324 
     
    5960        catch(CoreException e) 
    6061        { 
    61             throw new DebuildException("Could not get compiler for project " + 
     62            throw new BuildException("Could not get compiler for project " + 
    6263                    project.getElementName()); 
    6364        } 
     
    109110         
    110111        if(handles.isEmpty()) 
    111             throw new DebuildException("No target modules defined"); 
     112            throw new BuildException("No target modules defined"); 
    112113         
    113114        List<ICompilationUnit> modules =  
     
    146147         
    147148        if(modules.isEmpty()) 
    148             throw new DebuildException("None of the modules to be built exist in the project."); 
     149            throw new BuildException("None of the modules to be built exist in the project."); 
    149150         
    150151        return modules.toArray(new ICompilationUnit[modules.size()]); 
     
    199200        catch(JavaModelException e) 
    200201        { 
    201             throw new DebuildException(e); 
     202            throw new BuildException(e); 
    202203        } 
    203204    } 
     
    214215         
    215216        if(null == project) 
    216             throw new DebuildException(String.format("Cannot find project %1$s", projectName)); 
     217            throw new BuildException(String.format("Cannot find project %1$s", projectName)); 
    217218         
    218219        return project; 
  • trunk/descent.building/src/descent/internal/building/debuild/DebuildBuilder.java

    r1229 r1230  
    44import java.util.ArrayList; 
    55import java.util.HashSet; 
     6import java.util.Iterator; 
    67import java.util.List; 
    78import java.util.Set; 
     
    1415 
    1516import descent.core.IClasspathEntry; 
     17import descent.core.ICompilationUnit; 
    1618import descent.core.IJavaModel; 
    1719import descent.core.IJavaProject; 
     
    1921import descent.internal.building.BuilderUtil; 
    2022import descent.building.IDBuilder; 
     23import descent.building.compiler.BuildException; 
     24import descent.building.compiler.ICompileManager; 
     25import descent.building.compiler.ICompilerInterface; 
    2126import descent.building.compiler.IObjectFile; 
    2227 
     
    2732    private BuildRequest req; 
    2833    private ErrorReporter err; 
     34    private BuildManager buildMgr; 
     35    private ObjectFileFactory objFactory; 
     36     
    2937    private List<File> importPath; 
    3038     
     
    4452            req = new BuildRequest(config); 
    4553            err = new ErrorReporter(req.getProject()); 
     54            buildMgr = new BuildManager(); 
     55            objFactory = new ObjectFileFactory(req); 
    4656            pm.worked(5); // 5 
     57             
     58            // Check whether this build is even possible 
     59            // NEXTVERSION support internal dependency analysis 
     60            ICompilerInterface compilerInterface = req.getCompilerInterface(); 
     61            if(null == compilerInterface ||  
     62                    !compilerInterface.supportsInternalDependancyAnalysis()) 
     63                throw new BuildException("This compiler type is not supported in " + 
     64                        "this version of Descent."); 
    4765             
    4866            // If the launch configuration has changed, clear the output folder 
     
    6078                return null; 
    6179             
    62             // Collect dependancies and create the associated object files 
    63             ObjectFileFactory objFactory = new ObjectFileFactory(req); 
    64             RecursiveDependancyCollector collector =  
    65                 new RecursiveDependancyCollector(req, objFactory); 
    66             IObjectFile[] objectFiles = collector.getModules( 
    67                     new SubProgressMonitor(pm, 35)); // 50 
    68              
    69             // TODO 
    70             return null; 
     80            doCompile(new SubProgressMonitor(pm, 60)); // 85 
     81            if(pm.isCanceled()) 
     82                return null; 
     83             
     84            return doLink(new SubProgressMonitor(pm, 15)); // 100 
    7185        } 
    72         catch(DebuildException e) 
     86        catch(BuildException e) 
    7387        { 
    7488            err.projectError(e.getMessage()); 
     
    92106    } 
    93107 
     108    //-------------------------------------------------------------------------- 
     109    // Import path management 
     110     
    94111    private void createImportPath() 
    95112    { 
     
    104121        catch(JavaModelException e) 
    105122        { 
    106             throw new DebuildException(e.getMessage()); 
     123            throw new BuildException(e.getMessage()); 
    107124        } 
    108125    } 
     
    139156        } 
    140157    } 
     158     
     159    //-------------------------------------------------------------------------- 
     160    // Compile management 
     161     
     162    private void doCompile(IProgressMonitor pm) 
     163    { 
     164        try 
     165        { 
     166            // TODO what to do about progress monitoring? 
     167            pm.beginTask("Compiling object files", 1000); 
     168             
     169            ICompileManager compileMgr = req.getCompilerInterface(). 
     170                    getCompileManager(buildMgr); 
     171            Set<IObjectFile> pending = new HashSet<IObjectFile>(); 
     172            Set<IObjectFile> completed = new HashSet<IObjectFile>(); 
     173             
     174            // Add the initial/seed objects 
     175            for(ICompilationUnit cu : req.getModules()) 
     176            { 
     177                pending.add(objFactory.create(cu.getFullyQualifiedName())); 
     178                if(pm.isCanceled()) 
     179                    return; 
     180            } 
     181             
     182            while(!pending.isEmpty()) 
     183            { 
     184                // Remove any object files that should not be built 
     185                Iterator<IObjectFile> iter = pending.iterator(); 
     186                objects: while(iter.hasNext()) 
     187                { 
     188                    IObjectFile obj = iter.next(); 
     189                     
     190                    // Check if it's already been built during this run 
     191                    if(completed.contains(obj)) 
     192                    { 
     193                        iter.remove(); 
     194                        continue objects; 
     195                    } 
     196                     
     197                    // Check if the file has already been built during another 
     198                    // run and is still up-to-date 
     199                    if((obj.getInputFile().exists()) && 
     200                       (obj.getOutputFile().exists()) && 
     201                       (obj.getOutputFile().lastModified() >=  
     202                           obj.getInputFile().lastModified())) 
     203                    { 
     204                        completed.add(obj); 
     205                        iter.remove(); 
     206                        continue objects; 
     207                    } 
     208                } 
     209                 
     210                if(pending.isEmpty()) 
     211                    break; 
     212                if(pm.isCanceled()) 
     213                    return; 
     214                 
     215                // Compile the rest 
     216                String[] dependancies = compileMgr.compile( 
     217                        pending.toArray(new IObjectFile[pending.size()]), 
     218                        new SubProgressMonitor(pm, 10)); 
     219                if(pm.isCanceled()) 
     220                    return; 
     221                 
     222                // Flush the pending list into the completed list and put any 
     223                // dependencies into the pending list 
     224                completed.addAll(pending); 
     225                pending.clear(); 
     226                for(String moduleName : dependancies) 
     227                { 
     228                    IObjectFile obj = objFactory.create(moduleName); 
     229                    if(null != obj) 
     230                        pending.add(obj); 
     231                    if(pm.isCanceled()) 
     232                        return; 
     233                } 
     234            } 
     235        } 
     236        finally 
     237        { 
     238            pm.done(); 
     239        } 
     240    } 
     241     
     242    //-------------------------------------------------------------------------- 
     243    // Link management 
     244     
     245    private String doLink(IProgressMonitor pm) 
     246    { 
     247        try 
     248        { 
     249            pm.beginTask("Linking output file", 100); 
     250             
     251            return null; 
     252        } 
     253        finally 
     254        { 
     255            pm.done(); 
     256        } 
     257    } 
    141258} 
  • trunk/descent.building/src/descent/internal/building/debuild/IncrementalConsistencyManager.java

    r1229 r1230  
    88import org.eclipse.debug.core.ILaunchConfiguration; 
    99 
     10import descent.building.compiler.BuildException; 
    1011import descent.internal.building.BuilderUtil; 
    1112 
     
    103104        catch(CoreException e) 
    104105        { 
    105             throw new DebuildException(String.format( 
     106            throw new BuildException(String.format( 
    106107                    "Error preparing output folder: %1$s", e.getMessage())); 
    107108        } 
     
    145146            catch(CoreException e) 
    146147            { 
    147                 throw new DebuildException(String.format( 
     148                throw new BuildException(String.format( 
    148149                        "Error deleting resource %1$s: %2$s",  
    149150                        file.getFullPath().toString(), e.getMessage())); 
  • trunk/descent.building/src/descent/internal/building/debuild/ObjectFileFactory.java

    r1229 r1230  
    22 
    33import java.io.File; 
    4  
     4import java.util.HashMap; 
     5import java.util.HashSet; 
     6import java.util.Map; 
     7import java.util.Set; 
     8 
     9import descent.building.compiler.BuildException; 
    510import descent.building.compiler.IObjectFile; 
    611import descent.core.ICompilationUnit; 
     12import descent.core.IJavaModel; 
     13import descent.core.IJavaProject; 
     14import descent.core.IPackageFragment; 
     15import descent.core.IPackageFragmentRoot; 
     16import descent.core.JavaModelException; 
    717import descent.internal.building.BuilderUtil; 
    818 
     
    1121    private static final class ObjectFile implements IObjectFile 
    1222    { 
     23        private final String name; 
    1324        private final File inputFile; 
    1425        private final File outputFile; 
    1526        private final boolean isLibraryFile; 
    1627         
    17         public ObjectFile(File inputFile, File outputFile,  
     28        public ObjectFile(String name,  
     29                File inputFile, File outputFile,  
    1830                boolean isLibraryFile) 
    1931        { 
     32            this.name = name; 
    2033            this.inputFile = inputFile; 
    2134            this.outputFile = outputFile; 
    2235            this.isLibraryFile = isLibraryFile; 
    2336        } 
     37         
     38        public String getName() 
     39        { 
     40            return name; 
     41        } 
    2442 
    2543        public File getInputFile() 
     
    3755            return isLibraryFile; 
    3856        } 
     57 
     58        @Override 
     59        public boolean equals(Object other) 
     60        { 
     61            return ((null != other) && 
     62                    (other instanceof ObjectFile) && 
     63                    (((ObjectFile) other).name.equals(this.name))); 
     64        } 
     65 
     66        @Override 
     67        public int hashCode() 
     68        { 
     69            return name.hashCode(); 
     70        } 
     71 
     72        @Override 
     73        public String toString() 
     74        { 
     75            StringBuilder str = new StringBuilder(); 
     76             
     77            str.append(getName()); 
     78            if(isLibraryFile()) 
     79                str.append(" (ExTERNAL)"); 
     80             
     81            str.append("\n    "); 
     82            str.append("Input file: "); 
     83            str.append(getInputFile()); 
     84             
     85            str.append("\n    "); 
     86            str.append("Output file: "); 
     87            str.append(getOutputFile()); 
     88             
     89            return str.toString(); 
     90        } 
    3991    } 
    4092     
     
    4294     
    4395    private final BuildRequest req; 
     96    private Map<String, IObjectFile> cached =  
     97        new HashMap<String, IObjectFile>(); 
     98     
     99    // Since findModule() is called quite a bit, creating 
     100    // a new hash set every time sounds like a horrible thrashing of the GC. 
     101    // Instead, we'll just keep clearing out these set. They can't be static 
     102    // to maintain the threadsafe nature of the builder as a whole, however 
     103    private final Set<IJavaProject> visitedProjectAccumulator =  
     104        new HashSet<IJavaProject>(); 
    44105     
    45106    public ObjectFileFactory(BuildRequest req) 
     
    48109    } 
    49110     
    50     public IObjectFile create(ICompilationUnit cu, 
    51             boolean isLibraryFile) 
     111    public IObjectFile create(String moduleName) 
     112    { 
     113        // If there's a cached version, return that one 
     114        if(cached.containsKey(moduleName)) 
     115            return cached.get(moduleName); 
     116         
     117        // If we shouldn't be building it, return null 
     118        for(String ignored : req.getIgnoredModules()) 
     119            if(moduleName.startsWith(ignored)) 
     120                return null; 
     121         
     122        try 
     123        { 
     124            // Use a one-element array to get pointer semantics 
     125            boolean[] _isLibraryFile = new boolean[1]; 
     126            ICompilationUnit cu = findModule(moduleName, _isLibraryFile); 
     127            if(null == cu) 
     128                return null; 
     129            boolean isLibraryFile = _isLibraryFile[0]; 
     130            IObjectFile obj = getInstance(moduleName, cu, isLibraryFile); 
     131            cached.put(moduleName, obj); 
     132            return obj; 
     133        } 
     134        catch(JavaModelException e) 
     135        { 
     136            throw new BuildException(e); 
     137        } 
     138    } 
     139     
     140    private IObjectFile getInstance(String moduleName, 
     141            ICompilationUnit cu, boolean isLibraryFile) 
    52142    { 
    53143        File inputFile = new File(BuilderUtil.getAbsolutePath(cu.getResource(). 
     
    55145        File outputFile = new File(req.getOutputLocation().getAbsolutePath() + 
    56146                File.separator + getOutputFilename(cu)); 
    57         return new ObjectFile(inputFile, outputFile, isLibraryFile); 
    58     } 
     147        return new ObjectFile(moduleName, inputFile, outputFile, isLibraryFile); 
     148    } 
     149     
     150    private ICompilationUnit findModule(String moduleName, boolean[] isLibraryFile) 
     151        throws JavaModelException 
     152    { 
     153        visitedProjectAccumulator.clear(); 
     154        return findModuleInProject(req.getProject(), moduleName, isLibraryFile); 
     155    } 
     156     
     157    private ICompilationUnit findModuleInProject( 
     158            IJavaProject project, 
     159            String moduleName, 
     160            boolean[] isLibraryFile) 
     161        throws JavaModelException 
     162    { 
     163        if (visitedProjectAccumulator.contains(project)) 
     164            return null; 
     165         
     166        int index = moduleName.lastIndexOf('.'); 
     167        String packagePart = index > 0 ? moduleName.substring(0, index) : ""; 
     168        String modulePart = (index > 0 ? moduleName.substring(index + 1) :  
     169            moduleName) + ".d"; 
     170         
     171        ICompilationUnit module = null; 
     172        boolean libraryFile = false; 
     173        for(IPackageFragmentRoot root : project.getPackageFragmentRoots()) 
     174        { 
     175            IPackageFragment pkg = root.getPackageFragment(packagePart); 
     176            if (pkg.exists()) 
     177            { 
     178                // Check if it's in the package... 
     179                module = pkg.getCompilationUnit(modulePart); 
     180                 
     181                // If not, check if it's a class file 
     182                if (!module.exists()) 
     183                { 
     184                    module = pkg.getClassFile(modulePart); 
     185                    libraryFile = true; 
     186                } 
     187                 
     188                if(module.exists()) 
     189                { 
     190                    break; 
     191                } 
     192            } 
     193        } 
     194         
     195        if(null != module && module.exists()) 
     196        { 
     197            // Note: existance must be tested since an ICompilationUnit may 
     198            // be returned for non-existant modules 
     199            isLibraryFile[0] = libraryFile; 
     200            return module; 
     201        } 
     202         
     203        visitedProjectAccumulator.add(project); 
     204        IJavaModel javaModel= project.getJavaModel(); 
     205        String[] requiredProjectNames= project.getRequiredProjectNames(); 
     206        for (int i= 0; i < requiredProjectNames.length; i++) 
     207        { 
     208            IJavaProject requiredProject= javaModel.getJavaProject(requiredProjectNames[i]); 
     209            if (requiredProject.exists()) 
     210            { 
     211                module = findModuleInProject(requiredProject, moduleName, isLibraryFile); 
     212                if (module != null) 
     213                    return module; 
     214            } 
     215        } 
     216        return null; 
     217    } 
    59218     
    60219    private static String getOutputFilename(ICompilationUnit cu) 
    61220    { 
    62         String name = cu.getFullyQualifiedName().replace('.', '-') + "." + 
     221        String name = cu.getFullyQualifiedName().replace('.', '-') +  
    63222            BuilderUtil.EXTENSION_OBJECT_FILE; 
    64223        int len = name.length();