From 00e4151b04bee0e74861cda1e3944da89a722b98 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 17 Jun 2024 18:04:27 -0700 Subject: [PATCH] CppDockerGenerator.java passes smoke test --- .../generator/docker/CppDockerGenerator.java | 79 ++++++++++++++++++- .../org/lflang/generator/cpp/CppGenerator.kt | 25 +++++- .../generator/cpp/CppPlatformGenerator.kt | 2 +- .../cpp/CppStandaloneCmakeGenerator.kt | 6 ++ .../generator/cpp/CppStandaloneGenerator.kt | 12 +-- .../Cpp/src/docker/HelloWorldContainerized.lf | 3 +- 6 files changed, 113 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/docker/CppDockerGenerator.java b/core/src/main/java/org/lflang/generator/docker/CppDockerGenerator.java index c445765048..5bc8f2c31c 100644 --- a/core/src/main/java/org/lflang/generator/docker/CppDockerGenerator.java +++ b/core/src/main/java/org/lflang/generator/docker/CppDockerGenerator.java @@ -1,15 +1,20 @@ package org.lflang.generator.docker; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.lflang.generator.LFGeneratorContext; import org.lflang.generator.cpp.CppPlatformGenerator; +import org.lflang.generator.cpp.CppStandaloneGenerator; +import org.lflang.target.property.BuildTypeProperty; /** - * Generates the docker file related code for the Typescript target. + * Generates the docker file related code for the C++ target. * * @author Marten Lohstroh */ -public class CppDockerGenerator extends CDockerGenerator { +public class CppDockerGenerator extends DockerGenerator { private CppPlatformGenerator platformGenerator; @@ -19,9 +24,75 @@ public CppDockerGenerator(LFGeneratorContext context, CppPlatformGenerator platf this.platformGenerator = platformGenerator; } + @Override + protected String generateCopyForSources() { + return "COPY src-gen src-gen"; + } + + public static final String DEFAULT_BASE_IMAGE = "alpine:latest"; + + @Override + public String defaultImage() { + return DEFAULT_BASE_IMAGE; + } + + @Override + protected String generateRunForInstallingDeps() { + if (builderBase().equals(defaultImage())) { + return "RUN set -ex && apk add --no-cache g++ musl-dev cmake make && apk add --no-cache" + + " --update --repository=https://dl-cdn.alpinelinux.org/alpine/v3.16/main/" + + " libexecinfo-dev"; + } else { + return "# (Skipping installation of build dependencies; custom base image.)"; + } + } + + @Override + public List defaultEntryPoint() { + return List.of("./bin/" + context.getFileConfig().name); + } + @Override protected List defaultBuildCommands() { - // FIXME - return List.of(); + var mkdirCommand = List.of("mkdir", "-p", "build", "&&", "mkdir", "-p", "bin"); + var cmakeCommand = new ArrayList(); + cmakeCommand.add("cmake"); + cmakeCommand.addAll(platformGenerator.getCmakeArgs()); + cmakeCommand.addAll( + List.of( + "-DCMAKE_INSTALL_BINDIR=bin", + "-DCMAKE_INSTALL_PREFIX=.", + "-DREACTOR_CPP_LINK_EXECINFO=ON", + "-S", + "src-gen", + "-B", + "build")); + var makeCommand = + List.of( + "cmake", + "--build", + "build", + "--target", + context.getFileConfig().name, + "--config", + CppStandaloneGenerator.Companion.buildTypeToCmakeConfig( + context.getTargetConfig().get(BuildTypeProperty.INSTANCE))); + var installCommand = + List.of( + "cmake", + "--build", + "build", + "--target", + "install", + "--config", + CppStandaloneGenerator.Companion.buildTypeToCmakeConfig( + context.getTargetConfig().get(BuildTypeProperty.INSTANCE))); + return Stream.of(mkdirCommand, cmakeCommand, makeCommand, installCommand) + .map(CppDockerGenerator::argListToCommand) + .toList(); + } + + static String argListToCommand(List args) { + return args.stream().map(it -> "\"" + it + "\"").collect(Collectors.joining(" ")); } } diff --git a/core/src/main/kotlin/org/lflang/generator/cpp/CppGenerator.kt b/core/src/main/kotlin/org/lflang/generator/cpp/CppGenerator.kt index afa377f76c..9c63a713f6 100644 --- a/core/src/main/kotlin/org/lflang/generator/cpp/CppGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/cpp/CppGenerator.kt @@ -37,6 +37,8 @@ import org.lflang.scoping.LFGlobalScopeProvider import org.lflang.target.Target import org.lflang.target.property.* import org.lflang.util.FileUtil +import java.io.File +import java.io.IOException import java.nio.file.Files import java.nio.file.Path @@ -95,7 +97,27 @@ class CppGenerator( "Code generation complete. Compiling...", IntegratedBuilder.GENERATED_PERCENT_PROGRESS ) if (targetConfig.get(DockerProperty.INSTANCE).enabled) { - buildUsingDocker(); + FileUtil.deleteDirectory(context.fileConfig.srcGenPath.resolve("src-gen")) + try { + val tempDir = Files.createTempDirectory(context.fileConfig.outPath, "src-gen-directory") + try { + FileUtil.copyDirectoryContents(context.fileConfig.srcGenBasePath, tempDir, false) + FileUtil.copyDirectoryContents(tempDir, context.fileConfig.srcGenPath.resolve("src-gen"), false) + } catch (e: IOException) { + context.errorReporter.nowhere() + .error("Failed to copy sources to make them accessible to Docker: " + if (e.message == null) "No cause given" else e.message) + e.printStackTrace() + } finally { + FileUtil.deleteDirectory(tempDir) + } + if (errorsOccurred()) { + return + } + } catch (e: IOException) { + context.errorReporter.nowhere().error("Failed to create temporary directory.") + e.printStackTrace() + } + buildUsingDocker() } else { if (platformGenerator.doCompile(context)) { context.finish(GeneratorResult.Status.COMPILED, codeMaps) @@ -196,4 +218,3 @@ class CppGenerator( override fun getDockerGenerator(context: LFGeneratorContext?): DockerGenerator = CppDockerGenerator(context, getPlatformGenerator()) } - diff --git a/core/src/main/kotlin/org/lflang/generator/cpp/CppPlatformGenerator.kt b/core/src/main/kotlin/org/lflang/generator/cpp/CppPlatformGenerator.kt index 220770b6a9..6f0f295897 100644 --- a/core/src/main/kotlin/org/lflang/generator/cpp/CppPlatformGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/cpp/CppPlatformGenerator.kt @@ -28,7 +28,7 @@ abstract class CppPlatformGenerator(protected val generator: CppGenerator) { abstract fun doCompile(context: LFGeneratorContext, onlyGenerateBuildFiles: Boolean = false): Boolean - protected val cmakeArgs: List + val cmakeArgs: List get() = listOf( "-DCMAKE_BUILD_TYPE=${targetConfig.get(BuildTypeProperty.INSTANCE)}", "-DREACTOR_CPP_VALIDATE=${if (targetConfig.get(NoRuntimeValidationProperty.INSTANCE)) "OFF" else "ON"}", diff --git a/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneCmakeGenerator.kt b/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneCmakeGenerator.kt index 2c041fe6d2..5d36e8e327 100644 --- a/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneCmakeGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneCmakeGenerator.kt @@ -153,6 +153,8 @@ class CppStandaloneCmakeGenerator(private val targetConfig: TargetConfig, privat |cmake_minimum_required(VERSION 3.5) |project(${fileConfig.name} VERSION 0.0.0 LANGUAGES CXX) | + |option(REACTOR_CPP_LINK_EXECINFO "Link against execinfo" OFF) + | |${if (targetConfig.get(ExternalRuntimePathProperty.INSTANCE) != null) "find_package(reactor-cpp PATHS ${targetConfig.get(ExternalRuntimePathProperty.INSTANCE)})" else ""} | |set(LF_MAIN_TARGET ${fileConfig.name}) @@ -167,6 +169,10 @@ class CppStandaloneCmakeGenerator(private val targetConfig: TargetConfig, privat |) |target_link_libraries($S{LF_MAIN_TARGET} $reactorCppTarget) | + |if(REACTOR_CPP_LINK_EXECINFO) + | target_link_libraries($S{LF_MAIN_TARGET} execinfo) + |endif() + | |if(MSVC) | target_compile_options($S{LF_MAIN_TARGET} PRIVATE /W4) |else() diff --git a/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneGenerator.kt b/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneGenerator.kt index dd03db376d..1640432fd4 100644 --- a/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneGenerator.kt +++ b/core/src/main/kotlin/org/lflang/generator/cpp/CppStandaloneGenerator.kt @@ -16,6 +16,13 @@ import java.nio.file.Paths class CppStandaloneGenerator(generator: CppGenerator) : CppPlatformGenerator(generator) { + companion object { + fun buildTypeToCmakeConfig(type: BuildType) = when (type) { + BuildType.TEST -> "Debug" + else -> type.toString() + } + } + override fun generatePlatformFiles() { // generate the main source file (containing main()) @@ -132,11 +139,6 @@ class CppStandaloneGenerator(generator: CppGenerator) : return 0 } - private fun buildTypeToCmakeConfig(type: BuildType) = when (type) { - BuildType.TEST -> "Debug" - else -> type.toString() - } - private fun createMakeCommand(buildPath: Path, version: String, target: String): LFCommand { val makeArgs: List if (version.compareVersion("3.12.0") < 0) { diff --git a/test/Cpp/src/docker/HelloWorldContainerized.lf b/test/Cpp/src/docker/HelloWorldContainerized.lf index 85cdcc195e..a7ddb6205c 100644 --- a/test/Cpp/src/docker/HelloWorldContainerized.lf +++ b/test/Cpp/src/docker/HelloWorldContainerized.lf @@ -1,6 +1,5 @@ target Cpp { - // To test generating a custom trace file name. - logging: error, + logging: error, // To test generating a custom trace file name. docker: true, build-type: Debug }