/** * Copyright (C) 2009 STMicroelectronics * * This file is part of "Mind Compiler" is free software: you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact: mind@ow2.org * * Authors: Matthieu Leclercq * Contributors: Julien Tous */ package org.ow2.mind.adl; import static org.ow2.mind.PathHelper.fullyQualifiedNameToPath; import static org.ow2.mind.PathHelper.replaceExtension; import static org.ow2.mind.adl.CompilationDecorationHelper.getAdditionalCompilationUnit; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import org.objectweb.fractal.adl.ADLException; import org.objectweb.fractal.adl.CompilerError; import org.objectweb.fractal.adl.Definition; import org.objectweb.fractal.adl.error.GenericErrors; import org.ow2.mind.SourceFileWriter; import org.ow2.mind.adl.CompilationDecorationHelper.AdditionalCompilationUnitDecoration; import org.ow2.mind.adl.ast.ASTHelper; import org.ow2.mind.adl.ast.ImplementationContainer; import org.ow2.mind.adl.ast.Source; import org.ow2.mind.adl.compilation.CompilationCommandFactory; import org.ow2.mind.adl.implementation.ImplementationLocator; import org.ow2.mind.compilation.AssemblerCommand; import org.ow2.mind.compilation.CompilationCommand; import org.ow2.mind.compilation.CompilerCommand; import org.ow2.mind.compilation.PreprocessorCommand; import org.ow2.mind.io.IOErrors; import org.ow2.mind.io.OutputFileLocator; import org.ow2.mind.preproc.MPPCommand; import org.ow2.mind.st.BackendFormatRenderer; import com.google.inject.Inject; public class BasicDefinitionCompiler implements DefinitionCompiler { @Inject protected DefinitionSourceGenerator definitionSourceGeneratorItf; @Inject protected OutputFileLocator outputFileLocatorItf; @Inject protected ImplementationLocator implementationLocatorItf; @Inject protected CompilationCommandFactory compilationCommandFactory; // --------------------------------------------------------------------------- // Implementation of the Visitor interface // --------------------------------------------------------------------------- public Collection<CompilationCommand> visit(final Definition definition, final Map<Object, Object> context) throws ADLException { definitionSourceGeneratorItf.visit(definition, context); final Collection<CompilationCommand> result = new ArrayList<CompilationCommand>(); if (definition instanceof ImplementationContainer) visitImplementation(definition, (ImplementationContainer) definition, result, context); visitAdditionalCompilationUnits(definition, getAdditionalCompilationUnit(definition), result, context); return result; } // --------------------------------------------------------------------------- // Helper methods // --------------------------------------------------------------------------- protected void visitImplementation(final Definition definition, final ImplementationContainer container, final Collection<CompilationCommand> compilationTasks, final Map<Object, Object> context) throws ADLException { // we don't use the KeepSrcNameContextHelper here since it would need to // add a adl-backend -> mindc modules dependency, which is wrong. final Boolean keepSrcNameInCtx = (Boolean) context.get("keep-src-name"); final Boolean keepSrcName = (keepSrcNameInCtx != null) ? keepSrcNameInCtx : false; final Source[] sources = container.getSources(); for (int i = 0; i < sources.length; i++) { final Source src = sources[i]; // check if src path refer to an already compiled file if (ASTHelper.isPreCompiled(src)) { // src file is already compiled final File srcFile; final URL srcURL = implementationLocatorItf.findSource(src.getPath(), context); try { srcFile = new File(srcURL.toURI()); } catch (final URISyntaxException e) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, e); } compilationTasks.add(compilationCommandFactory .newFileProviderCompilerCommand(srcFile, context)); } else if (ASTHelper.isAssembly(src)) { // src file is an assembly file // default naming convention String implSuffix = "_impl" + i; final File srcFile; assert src.getPath() != null; final URL srcURL = implementationLocatorItf.findSource(src.getPath(), context); try { srcFile = new File(srcURL.toURI()); } catch (final URISyntaxException e) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, e); } if (keepSrcName) { // keep-source-name convention: override suffix final String srcName = srcFile.getName(); // replace all path separators by underscores and remove extension implSuffix = "_" + srcName.replace(File.separatorChar, '_').substring(0, srcFile.getName().lastIndexOf('.')); } final File objectFile = outputFileLocatorItf.getCCompiledOutputFile( fullyQualifiedNameToPath(definition.getName(), implSuffix, ".o"), context); final AssemblerCommand gccCommand = compilationCommandFactory .newAssemblerCommand(definition, src, srcFile, objectFile, context); compilationTasks.add(gccCommand); } else { // src file is a normal C file to be processed with MPP. // default naming convention, useful to keep for inlined C code String implSuffix = "_impl" + i; final File srcFile; String inlinedCCode = src.getCCode(); if (inlinedCCode != null) { // Implementation code is inlined in the ADL. Dump it in a file. srcFile = outputFileLocatorItf.getCSourceOutputFile( fullyQualifiedNameToPath(definition.getName(), implSuffix, ".c"), context); inlinedCCode = BackendFormatRenderer.sourceToLine(src) + "\n" + inlinedCCode + "\n"; try { SourceFileWriter.writeToFile(srcFile, inlinedCCode); } catch (final IOException e) { throw new CompilerError(IOErrors.WRITE_ERROR, e, srcFile.getAbsolutePath()); } } else { assert src.getPath() != null; final URL srcURL = implementationLocatorItf.findSource(src.getPath(), context); try { srcFile = new File(srcURL.toURI()); } catch (final URISyntaxException e) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, e); } if (keepSrcName) { // keep-source-name convention: override suffix final String srcName = srcFile.getName(); // replace all path separators by underscores and remove extension implSuffix = "_" + srcName.replace(File.separatorChar, '_').substring(0, srcFile.getName().lastIndexOf('.')); } } final File cppFile = outputFileLocatorItf .getCSourceTemporaryOutputFile( fullyQualifiedNameToPath(definition.getName(), implSuffix, ".i"), context); final File mppFile = outputFileLocatorItf .getCSourceTemporaryOutputFile( fullyQualifiedNameToPath(definition.getName(), implSuffix, ".mpp.c"), context); final File objectFile = outputFileLocatorItf.getCCompiledOutputFile( fullyQualifiedNameToPath(definition.getName(), implSuffix, ".o"), context); final File depFile = outputFileLocatorItf.getCCompiledOutputFile( fullyQualifiedNameToPath(definition.getName(), implSuffix, ".d"), context); final File headerFile; if (sources.length == 1) { headerFile = outputFileLocatorItf.getCSourceTemporaryOutputFile( ImplementationHeaderSourceGenerator .getImplHeaderFileName(definition), context); } else { headerFile = outputFileLocatorItf.getCSourceTemporaryOutputFile( ImplementationHeaderSourceGenerator.getImplHeaderFileName( definition, i), context); } final PreprocessorCommand cppCommand = compilationCommandFactory .newPreprocessorCommand(definition, src, srcFile, null, depFile, cppFile, context); final MPPCommand mppCommand = compilationCommandFactory.newMPPCommand( definition, src, cppFile, mppFile, headerFile, context); final CompilerCommand gccCommand = compilationCommandFactory .newCompilerCommand(definition, src, mppFile, true, null, null, objectFile, context); cppCommand.addIncludeFile(outputFileLocatorItf.getCSourceOutputFile( DefinitionIncSourceGenerator.getIncFileName(definition), context)); gccCommand.addIncludeFile(outputFileLocatorItf.getCSourceOutputFile( DefinitionMacroSourceGenerator.getMacroFileName(definition), context)); gccCommand.setAllDependenciesManaged(true); compilationTasks.add(cppCommand); compilationTasks.add(mppCommand); compilationTasks.add(gccCommand); } } } protected void visitAdditionalCompilationUnits( final Definition definition, final Collection<AdditionalCompilationUnitDecoration> additionalCompilationUnits, final Collection<CompilationCommand> compilationTasks, final Map<Object, Object> context) throws ADLException { for (final AdditionalCompilationUnitDecoration additionalCompilationUnit : additionalCompilationUnits) { final String path = additionalCompilationUnit.getPath(); final File cppFile = outputFileLocatorItf.getCSourceTemporaryOutputFile( replaceExtension(path, ".i"), context); final File mppFile = outputFileLocatorItf.getCSourceTemporaryOutputFile( replaceExtension(path, ".mpp.c"), context); final File objectFile = outputFileLocatorItf.getCCompiledOutputFile( replaceExtension(path, ".o"), context); final File depFile = outputFileLocatorItf.getCCompiledOutputFile( replaceExtension(path, ".d"), context); final File srcFile; if (additionalCompilationUnit.isGeneratedFile()) { srcFile = outputFileLocatorItf.getCSourceOutputFile( additionalCompilationUnit.getPath(), context); if (!srcFile.exists()) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, "Can't find source file \"" + additionalCompilationUnit + "\""); } } else { final URL srcURL = implementationLocatorItf.findSource( additionalCompilationUnit.getPath(), context); if (srcURL != null) { try { srcFile = new File(srcURL.toURI()); } catch (final URISyntaxException e) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, e); } } else { throw new ADLException(GenericErrors.INTERNAL_ERROR, "Can't find source file \"" + additionalCompilationUnit + "\""); } } if (additionalCompilationUnit.skipMPP()) { final PreprocessorCommand cppCommand = compilationCommandFactory .newPreprocessorCommand(definition, additionalCompilationUnit, srcFile, additionalCompilationUnit.getDependencies(), depFile, cppFile, context); final CompilerCommand gccCommand = compilationCommandFactory .newCompilerCommand(definition, additionalCompilationUnit, cppFile, true, null, null, objectFile, context); gccCommand.addIncludeFile(outputFileLocatorItf.getCSourceOutputFile( DefinitionMacroSourceGenerator.getMacroFileName(definition), context)); gccCommand.setAllDependenciesManaged(true); compilationTasks.add(cppCommand); compilationTasks.add(gccCommand); } else { final PreprocessorCommand cppCommand = compilationCommandFactory .newPreprocessorCommand(definition, additionalCompilationUnit, srcFile, additionalCompilationUnit.getDependencies(), depFile, cppFile, context); final MPPCommand mppCommand = compilationCommandFactory.newMPPCommand( definition, additionalCompilationUnit, cppFile, mppFile, null, context); final CompilerCommand gccCommand = compilationCommandFactory .newCompilerCommand(definition, additionalCompilationUnit, mppFile, true, null, null, objectFile, context); gccCommand.addIncludeFile(outputFileLocatorItf.getCSourceOutputFile( DefinitionMacroSourceGenerator.getMacroFileName(definition), context)); gccCommand.setAllDependenciesManaged(true); compilationTasks.add(cppCommand); compilationTasks.add(mppCommand); compilationTasks.add(gccCommand); } } } }