Skip to content

Commit

Permalink
Merge pull request #1713 from lf-lang/lfd
Browse files Browse the repository at this point in the history
lfd binary for generating diagrams from the command line
  • Loading branch information
cmnrd authored Jun 21, 2023
2 parents 1db4b0c + b8c2a18 commit ce052df
Show file tree
Hide file tree
Showing 22 changed files with 477 additions and 46 deletions.
20 changes: 20 additions & 0 deletions .github/scripts/test-lfd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bash

# Exit 1 if any command returns with a non-zero exit code.
set -euo pipefail

cd $GITHUB_WORKSPACE

function test_with_links() {
rm -rf foo
mkdir -p foo/bar/baz
ln -s ../bin/${1} foo/link-foo
ln -s ../link-foo foo/bar/link-bar
ln -s ../link-bar foo/bar/baz/link-${1}
foo/bar/baz/link-${1} --help
}

bin/lfd test/C/src/Minimal.lf

# Ensure that lfd is robust to symbolic links.
test_with_links "lfd"
8 changes: 7 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ jobs:
- name: Prepare build environment
uses: ./.github/actions/prepare-build-env
- name: Build and package lf cli tools (nightly build)
run: ./gradlew build -Pnightly
# We assume, that the nightly build only runs once on Ubuntu
run: |
./gradlew build -Pnightly -PtargetOS=Linux -PtargetPlatform=x86_64
./gradlew assemble -Pnightly -PtargetOS=Linux -PtargetPlatform=aarch64
./gradlew assemble -Pnightly -PtargetOS=MacOS -PtargetPlatform=x86_64
./gradlew assemble -Pnightly -PtargetOS=MacOS -PtargetPlatform=aarch64
./gradlew assemble -Pnightly -PtargetOS=Windows -PtargetPlatform=x86_64
shell: bash
if: ${{ inputs.nightly == true }}
- name: Build and package lf cli tools (regular build)
Expand Down
33 changes: 31 additions & 2 deletions .github/workflows/cli-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,45 @@ jobs:
- name: Test lfc bash scripts (Linux or macOS only)
run: |
.github/scripts/test-lfc.sh
./gradlew assemble
./build/install/lf-cli/bin/lfc --version
./build/install/lf-cli/bin/lfc test/C/src/Minimal.lf
if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }}
- name: Test lff bash scripts (Linux or macOS only)
run: |
.github/scripts/test-lff.sh
./gradlew assemble
./build/install/lf-cli/bin/lff --version
./build/install/lf-cli/bin/lff test/C/src/Minimal.lf
if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }}
- name: Test lfd bash scripts (Linux or macOS only)
run: |
.github/scripts/test-lfd.sh
./gradlew assemble
./build/install/lf-cli/bin/lfd --version
./build/install/lf-cli/bin/lfd test/C/src/Minimal.lf
if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }}
- name: Test lfc PowerShell script (Windows only)
run: |
bin/lfc.ps1 --help
bin/lfc.ps1 --version
bin/lfc.ps1 test/C/src/Minimal.lf
./gradlew assemble
./build/install/lf-cli/bin/lfc.bat --version
./build/install/lf-cli/bin/lfc.bat test/C/src/Minimal.lf
if: ${{ runner.os == 'Windows' }}
- name: Test lff PowerShell script (Windows only)
run: |
bin/lff.ps1 --help
bin/lff.ps1 --version
bin/lff.ps1 test/C/src/Minimal.lf
./gradlew assemble
./build/install/lf-cli/bin/lff.bat --version
./build/install/lf-cli/bin/lff.bat test/C/src/Minimal.lf
if: ${{ runner.os == 'Windows' }}
- name: Test lfd PowerShell script (Windows only)
run: |
bin/lfd.ps1 --version
bin/lfd.ps1 test/C/src/Minimal.lf
./gradlew assemble
./build/install/lf-cli/bin/lfd.bat --version
./build/install/lf-cli/bin/lfd.bat test/C/src/Minimal.lf
if: ${{ runner.os == 'Windows' }}
1 change: 1 addition & 0 deletions bin/lfd
9 changes: 9 additions & 0 deletions bin/lfd.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#==========================================================
# Description: Run the lff compiler.
# Authors: Ruomu Xu
# Usage: Usage: lff [options] files...
#==========================================================

$launchScript="$PSScriptRoot\..\util\scripts\launch.ps1"
# PS requires spattling: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Splatting?view=powershell-7.2
. $launchScript @args
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ distributions {
if (project.hasProperty('nightly')) {
def date = new Date()
def formattedDate = date.format('yyyyMMddHHmmss')
distributionClassifier = 'nightly-' + formattedDate
distributionClassifier = 'nightly-' + formattedDate + '-' + platform.os + '-' + platform.arch
} else if (!platform.isNative) {
distributionClassifier = platform.os + '-' + platform.arch
}
contents {
from tasks.getByPath('cli:lfc:installDist').outputs
from tasks.getByPath('cli:lff:installDist').outputs
from tasks.getByPath('cli:lfd:installDist').outputs
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
plugins {
id 'distribution'
id 'org.lflang.platform'
}

tasks.withType(Tar) {
compression = Compression.GZIP
archiveExtension = 'tar.gz'
enabled = !platform.isWindows
}

tasks.withType(Zip) {
enabled = platform.isWindows
}

tasks.withType(Jar) {
enabled = true
}

tasks.withType(CreateStartScripts) {
doLast {
if (platform.isWindows) {
delete unixScript
// Fix long path issue on Windows
// See https://github.com/gradle/gradle/issues/1989
windowsScript.text = windowsScript.text.replaceAll('set CLASSPATH=.*', 'set CLASSPATH=.;%APP_HOME%/lib/*')
} else {
delete windowsScript
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,3 @@ plugins {
id 'org.lflang.test-conventions'
id "org.lflang.distribution-conventions"
}

tasks.withType(Tar) {
compression = Compression.GZIP
archiveExtension = 'tar.gz'
}

// Fix long path issue on Windows
// See https://github.com/gradle/gradle/issues/1989
startScripts {
doLast {
windowsScript.text = windowsScript.text.replaceAll('set CLASSPATH=.*', 'set CLASSPATH=.;%APP_HOME%/lib/*')
}
}
26 changes: 26 additions & 0 deletions buildSrc/src/main/groovy/org.lflang.java-conventions.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'java'
id 'com.diffplug.spotless'
id 'org.lflang.platform'
}

repositories {
Expand All @@ -17,3 +18,28 @@ spotless {
formatAnnotations()
}
}

configurations.all {
resolutionStrategy {
dependencySubstitution {
// The maven property ${osgi.platform} is not handled by Gradle
// so we replace the dependency, using the osgi platform from the project settings
def arch = platform.arch
if (arch != 'x86_64' && arch != 'aarch64') {
throw new GradleException("Your system architecture $arch is not supported")
}

if (platform.isWindows) {
substitute module('org.eclipse.platform:org.eclipse.swt.${osgi.platform}') using module("org.eclipse.platform:org.eclipse.swt.win32.win32.$arch:$swtVersion")
}
else if (platform.isLinux) {
substitute module('org.eclipse.platform:org.eclipse.swt.${osgi.platform}') using module("org.eclipse.platform:org.eclipse.swt.gtk.linux.$arch:$swtVersion")
}
else if (platform.isMacos) {
substitute module('org.eclipse.platform:org.eclipse.swt.${osgi.platform}') using module("org.eclipse.platform:org.eclipse.swt.cocoa.macosx.$arch:$swtVersion")
} else {
throw new GradleException("Your operating system ${platform.os} is not supported")
}
}
}
}
16 changes: 16 additions & 0 deletions buildSrc/src/main/groovy/org.lflang.platform.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
tasks.register('platform') {
def osVar = project.hasProperty('targetOS') ? project.getProperty('targetOS') : System.getProperty('os.name')
def archVar = project.hasProperty('targetArch') ? project.getProperty('targetArch') : System.getProperty('os.arch')
if (archVar == 'amd64') {
archVar = 'x86_64'
}

ext {
os = osVar
arch = archVar
isWindows = osVar.toLowerCase().contains('windows')
isLinux = osVar.toLowerCase().contains('linux')
isMacos = osVar.toLowerCase().contains('mac')
isNative = !project.hasProperty('targetOS') && !project.hasProperty('targetArch')
}
}
25 changes: 25 additions & 0 deletions cli/lfd/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
id 'org.lflang.java-application-conventions'
}

dependencies {
implementation project(':cli:base')
implementation("de.cau.cs.kieler.klighd:de.cau.cs.kieler.klighd.standalone:$klighdVersion") {
exclude group: 'de.cau.cs.kieler.swt.mock'
}
implementation("de.cau.cs.kieler.klighd:de.cau.cs.kieler.klighd.piccolo:${klighdVersion}") {
exclude group: 'de.cau.cs.kieler.swt.mock'
}
implementation("de.cau.cs.kieler.klighd:de.cau.cs.kieler.klighd.piccolo.freehep:${klighdVersion}") {
exclude group: 'de.cau.cs.kieler.swt.mock'
}
implementation("org.freehep:freehep-graphicsio-svg:${freehepVersion}")

testImplementation(testFixtures(project(':core')))
testImplementation(testFixtures(project(':cli:base')))
}

application {
mainClass = 'org.lflang.cli.Lfd'
tasks.run.workingDir = System.getProperty("user.dir")
}
78 changes: 78 additions & 0 deletions cli/lfd/src/main/java/org/lflang/cli/Lfd.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.lflang.cli;

import de.cau.cs.kieler.klighd.Klighd;
import de.cau.cs.kieler.klighd.LightDiagramServices;
import de.cau.cs.kieler.klighd.standalone.KlighdStandaloneSetup;
import java.nio.file.Path;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.resource.Resource;
import org.lflang.lf.Model;
import org.lflang.util.FileUtil;
import picocli.CommandLine.Command;

/**
* Command lin tool for generating diagrams from Lingua Franca programs.
*
* @author Christian Menard
*/
@Command(
name = "lfd",
// Enable usageHelp (--help) and versionHelp (--version) options.
mixinStandardHelpOptions = true,
versionProvider = VersionProvider.class)
public class Lfd extends CliBase {

@Override
public void doRun() {
KlighdStandaloneSetup.initialize();
Klighd.setStatusManager(
(status, style) -> {
switch (status.getSeverity()) {
case IStatus.ERROR -> {
reporter.printError(status.getMessage());
if (status.getException() != null) {
status.getException().printStackTrace();
}
}
case IStatus.WARNING -> reporter.printWarning(status.getMessage());
default -> reporter.printInfo(status.getMessage());
}
});

for (Path relativePath : getInputPaths()) {
Path path = toAbsolutePath(relativePath);
final Resource resource = getResource(path);
if (resource == null) {
reporter.printFatalErrorAndExit(path.toString() + " is not an LF program.");
}
final Model model = (Model) resource.getContents().get(0);
String baseName = FileUtil.nameWithoutExtension(relativePath);
Path outFile = io.getWd().resolve(baseName + ".svg").toAbsolutePath();
IStatus status = LightDiagramServices.renderOffScreen(model, "svg", outFile.toString());
if (!status.isOK()) {
reporter.printFatalErrorAndExit(status.getMessage());
}
}

reporter.exit();
}

/**
* Main entry point of the diagram tool.
*
* @param args CLI arguments
*/
public static void main(String[] args) {
main(Io.SYSTEM, args);
}

/**
* Programmatic entry point, with a custom IO.
*
* @param io IO streams.
* @param args Command-line arguments.
*/
public static void main(Io io, final String... args) {
cliMain("lfd", Lfd.class, io, args);
}
}
Loading

0 comments on commit ce052df

Please sign in to comment.