Move compile script generation to ftl

parent a66fab83
......@@ -15,7 +15,7 @@ public class TemplateHelper {
}
String tmpStr = "";
String resourceFileName = "/de/monticore/lang/monticar/generator/middleware/" + fileName;
String resourceFileName = "/de/monticore/lang/monticar/generator/middleware/templates/" + fileName;
try {
tmpStr = IOUtils.toString(TemplateHelper.class.getResourceAsStream(resourceFileName));
......@@ -48,21 +48,4 @@ 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");
}
public static String getSubstTemplate(){
return getTemplate("subst.bat.template");
}
}
package de.monticore.lang.monticar.generator.middleware.templates;
import de.monticore.lang.monticar.generator.middleware.templates.compile.BashCompilationGenerator;
import de.monticore.lang.monticar.generator.middleware.templates.compile.MingwCompilationGenerator;
import de.monticore.lang.monticar.generator.middleware.templates.compile.MsbuildCompilationGenerator;
import de.monticore.lang.monticar.generator.middleware.templates.compile.WindowsCompilationGenerator;
import de.se_rwth.commons.logging.Log;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
public class MiddlewareTemplates {
private static final Template COMPILE_BATCH;
private static final Template COMPILE_BASH;
private static final Template COMPILE_SUBST;
static {
Configuration conf = new Configuration(Configuration.VERSION_2_3_23);
conf.setDefaultEncoding("UTF-8");
conf.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
conf.setLogTemplateExceptions(false);
conf.setClassForTemplateLoading(MiddlewareTemplates.class, "");
try {
COMPILE_BATCH = conf.getTemplate("compile.bat.ftl");
COMPILE_BASH = conf.getTemplate("compile.sh.ftl");
COMPILE_SUBST = conf.getTemplate("subst.bat.ftl");
} catch (IOException e) {
String msg = "could not load templates";
Log.error(msg, e);
throw new RuntimeException(msg, e);
}
}
public static String generateCompileMsbuild(MsbuildCompilationGenerator model) {
HashMap<String, Object> data = new HashMap<>();
data.put("model", model);
return generate(COMPILE_BATCH, data);
}
public static String generateCompileMingw(MingwCompilationGenerator model) {
HashMap<String, Object> data = new HashMap<>();
data.put("model", model);
return generate(COMPILE_BATCH, data);
}
public static String generateCompileBash(BashCompilationGenerator model) {
HashMap<String, Object> data = new HashMap<>();
data.put("model", model);
return generate(COMPILE_BASH, data);
}
public static String generateCompileSubst(WindowsCompilationGenerator model) {
HashMap<String, Object> data = new HashMap<>();
data.put("model", model);
return generate(COMPILE_SUBST, data);
}
private static String generate(Template template, Object dataForTemplate) {
Log.errorIfNull(template);
Log.errorIfNull(dataForTemplate);
StringWriter sw = new StringWriter();
try {
template.process(dataForTemplate, sw);
} catch (TemplateException | IOException e) {
Log.error("template generation failed, template: " + template.getName(), e);
}
return sw.toString();
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
package de.monticore.lang.monticar.generator.middleware.templates.compile;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import de.monticore.lang.monticar.generator.middleware.templates.MiddlewareTemplates;
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 String getContent() {
return MiddlewareTemplates.generateCompileBash(this);
}
@Override
public boolean supportsRos() {
......@@ -36,44 +25,24 @@ public class BashCompilationGenerator extends CompilationGenerator {
}
@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() {
public List<String> getAdditionalPathDirs() {
setAdditionalErrorMsg("roscore", defaultErrorMsg("ROS"));
setAdditionalErrorMsg("ros2", defaultErrorMsg("ROS2"));
return Arrays.asList("cmake","make");
}
@Override
protected String getFileName() {
public String getFileName() {
return "compile.sh";
}
@Override
protected String getNewlineDelimiter() {
public String getNewlineDelimiter() {
return "\n";
}
@Override
protected List<String> getPostSourceExecutables() {
public List<String> getPostSourceExecutables() {
ArrayList<String> res = new ArrayList<>();
if(useRos()){
res.add("roscore");
......@@ -85,7 +54,7 @@ public class BashCompilationGenerator extends CompilationGenerator {
}
@Override
protected List<String> getEnvironmentFiles() {
public List<String> getEnvironmentFiles() {
List<String> res = new ArrayList<>();
if(useRos()){
res.add("\"$ROS_HOME\"/setup.bash");
......@@ -97,8 +66,12 @@ public class BashCompilationGenerator extends CompilationGenerator {
}
@Override
protected List<String> getExecutables() {
return Arrays.asList("cmake","make");
public List<String> getExecutables() {
List<String> res = new ArrayList<>(Arrays.asList("cmake", "make"));
if(useRos2() && useStructMsgs()){
res.add("colcon");
}
return res;
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
package de.monticore.lang.monticar.generator.middleware.templates.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 boolean useStructMsgs = false;
private Map<String, String> additionalErrorMsg = new HashMap<>();
public abstract boolean supportsRos();
......@@ -18,28 +18,19 @@ public abstract class CompilationGenerator {
return (supportsRos() || !useRos()) && (supportsRos2() || !useRos2());
}
protected void setAdditionalErrorMsg(String executable, String errorMsg) {
public 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();
public String getAdditionalErrorMsg(String executable) {
return additionalErrorMsg.getOrDefault(executable, defaultErrorMsg(executable));
}
protected abstract String getPathTemplate();
public abstract List<String> getAdditionalPathDirs();
protected abstract String getCheckExeTemplate();
public abstract String getFileName();
protected abstract String getSourceEnvVarsTemplate();
protected abstract String getScriptTemplate();
protected abstract List<String> getAdditionalPathDirs();
protected abstract String getFileName();
protected abstract String getNewlineDelimiter();
public abstract String getNewlineDelimiter();
public boolean useRos() {
return useRos;
......@@ -57,57 +48,30 @@ public abstract class CompilationGenerator {
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);
public boolean useStructMsgs() {
return useStructMsgs;
}
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 void setUseStructMsgs(boolean useStructMsgs) {
this.useStructMsgs = useStructMsgs;
}
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);
List<FileContent> res = new ArrayList<>();
res.add(new FileContent(getContent(), getFileName()));
if(useRos2() && useStructMsgs()) {
res.add(new FileContent("", "src/comps/COLCON_IGNORE"));
}
return res;
}
protected abstract List<String> getPostSourceExecutables();
public abstract String getContent();
public abstract List<String> getPostSourceExecutables();
protected abstract List<String> getEnvironmentFiles();
public abstract List<String> getEnvironmentFiles();
protected abstract List<String> getExecutables();
public abstract List<String> getExecutables();
public static List<CompilationGenerator> getInstanceOfAllGenerators() {
List<CompilationGenerator> res = new ArrayList<>();
......@@ -117,7 +81,7 @@ public abstract class CompilationGenerator {
return res;
}
protected String defaultErrorMsg(String executable) {
public 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;
package de.monticore.lang.monticar.generator.middleware.templates.compile;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import de.monticore.lang.monticar.generator.middleware.templates.MiddlewareTemplates;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -9,37 +9,42 @@ import java.util.List;
public class MingwCompilationGenerator extends WindowsCompilationGenerator {
@Override
public boolean supportsRos2() {
return false;
public String getContent() {
return MiddlewareTemplates.generateCompileMingw(this);
}
@Override
protected String getScriptTemplate() {
return TemplateHelper.getCompilationMingwTemplate();
public WinGenKind getKind() {
return WinGenKind.MINGW;
}
@Override
public boolean supportsRos2() {
return false;
}
@Override
protected List<String> getAdditionalPathDirs() {
public List<String> getAdditionalPathDirs() {
return Arrays.asList("cmake","make","g++");
}
@Override
protected String getFileName() {
public String getFileName() {
return "compileMingw.bat";
}
@Override
protected List<String> getPostSourceExecutables() {
public List<String> getPostSourceExecutables() {
return new ArrayList<>();
}
@Override
protected List<String> getEnvironmentFiles() {
public List<String> getEnvironmentFiles() {
return new ArrayList<>();
}
@Override
protected List<String> getExecutables() {
public List<String> getExecutables() {
return Arrays.asList("cmake","make","g++");
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
package de.monticore.lang.monticar.generator.middleware.templates.compile;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import de.monticore.lang.monticar.generator.middleware.templates.MiddlewareTemplates;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MsbuildCompilationGenerator extends WindowsCompilationGenerator {
@Override
public boolean supportsRos2() {
return true;
public String getContent() {
return MiddlewareTemplates.generateCompileMsbuild(this);
}
@Override
protected String getScriptTemplate() {
return TemplateHelper.getCompilationMsbuildTemplate();
public boolean supportsRos2() {
return true;
}
@Override
protected List<String> getAdditionalPathDirs() {
public List<String> getAdditionalPathDirs() {
setAdditionalErrorMsg("vcvars64.bat", defaultErrorMsg("msbuild"));
setAdditionalErrorMsg("ros2", defaultErrorMsg("ROS2"));
return Arrays.asList("cmake","msbuild");
......@@ -26,12 +27,12 @@ public class MsbuildCompilationGenerator extends WindowsCompilationGenerator {
@Override
protected String getFileName() {
public String getFileName() {
return "compileMsbuild.bat";
}
@Override
protected List<String> getPostSourceExecutables() {
public List<String> getPostSourceExecutables() {
List<String> res = new ArrayList<>();
res.add("msbuild");
if(useRos2()){
......@@ -41,7 +42,7 @@ public class MsbuildCompilationGenerator extends WindowsCompilationGenerator {
}
@Override
protected List<String> getEnvironmentFiles() {
public List<String> getEnvironmentFiles() {
List<String> res = new ArrayList<>();
res.add("vcvars64.bat");
if(useRos2()){
......@@ -51,7 +52,16 @@ public class MsbuildCompilationGenerator extends WindowsCompilationGenerator {
}
@Override
protected List<String> getExecutables() {
return Arrays.asList("cmake","vcvars64.bat");
public List<String> getExecutables() {
List<String> res = new ArrayList<>(Arrays.asList("cmake","vcvars64.bat"));
if(useRos2() && useStructMsgs()){
res.add("colcon");
}
return res;
}
@Override
public WinGenKind getKind() {
return WinGenKind.MSBUILD;
}
}
package de.monticore.lang.monticar.generator.middleware.compile;
package de.monticore.lang.monticar.generator.middleware.templates.compile;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.middleware.helpers.TemplateHelper;
import de.monticore.lang.monticar.generator.middleware.templates.MiddlewareTemplates;
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() {
public String getNewlineDelimiter() {
return "\r\n";
}
......@@ -43,11 +17,6 @@ public abstract class WindowsCompilationGenerator extends CompilationGenerator {
return false;
}
private String fillSubstTemplate(String compileScript) {
return TemplateHelper.getSubstTemplate()
.replace("<compile_script>", compileScript);
}
@Override
public List<FileContent> getCompilationScripts() {
ArrayList<FileContent> fileContents = new ArrayList<>();
......@@ -55,9 +24,16 @@ public abstract class WindowsCompilationGenerator extends CompilationGenerator {
FileContent substScript = new FileContent();
substScript.setFileName("subst" + getFileName().substring(0,1).toUpperCase() + getFileName().substring(1));
substScript.setFileContent(fillSubstTemplate(getFileName()));
substScript.setFileContent(MiddlewareTemplates.generateCompileSubst(this));
fileContents.add(substScript);
return fileContents;
}
abstract WinGenKind getKind();
enum WinGenKind{
MINGW,
MSBUILD
}
}
#!/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
<#-- General batch -->
<#macro comment str>
:: ${str}
</#macro>
<#macro setCurDir>
SET curDir=%~dp0
</#macro>
<#macro evalCurDir postfix="">%curDir%/${postfix}</#macro>
<#macro passParams>%*</#macro>
<#macro source env_file>
call ${env_file}
</#macro>
<#macro localSource env_file>
call "%curDir%/${env_file}.bat"
</#macro>
<#-- Compile specific -->
<#macro addToPath new_exe>
IF NOT [%${new_exe}_HOME%] == [] (
set PATH="%${new_exe}_HOME%;%PATH%"
)
</#macro>
<#macro exeCheck exe>
where ${exe}
IF NOT %ERRORLEVEL% EQU 0 (
echo "Can not find ${exe} in PATH! Aborting."
echo "${model.getAdditionalErrorMsg(exe)}"
exit /B 1
)