Aufgrund einer Wartung wird GitLab am 04.06. zwischen 8:00 und 10:00 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to maintenance, GitLab will be temporarily unavailable on 04.06. between 8:00 and 10:00 am.

Commit 70315ca1 authored by Evgeny Kusmenko's avatar Evgeny Kusmenko

Merge branch 'CompileScripts' into 'master'

Compile scripts

See merge request !28
parents 6138102d be94088f
Pipeline #106159 passed with stages
in 11 minutes and 7 seconds
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<groupId>de.monticore.lang.monticar</groupId> <groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-middleware-generator</artifactId> <artifactId>embedded-montiarc-math-middleware-generator</artifactId>
<version>0.0.15-SNAPSHOT</version> <version>0.0.16-SNAPSHOT</version>
<!-- == PROJECT DEPENDENCIES ============================================= --> <!-- == PROJECT DEPENDENCIES ============================================= -->
......
...@@ -2,11 +2,13 @@ package de.monticore.lang.monticar.generator.middleware; ...@@ -2,11 +2,13 @@ package de.monticore.lang.monticar.generator.middleware;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.FileContent; 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.helpers.*;
import de.monticore.lang.monticar.generator.middleware.impls.GeneratorImpl; 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.RclCppGenImpl;
import de.monticore.lang.monticar.generator.middleware.impls.RosCppGenImpl;
import de.monticore.lang.tagging._symboltable.TaggingResolver; 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.File;
import java.io.IOException; import java.io.IOException;
...@@ -21,7 +23,14 @@ public class DistributedTargetGenerator extends CMakeGenerator { ...@@ -21,7 +23,14 @@ public class DistributedTargetGenerator extends CMakeGenerator {
@Override @Override
public void setGenerationTargetPath(String path) { 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 @Override
...@@ -50,12 +59,13 @@ public class DistributedTargetGenerator extends CMakeGenerator { ...@@ -50,12 +59,13 @@ public class DistributedTargetGenerator extends CMakeGenerator {
} }
files.add(generateCMake(componentInstanceSymbol)); files.add(generateCMake(componentInstanceSymbol));
files.addAll(generateCompileScripts());
return files; return files;
} }
private GeneratorImpl createFullGenerator(String subdir) { private GeneratorImpl createFullGenerator(String subdir) {
MiddlewareGenerator res = new MiddlewareGenerator(); 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))); this.getGeneratorImpls().forEach(gen -> res.add(gen, this.getImplSubdir(gen)));
...@@ -86,7 +96,32 @@ public class DistributedTargetGenerator extends CMakeGenerator { ...@@ -86,7 +96,32 @@ public class DistributedTargetGenerator extends CMakeGenerator {
fileContent.setFileContent(content.toString()); 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.addAll(FileHelper.generateFiles(generationTargetPath ,g.getCompilationScripts()));
} 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"+
"\texport PATH=\"$<new_exe>_HOME:$PATH\"\n" +
"fi";
private String CHECK_EXE_TEMPLATE = "if [[ `command -v <exe>` ]]\n" +
"then\n" +
"\techo \"Found <exe>\"\n" +
"else\n" +
"\techo \"Can not find <exe> in PATH! Aborting.\"\n" +
"<additional_error>" +
"\texit 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
protected String getPathTemplate() {
return PATH_TEMPLATE;
}
@Override
protected String getCheckExeTemplate() {
return CHECK_EXE_TEMPLATE;
}
@Override
protected String getSourceEnvVarsTemplate() {
return SOURCE_ENV_VARS_TEMPLATE;
}
@Override
protected String getScriptTemplate() {
return TemplateHelper.getCompilationBashTemplate().replace("\r\n", "\n");
}
@Override
protected List<String> getAdditionalPathDirs() {
setAdditionalErrorMsg("roscore", defaultErrorMsg("ROS"));
setAdditionalErrorMsg("ros2", defaultErrorMsg("ROS2"));
return Arrays.asList("cmake","make");
}
@Override
protected String getFileName() {
return "compile.sh";
}
@Override
protected String getNewlineDelimiter() {
return "\n";
}
@Override
protected List<String> getPostSourceExecutables() {
ArrayList<String> res = new ArrayList<>();
if(useRos()){
res.add("roscore");
}
if(useRos2()){
res.add("ros2");
}
return res;
}
@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.*;
import java.util.stream.Collectors;
public abstract class CompilationGenerator {
private boolean useRos = false;
private boolean useRos2 = false;
private Map<String, String> additionalErrorMsg = new HashMap<>();
public abstract boolean supportsRos();
public abstract boolean supportsRos2();
public boolean isValid() {
return (supportsRos() || !useRos()) && (supportsRos2() || !useRos2());
}
protected void setAdditionalErrorMsg(String executable, String errorMsg) {
additionalErrorMsg.put(executable, errorMsg);
}
protected String getAdditionalErrorMsg(String executable) {
String s = additionalErrorMsg.getOrDefault(executable, defaultErrorMsg(executable));
return "\techo \"" + s + "\"" + getNewlineDelimiter();
}
protected abstract String getPathTemplate();
protected abstract String getCheckExeTemplate();
protected abstract String getSourceEnvVarsTemplate();
protected abstract String getScriptTemplate();
protected 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)
.replace("<additional_error>", getAdditionalErrorMsg(exe));
}
protected String fillSourceEnvVarsTemplate(String envFile) {
return getSourceEnvVarsTemplate().replace("<env_file>", envFile);
}
protected String fillScriptTemplate(String additional_executables, String executable_checks, String additional_env, String post_executable_checks) {
return getScriptTemplate()
.replace("<additional_executables>", additional_executables)
.replace("<executable_checks>", executable_checks)
.replace("<additional_env>", additional_env)
.replace("<post_executable_checks>", post_executable_checks);
}
public List<FileContent> getCompilationScripts() {
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()));
String post_executable_checks = getPostSourceExecutables().stream()
.map(this::fillCheckExeTemplate)
.collect(Collectors.joining(getNewlineDelimiter()));
res.setFileName(getFileName());
res.setFileContent(fillScriptTemplate(additional_executables, executable_checks, additional_env, post_executable_checks));
return Arrays.asList(res);
}
protected abstract List<String> getPostSourceExecutables();
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;
}
protected String defaultErrorMsg(String executable) {
return "Try setting the environment variable " + executable + "_HOME to the base of your installation or adding it to your PATH!";
}
}
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
protected String getScriptTemplate() {
return TemplateHelper.getCompilationMingwTemplate();
}
@Override
protected List<String> getAdditionalPathDirs() {
return Arrays.asList("cmake","make","g++");
}
@Override
protected String getFileName() {
return "compileMingw.bat";
}
@Override
protected List<String> getPostSourceExecutables() {
return new ArrayList<>();
}
@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
protected String getScriptTemplate() {
return TemplateHelper.getCompilationMsbuildTemplate();
}
@Override
protected List<String> getAdditionalPathDirs() {
setAdditionalErrorMsg("vcvars64.bat", defaultErrorMsg("msbuild"));
setAdditionalErrorMsg("ros2", defaultErrorMsg("ROS2"));
return Arrays.asList("cmake","msbuild");
}
@Override
protected String getFileName() {
return "compileMsbuild.bat";
}
@Override
protected List<String> getPostSourceExecutables() {
List<String> res = new ArrayList<>();
res.add("msbuild");
if(useRos2()){
res.add("ros2");
}
return res;
}
@Override
protected List<String> getEnvironmentFiles() {
List<String> res = new ArrayList<>();
res.add("vcvars64.bat");
if(useRos2()){
res.add("%ROS2_HOME%\\local_setup.bat");
}
return res;
}
@Override
protected List<String> getExecutables() {
return Arrays.asList("cmake","vcvars64.bat");
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import java.util.ArrayList;
import java.util.List;
public abstract class WindowsCompilationGenerator extends CompilationGenerator {
private String PATH_TEMPLATE = "IF NOT [%<new_exe>_HOME%] == [] (\n" +
"\tset PATH=\"%<new_exe>_HOME%;%PATH%\"\n" +
")";
private String CHECK_EXE_TEMPLATE = "where <exe>\n" +
"IF NOT %ERRORLEVEL% EQU 0 (\n" +
"\techo \"Can not find <exe> in PATH! Aborting.\"\n" +
"<additional_error>" +
"\texit /B 1\n" +
")";
private String SOURCE_ENV_VARS_TEMPLATE = "call <env_file>";
@Override
protected String getPathTemplate() {
return PATH_TEMPLATE;
}
@Override
protected String getCheckExeTemplate() {
return CHECK_EXE_TEMPLATE;
}
@Override
protected String getSourceEnvVarsTemplate() {
return SOURCE_ENV_VARS_TEMPLATE;
}
@Override
protected String getNewlineDelimiter() {
return "\r\n";
}
@Override
public boolean supportsRos() {
return false;
}
private String fillSubstTemplate(String compileScript) {
return TemplateHelper.getSubstTemplate()
.replace("<compile_script>", compileScript);
}
@Override
public List<FileContent> getCompilationScripts() {
ArrayList<FileContent> fileContents = new ArrayList<>();
fileContents.addAll(super.getCompilationScripts());
FileContent substScript = new FileContent();
substScript.setFileName("subst" + getFileName().substring(0,1).toUpperCase() + getFileName().substring(1));
substScript.setFileContent(fillSubstTemplate(getFileName()));
fileContents.add(substScript);
return fileContents;
}
}
...@@ -7,6 +7,8 @@ import java.io.BufferedWriter; ...@@ -7,6 +7,8 @@ import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class FileHelper { public class FileHelper {
...@@ -24,4 +26,12 @@ public class FileHelper { ...@@ -24,4 +26,12 @@ public class FileHelper {
bufferedWriter.close(); bufferedWriter.close();
return f; return f;
} }
public static List<File> generateFiles(String targetPath, List<FileContent> fileContents) throws IOException {
ArrayList<File> files = new ArrayList<>();
for (FileContent fc : fileContents) {
files.add(generateFile(targetPath, fc));
}
return files;
}
} }
...@@ -48,4 +48,21 @@ public class TemplateHelper { ...@@ -48,4 +48,21 @@ public class TemplateHelper {
return getTemplate("coordinatorCmakeListsTemplate.ftl"); 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");
}
public static String getSubstTemplate(){
return getTemplate("subst.bat.template");
}
} }
#!/usr/bin/env bash
set -e
# add *_HOME to PATH temporarily
<additional_executables>
# check if needed programs are in PATH
<executable_checks>
# source additional environment variables
<additional_env>
# Post source check if needed programs are in PATH
<post_executable_checks>
# cmake
curDir=`dirname "$0"`
cmake -B"$curDir"/build/ -H"$curDir/src" "$@"
# make
make -j4 -C "$curDir/build"
\ No newline at end of file
@ECHO Off
:: add *_HOME to PATH temporarily
<additional_executables>
:: check if needed programs are in PATH
<executable_checks>
:: source additional environment variables
<additional_env>
:: Post source check if needed programs are in PATH
<post_executable_checks>
:: cmake
cmake -B./build/ -G "MinGW Makefiles" %* ./src
:: make
cd .\build
make -j4
cd ..
\ No newline at end of file
@ECHO Off
:: add *_HOME to PATH temporarily
<additional_executables>
:: check if needed programs are in PATH
<executable_checks>
:: source additional environment variables
<additional_env>
:: Post source check if needed programs are in PATH
<post_executable_checks>
:: cmake
cmake -B./build/ -G "Visual Studio 15 2017 Win64" %* ./src
:: msbuild
cd .\build
msbuild /m /t:build /p:Configuration=Release ALL_BUILD.vcxproj
cd ..
\ No newline at end of file
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project (Coordinator_${compName} CXX) project (Coordinator_${compName} LANGUAGES CXX)
set (CMAKE_CXX_STANDARD 14) set (CMAKE_CXX_STANDARD 14)
set (THREADS_PREFER_PTHREAD_FLAG ON) set (THREADS_PREFER_PTHREAD_FLAG ON)
......
:: Substituting the current dir with a drive letter to bypass windows path length limit
:: Set environment variable EMA_SUBST_LETTER to change letter is used
:: Default is N