Commit 2dbb6fdd authored by Christoph Richter's avatar Christoph Richter
Browse files

GeneratorCPP: Now is able to generate CMake files

parent a7aa7101
package de.monticore.lang.monticar.generator.cmake;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cpp.template.AllTemplates;
import de.monticore.lang.monticar.generator.cpp.template.TemplateHelper;
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.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Class to configure cmake file generation.
* Is responsible for generating the cmake files from freemarker templates.
* CMake dependencies to other modules can be added as Find Package file.
* See also https://cmake.org/cmake/help/v3.8/command/find_package.html?highlight=i
*
* @author Christoph Richter
*/
public class CMakeConfig {
private static final Template CMAKE_LISTS_CPP;
private static final Template CMAKE_FIND_PACKAGE;
static {
Configuration conf = new Configuration(Configuration.VERSION_2_3_23);
conf.setDefaultEncoding("UTF-8");
conf.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
conf.setLogTemplateExceptions(false);
conf.setClassForTemplateLoading(AllTemplates.class, "/template/cmake/");
try {
CMAKE_LISTS_CPP = conf.getTemplate("CMakeListsCppTemplate.ftl");
CMAKE_FIND_PACKAGE = conf.getTemplate("CMakeFindPackageTemplate.ftl");
} catch (IOException e) {
String msg = "could not load cmake templates";
Log.error(msg, e);
throw new RuntimeException(msg, e);
}
}
// fields
private CMakeListsCPPViewModel cMakeListsViewModel = new CMakeListsCPPViewModel();
private List<CMakeFindModule> moduleList = new ArrayList<>();
// constructor
public CMakeConfig(String compName) {
cMakeListsViewModel.setCompName(compName);
cMakeListsViewModel.setModuleDependencies(moduleList);
}
// methods
protected void configureCMakeListsViewModel() {
// nothing here
}
public List<FileContent> generateCMakeFiles() {
List<FileContent> files = new ArrayList<FileContent>();
// generate CMakeLists.txt
files.add(generateCMakeLists());
// generate FindModule.cmake's
for (CMakeFindModule module : moduleList) {
files.add(generateCMakeFindPackage(module));
}
return files;
}
private FileContent generateCMakeFindPackage(CMakeFindModule module) {
FileContent result = null;
// map data
Map<String, Object> dataForTemplate = TemplateHelper.getDataForTemplate(module);
// try generate file content
try {
StringWriter sw = new StringWriter();
CMAKE_FIND_PACKAGE.process(dataForTemplate, sw);
result = (new FileContent(sw.toString(), "/cmake/" + module.getFileName()));
} catch (TemplateException | IOException e) {
Log.error("CMakeFindPackage template generation failed. ", e);
}
return result;
}
public FileContent generateCMakeLists() {
FileContent result = null;
configureCMakeListsViewModel();
// map data
Map<String, Object> dataForTemplate = TemplateHelper.getDataForTemplate(cMakeListsViewModel);
// try generate file content
try {
StringWriter sw = new StringWriter();
CMAKE_LISTS_CPP.process(dataForTemplate, sw);
result = (new FileContent(sw.toString(), "/" + cMakeListsViewModel.CMAKELISTS_FILE_NAME));
} catch (TemplateException | IOException e) {
Log.error("CMakeLists template generation failed. ", e);
}
return result;
}
public void addModuleDependency(CMakeFindModule module) {
moduleList.add(module);
}
public CMakeListsCPPViewModel getCMakeListsViewModel() {
return cMakeListsViewModel;
}
}
package de.monticore.lang.monticar.generator.cmake;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ViewModelBase;
import java.util.ArrayList;
import java.util.List;
/**
* Representation of CMake Find files as Java class.
* Additionally acts as view model for the corresponding freemarker template.
*
* @author Christoph Richter
*/
public class CMakeFindModule extends ViewModelBase {
// fields
private String packageName;
private String includeName;
private String libName;
private List<String> includePaths = new ArrayList<>();
private List<String> libPaths = new ArrayList<>();
private Boolean findPath;
private Boolean findLibrary;
private boolean required;
public CMakeFindModule(String moduleName, Boolean required) {
this.packageName = moduleName;
this.required = required;
// guess rest
this.includeName = moduleName.toLowerCase();
this.libName = moduleName.toLowerCase();
findPath = true;
findLibrary = true;
}
public CMakeFindModule(String packageName, String includeName, String libName, List<String> includePaths, List<String> libPaths, Boolean findPath, Boolean findLibrary, boolean required) {
this.packageName = packageName;
this.includeName = includeName;
this.libName = libName;
this.includePaths = includePaths;
this.libPaths = libPaths;
this.findPath = findPath;
this.findLibrary = findLibrary;
this.required = required;
}
// methods
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getIncludeName() {
return includeName;
}
public void setIncludeName(String includeName) {
this.includeName = includeName;
}
public String getLibName() {
return libName;
}
public void setLibName(String libName) {
this.libName = libName;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public List<String> getIncludePaths() {
return includePaths;
}
public void setIncludePaths(List<String> includePaths) {
this.includePaths = includePaths;
}
public List<String> getLibPaths() {
return libPaths;
}
public void setLibPaths(List<String> libPaths) {
this.libPaths = libPaths;
}
public String getFileName() {
return String.format("Find%s.cmake", packageName);
}
public Boolean getFindPath() {
return findPath;
}
public void setFindPath(Boolean findPath) {
this.findPath = findPath;
}
public Boolean getFindLibrary() {
return findLibrary;
}
public void setFindLibrary(Boolean findLibrary) {
this.findLibrary = findLibrary;
}
}
package de.monticore.lang.monticar.generator.cmake;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ViewModelBase;
import java.util.List;
/**
* View model which is used by the freemarker template
*
* @author Christoph Richter
*/
public class CMakeListsCPPViewModel extends ViewModelBase {
// const
public static final String CMAKELISTS_FILE_NAME = "CMakeLists.txt";
// fields
private String compName;
private List<CMakeFindModule> moduleDependencies;
// methods
public String getCompName() {
return compName;
}
public void setCompName(String compName) {
this.compName = compName;
}
public List<CMakeFindModule> getModuleDependencies() {
return moduleDependencies;
}
public void setModuleDependencies(List<CMakeFindModule> moduleDependencies) {
this.moduleDependencies = moduleDependencies;
}
}
......@@ -2,15 +2,12 @@ package de.monticore.lang.monticar.generator.cpp;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
import de.monticore.lang.math._symboltable.MathStatementsSymbol;
import de.monticore.lang.monticar.generator.BluePrint;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.Generator;
import de.monticore.lang.monticar.generator.Helper;
import de.monticore.lang.monticar.generator.MathCommandRegister;
import de.monticore.lang.monticar.generator.*;
import de.monticore.lang.monticar.generator.cmake.CMakeConfig;
import de.monticore.lang.monticar.generator.cmake.CMakeFindModule;
import de.monticore.lang.monticar.generator.cpp.converter.MathConverter;
import de.monticore.lang.monticar.generator.cpp.converter.TypeConverter;
import de.monticore.lang.monticar.generator.cpp.template.AllTemplates;
import de.monticore.lang.monticar.generator.cpp.viewmodel.AutopilotAdapterViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ServerWrapperViewModel;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
......@@ -48,11 +45,24 @@ public class GeneratorCPP implements Generator {
protected boolean generateSimulatorInterface = false;
protected boolean checkModelDir = false;
// CMake
private boolean generateCMake = true;
private CMakeConfig cMakeConfig;
public GeneratorCPP() {
this.mathCommandRegister = new MathCommandRegisterCPP();
useOctaveBackend();
TypeConverter.clearTypeSymbols();
currentInstance = this;
setupCMake();
}
protected void setupCMake() {
cMakeConfig = new CMakeConfig("");
if (usesArmadilloBackend()) {
// add dependency on module Armadillo
cMakeConfig.addModuleDependency(new CMakeFindModule("Armadillo", true));
}
}
......@@ -60,6 +70,10 @@ public class GeneratorCPP implements Generator {
MathConverter.curBackend = new ArmadilloBackend();
}
public boolean usesArmadilloBackend() {
return MathConverter.curBackend instanceof ArmadilloBackend;
}
public void useOctaveBackend() {
MathConverter.curBackend = new OctaveBackend();
//Log.warn("This backend has been deprecated. Armadillo is the recommended backend now.");
......@@ -164,10 +178,26 @@ public class GeneratorCPP implements Generator {
setGenerationTargetPath(getGenerationTargetPath() + "/");
}
List<File> files = saveFilesToDisk(fileContents);
//cmake
if (generateCMake)
files.addAll(generateCMakeFiles(componentSymbol));
return files;
}
protected List<File> generateCMakeFiles(ExpandedComponentInstanceSymbol componentInstanceSymbol) {
List<File> files = new ArrayList<>();
cMakeConfig.getCMakeListsViewModel().setCompName(componentInstanceSymbol.getFullName().replace('.', '_').replace('[', '_').replace(']', '_'));
List<FileContent> contents = cMakeConfig.generateCMakeFiles();
try {
for (FileContent content : contents)
files.add(generateFile(content));
} catch (IOException e) {
e.printStackTrace();
}
return files;
}
public List<File> saveFilesToDisk(List<FileContent> fileContents) throws IOException {
List<File> files = new ArrayList<>();
for (FileContent fileContent : fileContents) {
......@@ -365,11 +395,24 @@ public class GeneratorCPP implements Generator {
private static FileContent generateServerWrapper(ExpandedComponentInstanceSymbol componentSymbol) {
return generateWrapper(componentSymbol, "server.cc");
}
private static FileContent generateWrapper(ExpandedComponentInstanceSymbol componentSymbol, String name) {
private static FileContent generateWrapper(ExpandedComponentInstanceSymbol componentSymbol, String name) {
ServerWrapperViewModel vm = new ServerWrapperViewModel();
vm.setMainModelName(GeneralHelperMethods.getTargetLanguageComponentName(componentSymbol.getFullName()));
String fileContents = AllTemplates.generateServerWrapper(vm);
return new FileContent(fileContents, name);
}
public boolean isGenerateCMakeEnabled() {
return generateCMake;
}
public void setGenerateCMake(boolean generateCMake) {
this.generateCMake = generateCMake;
}
public CMakeConfig getcMakeConfig() {
return cMakeConfig;
}
}
# Automatically generated file
#
# - Try to find ${viewModel.packageName}
# Once done this will define
# ${viewModel.packageName}_FOUND - System has ${viewModel.packageName}
# ${viewModel.packageName}_INCLUDE_DIRS - The ${viewModel.packageName} include directories
# ${viewModel.packageName}_LIBRARY_DIRS - The library directories needed to use ${viewModel.packageName}
# ${viewModel.packageName}_LIBRARIES - The libraries needed to use ${viewModel.packageName}
<#if viewModel.findPath>
find_path(${viewModel.packageName}_INCLUDE_DIR
NAMES ${viewModel.includeName}
PATH_SUFFIXES "include"
PATHS
<#list viewModel.includePaths as var>
\" ${var} \"
</#list>
)
</#if>
<#if viewModel.findLibrary>
find_library(${viewModel.packageName}_LIBRARY
NAMES ${viewModel.libName}
PATH_SUFFIXES "lib" "lib64" "lib/x86_64-linux-gnu" "examples/lib_win64" "build"
PATHS
<#list viewModel.libPaths as var>
\" ${var} \"
</#list>
)
</#if>
include(FindPackageHandleStandardArgs)
# if all listed variables are TRUE
find_package_handle_standard_args(
${viewModel.packageName}
DEFAULT_MSG
<#if viewModel.findPath>${viewModel.packageName}_INCLUDE_DIR</#if>
<#if viewModel.findLibrary>${viewModel.packageName}_LIBRARY</#if>
)
mark_as_advanced(
<#if viewModel.findPath>${viewModel.packageName}_INCLUDE_DIR</#if>
<#if viewModel.findLibrary>${viewModel.packageName}_LIBRARY</#if>
)
<#if viewModel.findPath>set(${viewModel.packageName}_INCLUDE_DIRS ${r"${"}${viewModel.packageName}${r"_INCLUDE_DIR}"})</#if>
<#if viewModel.findLibrary>set(${viewModel.packageName}_LIBRARIES ${r"${"}${viewModel.packageName}${r"_LIBRARY}"})</#if>
\ No newline at end of file
cmake_minimum_required(VERSION 3.5)
set(CMAKE_CXX_STANDARD 11)
project(${viewModel.compName} LANGUAGES CXX)
#set cmake module path
set(CMAKE_MODULE_PATH ${r"${CMAKE_MODULE_PATH}"} ${r"${CMAKE_CURRENT_SOURCE_DIR}"}/cmake)
# add dependencies
<#list viewModel.moduleDependencies as var>
find_package(${var.packageName} <#if var.required>REQUIRED<#else>OPTIONAL</#if>)
<#if var.findPath>set(INCLUDE_DIRS ${r"${INCLUDE_DIRS}"} ${r"${"}${var.packageName}${r"_INCLUDE_DIRS}"})</#if>
<#if var.findLibrary>set(LIBS ${r"${LIBS}"} ${r"${"}${var.packageName}${r"_LIBRARIES}"})</#if>
</#list>
# create static library
include_directories(${r"${INCLUDE_DIRS}"})
add_library(${viewModel.compName} ${viewModel.compName}.h)
target_include_directories(${viewModel.compName} PUBLIC ${r"${CMAKE_CURRENT_SOURCE_DIR}"})
target_link_libraries(${viewModel.compName} PUBLIC ${r"${LIBS}"})
set_target_properties(${viewModel.compName} PROPERTIES LINKER_LANGUAGE CXX)
# export cmake project
export(TARGETS ${viewModel.compName} FILE ${viewModel.compName}.cmake)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment