Added generation of compile scripts

parent 6138102d
Pipeline #106013 passed with stages
in 8 minutes and 51 seconds
......@@ -9,7 +9,7 @@
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-middleware-generator</artifactId>
<version>0.0.15-SNAPSHOT</version>
<version>0.0.16-SNAPSHOT</version>
<!-- == PROJECT DEPENDENCIES ============================================= -->
......
......@@ -2,11 +2,13 @@ package de.monticore.lang.monticar.generator.middleware;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.middleware.compile.CompilationGenerator;
import de.monticore.lang.monticar.generator.middleware.helpers.*;
import de.monticore.lang.monticar.generator.middleware.impls.GeneratorImpl;
import de.monticore.lang.monticar.generator.middleware.impls.RclCppGenImpl;
import de.monticore.lang.monticar.generator.middleware.impls.RosCppGenImpl;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import org.apache.commons.io.FileUtils;
import de.se_rwth.commons.logging.Log;
import java.io.File;
import java.io.IOException;
......@@ -21,7 +23,14 @@ public class DistributedTargetGenerator extends CMakeGenerator {
@Override
public void setGenerationTargetPath(String path) {
super.setGenerationTargetPath(path);
String res = path;
if(res.endsWith("/") || res.endsWith("\\")){
res = res.substring(0,res.length() - 1);
}
if(res.endsWith("/src") || res.endsWith("\\src")){
res = res.substring(0, res.length() - 4);
}
super.setGenerationTargetPath(res);
}
@Override
......@@ -50,12 +59,13 @@ public class DistributedTargetGenerator extends CMakeGenerator {
}
files.add(generateCMake(componentInstanceSymbol));
files.addAll(generateCompileScripts());
return files;
}
private GeneratorImpl createFullGenerator(String subdir) {
MiddlewareGenerator res = new MiddlewareGenerator();
res.setGenerationTargetPath(generationTargetPath + (subdir.endsWith("/") ? subdir : subdir + "/"));
res.setGenerationTargetPath(generationTargetPath + "src/" + (subdir.endsWith("/") ? subdir : subdir + "/"));
this.getGeneratorImpls().forEach(gen -> res.add(gen, this.getImplSubdir(gen)));
......@@ -86,7 +96,32 @@ public class DistributedTargetGenerator extends CMakeGenerator {
fileContent.setFileContent(content.toString());
return FileHelper.generateFile(generationTargetPath, fileContent);
return FileHelper.generateFile(generationTargetPath + "src/", fileContent);
}
protected List<File> generateCompileScripts(){
List<File> res = new ArrayList<>();
boolean useRos = this.getGeneratorImpls().stream().anyMatch(impl -> impl instanceof RosCppGenImpl);
boolean useRos2 = this.getGeneratorImpls().stream().anyMatch(impl -> impl instanceof RclCppGenImpl);
List<CompilationGenerator> generators = CompilationGenerator.getInstanceOfAllGenerators();
generators.forEach(g -> g.setUseRos(useRos));
generators.forEach(g -> g.setUseRos2(useRos2));
generators.stream()
.peek(g -> g.setUseRos(useRos))
.peek(g -> g.setUseRos2(useRos2))
.filter(CompilationGenerator::isValid)
.forEach(g -> {
try {
res.add(FileHelper.generateFile(generationTargetPath ,g.getCompilationScript()));
} catch (IOException e) {
Log.error("0xD4BAA: Error generating compile scripts!", e);
}
});
return res;
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BashCompilationGenerator extends CompilationGenerator {
private String PATH_TEMPLATE = "if [ -n \"$<new_exe>_HOME\" ]\n" +
"then\n"+
" export PATH=\"$<new_exe>_HOME:$PATH\"\n"+
"fi";
private String CHECK_EXE_TEMPLATE = "if [[ `command -v <exe>` ]]\n" +
"then\n" +
" echo \"Found <exe>\"\n" +
"else\n" +
" echo \"Can not find <exe> in PATH! Aborting.\"\n" +
" exit 1\n" +
"fi";
private String SOURCE_ENV_VARS_TEMPLATE = "source <env_file>";
@Override
public boolean supportsRos() {
return true;
}
@Override
public boolean supportsRos2() {
return true;
}
@Override
public String getPathTemplate() {
return PATH_TEMPLATE;
}
@Override
public String getCheckExeTemplate() {
return CHECK_EXE_TEMPLATE;
}
@Override
public String getSourceEnvVarsTemplate() {
return SOURCE_ENV_VARS_TEMPLATE;
}
@Override
public String getScriptTemplate() {
return TemplateHelper.getCompilationBashTemplate();
}
@Override
public List<String> getAdditionalPathDirs() {
return Arrays.asList("cmake","make");
}
@Override
protected String getFileName() {
return "compile.sh";
}
@Override
protected String getNewlineDelimiter() {
return "\n";
}
@Override
protected List<String> getEnvironmentFiles() {
List<String> res = new ArrayList<>();
if(useRos()){
res.add("\"$ROS_HOME\"/setup.bash");
}
if(useRos2()){
res.add("\"$ROS2_HOME\"/setup.bash");
}
return res;
}
@Override
protected List<String> getExecutables() {
return Arrays.asList("cmake","make");
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
import de.monticore.lang.monticar.generator.FileContent;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class CompilationGenerator {
private boolean useRos = false;
private boolean useRos2 = false;
public abstract boolean supportsRos();
public abstract boolean supportsRos2();
public boolean isValid(){
return (supportsRos() || !useRos()) && (supportsRos2() || !useRos2());
}
public abstract String getPathTemplate();
public abstract String getCheckExeTemplate();
public abstract String getSourceEnvVarsTemplate();
public abstract String getScriptTemplate();
public abstract List<String> getAdditionalPathDirs();
protected abstract String getFileName();
protected abstract String getNewlineDelimiter();
public boolean useRos() {
return useRos;
}
public void setUseRos(boolean useRos) {
this.useRos = useRos;
}
public boolean useRos2() {
return useRos2;
}
public void setUseRos2(boolean useRos2) {
this.useRos2 = useRos2;
}
protected String fillPathTemplate(String newExe){
return getPathTemplate().replace("<new_exe>",newExe);
}
protected String fillCheckExeTemplate(String exe){
return getCheckExeTemplate().replace("<exe>",exe);
}
protected String fillSourceEnvVarsTemplate(String envFile){
return getSourceEnvVarsTemplate().replace("<env_file>",envFile);
}
protected String fillScriptTemplate(String additional_executables, String executable_checks, String additional_env){
return getScriptTemplate()
.replace("<additional_executables>",additional_executables)
.replace("<executable_checks>",executable_checks)
.replace("<additional_env>",additional_env);
}
public FileContent getCompilationScript(){
FileContent res = new FileContent();
String additional_executables = getAdditionalPathDirs().stream()
.map(this::fillPathTemplate)
.collect(Collectors.joining(getNewlineDelimiter()));
String executable_checks = getExecutables().stream()
.map(this::fillCheckExeTemplate)
.collect(Collectors.joining(getNewlineDelimiter()));
String additional_env = getEnvironmentFiles().stream()
.map(this::fillSourceEnvVarsTemplate)
.collect(Collectors.joining(getNewlineDelimiter()));
res.setFileName(getFileName());
res.setFileContent(fillScriptTemplate(additional_executables,executable_checks,additional_env));
return res;
}
protected abstract List<String> getEnvironmentFiles();
protected abstract List<String> getExecutables();
public static List<CompilationGenerator> getInstanceOfAllGenerators(){
List<CompilationGenerator> res = new ArrayList<>();
res.add(new BashCompilationGenerator());
res.add(new MingwCompilationGenerator());
res.add(new MsbuildCompilationGenerator());
return res;
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MingwCompilationGenerator extends WindowsCompilationGenerator {
@Override
public boolean supportsRos2() {
return false;
}
@Override
public String getScriptTemplate() {
return TemplateHelper.getCompilationMingwTemplate();
}
@Override
public List<String> getAdditionalPathDirs() {
return Arrays.asList("cmake","make","g++");
}
@Override
protected String getFileName() {
return "compileMingw.bat";
}
@Override
protected List<String> getEnvironmentFiles() {
return new ArrayList<>();
}
@Override
protected List<String> getExecutables() {
return Arrays.asList("cmake","make","g++");
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MsbuildCompilationGenerator extends WindowsCompilationGenerator {
@Override
public boolean supportsRos2() {
return true;
}
@Override
public String getScriptTemplate() {
return TemplateHelper.getCompilationMsbuildTemplate();
}
@Override
public List<String> getAdditionalPathDirs() {
return Arrays.asList("cmake","msbuild");
}
@Override
protected String getFileName() {
return "compileMsbuild.bat";
}
@Override
protected List<String> getEnvironmentFiles() {
List<String> res = new ArrayList<>();
res.add("vcvars64.bat");
if(useRos2()){
res.add("%ROS_HOME%\\local_setup.bat");
}
return res;
}
@Override
protected List<String> getExecutables() {
return Arrays.asList("cmake","vcvars64.bat","msbuild");
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
public abstract class WindowsCompilationGenerator extends CompilationGenerator {
private String PATH_TEMPLATE = "IF NOT [%<new_exe>_HOME%] == [] (\n" +
" set PATH=\"%<new_exe>_HOME%;%PATH%\"\n" +
")";
private String CHECK_EXE_TEMPLATE = "where <exe>\n" +
"IF NOT %ERRORLEVEL% EQU 0 (\n" +
" echo \"Can not find <exe> in PATH! Aborting.\"\n" +
" exit /B 1\n" +
")";
private String SOURCE_ENV_VARS_TEMPLATE = "call <env_file>";
@Override
public String getPathTemplate() {
return PATH_TEMPLATE;
}
@Override
public String getCheckExeTemplate() {
return CHECK_EXE_TEMPLATE;
}
@Override
public String getSourceEnvVarsTemplate() {
return SOURCE_ENV_VARS_TEMPLATE;
}
@Override
protected String getNewlineDelimiter() {
return "\r\n";
}
@Override
public boolean supportsRos() {
return false;
}
}
......@@ -48,4 +48,17 @@ public class TemplateHelper {
return getTemplate("coordinatorCmakeListsTemplate.ftl");
}
public static String getCompilationBashTemplate(){
return getTemplate("compile.sh.template");
}
public static String getCompilationMingwTemplate(){
return getTemplate("compileMingw.bat.template");
}
public static String getCompilationMsbuildTemplate(){
return getTemplate("compileMsbuild.bat.template");
}
}
#!/usr/bin/env bash
set -e
# add *_HOME to PATH temporarily
<additional_executables>
# source additional environment variables
<additional_env>
# check if needed programs are in PATH
<executable_checks>
# cmake
curDir=`dirname "$0"`
cmake -B"$curDir"/build/ -H"$curDir/src" "$@"
# make
make -C "$curDir"
\ No newline at end of file
@ECHO Off
:: add *_HOME to PATH temporarily
<additional_executables>
:: source additional environment variables
<additional_env>
:: check if needed programs are in PATH
<executable_checks>
:: cmake
cmake -B./build/ -G "MinGW Makefiles" %* ./src
:: make
cd .\build
make
cd ..
\ No newline at end of file
@ECHO Off
:: add *_HOME to PATH temporarily
<additional_executables>
:: source additional environment variables
<additional_env>
:: check if needed programs are in PATH
<executable_checks>
:: cmake
cmake -B./build/ -G "Visual Studio 15 2017 Win64" %* ./src
:: msbuild
cd .\build
msbuild /t:build /p:Configuration=Release ALL_BUILD.vcxproj
cd ..
\ No newline at end of file
......@@ -120,7 +120,7 @@ public class CliTest {
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......@@ -139,7 +139,7 @@ public class CliTest {
String[] positiveFileNames = getEMADLGeneratedFilesList(false);
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......@@ -157,7 +157,7 @@ public class CliTest {
String[] positiveFileNames = getEMADLGeneratedFilesList(true);
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......@@ -169,7 +169,7 @@ public class CliTest {
String[] positiveFileNames = getEMADLGeneratedFilesList(true);
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......@@ -223,7 +223,7 @@ public class CliTest {
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get("target/cliTest/validConfigFile/" + positiveFileName)));
assertTrue(Files.exists(Paths.get("target/cliTest/validConfigFile/src/" + positiveFileName)));
}
}
......@@ -249,7 +249,7 @@ public class CliTest {
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......@@ -309,7 +309,7 @@ public class CliTest {
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......@@ -335,7 +335,7 @@ public class CliTest {
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
assertTrue(Files.exists(Paths.get(targetDir + "src/" + positiveFileName)));
}
}
......
package de.monticore.lang.monticar.generator.middleware.compile;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.middleware.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.middleware.helpers.FileHelper;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import static org.junit.Assert.*;
public class CompilationGeneratorTest extends AbstractSymtabTest {
private static String OUT_BASE = "target/compileScripts/";
@Test
public void testBashWithRos() throws IOException {
BashCompilationGenerator bashCompilationGenerator = new BashCompilationGenerator();
bashCompilationGenerator.setUseRos(true);
FileContent script = bashCompilationGenerator.getCompilationScript();
assertEquals("compile.sh", script.getFileName());
File f1 = FileHelper.generateFile(OUT_BASE + "Ros/", script);
testFilesAreEqual(Arrays.asList(f1), "compileScripts/Ros/");
}
@Test
public void testNoRos() throws IOException {
BashCompilationGenerator bashCompilationGenerator = new BashCompilationGenerator();
FileContent script1 = bashCompilationGenerator.getCompilationScript();
assertEquals("compile.sh", script1.getFileName());
File f1 = FileHelper.generateFile(OUT_BASE + "NoRos/", script1);
MingwCompilationGenerator mingwCompilationGenerator = new MingwCompilationGenerator();
FileContent script2 = mingwCompilationGenerator.getCompilationScript();
assertEquals("compileMingw.bat", script2.getFileName());
File f2 = FileHelper.generateFile(OUT_BASE + "NoRos/", script2);
MsbuildCompilationGenerator msbuildCompilationGenerator = new MsbuildCompilationGenerator();
FileContent script3 = msbuildCompilationGenerator.getCompilationScript();
assertEquals("compileMsbuild.bat", script3.getFileName());
File f3 = FileHelper.generateFile(OUT_BASE + "NoRos/", script3);
testFilesAreEqual(Arrays.asList(f1, f2, f3), "compileScripts/NoRos/");
}
@Test
public void testRos2() throws IOException {
BashCompilationGenerator bashCompilationGenerator = new BashCompilationGenerator();
bashCompilationGenerator.setUseRos2(true);
FileContent script1 = bashCompilationGenerator.getCompilationScript();
assertEquals("compile.sh", script1.getFileName());
File f1 = FileHelper.generateFile(OUT_BASE + "Ros2/", script1);
MsbuildCompilationGenerator msbuildCompilationGenerator = new MsbuildCompilationGenerator();
msbuildCompilationGenerator.setUseRos2(true);
FileContent script3 = msbuildCompilationGenerator.getCompilationScript();
assertEquals("compileMsbuild.bat", script3.getFileName());
File f2 = FileHelper.generateFile(OUT_BASE + "Ros2/", script3);
testFilesAreEqual(Arrays.asList(f1, f2), "compileScripts/Ros2/");
}
}
\ No newline at end of file