Addded Master Generator + CMakeGenerator + MiddlewareMasterGenerator

parents
# Java Maven CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
version: 2
general:
branches:
ignore:
- gh-pages
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/openjdk:8-jdk
cmd: ["/bin/bash"]
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
working_directory: ~/repo
environment:
# Customize the JVM maximum heap limit
- MAVEN_OPTS: -Xmx3200m
- ES_JAVA_OPTS=-Xms3200m -Xmx3200m
steps:
- checkout
# run tests!
- run: mvn -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B clean install --settings "settings.xml"
workflows:
version: 2
commit-workflow:
jobs:
- build
scheduled-workflow:
triggers:
- schedule:
cron: "30 1 * * *"
filters:
branches:
only: master
jobs:
- build
target
.project
.settings
.classpath
.idea
.git
*.iml
script:
- mvn -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B clean install cobertura:cobertura org.eluder.coveralls:coveralls-maven-plugin:report --settings "settings.xml"
after_success:
- if [ "${TRAVIS_BRANCH}" == "master" ]; then mvn -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B deploy --debug --settings "./settings.xml"; fi
# MasterGenerator
TODO
This diff is collapsed.
This diff is collapsed.
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class CMakeMasterGenerator extends MasterGenerator {
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver, String targetPath) throws IOException {
long notInSubfolders = getGeneratorImpls().stream()
.map(this::getImplSubfolder)
.filter(Objects::isNull)
.count();
if (notInSubfolders > 0) {
Log.error("All generators must have subfolders!");
return new ArrayList<>();
}
List<File> res = super.generate(componentInstanceSymbol, taggingResolver, targetPath);
res.add(generateCMake(targetPath));
return res;
}
private File generateCMake(String targetPath) throws IOException {
FileContent fileContent = new FileContent();
fileContent.setFileName("CMakeLists.txt");
StringBuilder content = new StringBuilder();
content.append("cmake_minimum_required(VERSION 3.5)\n");
//TODO setProjectName?
content.append("project (default)\n");
content.append("set (CMAKE_CXX_STANDARD 11)\n");
getGeneratorImpls().stream()
.map(this::getImplSubfolder)
.forEach(subfolder -> content.append("add_subdirectory(" + subfolder + ")\n"));
fileContent.setFileContent(content.toString());
return FileHelper.generateFile(targetPath, fileContent);
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.monticar.generator.roscpp.helper.NameHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class CPPImpl implements GeneratorImpl {
private String generationTargetPath;
private String cmakeTemplate =
"cmake_minimum_required(VERSION 3.5)\n" +
"project(<name> LANGUAGES CXX)\n" +
"add_library(<name> <name>.h)\n" +
"target_include_directories(<name> PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" +
"set_target_properties(<name> PROPERTIES LINKER_LANGUAGE CXX)\n" +
"export(TARGETS <name> FILE <name>.cmake)";
//TODO: make GeneratorCpp implement GeneratorImpl directly!
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
List<File> files = new ArrayList<>();
GeneratorCPP generatorCPP = new GeneratorCPP();
generatorCPP.setGenerationTargetPath(generationTargetPath);
generatorCPP.useArmadilloBackend();
files.add(generatorCPP.generateFile(generateCMake(componentInstanceSymbol)));
files.addAll(generatorCPP.generateFiles(componentInstanceSymbol, taggingResolver));
return files;
}
@Override
public void setGenerationTargetPath(String path) {
this.generationTargetPath = path;
}
private FileContent generateCMake(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
FileContent cmake = new FileContent();
cmake.setFileName("CMakeLists.txt");
String name = NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName());
cmake.setFileContent(cmakeTemplate.replace("<name>", name));
return cmake;
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.roscpp.helper.NameHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class DummyMiddlewareGenerator implements GeneratorImpl {
private String generationTargetPath;
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
List<File> res = new ArrayList<>();
res.add(FileHelper.generateFile(generationTargetPath, generateCMake(componentInstanceSymbol)));
res.add(FileHelper.generateFile(generationTargetPath, generateWrapper(componentInstanceSymbol)));
return res;
}
private String dummyWrapperTemplate = "#pragma once\n" +
"#include \"<name>.h\"\n" +
"#include <thread>\n" +
"#include <chrono>\n" +
"#include \"IAdapter.h\"\n" +
"\n" +
"class <name>_DummyWrapper: public IAdapter{\n" +
"\t<name>* component;\n" +
"\n" +
"public:\n" +
"\t<name>_DummyWrapper(){\n" +
"\n" +
"\t}\n" +
"\n" +
"\tvoid tick(){\n" +
"\t\tcout << \"Dummy publish data: component.out1 = \"<< component->out1 << endl;\n" +
"\t}\n" +
"\t\n" +
"\tvoid init(<name>* comp){\n" +
"\t\tthis->component = comp;\n" +
"\t\twhile(1){\n" +
" \t\t std::this_thread::sleep_for(std::chrono::seconds(1));\n" +
"\t\t component->in2 += 1000;\n" +
"\t\t}\n" +
"\t}\n" +
"\n" +
"\t\n" +
"};";
private FileContent generateWrapper(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
String name = NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName());
String content = dummyWrapperTemplate
.replace("<name>", name);
FileContent res = new FileContent();
res.setFileName(name + "_DummyWrapper.h");
res.setFileContent(content);
return res;
}
@Override
public void setGenerationTargetPath(String path) {
this.generationTargetPath = path;
}
private String cmakeTemplate =
"cmake_minimum_required(VERSION 3.5)\n" +
"project (<name>_DummyWrapper)\n" +
"\n" +
"add_library(<name>_DummyWrapper <name>_DummyWrapper.h)\n" +
"set_target_properties(<name>_DummyWrapper PROPERTIES LINKER_LANGUAGE CXX)\n" +
"target_link_libraries(<name>_DummyWrapper <name>)\n" +
"target_include_directories(<name>_DummyWrapper PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" +
"export(TARGETS <name>_DummyWrapper FILE <name>_DummyWrapper.cmake)";
private FileContent generateCMake(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
FileContent res = new FileContent();
String name = NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName());
String content = cmakeTemplate
.replace("<name>", name);
res.setFileName("CMakeLists.txt");
res.setFileContent(content);
return res;
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.monticar.generator.FileContent;
import de.se_rwth.commons.logging.Log;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class FileHelper {
public static File generateFile(String targetPath, FileContent fileContent) throws IOException {
File f = new File(targetPath + fileContent.getFileName());
Log.info(f.getName(), "FileCreation:");
if (!f.exists()) {
f.getParentFile().mkdirs();
if (!f.createNewFile()) {
Log.error("File could not be created");
}
}
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(f));
bufferedWriter.write(fileContent.getFileContent(), 0, fileContent.getFileContent().length());
bufferedWriter.close();
return f;
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public interface GeneratorImpl {
default List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
return new ArrayList<>();
}
default void setGenerationTargetPath(String path) {
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class MasterGenerator {
private Map<GeneratorImpl, String> generatorImpls = new HashMap<>();
public void add(GeneratorImpl generator, String subfolder) {
generatorImpls.put(generator, subfolder);
}
public Set<GeneratorImpl> getGeneratorImpls() {
return generatorImpls.keySet();
}
public String getImplSubfolder(GeneratorImpl generator) {
return generatorImpls.get(generator);
}
public boolean remove(GeneratorImpl generator) {
return generatorImpls.remove(generator) != null;
}
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver, String targetPath) throws IOException {
List<File> result = new ArrayList<>();
generatorImpls.entrySet()
.forEach(entrySet -> {
String fullTargetPath = targetPath;
if (!fullTargetPath.endsWith("/"))
fullTargetPath = fullTargetPath + "/";
if (entrySet.getValue() != null)
fullTargetPath = fullTargetPath + entrySet.getValue();
if (!fullTargetPath.endsWith("/"))
fullTargetPath = fullTargetPath + "/";
entrySet.getKey().setGenerationTargetPath(fullTargetPath);
try {
result.addAll(entrySet.getKey().generate(componentInstanceSymbol, taggingResolver));
} catch (IOException e) {
Log.error("IOException occurred!", e);
}
});
return result;
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.roscpp.helper.NameHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
public class MiddlewareMasterGenerator extends CMakeMasterGenerator {
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver, String targetPath) throws IOException {
//Add dummy GeneratorImpl for the subdir
// String subdir = "Coordinator_"+NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName()) +"/";
String subdir = "coordinator/";
this.add(new GeneratorImpl() {
}, subdir);
List<File> files = super.generate(componentInstanceSymbol, taggingResolver, targetPath);
files.add(FileHelper.generateFile(targetPath + subdir, generateIAdapter(componentInstanceSymbol)));
files.add(FileHelper.generateFile(targetPath + subdir, generateCoordinator(componentInstanceSymbol, files)));
files.add(FileHelper.generateFile(targetPath + subdir, generateCMakeList(componentInstanceSymbol, files)));
return files;
}
private FileContent generateIAdapter(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
FileContent res = new FileContent();
res.setFileName("IAdapter.h");
String name = NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName());
String iAdapterTemplate = "#pragma once\n" +
"#include \"<name>.h\"\n" +
"\n" +
"class IAdapter{\n" +
"\tpublic:\n" +
"\t\tvirtual ~IAdapter(){}\n" +
"\t\tvirtual void init(<name>* comp) = 0;\n" +
"\t\tvirtual void tick() = 0;\n" +
"};";
res.setFileContent(iAdapterTemplate.replace("<name>", name));
return res;
}
private String coordinatorTemplate =
"#include <iostream>\n" +
"#include <thread>\n" +
"#include <chrono>\n" +
"#include <atomic>\n" +
"#include <list>\n" +
"#include \"IAdapter.h\"\n" +
"\n" +
"<includes>" +
"\n" +
"using namespace std;\n" +
"using namespace chrono;\n" +
"\n" +
"void startMiddleware(IAdapter& adapter,<name>& comp,atomic<bool>& done){\n" +
" adapter.init(&comp);\n" +
" done = true;\n" +
"}\n" +
"\n" +
"int main() \n" +
"{\n" +
" atomic<bool> done(false);\n" +
" <name> comp;\n" +
" comp.init();\n" +
"\n" +
" list<IAdapter*> adapters;\n" +
"<addAdapters>" +
"\n" +
" list<thread*> threads;\n" +
" for(auto a : adapters){\n" +
" threads.push_back(new thread(startMiddleware,ref(*a),ref(comp),ref(done)));\n" +
" }\n" +
"\n" +
" cout << \"waiting for all middleware to start\\n\";\n" +
" this_thread::sleep_for(seconds(3));\n" +
" cout << \"started!\\n\";\n" +
"\n" +
" int exeMs = 100;\n" +
" time_point<system_clock> start, end;\n" +
" while(!done){\n" +
" start = system_clock::now();\n" +
"\n" +
" comp.execute();\n" +
" for(auto a : adapters){\n" +
" (*a).tick();\n" +
" }\n" +
"\n" +
" end = system_clock::now();\n" +
" int elapsedMs = duration_cast<milliseconds>(end-start).count();\n" +
" int newSleep = exeMs - elapsedMs;\n" +
" if(newSleep <= 0){\n" +
" cout << \"Cant keep up! \"<< (-newSleep) <<\"ms late!\\n\";\n" +
" }else{\n" +
" this_thread::sleep_for(milliseconds(newSleep));\n" +
" }\n" +
" }\n" +
"\n" +
" return 0;\n" +
"}";
private FileContent generateCoordinator(ExpandedComponentInstanceSymbol componentInstanceSymbol, List<File> files) {
String name = NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName());
List<String> filesNames = files.stream()
.map(File::getName)
.collect(Collectors.toList());
//TODO: DIRTY HACK!
String includes = filesNames.stream()
.filter(fn -> fn.matches(name + "\\w*\\.h"))
.map(fn -> "#include \"" + fn + "\"")
.collect(Collectors.joining("\n"));
//TODO: DIRTY HACK!
String addAdapters = filesNames.stream()
.filter(fn -> fn.matches(name + "\\w*Wrapper\\.h"))
.map(fn -> fn.substring(0, fn.length() - 2))
.map(fn -> " adapters.push_back(new " + fn + "());")
.collect(Collectors.joining("\n"));
String content = coordinatorTemplate
.replace("<name>", name)
.replace("<includes>", includes)
.replace("<addAdapters>", addAdapters);
FileContent res = new FileContent();
res.setFileName("Coordinator_" + name + ".cpp");
res.setFileContent(content);
return res;
}
private String cmakeListsTemplate =
"cmake_minimum_required(VERSION 3.5)\n" +
"project (Coordinator_<name> CXX)\n" +
"\n" +
"set (CMAKE_CXX_STANDARD 11)\n" +
"\n" +
"add_executable(Coordinator_<name> Coordinator_<name>.cpp)\n" +
"set_target_properties(Coordinator_<name> PROPERTIES LINKER_LANGUAGE CXX)\n" +
"target_link_libraries(Coordinator_<name> <targets>)\n" +
"target_include_directories(Coordinator_<name> PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})\n" +
"\n" +
"export(TARGETS Coordinator_<name> FILE Coordinator_<name>.cmake)";
private FileContent generateCMakeList(ExpandedComponentInstanceSymbol componentInstanceSymbol, List<File> files) {
FileContent res = new FileContent();
String name = NameHelper.getComponentNameTargetLanguage(componentInstanceSymbol.getFullName());
String targets = files.stream()
.map(File::getName)
.filter(fn -> fn.matches(name + "\\w*\\.h"))
.map(fn -> fn.substring(0, fn.length() - 2))
.collect(Collectors.joining(" "));
String content = cmakeListsTemplate
.replace("<targets>", targets)
.replace("<name>", name);
res.setFileName("CMakeLists.txt");
res.setFileContent(content);
return res;
}
}
package de.monticore.lang.monticar.generator.master;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.roscpp.GeneratorRosCpp;
import de.monticore.lang.monticar.generator.roscpp.helper.TagHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class RosCppImpl implements GeneratorImpl {
private String generationTargetPath;
@Override
public List<File> generate(ExpandedComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
GeneratorRosCpp generatorRosCpp = new GeneratorRosCpp();
generatorRosCpp.setGenerateCpp(false);
generatorRosCpp.setGenerateCMake(true);
generatorRosCpp.setGenerationTargetPath(generationTargetPath);
return TagHelper.generate(generatorRosCpp, taggingResolver, componentInstanceSymbol);
}
@Override
public void setGenerationTargetPath(String path) {
this.generationTargetPath = path;
}
}
package de.monticore.lang.monticar.generator.master;
/*
* Copyright (c) 2015 RWTH Aachen. All rights reserved.
*
* http://www.se-rwth.de/
*/
import de.monticore.lang.monticar.generator.order.simulator.AbstractSymtab;
import org.junit.Assert;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.Assert.assertTrue;
/**
* Common methods for symboltable tests
*/
public class AbstractSymtabTest extends AbstractSymtab {
public static void testFilesAreEqual(List<File> files, String restPath) {
assertTrue(files.size() > 0);
for (File f : files) {
File fileTarget = new File("./src/test/resources/results/" + restPath + f.getName());
// System.out.println("" + fileTarget.exists() + "Exists:");
// System.out.println(f.getName() + " " + fileTarget.getName() + "Comparing:");
assertTrue(areBothFilesEqual(f, fileTarget));
}
}
public static void testFilesAreEqual(List<File> files, String relResultPath, String basePath) {
String resultPath = "src/test/resources/results/";
for (File f : files) {
File tmpFile = new File(basePath);
String relativePath = f.getAbsolutePath().replace(tmpFile.getAbsolutePath(), "");
File fileTarget = new File(resultPath + relResultPath + relativePath);
assertTrue(areBothFilesEqual(f, fileTarget));
}
}
public static boolean areBothFilesEqual(File file1, File file2) {
if (!file1.exists()) {
Assert.fail("file does not exist: " + file1.getAbsolutePath());
return false;
}
if (!file2.exists()) {
Assert.fail("file does not exist: " + file2.getAbsolutePath());
return false;
}