From 47c4a2d76de9d07240ef9aebc0be81084b67ceca Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 21:59:24 -0800 Subject: [PATCH 01/42] Removed CMake Toolchain References. --- .gitmodules | 3 --- .../lib/platform/arduino/Arduino-CMake-Toolchain | 1 - .../src/org/lflang/generator/c/CCmakeGenerator.java | 5 ----- .../src/org/lflang/generator/c/CCompiler.java | 13 +++++-------- 4 files changed, 5 insertions(+), 17 deletions(-) delete mode 160000 org.lflang/src/lib/platform/arduino/Arduino-CMake-Toolchain diff --git a/.gitmodules b/.gitmodules index d5763bfbc0..3ccd9f3a7f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,6 @@ [submodule "org.lflang/src/lib/cpp/reactor-cpp"] path = org.lflang/src/lib/cpp/reactor-cpp url = https://github.com/lf-lang/reactor-cpp -[submodule "org.lflang/src/lib/platform/arduino/Arduino-CMake-Toolchain"] - path = org.lflang/src/lib/platform/arduino/Arduino-CMake-Toolchain - url = https://github.com/a9183756-gh/Arduino-CMake-Toolchain.git [submodule "org.lflang/src/lib/rs/reactor-rs"] path = org.lflang/src/lib/rs/reactor-rs url = https://github.com/lf-lang/reactor-rs diff --git a/org.lflang/src/lib/platform/arduino/Arduino-CMake-Toolchain b/org.lflang/src/lib/platform/arduino/Arduino-CMake-Toolchain deleted file mode 160000 index e745a9bed3..0000000000 --- a/org.lflang/src/lib/platform/arduino/Arduino-CMake-Toolchain +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e745a9bed3c3fb83442d55bf05630f31574674f2 diff --git a/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java b/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java index ef3c5352eb..35dbd24bc1 100644 --- a/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CCmakeGenerator.java @@ -270,11 +270,6 @@ CodeBuilder generateCMakeCode( cMakeCode.pr(installCode); cMakeCode.newLine(); - if (targetConfig.platformOptions.platform == Platform.ARDUINO) { - cMakeCode.pr("target_link_arduino_libraries ( ${LF_MAIN_TARGET} AUTO_PUBLIC)"); - cMakeCode.pr("target_enable_arduino_upload(${LF_MAIN_TARGET})"); - } - // Add the include file for (String includeFile : targetConfig.cmakeIncludesWithoutPath) { cMakeCode.pr("include(\""+includeFile+"\")"); diff --git a/org.lflang/src/org/lflang/generator/c/CCompiler.java b/org.lflang/src/org/lflang/generator/c/CCompiler.java index 02333e3704..fc09ccf650 100644 --- a/org.lflang/src/org/lflang/generator/c/CCompiler.java +++ b/org.lflang/src/org/lflang/generator/c/CCompiler.java @@ -221,12 +221,6 @@ private static List cmakeOptions(TargetConfig targetConfig, FileConfig f ), FileUtil.toUnixString(fileConfig.getSrcGenPath()) )); - if (targetConfig.platformOptions.platform == Platform.ARDUINO) { - arguments.add(0, "-DCMAKE_TOOLCHAIN_FILE=" - + FileUtil.globFilesEndsWith(fileConfig.srcPkgPath.getParent().getParent(), "Arduino-toolchain.cmake").get(0)); - arguments.add(0, "-DARDUINO_BOARD_OPTIONS_FILE=" - + FileUtil.globFilesEndsWith(fileConfig.getSrcGenPath(), "BoardOptions.cmake").get(0)); - } if (GeneratorUtils.isHostWindows()) { arguments.add("-DCMAKE_SYSTEM_VERSION=\"10.0\""); @@ -321,7 +315,7 @@ public LFCommand compileCCommand( String fileToCompile, boolean noBinary ) { - String cFilename = getTargetFileName(fileToCompile, cppMode); + String cFilename = getTargetFileName(fileToCompile, cppMode, targetConfig); Path relativeSrcPath = fileConfig.getOutPath().relativize( fileConfig.getSrcGenPath().resolve(Paths.get(cFilename))); @@ -383,7 +377,10 @@ public LFCommand compileCCommand( * In C++ mode, the compiler produces .cpp files instead * of .c files and uses a C++ compiler to compiler the code. */ - static String getTargetFileName(String fileName, boolean cppMode) { + static String getTargetFileName(String fileName, boolean cppMode, TargetConfig targetConfig) { + if (targetConfig.platformOptions.platform == Platform.ARDUINO) { + return fileName + ".ino"; + } if (cppMode) { // If the C++ mode is enabled, use a .cpp extension return fileName + ".cpp"; From 89af268139da20decc6c01244e08873ca848dfa0 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:00:02 -0800 Subject: [PATCH 02/42] Conversion of Arduino IDE dependency to Arduino-CLI dependency for testing --- .github/workflows/c-tests.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/c-tests.yml b/.github/workflows/c-tests.yml index b4485fe459..e700ad168b 100644 --- a/.github/workflows/c-tests.yml +++ b/.github/workflows/c-tests.yml @@ -47,16 +47,13 @@ jobs: - name: Install RTI uses: ./.github/actions/install-rti if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }} - - name: Install Arduino Platform for MacOS + - name: Install Arduino CLI for MacOS run: | - brew install --cask arduino + brew install arduino-cli if: ${{ runner.os == 'macOS' }} - - name: Install Arduino Platform for Linux + - name: Install Arduino CLI for Linux run: | - wget "https://downloads.arduino.cc/arduino-1.8.19-linux32.tar.xz" - tar -xvf arduino-1.8.19-linux32.tar.xz - cd arduino-1.8.19/ - sudo ./install.sh + curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh if: ${{ runner.os == 'Linux' }} - name: Build RTI docker image uses: ./.github/actions/build-rti-docker From 1d5b36702dc5c48fa9d102bab07324bb0866ba41 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:01:58 -0800 Subject: [PATCH 03/42] Added Support for Regex String Matching for Relative Include Support --- .../lflang/generator/c/CCoreFilesUtils.java | 6 -- .../org/lflang/generator/c/CGenerator.java | 95 +++++++++---------- .../generator/c/CPreambleGenerator.java | 31 +++--- .../generator/c/CReactionGenerator.java | 13 ++- org.lflang/src/org/lflang/util/FileUtil.java | 86 +++++++++++++++++ 5 files changed, 160 insertions(+), 71 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java index aaf080467b..c563d4a239 100644 --- a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java +++ b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java @@ -16,12 +16,6 @@ public static List getCTargetSrc() { ); } - public static List getArduinoTargetHeaders() { - return List.of( - "Arduino.h" - ); - } - public static List getCTargetHeader() { return List.of( "include/api/api.h" diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index ec2b7986c3..169eced866 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -39,6 +39,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Paths; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; @@ -539,7 +540,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { generateCodeForCurrentFederate(lfModuleName); // Derive target filename from the .lf filename. - var cFilename = CCompiler.getTargetFileName(lfModuleName, this.CCppMode); + var cFilename = CCompiler.getTargetFileName(lfModuleName, this.CCppMode, targetConfig); var targetFile = fileConfig.getSrcGenPath() + File.separator + cFilename; try { if (isFederated) { @@ -548,41 +549,17 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { copyUserFiles(this.targetConfig, this.fileConfig); } + String srcPrefix = targetConfig.platformOptions.platform == Platform.ARDUINO ? "src/" : ""; + // Copy the core lib FileUtil.copyDirectoryFromClassPath( "/lib/c/reactor-c/core", - fileConfig.getSrcGenPath().resolve("core"), + fileConfig.getSrcGenPath().resolve(srcPrefix + "core"), true ); // Copy the C target files copyTargetFiles(); - // If we are running an Arduino Target, need to copy over the Arduino-CMake files. - if (targetConfig.platformOptions.platform == Platform.ARDUINO) { - FileUtil.copyDirectoryFromClassPath( - "/lib/platform/arduino/Arduino-CMake-Toolchain/Arduino", - fileConfig.getSrcGenPath().resolve("toolchain/Arduino"), - false - ); - FileUtil.copyDirectoryFromClassPath( - "/lib/platform/arduino/Arduino-CMake-Toolchain/Platform", - fileConfig.getSrcGenPath().resolve("toolchain/Platform"), - false - ); - FileUtil.copyFileFromClassPath( - "/lib/platform/arduino/Arduino-CMake-Toolchain/Arduino-toolchain.cmake", - fileConfig.getSrcGenPath().resolve("toolchain/Arduino-toolchain.cmake"), - true - ); - - StringBuilder s = new StringBuilder(); - s.append("set(ARDUINO_BOARD \""); - s.append(targetConfig.platformOptions.board.getBoardName()); - s.append("\")"); - FileUtil.writeToFile(s.toString(), - fileConfig.getSrcGenPath().resolve("toolchain/BoardOptions.cmake")); - } - // Write the generated code code.writeToFile(targetFile); } catch (IOException e) { @@ -596,21 +573,32 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { dockerGenerator.fromData(lfModuleName, federate.name, fileConfig)); } // If cmake is requested, generate the CMakeLists.txt - var cmakeFile = fileConfig.getSrcGenPath() + File.separator + "CMakeLists.txt"; - var cmakeCode = cmakeGenerator.generateCMakeCode( - List.of(cFilename), - lfModuleName, - errorReporter, - CCppMode, - mainDef != null, - cMakeExtras, - targetConfig - ); - try { - cmakeCode.writeToFile(cmakeFile); - } catch (IOException e) { - //noinspection ThrowableNotThrown,ResultOfMethodCallIgnored - Exceptions.sneakyThrow(e); + if (targetConfig.platformOptions.platform != Platform.ARDUINO){ + var cmakeFile = fileConfig.getSrcGenPath() + File.separator + "CMakeLists.txt"; + var cmakeCode = cmakeGenerator.generateCMakeCode( + List.of(cFilename), + lfModuleName, + errorReporter, + CCppMode, + mainDef != null, + cMakeExtras, + targetConfig + ); + try { + cmakeCode.writeToFile(cmakeFile); + } catch (IOException e) { + //noinspection ThrowableNotThrown,ResultOfMethodCallIgnored + Exceptions.sneakyThrow(e); + } + } else { + try { + Files.deleteIfExists(fileConfig.getSrcGenPath().resolve("src/lib/util.c")); + FileUtil.relativeIncludeHelper(fileConfig.getSrcGenPath().resolve("src/")); + FileUtil.arduinoDeleteHelper(fileConfig.getSrcGenPath().resolve("src/")); + } catch (IOException e) { + //noinspection ThrowableNotThrown,ResultOfMethodCallIgnored + Exceptions.sneakyThrow(e); + } } // If this code generator is directly compiling the code, compile it now so that we @@ -845,7 +833,7 @@ private void generateCodeForCurrentFederate( // is set to decentralized) or, if there are // downstream federates, will notify the RTI // that the specified logical time is complete. - if (CCppMode) code.pr("extern \"C\""); + if (CCppMode || targetConfig.platformOptions.platform == Platform.ARDUINO) code.pr("extern \"C\""); code.pr(String.join("\n", "void logical_tag_complete(tag_t tag_to_send) {", isFederatedAndCentralized() ? @@ -1150,14 +1138,17 @@ protected void initializeClockSynchronization() { * Copy target-specific header file to the src-gen directory. */ protected void copyTargetFiles() throws IOException { + + String srcPrefix = targetConfig.platformOptions.platform == Platform.ARDUINO ? "src/" : ""; + FileUtil.copyDirectoryFromClassPath( "/lib/c/reactor-c/include", - fileConfig.getSrcGenPath().resolve("include"), + fileConfig.getSrcGenPath().resolve(srcPrefix + "include"), false ); FileUtil.copyDirectoryFromClassPath( "/lib/c/reactor-c/lib", - fileConfig.getSrcGenPath().resolve("lib"), + fileConfig.getSrcGenPath().resolve(srcPrefix + "lib"), false ); } @@ -1548,6 +1539,7 @@ public void generateReactions(ReactorDecl decl, FederateInstance federate) { * @param reactionIndex The position of the reaction within the reactor. */ protected void generateReaction(Reaction reaction, ReactorDecl decl, int reactionIndex) { + code.pr(CReactionGenerator.generateReaction( reaction, decl, @@ -1556,7 +1548,8 @@ protected void generateReaction(Reaction reaction, ReactorDecl decl, int reactio errorReporter, types, isFederatedAndDecentralized(), - getTarget().requiresTypes + getTarget().requiresTypes, + targetConfig )); } @@ -2171,13 +2164,19 @@ protected void setUpGeneralParameters() { targetConfig.compileDefinitions.put("MODAL_REACTORS", "TRUE"); } if (targetConfig.threading && targetConfig.platformOptions.platform == Platform.ARDUINO) { - //Add error message when user attempts to set threading=true for Arduino if (targetConfig.setByUser.contains(TargetProperty.THREADING)) { errorReporter.reportWarning("Threading is incompatible on Arduino. Setting threading to false."); } targetConfig.threading = false; } + if (!targetConfig.noCompile && targetConfig.platformOptions.platform == Platform.ARDUINO) { + //Add warning message when user attempts to set threading=true for Arduino + if (!targetConfig.setByUser.contains(TargetProperty.NO_COMPILE)) { + errorReporter.reportWarning("Compilation should be done through arduino-cli. Setting no-compile to true."); + } + targetConfig.noCompile = true; + } if (targetConfig.threading) { // FIXME: This logic is duplicated in CMake pickScheduler(); // FIXME: this and pickScheduler should be combined. diff --git a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java index 7bf079f515..199c0107a9 100644 --- a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java @@ -39,32 +39,37 @@ public static String generateIncludeStatements( ) { var tracing = targetConfig.tracing; CodeBuilder code = new CodeBuilder(); - if (cppMode) { + if (cppMode || targetConfig.platformOptions.platform == Platform.ARDUINO) { code.pr("extern \"C\" {"); } + + String relPathHeader = ""; if (targetConfig.platformOptions.platform == Platform.ARDUINO) { - CCoreFilesUtils.getArduinoTargetHeaders().forEach( + relPathHeader = "src/include/"; + + CCoreFilesUtils.getCTargetHeader().forEach( + it -> code.pr("#include " + StringUtil.addDoubleQuotes("src/" + it)) + ); + } else { + CCoreFilesUtils.getCTargetHeader().forEach( it -> code.pr("#include " + StringUtil.addDoubleQuotes(it)) ); } - CCoreFilesUtils.getCTargetHeader().forEach( - it -> code.pr("#include " + StringUtil.addDoubleQuotes(it)) - ); - code.pr("#include \"core/reactor.h\""); - code.pr("#include \"core/reactor_common.h\""); + code.pr("#include \"" + relPathHeader + "core/reactor.h\""); + code.pr("#include \"" + relPathHeader + "core/reactor_common.h\""); if (targetConfig.threading) { - code.pr("#include \"core/threaded/scheduler.h\""); + code.pr("#include \"" + relPathHeader + "core/threaded/scheduler.h\""); } if (isFederated) { - code.pr("#include \"core/federated/federate.c\""); + code.pr("#include \"" + relPathHeader + "core/federated/federate.c\""); } if (tracing != null) { - code.pr("#include \"core/trace.h\""); + code.pr("#include \"" + relPathHeader + "core/trace.h\""); } - code.pr("#include \"core/mixed_radix.h\""); - code.pr("#include \"core/port.h\""); + code.pr("#include \"" + relPathHeader + "core/mixed_radix.h\""); + code.pr("#include \"" + relPathHeader + "core/port.h\""); code.pr("int lf_reactor_c_main(int argc, const char* argv[]);"); - if (cppMode) { + if (cppMode || targetConfig.platformOptions.platform == Platform.ARDUINO) { code.pr("}"); } return code.toString(); diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index cac6594edc..fff77b6fbd 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -13,6 +13,8 @@ import org.lflang.ASTUtils; import org.lflang.ErrorReporter; import org.lflang.InferredType; +import org.lflang.TargetConfig; +import org.lflang.TargetProperty.Platform; import org.lflang.federated.CGeneratorExtension; import org.lflang.federated.FederateInstance; import org.lflang.generator.CodeBuilder; @@ -1080,7 +1082,8 @@ public static String generateReaction( ErrorReporter errorReporter, CTypes types, boolean isFederatedAndDecentralized, - boolean requiresType + boolean requiresType, + TargetConfig targetConfig ) { var code = new CodeBuilder(); var body = ASTUtils.toText(reaction.getCode()); @@ -1089,15 +1092,17 @@ public static String generateReaction( types, errorReporter, mainDef, isFederatedAndDecentralized, requiresType); + + String srcPrefix = targetConfig.platformOptions.platform == Platform.ARDUINO ? "src/" : ""; code.pr( "#include " + StringUtil.addDoubleQuotes( - CCoreFilesUtils.getCTargetSetHeader())); + srcPrefix + CCoreFilesUtils.getCTargetSetHeader())); + CMethodGenerator.generateMacrosForMethods(ASTUtils.toDefinition(decl), code); code.pr(generateFunction( generateReactionFunctionHeader(decl, reactionIndex), init, reaction.getCode() )); - // Now generate code for the late function, if there is one // Note that this function can only be defined on reactions // in federates that have inputs from a logical connection. @@ -1116,7 +1121,7 @@ public static String generateReaction( CMethodGenerator.generateMacroUndefsForMethods(ASTUtils.toDefinition(decl), code); code.pr( "#include " + StringUtil.addDoubleQuotes( - CCoreFilesUtils.getCTargetSetUndefHeader())); + srcPrefix + CCoreFilesUtils.getCTargetSetUndefHeader())); return code.toString(); } diff --git a/org.lflang/src/org/lflang/util/FileUtil.java b/org.lflang/src/org/lflang/util/FileUtil.java index 3efcbfb228..154e00acc8 100644 --- a/org.lflang/src/org/lflang/util/FileUtil.java +++ b/org.lflang/src/org/lflang/util/FileUtil.java @@ -17,9 +17,13 @@ import java.util.Arrays; import java.util.Comparator; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -383,6 +387,88 @@ private static void copyDirectoryFromJar(JarURLConnection connection, final Path } } + /** + * Deletes Unused Files from Arduino-CLI based compilation. + * + * Arduino-CLI (the build system) uses lazy compilation (i.e. compiles every file recursively from + * a source directory). This does the work of CMake by explicitly deleting files that + * shouldn't get compiled by the CLI. Generally, we delete all CMake artifacts and multithreaded + * support files (including semaphores and thread folders) + * + * @param dir The folder to search for folders and files to delete. + * @throws IOException If the given folder and unneeded files cannot be deleted. + */ + public static void arduinoDeleteHelper(Path dir) throws IOException { + deleteDirectory(dir.resolve("core/federated")); // TODO: Add Federated Support to Arduino + deleteDirectory(dir.resolve("include/core/federated")); // TODO: Add Federated Support to Arduino + + deleteDirectory(dir.resolve("core/threaded")); // No Threaded Support for Arduino + deleteDirectory(dir.resolve("include/core/threaded")); // No Threaded Support for Arduino + + List allPaths = Files.walk(dir) + .sorted(Comparator.reverseOrder()) + .collect(Collectors.toList()); + for (Path path : allPaths) { + String toCheck = path.toString().toLowerCase(); + if (toCheck.contains("cmake") || toCheck.contains("semaphore") + || path.endsWith("lib/util.c") || (toCheck.contains("core/platform/") && !toCheck.contains("lf_arduino"))) { + Files.delete(path); + } + } + } + + private static String fileNameMatchConverter(String fileName, Path currPath, Map fileStringToFilePath) + throws NullPointerException { + // First get the child file + int lastPath = fileName.lastIndexOf(File.separator); + if (lastPath != -1){ + fileName = fileName.substring(lastPath+1); + } + Path p = fileStringToFilePath.get(fileName); + if(p == null){ + return "#include \"" + fileName + "\""; + } + String relativePath = currPath.getParent().relativize(p).toString(); + return "#include \"" + relativePath + "\""; + } + + /** + * Converts all includes recursively inside files within a specified folder to relative links + * + * @param dir The folder to search for includes to change. + * @throws IOException If the given set of files cannot be relativized. + */ + public static void relativeIncludeHelper(Path dir) throws IOException { + System.out.println("Relativizing all includes in " + dir.toString()); + List allPaths = Files.walk(dir) + .filter(Files::isRegularFile) + .sorted(Comparator.reverseOrder()) + .collect(Collectors.toList()); + Map fileStringToFilePath = new HashMap(); + for (Path path : allPaths) { + String fileName = path.getFileName().toString(); + fileStringToFilePath.put(fileName, path); + } + Pattern regexExpression = Pattern.compile("#include\s+[\"]([^\"]+)*[\"]"); + for (Path path : allPaths) { + String fileName = path.getFileName().toString(); + String fileContents = Files.readString(path); + Matcher matcher = regexExpression.matcher(fileContents); + int lastIndex = 0; + StringBuilder output = new StringBuilder(); + while (matcher.find()) { + output.append(fileContents, lastIndex, matcher.start()) + .append(fileNameMatchConverter(matcher.group(1), path, fileStringToFilePath)); + lastIndex = matcher.end(); + } + if (lastIndex < fileContents.length()) { + output.append(fileContents, lastIndex, fileContents.length()); + } + writeToFile(output.toString(), path); + } + } + + /** * Recursively delete a directory if it exists. * From 710c359b017b640ac3ecba2dc522e8fc4f46357e Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:51:06 -0800 Subject: [PATCH 04/42] Fixed Syntax to Match LF Standards Co-authored-by: Marten Lohstroh --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 2 +- org.lflang/src/org/lflang/util/FileUtil.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index c9bc092723..2b2bd8a260 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -585,7 +585,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { dockerGenerator.fromData(lfModuleName, federate.name, fileConfig)); } // If cmake is requested, generate the CMakeLists.txt - if (targetConfig.platformOptions.platform != Platform.ARDUINO){ + if (targetConfig.platformOptions.platform != Platform.ARDUINO) { var cmakeFile = fileConfig.getSrcGenPath() + File.separator + "CMakeLists.txt"; var cmakeCode = cmakeGenerator.generateCMakeCode( List.of(cFilename), diff --git a/org.lflang/src/org/lflang/util/FileUtil.java b/org.lflang/src/org/lflang/util/FileUtil.java index 154e00acc8..fc78b6503f 100644 --- a/org.lflang/src/org/lflang/util/FileUtil.java +++ b/org.lflang/src/org/lflang/util/FileUtil.java @@ -388,7 +388,7 @@ private static void copyDirectoryFromJar(JarURLConnection connection, final Path } /** - * Deletes Unused Files from Arduino-CLI based compilation. + * Delete unused Files from Arduino-CLI based compilation. * * Arduino-CLI (the build system) uses lazy compilation (i.e. compiles every file recursively from * a source directory). This does the work of CMake by explicitly deleting files that @@ -425,7 +425,7 @@ private static String fileNameMatchConverter(String fileName, Path currPath, Map fileName = fileName.substring(lastPath+1); } Path p = fileStringToFilePath.get(fileName); - if(p == null){ + if(p == null) { return "#include \"" + fileName + "\""; } String relativePath = currPath.getParent().relativize(p).toString(); @@ -433,7 +433,7 @@ private static String fileNameMatchConverter(String fileName, Path currPath, Map } /** - * Converts all includes recursively inside files within a specified folder to relative links + * Convert all includes recursively inside files within a specified folder to relative links * * @param dir The folder to search for includes to change. * @throws IOException If the given set of files cannot be relativized. From fe1ada34139b115b5ce91336270e86e6c923faa7 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 22:59:21 -0800 Subject: [PATCH 05/42] Added JavaDoc Comment for fileNameMatchConverter --- org.lflang/src/org/lflang/util/FileUtil.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/org.lflang/src/org/lflang/util/FileUtil.java b/org.lflang/src/org/lflang/util/FileUtil.java index fc78b6503f..c7b518f32b 100644 --- a/org.lflang/src/org/lflang/util/FileUtil.java +++ b/org.lflang/src/org/lflang/util/FileUtil.java @@ -417,6 +417,17 @@ public static void arduinoDeleteHelper(Path dir) throws IOException { } } + /** + * Helper function for getting the string representation of the relative path + * to take to get from one file (currPath) to get to the other (fileName). + * + * Generally, this is useful for converting includes to have relative pathing when + * you lack access to adding additional include paths when compiling. + * + * @param fileName File to search for. + * @param currPath The current path to the file whose include statements we are modifying. + * @param fileStringToFilePath Mapping of File Names to their paths. + */ private static String fileNameMatchConverter(String fileName, Path currPath, Map fileStringToFilePath) throws NullPointerException { // First get the child file From 71a56c4bb2b22381de69d88c828770e7b6e6f184 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 23:08:23 -0800 Subject: [PATCH 06/42] Added check to Map to prevent duplicates Exception is CMakeLists.txt, which itself should not be in the map. --- org.lflang/src/org/lflang/util/FileUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/util/FileUtil.java b/org.lflang/src/org/lflang/util/FileUtil.java index c7b518f32b..f3d6c87a34 100644 --- a/org.lflang/src/org/lflang/util/FileUtil.java +++ b/org.lflang/src/org/lflang/util/FileUtil.java @@ -458,7 +458,10 @@ public static void relativeIncludeHelper(Path dir) throws IOException { Map fileStringToFilePath = new HashMap(); for (Path path : allPaths) { String fileName = path.getFileName().toString(); - fileStringToFilePath.put(fileName, path); + if(path.getFileName().toString().contains("CMakeLists.txt")) continue; + if(fileStringToFilePath.put(fileName, path) != null) { + throw new IOException("Directory has different files with the same name. Cannot Relativize."); + } } Pattern regexExpression = Pattern.compile("#include\s+[\"]([^\"]+)*[\"]"); for (Path path : allPaths) { From bfff7865a2809dbcd5c0087475c9df62f9d742af Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 23:36:20 -0800 Subject: [PATCH 07/42] Added explicit version download of arduino-cli to 0.29.0 --- .github/workflows/c-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c-tests.yml b/.github/workflows/c-tests.yml index a7987b7c46..c11ea0d849 100644 --- a/.github/workflows/c-tests.yml +++ b/.github/workflows/c-tests.yml @@ -55,7 +55,7 @@ jobs: if: ${{ runner.os == 'macOS' }} - name: Install Arduino CLI for Linux run: | - curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh + curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh -s 0.29.0 if: ${{ runner.os == 'Linux' }} - name: Build RTI docker image uses: ./.github/actions/build-rti-docker From d512671ceb82daa1770e21e359cee9e7f79d5c71 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sun, 8 Jan 2023 23:36:39 -0800 Subject: [PATCH 08/42] Update reactor-c dependency to working arduino branch --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index d97620bb54..3a5b2f7207 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit d97620bb54734a25521271169dadae68b6b3ad9b +Subproject commit 3a5b2f7207377466a39f203ec98c261bdb3da9fe From 96b5592d7644b876fe20b0c13df38066c9bf3f9d Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Mon, 9 Jan 2023 07:10:24 -0800 Subject: [PATCH 09/42] Update submodule of reactor-c --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 3a5b2f7207..66096e0415 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 3a5b2f7207377466a39f203ec98c261bdb3da9fe +Subproject commit 66096e0415494b170abb3565b4d09c3ea65101df From d28fe2dab48ead17fbc64b661a05f94d56c62c88 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Mon, 9 Jan 2023 07:20:10 -0800 Subject: [PATCH 10/42] Added author tags --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 1 + org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java | 1 + 2 files changed, 2 insertions(+) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 5d16424297..287e9a12ad 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -328,6 +328,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * @author Soroush Bateni * @author Alexander Schulz-Rosengarten * @author Hou Seng Wong + * @author Anirudh Rengarajan */ @SuppressWarnings("StaticPseudoFunctionalStyleMethod") public class CGenerator extends GeneratorBase { diff --git a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java index 8c46fa5c66..3d9babbb04 100644 --- a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java @@ -29,6 +29,7 @@ * @author Alexander Schulz-Rosengarten * @author Hou Seng Wong * @author Peter Donovan + * @author Anirudh Rengarajan */ public class CPreambleGenerator { /** Add necessary source files specific to the target language. */ From 2e525eef3cf1456c0713c97a19a7ed651c03a04a Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:26:49 -0800 Subject: [PATCH 11/42] Update submodule dependency --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 66096e0415..a03131a1e8 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 66096e0415494b170abb3565b4d09c3ea65101df +Subproject commit a03131a1e846fdd42632a1db94a7915362a3a58d From e0ab6ce2ef1c32992173ea60430dac1bc11fb194 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sat, 14 Jan 2023 17:37:22 -0800 Subject: [PATCH 12/42] Moved Arduino Files out of failing since tests are now successful --- .../src/org/lflang/tests/TestBase.java | 46 +++++++++++++++++++ .../arduino/{failing => }/AnalogReadSerial.lf | 0 test/C/src/arduino/{failing => }/Blink.lf | 0 .../{failing => }/BlinkAttemptThreading.lf | 0 .../{failing => }/BlinkCustomPlatform.lf | 2 +- .../{failing => }/DigitalReadSerial.lf | 0 test/C/src/arduino/{failing => }/Fade.lf | 0 .../{failing => }/ReadAnalogVoltage.lf | 0 8 files changed, 47 insertions(+), 1 deletion(-) rename test/C/src/arduino/{failing => }/AnalogReadSerial.lf (100%) rename test/C/src/arduino/{failing => }/Blink.lf (100%) rename test/C/src/arduino/{failing => }/BlinkAttemptThreading.lf (100%) rename test/C/src/arduino/{failing => }/BlinkCustomPlatform.lf (93%) rename test/C/src/arduino/{failing => }/DigitalReadSerial.lf (100%) rename test/C/src/arduino/{failing => }/Fade.lf (100%) rename test/C/src/arduino/{failing => }/ReadAnalogVoltage.lf (100%) diff --git a/org.lflang.tests/src/org/lflang/tests/TestBase.java b/org.lflang.tests/src/org/lflang/tests/TestBase.java index 8770b50b1f..4247a41f05 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestBase.java +++ b/org.lflang.tests/src/org/lflang/tests/TestBase.java @@ -159,6 +159,7 @@ public static class Message { /* Missing dependency messages */ public static final String MISSING_DOCKER = "Executable 'docker' not found or 'docker' daemon thread not running"; + public static final String MISSING_ARDUINO_CLI = "Executable 'arduino-cli' not found"; } /** Constructor for test classes that test a single target. */ @@ -496,7 +497,9 @@ private void execute(LFTest test, GeneratorResult generatorResult) throws TestEr } try { for (ProcessBuilder pb : pbList) { + System.out.println(pb.command()); var p = pb.start(); + var stdout = test.recordStdOut(p); var stderr = test.recordStdErr(p); @@ -586,6 +589,47 @@ private String getDockerRunScript(List dockerFiles, Path dockerComposeFile return shCode.toString(); } + /** + * Returns true if arduino-cli exists, false otherwise. + */ + private boolean checkArduinoCLIExists() { + LFCommand checkCommand = LFCommand.get("arduino-cli", List.of("version")); + return checkCommand.run() == 0; + } + + /** + * Return a ProcessBuilder used to test Arduino in a non-federated, unthreaded environment. + * See the following for references on arduino-cli: + * https://arduino.github.io/arduino-cli/ + * + * @param test The test to get the execution command for. + */ + private List getArduinoExecCommand(LFTest test) { + if (!checkArduinoCLIExists()) { + System.out.println(Message.MISSING_ARDUINO_CLI); + return List.of(new ProcessBuilder("exit", "1")); + } + var srcGenPath = test.getFileConfig().getSrcGenPath(); + try { + //Write to a temporary file to execute since ProcessBuilder does not like spaces and double quotes in its arguments. + File testScript = File.createTempFile("arduinotest", null); + testScript.deleteOnExit(); + if (!testScript.setExecutable(true)) { + throw new IOException("Failed to make test script executable"); + } + FileWriter fileWriter = new FileWriter(testScript.getAbsoluteFile(), true); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + bufferedWriter.write("arduino-cli compile -b arduino:avr:leonardo --build-property " + + "compiler.c.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + + "--build-property compiler.cpp.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + + srcGenPath.toString()); + bufferedWriter.close(); + return List.of(new ProcessBuilder(testScript.getAbsolutePath())); + } catch (IOException e) { + return List.of(new ProcessBuilder("exit", "1")); + } + } + /** * Returns true if docker exists, false otherwise. */ @@ -658,6 +702,8 @@ private List getExecCommand(LFTest test, GeneratorResult generat return getNonfederatedDockerExecCommand(test); } else if (relativePathName.equalsIgnoreCase(TestCategory.DOCKER_FEDERATED.getPath())) { return getFederatedDockerExecCommand(test); + } else if (relativePathName.equalsIgnoreCase(TestCategory.ARDUINO.getPath())) { + return getArduinoExecCommand(test); } else { LFCommand command = generatorResult.getCommand(); if (command == null) { diff --git a/test/C/src/arduino/failing/AnalogReadSerial.lf b/test/C/src/arduino/AnalogReadSerial.lf similarity index 100% rename from test/C/src/arduino/failing/AnalogReadSerial.lf rename to test/C/src/arduino/AnalogReadSerial.lf diff --git a/test/C/src/arduino/failing/Blink.lf b/test/C/src/arduino/Blink.lf similarity index 100% rename from test/C/src/arduino/failing/Blink.lf rename to test/C/src/arduino/Blink.lf diff --git a/test/C/src/arduino/failing/BlinkAttemptThreading.lf b/test/C/src/arduino/BlinkAttemptThreading.lf similarity index 100% rename from test/C/src/arduino/failing/BlinkAttemptThreading.lf rename to test/C/src/arduino/BlinkAttemptThreading.lf diff --git a/test/C/src/arduino/failing/BlinkCustomPlatform.lf b/test/C/src/arduino/BlinkCustomPlatform.lf similarity index 93% rename from test/C/src/arduino/failing/BlinkCustomPlatform.lf rename to test/C/src/arduino/BlinkCustomPlatform.lf index 609d4034b6..a5df2a94e4 100644 --- a/test/C/src/arduino/failing/BlinkCustomPlatform.lf +++ b/test/C/src/arduino/BlinkCustomPlatform.lf @@ -9,7 +9,7 @@ target CCpp { platform: { name: "arduino", baud-rate: 9600, - board: "mega_2560" + board: "arduino:mbed_nano:nano33ble" } } diff --git a/test/C/src/arduino/failing/DigitalReadSerial.lf b/test/C/src/arduino/DigitalReadSerial.lf similarity index 100% rename from test/C/src/arduino/failing/DigitalReadSerial.lf rename to test/C/src/arduino/DigitalReadSerial.lf diff --git a/test/C/src/arduino/failing/Fade.lf b/test/C/src/arduino/Fade.lf similarity index 100% rename from test/C/src/arduino/failing/Fade.lf rename to test/C/src/arduino/Fade.lf diff --git a/test/C/src/arduino/failing/ReadAnalogVoltage.lf b/test/C/src/arduino/ReadAnalogVoltage.lf similarity index 100% rename from test/C/src/arduino/failing/ReadAnalogVoltage.lf rename to test/C/src/arduino/ReadAnalogVoltage.lf From dfe5ffa28554b46cbeee40685945be97b1c05561 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sat, 14 Jan 2023 17:37:52 -0800 Subject: [PATCH 13/42] Update Test Registry since we now execute via the arduino-cli --- org.lflang.tests/src/org/lflang/tests/TestRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang.tests/src/org/lflang/tests/TestRegistry.java b/org.lflang.tests/src/org/lflang/tests/TestRegistry.java index 3aea7a6e58..2670dcd0be 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestRegistry.java +++ b/org.lflang.tests/src/org/lflang/tests/TestRegistry.java @@ -147,7 +147,7 @@ public enum TestCategory { DOCKER(true), DOCKER_FEDERATED(true, "docker" + File.separator + "federated"), SERIALIZATION(false), - ARDUINO(false, TestLevel.BUILD), + ARDUINO(false), TARGET(false); /** From 031e3f60289944f778b465d53873a867170289b9 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sat, 14 Jan 2023 17:38:42 -0800 Subject: [PATCH 14/42] Added custom print function to interface Arduino Prints with LF printing --- .../lflang/generator/c/CMainFunctionGenerator.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CMainFunctionGenerator.java b/org.lflang/src/org/lflang/generator/c/CMainFunctionGenerator.java index 7b05a52923..919f592f99 100644 --- a/org.lflang/src/org/lflang/generator/c/CMainFunctionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CMainFunctionGenerator.java @@ -44,11 +44,17 @@ private String generateMainFunction() { - Logging */ return String.join("\n", + "\nvoid _lf_arduino_print_message_function(const char* format, va_list args) {", + "\tchar buf[128];", + "\tvsnprintf(buf, 128, format, args);", + "\tSerial.print(buf);", + "}\n", "// Arduino setup() and loop() functions", "void setup() {", - "Serial.begin(" + targetConfig.platformOptions.baudRate + ");", - "lf_reactor_c_main(0, NULL);", - "}", + "\tSerial.begin(" + targetConfig.platformOptions.baudRate + ");", + "\tlf_register_print_function(&_lf_arduino_print_message_function, LOG_LEVEL);", + "\tlf_reactor_c_main(0, NULL);", + "}\n", "void loop() {}" ); } From 912a66b90e8c246de93a69b4c50fcbacc76e5150 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sat, 14 Jan 2023 17:39:14 -0800 Subject: [PATCH 15/42] Modified Board Params and Added Flash and Port functionality to Target Property --- org.lflang/src/org/lflang/TargetConfig.java | 78 ++++--------------- org.lflang/src/org/lflang/TargetProperty.java | 24 +++--- 2 files changed, 26 insertions(+), 76 deletions(-) diff --git a/org.lflang/src/org/lflang/TargetConfig.java b/org.lflang/src/org/lflang/TargetConfig.java index 6e68ce3042..21a1456435 100644 --- a/org.lflang/src/org/lflang/TargetConfig.java +++ b/org.lflang/src/org/lflang/TargetConfig.java @@ -343,68 +343,6 @@ public static class DockerOptions { public String from = "alpine:latest"; } - /** - * Enum representing the different boards supported by Arduino-CMake and future embedded boards. - */ - public enum Board { - NONE(), - YN("Arduino Yn [avr.yun]"), - UNO("Arduino Uno [avr.uno]"), - DUEMILANOVE("Arduino Duemilanove or Diecimila [avr.diecimila]"), - DIECIMILA("Arduino Duemilanove or Diecimila [avr.diecimila]"), - NANO("Arduino Nano [avr.nano]"), - MEGA("Arduino Mega or Mega 2560 [avr.mega]"), - MEGA_2560("Arduino Mega or Mega 2560 [avr.mega]"), - MEGA_ADK("Arduino Mega ADK [avr.megaADK]"), - LEONARDO("Arduino Leonardo [avr.leonardo]"), - LEONARDO_ETH("Arduino Leonardo ETH [avr.leonardoeth]"), - MICRO("Arduino Micro [avr.micro]"), - ESPLORA("Arduino Esplora [avr.esplora]"), - MINI("Arduino Mini [avr.mini]"), - ETHERNET("Arduino Ethernet [avr.ethernet]"), - FIO("Arduino Fio [avr.fio]"), - BT("Arduino BT [avr.bt]"), - LILYPAD_USB("LilyPad Arduino USB [avr.LilyPadUSB]"), - LILYPAD("LilyPad Arduino [avr.lilypad]"), - PRO("Arduino Pro or Pro Mini [avr.pro]"), - PRO_MINI("Arduino Pro or Pro Mini [avr.pro]"), - NG("Arduino NG or older [avr.atmegang]"), - OLDER("Arduino NG or older [avr.atmegang]"), - ROBOT_CONTROL("Arduino Robot Control [avr.robotControl]"), - ROBOT_MOTOR("Arduino Robot Motor [avr.robotMotor]"), - GEMMA("Arduino Gemma [avr.gemma]"), - CIRCUIT_PLAYGROUND("Adafruit Circuit Playground [avr.circuitplay32u4cat]"), - YN_MINI("Arduino Yn Mini [avr.yunmini]"), - INDUSTRIAL_101("Arduino Industrial 101 [avr.chiwawa]"), - LININO_ONE("Linino One [avr.one]"), - UNO_WIFI("Arduino Uno WiFi [avr.unowifi]"), - SAM_DUE_PROG("Arduino Due (Programming Port) [sam.arduino_due_x_dbg]"), - SAM_DUE_NATIVE("Arduino Due (Native USB Port) [sam.arduino_due_x]"); - - String boardName; - Board() { - this.boardName = this.toString(); - } - Board(String boardName) { - this.boardName = boardName; - } - - /** - * Return the name in lower case. - */ - @Override - public String toString() { - return this.name().toLowerCase(); - } - - /** - * Get the CMake name for the platform. - */ - public String getBoardName() { - return this.boardName; - } - } - /** * Settings related to Platform Options. */ @@ -416,14 +354,26 @@ public static class PlatformOptions { public Platform platform = Platform.AUTO; /** - * The base board we target when building LF on Arduino/Embedded Boards. For OS development and generic embedded systems, this value is unused. + * The string value used to determine what type of embedded board we work with and can be used to simplify the build process. For example, + * when we want to flash to an Arduino Nano 33 BLE board, we can use the string arduino:mbed_nano:nano33ble */ - public Board board = Board.UNO; + public String board = ""; + + /** + * The string value used to determine the port on which to flash the compiled program (i.e. /dev/cu.usbmodem21301) + */ + public String port = ""; /** * The baud rate used as a parameter to certain embedded platforms. 9600 is a standard rate amongst systems like Arduino, so it's the default value. */ public int baudRate = 9600; + + /** + * The boolean statement used to determine whether we should automatically attempt to flash once we compile. This may require the use of board and + * port values depending on the infrastructure you use to flash the boards. + */ + public boolean flash = false; } /** diff --git a/org.lflang/src/org/lflang/TargetProperty.java b/org.lflang/src/org/lflang/TargetProperty.java index 404a6c44a6..6684100464 100644 --- a/org.lflang/src/org/lflang/TargetProperty.java +++ b/org.lflang/src/org/lflang/TargetProperty.java @@ -33,8 +33,9 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import javax.lang.model.type.PrimitiveType; + import org.eclipse.xtext.util.RuntimeIOException; -import org.lflang.TargetConfig.Board; import org.lflang.TargetConfig.DockerOptions; import org.lflang.TargetConfig.PlatformOptions; import org.lflang.TargetConfig.TracingOptions; @@ -327,15 +328,13 @@ public enum TargetProperty { config.platformOptions.baudRate = ASTUtils.toInteger(entry.getValue()); break; case BOARD: - Board b = (Board) UnionType.BOARD_UNION - .forName(ASTUtils.elementToSingleString(entry.getValue())); - if(b == null){ - String s = "Unidentified Board Type, LF supports the following board types: " + Arrays.asList(Board.values()).toString(); - err.reportError(s); - throw new AssertionError(s); - } - - config.platformOptions.board = b; + config.platformOptions.board = ASTUtils.elementToSingleString(entry.getValue()); + break; + case FLASH: + config.platformOptions.flash = ASTUtils.toBoolean(entry.getValue()); + break; + case PORT: + config.platformOptions.port = ASTUtils.elementToSingleString(entry.getValue()); break; default: break; @@ -851,7 +850,6 @@ public enum UnionType implements TargetPropertyType { SCHEDULER_UNION(Arrays.asList(SchedulerOption.values()), SchedulerOption.getDefault()), LOGGING_UNION(Arrays.asList(LogLevel.values()), LogLevel.INFO), PLATFORM_UNION(Arrays.asList(Platform.values()), Platform.AUTO), - BOARD_UNION(Arrays.asList(Board.values()), Board.NONE), CLOCK_SYNC_UNION(Arrays.asList(ClockSyncMode.values()), ClockSyncMode.INIT), DOCKER_UNION(Arrays.asList(PrimitiveType.BOOLEAN, DictionaryType.DOCKER_DICT), @@ -1327,7 +1325,9 @@ public TargetPropertyType getType() { public enum PlatformOption implements DictionaryElement { NAME("name", PrimitiveType.STRING), BAUDRATE("baud-rate", PrimitiveType.NON_NEGATIVE_INTEGER), - BOARD("board", PrimitiveType.STRING); + BOARD("board", PrimitiveType.STRING), + FLASH("flash", PrimitiveType.BOOLEAN), + PORT("port", PrimitiveType.STRING); public final PrimitiveType type; From c0758540d7d5ba77595d8caa8631fc86a386c79e Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Sat, 14 Jan 2023 20:35:37 -0800 Subject: [PATCH 16/42] Update submodule dependency --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index a03131a1e8..a7ef3a4953 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit a03131a1e846fdd42632a1db94a7915362a3a58d +Subproject commit a7ef3a495337b13c14ac3cda048dac057323cddf From f3ae2d2f062e1617bfa1281f945f6cc71a9a9b94 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Tue, 24 Jan 2023 08:56:42 -0800 Subject: [PATCH 17/42] Remove deprecated util.c delete line. --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 287e9a12ad..a913ae7b20 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -605,7 +605,6 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { } } else { try { - Files.deleteIfExists(fileConfig.getSrcGenPath().resolve("src/lib/util.c")); FileUtil.relativeIncludeHelper(fileConfig.getSrcGenPath().resolve("src/")); FileUtil.arduinoDeleteHelper(fileConfig.getSrcGenPath().resolve("src/")); } catch (IOException e) { From 93b10f4e7d3310a430b765507762c1f441b59725 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Tue, 24 Jan 2023 19:09:15 -0800 Subject: [PATCH 18/42] Fix merge artifact --- org.lflang.tests/src/org/lflang/tests/TestRegistry.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.lflang.tests/src/org/lflang/tests/TestRegistry.java b/org.lflang.tests/src/org/lflang/tests/TestRegistry.java index df2bab5bbe..44eab63a16 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestRegistry.java +++ b/org.lflang.tests/src/org/lflang/tests/TestRegistry.java @@ -146,10 +146,11 @@ public enum TestCategory { DOCKER_FEDERATED(true, "docker" + File.separator + "federated"), SERIALIZATION(false), ARDUINO(false), + ZEPHYR(false, TestLevel.BUILD), TARGET(false); /** - * Whether or not we should compare coverage against other targets. + * Whether we should compare coverage against other targets. */ public final boolean isCommon; public final String path; From 43f6a8b4f6fe9ef4cb510266f65e508b15fb211a Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Tue, 24 Jan 2023 20:07:17 -0800 Subject: [PATCH 19/42] Fixed tests that broke build. --- test/C/src/arduino/AnalogReadSerial.lf | 2 +- test/C/src/arduino/Blink.lf | 2 +- test/C/src/arduino/BlinkAttemptThreading.lf | 2 +- test/C/src/arduino/BlinkCustomPlatform.lf | 2 +- test/C/src/arduino/DigitalReadSerial.lf | 2 +- test/C/src/arduino/Fade.lf | 2 +- test/C/src/arduino/ReadAnalogVoltage.lf | 6 +++--- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/C/src/arduino/AnalogReadSerial.lf b/test/C/src/arduino/AnalogReadSerial.lf index 22e45f6719..39eda80bd4 100644 --- a/test/C/src/arduino/AnalogReadSerial.lf +++ b/test/C/src/arduino/AnalogReadSerial.lf @@ -4,7 +4,7 @@ * Serial Plotter menu). Attach the center pin of a potentiometer to pin A0, and * the outside pins to +5V and ground. */ -target CCpp { +target C { platform: "Arduino" } diff --git a/test/C/src/arduino/Blink.lf b/test/C/src/arduino/Blink.lf index 32c1f85e32..da1820e008 100644 --- a/test/C/src/arduino/Blink.lf +++ b/test/C/src/arduino/Blink.lf @@ -3,7 +3,7 @@ * off an LED on the Arduino Board with a 50% duty cycle switching every * half-second. */ -target CCpp { +target C { platform: "Arduino" } diff --git a/test/C/src/arduino/BlinkAttemptThreading.lf b/test/C/src/arduino/BlinkAttemptThreading.lf index 2e84bcfed5..96e7571db0 100644 --- a/test/C/src/arduino/BlinkAttemptThreading.lf +++ b/test/C/src/arduino/BlinkAttemptThreading.lf @@ -4,7 +4,7 @@ * half-second. Note: if we try to enable threading, the system will give us a * warning and default back to no threading. */ -target CCpp { +target C { platform: "Arduino", threading: true } diff --git a/test/C/src/arduino/BlinkCustomPlatform.lf b/test/C/src/arduino/BlinkCustomPlatform.lf index a5df2a94e4..89bc55514b 100644 --- a/test/C/src/arduino/BlinkCustomPlatform.lf +++ b/test/C/src/arduino/BlinkCustomPlatform.lf @@ -5,7 +5,7 @@ * * This tests the overloading capabilities of the platform argument. */ -target CCpp { +target C { platform: { name: "arduino", baud-rate: 9600, diff --git a/test/C/src/arduino/DigitalReadSerial.lf b/test/C/src/arduino/DigitalReadSerial.lf index 243a5f7ca5..f7a53c5c2d 100644 --- a/test/C/src/arduino/DigitalReadSerial.lf +++ b/test/C/src/arduino/DigitalReadSerial.lf @@ -2,7 +2,7 @@ * This example reads a digital input on pin 2, prints the result to the Serial * Monitor */ -target CCpp { +target C { platform: "Arduino" } diff --git a/test/C/src/arduino/Fade.lf b/test/C/src/arduino/Fade.lf index ac16ff3943..8240a0ee89 100644 --- a/test/C/src/arduino/Fade.lf +++ b/test/C/src/arduino/Fade.lf @@ -5,7 +5,7 @@ * the PWM pins are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and * ~11. */ -target CCpp { +target C { platform: "Arduino" } diff --git a/test/C/src/arduino/ReadAnalogVoltage.lf b/test/C/src/arduino/ReadAnalogVoltage.lf index ad507d1e5d..ebb7a8f9c6 100644 --- a/test/C/src/arduino/ReadAnalogVoltage.lf +++ b/test/C/src/arduino/ReadAnalogVoltage.lf @@ -5,14 +5,14 @@ * center pin of a potentiometer to pin A0, and the outside pins to +5V and * ground. */ -target CCpp { +target C { platform: "Arduino" } main reactor ReadAnalogVoltage { logical action a - reaction(startup) -> a {= schedule(a, 0); =} + reaction(startup) -> a {= lf_schedule(a, 0); =} reaction(a) -> a {= int sensorValue = analogRead(A0); @@ -20,6 +20,6 @@ main reactor ReadAnalogVoltage { float voltage = sensorValue * (5.0 / 1023.0); // print out the value you read: Serial.println(voltage); - schedule(a, 0); + lf_schedule(a, 0); =} } From 781b13941d6b6cc5c495d4864fc5f6717c0f65db Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 26 Jan 2023 15:46:31 -0800 Subject: [PATCH 20/42] Bring back code from @erlingrj to handle Zephyr --- .../org/lflang/generator/c/CGenerator.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index f411a53aa6..799944eee3 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -493,6 +493,26 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { // Copy the C target files copyTargetFiles(); + // For the Zephyr target, copy default config and board files. + if (targetConfig.platformOptions.platform == Platform.ZEPHYR) { + FileUtil.copyDirectoryFromClassPath( + "/lib/platform/zephyr/boards", + fileConfig.getSrcGenPath().resolve("boards"), + false + ); + FileUtil.copyFileFromClassPath( + "/lib/platform/zephyr/prj_lf.conf", + fileConfig.getSrcGenPath().resolve("prj_lf.conf"), + true + ); + + FileUtil.copyFileFromClassPath( + "/lib/platform/zephyr/Kconfig", + fileConfig.getSrcGenPath().resolve("Kconfig"), + true + ); + } + // Write the generated code code.writeToFile(targetFile); } catch (IOException e) { From 5f1226f67f61bc6fe0f3dfb2586d78d4e51c5243 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 26 Jan 2023 16:19:15 -0800 Subject: [PATCH 21/42] Minor adjustments in FileUtil --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 2 +- org.lflang/src/org/lflang/util/FileUtil.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 799944eee3..68ced995ab 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -551,8 +551,8 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { } } else { try { - FileUtil.relativeIncludeHelper(fileConfig.getSrcGenPath().resolve("src/")); FileUtil.arduinoDeleteHelper(fileConfig.getSrcGenPath().resolve("src/")); + FileUtil.relativeIncludeHelper(fileConfig.getSrcGenPath().resolve("src/")); } catch (IOException e) { //noinspection ThrowableNotThrown,ResultOfMethodCallIgnored Exceptions.sneakyThrow(e); diff --git a/org.lflang/src/org/lflang/util/FileUtil.java b/org.lflang/src/org/lflang/util/FileUtil.java index 60397b99f1..2761a0f84c 100644 --- a/org.lflang/src/org/lflang/util/FileUtil.java +++ b/org.lflang/src/org/lflang/util/FileUtil.java @@ -411,9 +411,9 @@ public static void arduinoDeleteHelper(Path dir) throws IOException { for (Path path : allPaths) { String toCheck = path.toString().toLowerCase(); if (toCheck.contains("cmake") || toCheck.contains("semaphore") - || path.endsWith("lib/util.c") || (toCheck.contains("core/platform/") && !toCheck.contains("lf_arduino"))) { + || (toCheck.contains("core/platform/") && !toCheck.contains("lf_arduino"))) { Files.delete(path); - } + } } } @@ -458,8 +458,8 @@ public static void relativeIncludeHelper(Path dir) throws IOException { Map fileStringToFilePath = new HashMap(); for (Path path : allPaths) { String fileName = path.getFileName().toString(); - if(path.getFileName().toString().contains("CMakeLists.txt")) continue; - if(fileStringToFilePath.put(fileName, path) != null) { + if (path.getFileName().toString().contains("CMakeLists.txt")) continue; + if (fileStringToFilePath.put(fileName, path) != null) { throw new IOException("Directory has different files with the same name. Cannot Relativize."); } } From b7f548b427f11ea0f6b0dc4dd1aa4e6372071dbe Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 26 Jan 2023 16:49:35 -0800 Subject: [PATCH 22/42] Fix NPE in checkArduinoCLIExists --- org.lflang.tests/src/org/lflang/tests/TestBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang.tests/src/org/lflang/tests/TestBase.java b/org.lflang.tests/src/org/lflang/tests/TestBase.java index 373e4e5bb7..6368a4ac13 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestBase.java +++ b/org.lflang.tests/src/org/lflang/tests/TestBase.java @@ -582,7 +582,7 @@ static public String stackTraceToString(Throwable t) { */ private boolean checkArduinoCLIExists() { LFCommand checkCommand = LFCommand.get("arduino-cli", List.of("version")); - return checkCommand.run() == 0; + return checkCommand != null && checkCommand.run() == 0; } /** From 0c6c8e87044ebdc9c155f6cf76f07803b39cb77d Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 26 Jan 2023 16:54:05 -0800 Subject: [PATCH 23/42] Install Arduino CLI using a GitHub Action --- .github/workflows/c-tests.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/c-tests.yml b/.github/workflows/c-tests.yml index c11ea0d849..e5d38c8008 100644 --- a/.github/workflows/c-tests.yml +++ b/.github/workflows/c-tests.yml @@ -49,14 +49,8 @@ jobs: - name: Install RTI uses: ./.github/actions/install-rti if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }} - - name: Install Arduino CLI for MacOS - run: | - brew install arduino-cli - if: ${{ runner.os == 'macOS' }} - - name: Install Arduino CLI for Linux - run: | - curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh -s 0.29.0 - if: ${{ runner.os == 'Linux' }} + - name: Install Arduino CLI + uses: arduino/setup-arduino-cli@v1 - name: Build RTI docker image uses: ./.github/actions/build-rti-docker if: ${{ runner.os == 'Linux' }} From ab82d733d168f6e0123e2ac636e111a48ff7a1a8 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 26 Jan 2023 17:23:52 -0800 Subject: [PATCH 24/42] Update org.lflang.tests/src/org/lflang/tests/TestRegistry.java --- org.lflang.tests/src/org/lflang/tests/TestRegistry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang.tests/src/org/lflang/tests/TestRegistry.java b/org.lflang.tests/src/org/lflang/tests/TestRegistry.java index 44eab63a16..232e735641 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestRegistry.java +++ b/org.lflang.tests/src/org/lflang/tests/TestRegistry.java @@ -145,7 +145,7 @@ public enum TestCategory { DOCKER(true), DOCKER_FEDERATED(true, "docker" + File.separator + "federated"), SERIALIZATION(false), - ARDUINO(false), + ARDUINO(false, TestLevel.BUILD), ZEPHYR(false, TestLevel.BUILD), TARGET(false); From 7a6182956b0dd95c9878abbf2c86caf3d155d95f Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:12:42 -0800 Subject: [PATCH 25/42] Added Arduino Util Static Class to contain Arduino specific logic for building. --- org.lflang/src/org/lflang/TargetConfig.java | 2 +- .../org/lflang/generator/c/CGenerator.java | 35 ++++-- .../src/org/lflang/util/ArduinoUtil.java | 101 ++++++++++++++++++ 3 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 org.lflang/src/org/lflang/util/ArduinoUtil.java diff --git a/org.lflang/src/org/lflang/TargetConfig.java b/org.lflang/src/org/lflang/TargetConfig.java index 096d3a77be..446460d5c1 100644 --- a/org.lflang/src/org/lflang/TargetConfig.java +++ b/org.lflang/src/org/lflang/TargetConfig.java @@ -386,7 +386,7 @@ public static class PlatformOptions { /** * The string value used to determine the port on which to flash the compiled program (i.e. /dev/cu.usbmodem21301) */ - public String port = ""; + public String port = null; /** * The baud rate used as a parameter to certain embedded platforms. 9600 is a standard rate amongst systems like Arduino, so it's the default value. diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 68ced995ab..cbbaad7107 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -36,7 +36,9 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import static org.lflang.ASTUtils.toText; import static org.lflang.util.StringUtil.addDoubleQuotes; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -95,7 +97,9 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.ReactorDecl; import org.lflang.lf.StateVar; import org.lflang.lf.Variable; +import org.lflang.util.ArduinoUtil; import org.lflang.util.FileUtil; +import org.lflang.util.LFCommand; import com.google.common.base.Objects; import com.google.common.collect.Iterables; @@ -557,12 +561,28 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { //noinspection ThrowableNotThrown,ResultOfMethodCallIgnored Exceptions.sneakyThrow(e); } + + if (!targetConfig.noCompile) { + ArduinoUtil arduinoUtil = new ArduinoUtil(context, commandFactory, errorReporter); + arduinoUtil.buildArduino(fileConfig, targetConfig); + context.finish( + GeneratorResult.Status.COMPILED, null + ); + } else { + System.out.println("********"); + System.out.println("To compile your program, run the following command to see information about the board you plugged in:\n\n\tarduino-cli board list\n\nGrab the FQBN and PORT from the command and run the following command in the generated sources directory:\n\n\tarduino-cli compile -b --build-property compiler.c.extra_flags='-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10' --build-property compiler.cpp.extra_flags='-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10' .\n\nTo flash/upload your generated sketch to the board, run the following command in the generated sources directory:\n\n\tarduino-cli upload -b -p \n"); + // System.out.println("For a list of all boards installed on your computer, you can use the following command:\n\n\tarduino-cli board listall\n"); + context.finish( + GeneratorResult.GENERATED_NO_EXECUTABLE.apply(context, null) + ); + } + GeneratorUtils.refreshProject(resource, context.getMode()); + return; } // Dump the additional compile definitions to a file to keep the generated project // self-contained. In this way, third-party build tools like PlatformIO, west, arduino-cli can // take over and do the rest of compilation. - try { String compileDefs = targetConfig.compileDefinitions.keySet().stream() .map(key -> key + "=" + targetConfig.compileDefinitions.get(key)) @@ -599,6 +619,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { // 100 * federateCount / federates.size() // ); // FIXME: Move to FedGenerator // Create the compiler to be used later + var cCompiler = new CCompiler(targetConfig, threadFileConfig, errorReporter, CppMode); try { if (!cCompiler.runCCompiler(generator, context)) { @@ -616,6 +637,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { } catch (IOException e) { Exceptions.sneakyThrow(e); } + } // If a build directive has been given, invoke it now. @@ -1974,15 +1996,14 @@ protected void setUpGeneralParameters() { if (targetConfig.threading && targetConfig.platformOptions.platform == Platform.ARDUINO) { //Add error message when user attempts to set threading=true for Arduino if (targetConfig.setByUser.contains(TargetProperty.THREADING)) { - errorReporter.reportWarning("Threading is incompatible on Arduino. Setting threading to false."); + System.out.println("Threading is incompatible on Arduino. Setting threading to false."); } targetConfig.threading = false; } - if (!targetConfig.noCompile && targetConfig.platformOptions.platform == Platform.ARDUINO) { - //Add warning message when user attempts to set threading=true for Arduino - if (!targetConfig.setByUser.contains(TargetProperty.NO_COMPILE)) { - errorReporter.reportWarning("Compilation should be done through arduino-cli. Setting no-compile to true."); - } + + if (targetConfig.platformOptions.platform == Platform.ARDUINO && !targetConfig.noCompile + && targetConfig.platformOptions.board == null) { + System.out.println("To enable compilation for the arduino platform, you must specify the board name by its FQBN. Setting to no compile."); targetConfig.noCompile = true; } if (targetConfig.threading) { // FIXME: This logic is duplicated in CMake diff --git a/org.lflang/src/org/lflang/util/ArduinoUtil.java b/org.lflang/src/org/lflang/util/ArduinoUtil.java new file mode 100644 index 0000000000..b6f4cc3678 --- /dev/null +++ b/org.lflang/src/org/lflang/util/ArduinoUtil.java @@ -0,0 +1,101 @@ +package org.lflang.util; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; + +import org.lflang.ErrorReporter; +import org.lflang.FileConfig; +import org.lflang.TargetConfig; +import org.lflang.generator.GeneratorCommandFactory; +import org.lflang.generator.LFGeneratorContext; + +import org.eclipse.xtext.xbase.lib.Exceptions; + +public class ArduinoUtil { + + private LFGeneratorContext context; + private GeneratorCommandFactory commandFactory; + private ErrorReporter errorReporter; + + public ArduinoUtil (LFGeneratorContext context, GeneratorCommandFactory commandFactory, ErrorReporter errorReporter) { + this.context = context; + this.commandFactory = commandFactory; + this.errorReporter = errorReporter; + } + + /** + * Returns true if arduino-cli exists, false otherwise. + */ + private boolean checkArduinoCLIExists() { + LFCommand checkCommand = LFCommand.get("arduino-cli", List.of("version")); + return checkCommand != null && checkCommand.run() == 0; + } + + private LFCommand arduinoCompileCommand(FileConfig fileConfig, TargetConfig targetConfig) throws IOException { + if (!checkArduinoCLIExists()) { + throw new IOException("Must have arduino-cli installed to auto-compile."); + } else { + var srcGenPath = fileConfig.getSrcGenPath(); + try { + // Write to a temporary file to execute since ProcessBuilder does not like spaces and double quotes in its arguments. + File testScript = File.createTempFile("arduino", null); + testScript.deleteOnExit(); + if (!testScript.setExecutable(true)) { + throw new IOException("Failed to make compile script executable"); + } + var fileWriter = new FileWriter(testScript.getAbsoluteFile(), true); + BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); + String board = targetConfig.platformOptions.board != null ? targetConfig.platformOptions.board : "arduino:avr:leonardo"; + bufferedWriter.write("arduino-cli compile -b " + board + " --build-property " + + "compiler.c.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + + "--build-property compiler.cpp.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + + srcGenPath.toString()); + bufferedWriter.close(); + return commandFactory.createCommand( + testScript.getAbsolutePath(), List.of(), null); + } catch (IOException e) { + e.printStackTrace(); + throw new IOException(e); + } + } + } + + public void buildArduino(FileConfig fileConfig, TargetConfig targetConfig) { + System.out.println("Retrieving Arduino Compile Script"); + try { + LFCommand command = arduinoCompileCommand(fileConfig, targetConfig); // Use ProcessBuilder for finer control. + int retCode = 0; + retCode = command.run(context.getCancelIndicator()); + if (retCode != 0 && context.getMode() == LFGeneratorContext.Mode.STANDALONE) { + errorReporter.reportError("arduino-cli failed with error code " + retCode); + throw new IOException("arduino-cli failure"); + } + } catch (IOException e){ + Exceptions.sneakyThrow(e); + } + System.out.println("SUCCESS: Compiling generated code for " + fileConfig.name + " finished with no errors."); + if (targetConfig.platformOptions.flash) { + if (targetConfig.platformOptions.port != null) { + System.out.println("Invoking flash command for Arduino"); + LFCommand flash = commandFactory.createCommand( + "arduino-cli", List.of("upload", "-b", targetConfig.platformOptions.board, "-p", targetConfig.platformOptions.port), fileConfig.getSrcGenPath()); + if (flash == null) { + errorReporter.reportError( + "Could not create arduino-cli flash command." + ); + } + int flashRet = flash.run(); + if (flashRet != 0) { + errorReporter.reportError("arduino-cli flash command failed with error code " + flashRet); + } else { + System.out.println("SUCCESS: Flashed board using arduino-cli"); + } + } else { + errorReporter.reportError("Need to provide a port on which to automatically flash."); + } + } + } +} From 91d6957ca7cc2aa38301792a03af2cb15186bf13 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:13:09 -0800 Subject: [PATCH 26/42] Added Auto Compile Test for Arduino given Board Name --- test/C/src/arduino/BlinkAutoCompile.lf | 24 +++++++++++++++++++++++ test/C/src/arduino/BlinkCustomPlatform.lf | 3 +-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 test/C/src/arduino/BlinkAutoCompile.lf diff --git a/test/C/src/arduino/BlinkAutoCompile.lf b/test/C/src/arduino/BlinkAutoCompile.lf new file mode 100644 index 0000000000..d641401d65 --- /dev/null +++ b/test/C/src/arduino/BlinkAutoCompile.lf @@ -0,0 +1,24 @@ +/** + * This example demonstrates a very simple blink program that will turn on and + * off an LED on the Arduino Board with a 50% duty cycle switching every + * half-second. + * + * This tests the overloading capabilities of the platform argument as well as autocompilation given a board name. + */ +target C { + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + } +} + +main reactor BlinkAutoCompile { + timer t1(0, 1 sec) + timer t2(500 msec, 1 sec) + + reaction(startup) {= pinMode(LED_BUILTIN, OUTPUT); =} + + reaction(t1) {= digitalWrite(LED_BUILTIN, HIGH); =} + + reaction(t2) {= digitalWrite(LED_BUILTIN, LOW); =} +} diff --git a/test/C/src/arduino/BlinkCustomPlatform.lf b/test/C/src/arduino/BlinkCustomPlatform.lf index 89bc55514b..a3c4d11e40 100644 --- a/test/C/src/arduino/BlinkCustomPlatform.lf +++ b/test/C/src/arduino/BlinkCustomPlatform.lf @@ -8,8 +8,7 @@ target C { platform: { name: "arduino", - baud-rate: 9600, - board: "arduino:mbed_nano:nano33ble" + baud-rate: 9600 } } From bb036ab93f499e1edcbabc925a47898d9d4113b1 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:13:30 -0800 Subject: [PATCH 27/42] Removed Exec Logic of Arduino and Converted to Build Logic --- .../src/org/lflang/tests/TestBase.java | 53 ++++--------------- 1 file changed, 9 insertions(+), 44 deletions(-) diff --git a/org.lflang.tests/src/org/lflang/tests/TestBase.java b/org.lflang.tests/src/org/lflang/tests/TestBase.java index 6368a4ac13..ea792476c2 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestBase.java +++ b/org.lflang.tests/src/org/lflang/tests/TestBase.java @@ -48,11 +48,14 @@ import org.lflang.generator.LFGeneratorContext; import org.lflang.generator.LFGeneratorContext.BuildParm; import org.lflang.generator.MainContext; +import org.lflang.generator.GeneratorCommandFactory; import org.lflang.tests.Configurators.Configurator; import org.lflang.tests.LFTest.Result; import org.lflang.tests.TestRegistry.TestCategory; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; +import org.lflang.util.ArduinoUtil; + import com.google.inject.Inject; import com.google.inject.Injector; @@ -471,7 +474,6 @@ private GeneratorResult generateCode(LFTest test) throws TestError { if (test.getFileConfig().resource == null) { return GeneratorResult.NOTHING; } - try { generator.doGenerate(test.getFileConfig().resource, fileAccess, test.getContext()); } catch (Throwable e) { @@ -577,47 +579,6 @@ static public String stackTraceToString(Throwable t) { exit 0 """; - /** - * Returns true if arduino-cli exists, false otherwise. - */ - private boolean checkArduinoCLIExists() { - LFCommand checkCommand = LFCommand.get("arduino-cli", List.of("version")); - return checkCommand != null && checkCommand.run() == 0; - } - - /** - * Return a ProcessBuilder used to test Arduino in a non-federated, unthreaded environment. - * See the following for references on arduino-cli: - * https://arduino.github.io/arduino-cli/ - * - * @param test The test to get the execution command for. - */ - private ProcessBuilder getArduinoExecCommand(LFTest test) { - if (!checkArduinoCLIExists()) { - System.out.println(Message.MISSING_ARDUINO_CLI); - return new ProcessBuilder("exit", "1"); - } - var srcGenPath = test.getFileConfig().getSrcGenPath(); - try { - // Write to a temporary file to execute since ProcessBuilder does not like spaces and double quotes in its arguments. - File testScript = File.createTempFile("arduinotest", null); - testScript.deleteOnExit(); - if (!testScript.setExecutable(true)) { - throw new IOException("Failed to make test script executable"); - } - var fileWriter = new FileWriter(testScript.getAbsoluteFile(), true); - BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); - bufferedWriter.write("arduino-cli compile -b arduino:avr:leonardo --build-property " + - "compiler.c.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " + - "--build-property compiler.cpp.extra_flags=\"-DLF_UNTHREADED -DPLATFORM_ARDUINO -DINITIAL_EVENT_QUEUE_SIZE=10 -DINITIAL_REACT_QUEUE_SIZE=10\" " - + srcGenPath.toString()); - bufferedWriter.close(); - return new ProcessBuilder(testScript.getAbsolutePath()); - } catch (IOException e) { - return new ProcessBuilder("exit", "1"); - } - } - /** * Path to a bash script containing DOCKER_RUN_SCRIPT. */ @@ -685,8 +646,6 @@ private ProcessBuilder getExecCommand(LFTest test) throws TestError { if (relativePathName.equalsIgnoreCase(TestCategory.DOCKER.getPath()) || relativePathName.equalsIgnoreCase(TestCategory.DOCKER_FEDERATED.getPath())) { return getDockerExecCommand(test); - } else if (relativePathName.equalsIgnoreCase(TestCategory.ARDUINO.getPath())) { - return getArduinoExecCommand(test); } else { LFCommand command = test.getFileConfig().getCommand(); if (command == null) { @@ -719,6 +678,12 @@ private void validateAndRun(Set tests, Configurator configurator, TestLe validate(test); if (level.compareTo(TestLevel.CODE_GEN) >= 0) { generateCode(test); + var srcBasePath = test.getFileConfig().srcPkgPath.resolve("src"); + var relativePathName = srcBasePath.relativize(test.getFileConfig().srcPath).toString(); + if (relativePathName.equalsIgnoreCase(TestCategory.ARDUINO.getPath())) { + ArduinoUtil arduinoUtil = new ArduinoUtil(test.getContext(), new GeneratorCommandFactory(test.getContext().getErrorReporter(), test.getFileConfig()), test.getContext().getErrorReporter()); + arduinoUtil.buildArduino(test.getFileConfig(), test.getContext().getTargetConfig()); + } } if (level == TestLevel.EXECUTION) { execute(test); From 382a61b47208d2dd4add0e90b2da89799d3171a0 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:17:30 -0800 Subject: [PATCH 28/42] Update submodule dependency --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index c8455ba113..6dce219ffc 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit c8455ba113cca52d59719986a304e4c549c9590e +Subproject commit 6dce219ffc91975179dad1879e73e2c7532fa538 From 7f304435a8113d2f13b3d0c0b95e360fb05e9144 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:43:43 -0800 Subject: [PATCH 29/42] Fixed RoundTripTest error --- test/C/src/arduino/BlinkAutoCompile.lf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/C/src/arduino/BlinkAutoCompile.lf b/test/C/src/arduino/BlinkAutoCompile.lf index d641401d65..44b506d455 100644 --- a/test/C/src/arduino/BlinkAutoCompile.lf +++ b/test/C/src/arduino/BlinkAutoCompile.lf @@ -3,7 +3,8 @@ * off an LED on the Arduino Board with a 50% duty cycle switching every * half-second. * - * This tests the overloading capabilities of the platform argument as well as autocompilation given a board name. + * This tests the overloading capabilities of the platform argument as well as + * autocompilation given a board name. */ target C { platform: { From 57bed1d5ff0491eb94d2a9ba19c5db87f7c81c4a Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:20:01 -0800 Subject: [PATCH 30/42] Point CI to updated c-tests branch. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82c80889ff..8a6e2a15fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: # Run the C integration tests. c-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@ci-no-rti-image + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@arduino-cli-support needs: cancel # Run the C Zephyr integration tests. @@ -70,7 +70,7 @@ jobs: # Run the CCpp integration tests. ccpp-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@arduino-cli-support with: use-cpp: true needs: cancel From e1bb22406b9834c63aefd9f8277295a0b9b7ef00 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:45:37 -0800 Subject: [PATCH 31/42] Revert "Point CI to updated c-tests branch." This reverts commit 57bed1d5ff0491eb94d2a9ba19c5db87f7c81c4a. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a6e2a15fb..82c80889ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: # Run the C integration tests. c-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@arduino-cli-support + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@ci-no-rti-image needs: cancel # Run the C Zephyr integration tests. @@ -70,7 +70,7 @@ jobs: # Run the CCpp integration tests. ccpp-tests: - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@arduino-cli-support + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master with: use-cpp: true needs: cancel From 7897380852c14d565b44ae8e7a4dad56acd1a20f Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:46:43 -0800 Subject: [PATCH 32/42] Decouple Arduino from C Tests Follows template of Zephyr --- .github/workflows/c-arduino-tests.yml | 55 +++++++++++++++++++ .github/workflows/c-tests.yml | 2 - .github/workflows/ci.yml | 5 ++ .../lflang/tests/runtime/CArduinoTest.java | 32 +++++++++++ .../src/org/lflang/tests/runtime/CTest.java | 9 --- 5 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/c-arduino-tests.yml create mode 100644 org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java diff --git a/.github/workflows/c-arduino-tests.yml b/.github/workflows/c-arduino-tests.yml new file mode 100644 index 0000000000..c930ee92bf --- /dev/null +++ b/.github/workflows/c-arduino-tests.yml @@ -0,0 +1,55 @@ +name: C Arduino tests + +on: + workflow_call: + inputs: + compiler-ref: + required: false + type: string + runtime-ref: + required: false + type: string + use-cpp: + required: false + type: boolean + default: false + scheduler: + required: false + type: string + +jobs: + run: + strategy: + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.platform }} + steps: + - name: Check out lingua-franca repository + uses: actions/checkout@v3 + with: + repository: lf-lang/lingua-franca + submodules: true + ref: ${{ inputs.compiler-ref }} + fetch-depth: 0 + - name: Prepare build environment + uses: ./.github/actions/prepare-build-env + - name: Check out specific ref of reactor-c + uses: actions/checkout@v3 + with: + repository: lf-lang/reactor-c + path: org.lflang/src/lib/c/reactor-c + ref: ${{ inputs.runtime-ref }} + if: ${{ inputs.runtime-ref }} + - name: Install dependencies OS X + run: | + brew install coreutils + brew install openssl + brew link openssl --force + if: ${{ runner.os == 'macOS' }} + - name: Install RTI + uses: ./.github/actions/install-rti + if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }} + - name: Install Arduino CLI + uses: arduino/setup-arduino-cli@v1 + - name: Perform Arduino tests for C target with default scheduler + run: ./gradlew test --tests org.lflang.tests.runtime.CArduinoTest.runArduinoTests \ No newline at end of file diff --git a/.github/workflows/c-tests.yml b/.github/workflows/c-tests.yml index 268d03c43d..4888806cc8 100644 --- a/.github/workflows/c-tests.yml +++ b/.github/workflows/c-tests.yml @@ -49,8 +49,6 @@ jobs: - name: Install RTI uses: ./.github/actions/install-rti if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }} - - name: Install Arduino CLI - uses: arduino/setup-arduino-cli@v1 - name: Perform tests for C target with default scheduler run: | ./gradlew test --tests org.lflang.tests.runtime.CTest.* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82c80889ff..a2506610c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,11 @@ jobs: uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@ci-no-rti-image needs: cancel + # Run the C Arduino integration tests. + c-arduino-tests: + uses: lf-lang/lingua-franca/.github/workflows/c-arduino-tests.yml@arduino-cli-support + needs: cancel + # Run the C Zephyr integration tests. c-zephyr-tests: uses: lf-lang/lingua-franca/.github/workflows/c-zephyr-tests.yml@c-zephyr-support diff --git a/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java b/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java new file mode 100644 index 0000000000..3e2a80ae77 --- /dev/null +++ b/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java @@ -0,0 +1,32 @@ +package org.lflang.tests.runtime; + +import java.util.List; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import org.lflang.Target; +import org.lflang.tests.Configurators; +import org.lflang.tests.RuntimeTest; +import org.lflang.tests.TestRegistry.TestCategory; + +/** + * Collection of Zephyr tests for the C target. + * + * @author Erling Rennemo Jellum + */ +public class CArduinoTest extends RuntimeTest { + + public CArduinoTest() { + super(Target.C); + } + + @Test + public void runArduinoTests() { + Assumptions.assumeFalse(isWindows(), Message.NO_WINDOWS_SUPPORT); + super.runTestsFor(List.of(Target.C), + Message.DESC_ARDUINO, + TestCategory.ARDUINO::equals, Configurators::noChanges, + false); + } +} diff --git a/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java b/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java index 82225471a8..bc906b0d95 100644 --- a/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java +++ b/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java @@ -85,15 +85,6 @@ public void runMultiportTests() { super.runMultiportTests(); } - @Test - public void runArduinoTests() { - Assumptions.assumeFalse(isWindows(), Message.NO_WINDOWS_SUPPORT); - super.runTestsFor(List.of(Target.C), - Message.DESC_ARDUINO, - TestCategory.ARDUINO::equals, Configurators::noChanges, - false); - } - @Test @Override public void runWithThreadingOff() { From eedba900845748b8cc728cd5c6adafcd7b089f3b Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:49:42 -0800 Subject: [PATCH 33/42] Remove windows since we don't support it as a platform --- .github/workflows/c-arduino-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/c-arduino-tests.yml b/.github/workflows/c-arduino-tests.yml index c930ee92bf..065a1e5466 100644 --- a/.github/workflows/c-arduino-tests.yml +++ b/.github/workflows/c-arduino-tests.yml @@ -21,7 +21,7 @@ jobs: run: strategy: matrix: - platform: [ubuntu-latest, macos-latest, windows-latest] + platform: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.platform }} steps: - name: Check out lingua-franca repository From 5e0587d4c2efbab263c467bfb8f626a6a0f7b7f7 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:59:26 -0800 Subject: [PATCH 34/42] Added install for Arduino Core Libraries --- .github/workflows/c-arduino-tests.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/c-arduino-tests.yml b/.github/workflows/c-arduino-tests.yml index 065a1e5466..a4a3a63f5f 100644 --- a/.github/workflows/c-arduino-tests.yml +++ b/.github/workflows/c-arduino-tests.yml @@ -51,5 +51,11 @@ jobs: if: ${{ runner.os == 'macOS' || runner.os == 'Linux' }} - name: Install Arduino CLI uses: arduino/setup-arduino-cli@v1 + - name: Install Arduino Core Libraries + run: | + arduino-cli core install arduino:avr + arduino-cli core install arduino:megaavr + arduino-cli core install arduino:samd + arduino-cli core install arduino:sam - name: Perform Arduino tests for C target with default scheduler run: ./gradlew test --tests org.lflang.tests.runtime.CArduinoTest.runArduinoTests \ No newline at end of file From 874022cf66f1f7114dea9ba5f6d807952c3cfb9d Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 17:30:14 -0800 Subject: [PATCH 35/42] Edit Comments of Arduino Test file. --- .../src/org/lflang/tests/runtime/CArduinoTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java b/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java index 3e2a80ae77..0c380517c3 100644 --- a/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java +++ b/org.lflang.tests/src/org/lflang/tests/runtime/CArduinoTest.java @@ -11,9 +11,9 @@ import org.lflang.tests.TestRegistry.TestCategory; /** - * Collection of Zephyr tests for the C target. + * Collection of Arduino tests for the C target. * - * @author Erling Rennemo Jellum + * @author Anirudh Rengarajan */ public class CArduinoTest extends RuntimeTest { From 788cd0e0f55c484ac050358f255d7e9df8fd63a7 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 17:31:57 -0800 Subject: [PATCH 36/42] Exclude Arduino Tests from CCpp and Threading Off Tests --- org.lflang.tests/src/org/lflang/tests/Configurators.java | 6 ++++-- org.lflang.tests/src/org/lflang/tests/runtime/CCppTest.java | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/org.lflang.tests/src/org/lflang/tests/Configurators.java b/org.lflang.tests/src/org/lflang/tests/Configurators.java index 81e015dfbf..452cef656e 100644 --- a/org.lflang.tests/src/org/lflang/tests/Configurators.java +++ b/org.lflang.tests/src/org/lflang/tests/Configurators.java @@ -90,15 +90,17 @@ public static boolean compatibleWithThreadingOff(TestCategory category) { // CONCURRENT, FEDERATED, DOCKER_FEDERATED, DOCKER // are not compatible with single-threaded execution. + // ARDUINO and ZEPHYR have their own test suites, so we don't need to rerun. boolean excluded = category == TestCategory.CONCURRENT || category == TestCategory.SERIALIZATION || category == TestCategory.FEDERATED || category == TestCategory.DOCKER_FEDERATED || category == TestCategory.DOCKER + || category == TestCategory.ARDUINO || category == TestCategory.ZEPHYR; - // SERIALIZATION, TARGET, and ARDUINO tests are excluded on Windows. - excluded |= TestBase.isWindows() && (category == TestCategory.TARGET || category == TestCategory.ARDUINO); + // SERIALIZATION and TARGET tests are excluded on Windows. + excluded |= TestBase.isWindows() && (category == TestCategory.TARGET); return !excluded; } } diff --git a/org.lflang.tests/src/org/lflang/tests/runtime/CCppTest.java b/org.lflang.tests/src/org/lflang/tests/runtime/CCppTest.java index 98dbd1b37e..d70615c7fd 100644 --- a/org.lflang.tests/src/org/lflang/tests/runtime/CCppTest.java +++ b/org.lflang.tests/src/org/lflang/tests/runtime/CCppTest.java @@ -41,9 +41,10 @@ public void runAsCCpp() { */ private static boolean isExcludedFromCCpp(TestCategory category) { boolean excluded = category == TestCategory.SERIALIZATION; - excluded |= isWindows() && (category == TestCategory.DOCKER_FEDERATED || category == TestCategory.ARDUINO) ; + excluded |= isWindows() && (category == TestCategory.DOCKER_FEDERATED); excluded |= isMac() && (category == TestCategory.DOCKER_FEDERATED || category == TestCategory.DOCKER); excluded |= category == TestCategory.ZEPHYR; + excluded |= category == TestCategory.ARDUINO; return !excluded; } } From 4573565428448e6484b2a38aaaf8ff3936544441 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:02:53 -0800 Subject: [PATCH 37/42] Update submodule dependency. --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 6dce219ffc..eb345fe4f7 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 6dce219ffc91975179dad1879e73e2c7532fa538 +Subproject commit eb345fe4f77bfdd0698cc46cc024a7dbc58287f5 From deac0ee40e21c7c83c06f5f7f8ffaac399ab87bd Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:09:14 -0800 Subject: [PATCH 38/42] Edit comments from code review Co-authored-by: Marten Lohstroh --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 2 +- org.lflang/src/org/lflang/util/ArduinoUtil.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index cbbaad7107..6b1fc1d802 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -2003,7 +2003,7 @@ protected void setUpGeneralParameters() { if (targetConfig.platformOptions.platform == Platform.ARDUINO && !targetConfig.noCompile && targetConfig.platformOptions.board == null) { - System.out.println("To enable compilation for the arduino platform, you must specify the board name by its FQBN. Setting to no compile."); + System.out.println("To enable compilation for the Arduino platform, you must specify the fully-qualified board name (FQBN) in the target property. For example, platform: {name: arduino, board: arduino:avr:leonardo}. Entering "no-compile" mode and generating target code only.); targetConfig.noCompile = true; } if (targetConfig.threading) { // FIXME: This logic is duplicated in CMake diff --git a/org.lflang/src/org/lflang/util/ArduinoUtil.java b/org.lflang/src/org/lflang/util/ArduinoUtil.java index b6f4cc3678..0ab7f4dd6c 100644 --- a/org.lflang/src/org/lflang/util/ArduinoUtil.java +++ b/org.lflang/src/org/lflang/util/ArduinoUtil.java @@ -27,7 +27,7 @@ public ArduinoUtil (LFGeneratorContext context, GeneratorCommandFactory commandF } /** - * Returns true if arduino-cli exists, false otherwise. + * Return true if arduino-cli exists, false otherwise. */ private boolean checkArduinoCLIExists() { LFCommand checkCommand = LFCommand.get("arduino-cli", List.of("version")); From 5f212e0b35572c62cd60c3b8ed60296887d44c20 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:17:31 -0800 Subject: [PATCH 39/42] Add JavaDoc to new ArduinoUtil file. --- .../src/org/lflang/util/ArduinoUtil.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/org.lflang/src/org/lflang/util/ArduinoUtil.java b/org.lflang/src/org/lflang/util/ArduinoUtil.java index 0ab7f4dd6c..5e8b61842e 100644 --- a/org.lflang/src/org/lflang/util/ArduinoUtil.java +++ b/org.lflang/src/org/lflang/util/ArduinoUtil.java @@ -14,6 +14,16 @@ import org.eclipse.xtext.xbase.lib.Exceptions; +/** + * Utilities for Building using Arduino CLI. + * + * We take in a Generator Context, Command Factory, and Error Reporter and + * make subsequent calls to arduino-cli given a FileConfig and TargetConfig. + * + * This should be used immediately after CodeGen to compile if the user provides + * a board type within their LF file. If the user also provides a port with flash enabled, + * we will also attempt to upload the compiled sketch directly to the board. + */ public class ArduinoUtil { private LFGeneratorContext context; @@ -34,6 +44,13 @@ private boolean checkArduinoCLIExists() { return checkCommand != null && checkCommand.run() == 0; } + /** + * Generate an LF style command for Arduino compilation based on FQBN + * @param fileConfig + * @param targetConfig + * @return LFCommand to compile an Arduino program given an FQBN. + * @throws IOException + */ private LFCommand arduinoCompileCommand(FileConfig fileConfig, TargetConfig targetConfig) throws IOException { if (!checkArduinoCLIExists()) { throw new IOException("Must have arduino-cli installed to auto-compile."); @@ -63,6 +80,11 @@ private LFCommand arduinoCompileCommand(FileConfig fileConfig, TargetConfig targ } } + /** + * Compiles (and possibly auto-flashes) an Arduino program once code generation is completed. + * @param fileConfig + * @param targetConfig + */ public void buildArduino(FileConfig fileConfig, TargetConfig targetConfig) { System.out.println("Retrieving Arduino Compile Script"); try { From d99f37fe7e7defd3fa5037737097eec130022223 Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:32:26 -0800 Subject: [PATCH 40/42] Fixed Bug in Helper String --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 6b1fc1d802..b2cc4c7968 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -2003,7 +2003,7 @@ protected void setUpGeneralParameters() { if (targetConfig.platformOptions.platform == Platform.ARDUINO && !targetConfig.noCompile && targetConfig.platformOptions.board == null) { - System.out.println("To enable compilation for the Arduino platform, you must specify the fully-qualified board name (FQBN) in the target property. For example, platform: {name: arduino, board: arduino:avr:leonardo}. Entering "no-compile" mode and generating target code only.); + System.out.println("To enable compilation for the Arduino platform, you must specify the fully-qualified board name (FQBN) in the target property. For example, platform: {name: arduino, board: arduino:avr:leonardo}. Entering \"no-compile\" mode and generating target code only."); targetConfig.noCompile = true; } if (targetConfig.threading) { // FIXME: This logic is duplicated in CMake From 081b95be328b1b0815cccf0ea4c0260d9585918f Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:33:08 -0800 Subject: [PATCH 41/42] Removed Additional Arduino Checks in Test Base to reduce clutter and increase efficiency of all tests. --- .../src/org/lflang/tests/TestBase.java | 6 ----- test/C/src/arduino/AnalogReadSerial.lf | 5 +++- test/C/src/arduino/Blink.lf | 5 +++- test/C/src/arduino/BlinkAttemptThreading.lf | 5 +++- test/C/src/arduino/BlinkAutoCompile.lf | 25 ------------------- test/C/src/arduino/BlinkCustomPlatform.lf | 24 ------------------ test/C/src/arduino/DigitalReadSerial.lf | 5 +++- test/C/src/arduino/Fade.lf | 5 +++- test/C/src/arduino/ReadAnalogVoltage.lf | 5 +++- 9 files changed, 24 insertions(+), 61 deletions(-) delete mode 100644 test/C/src/arduino/BlinkAutoCompile.lf delete mode 100644 test/C/src/arduino/BlinkCustomPlatform.lf diff --git a/org.lflang.tests/src/org/lflang/tests/TestBase.java b/org.lflang.tests/src/org/lflang/tests/TestBase.java index ea792476c2..1ad5d6467c 100644 --- a/org.lflang.tests/src/org/lflang/tests/TestBase.java +++ b/org.lflang.tests/src/org/lflang/tests/TestBase.java @@ -678,12 +678,6 @@ private void validateAndRun(Set tests, Configurator configurator, TestLe validate(test); if (level.compareTo(TestLevel.CODE_GEN) >= 0) { generateCode(test); - var srcBasePath = test.getFileConfig().srcPkgPath.resolve("src"); - var relativePathName = srcBasePath.relativize(test.getFileConfig().srcPath).toString(); - if (relativePathName.equalsIgnoreCase(TestCategory.ARDUINO.getPath())) { - ArduinoUtil arduinoUtil = new ArduinoUtil(test.getContext(), new GeneratorCommandFactory(test.getContext().getErrorReporter(), test.getFileConfig()), test.getContext().getErrorReporter()); - arduinoUtil.buildArduino(test.getFileConfig(), test.getContext().getTargetConfig()); - } } if (level == TestLevel.EXECUTION) { execute(test); diff --git a/test/C/src/arduino/AnalogReadSerial.lf b/test/C/src/arduino/AnalogReadSerial.lf index 39eda80bd4..32573cffe7 100644 --- a/test/C/src/arduino/AnalogReadSerial.lf +++ b/test/C/src/arduino/AnalogReadSerial.lf @@ -5,7 +5,10 @@ * the outside pins to +5V and ground. */ target C { - platform: "Arduino" + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + } } main reactor AnalogReadSerial { diff --git a/test/C/src/arduino/Blink.lf b/test/C/src/arduino/Blink.lf index da1820e008..c6570381ef 100644 --- a/test/C/src/arduino/Blink.lf +++ b/test/C/src/arduino/Blink.lf @@ -4,7 +4,10 @@ * half-second. */ target C { - platform: "Arduino" + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + } } main reactor Blink { diff --git a/test/C/src/arduino/BlinkAttemptThreading.lf b/test/C/src/arduino/BlinkAttemptThreading.lf index 96e7571db0..86fb9bf2f7 100644 --- a/test/C/src/arduino/BlinkAttemptThreading.lf +++ b/test/C/src/arduino/BlinkAttemptThreading.lf @@ -5,7 +5,10 @@ * warning and default back to no threading. */ target C { - platform: "Arduino", + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + }, threading: true } diff --git a/test/C/src/arduino/BlinkAutoCompile.lf b/test/C/src/arduino/BlinkAutoCompile.lf deleted file mode 100644 index 44b506d455..0000000000 --- a/test/C/src/arduino/BlinkAutoCompile.lf +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This example demonstrates a very simple blink program that will turn on and - * off an LED on the Arduino Board with a 50% duty cycle switching every - * half-second. - * - * This tests the overloading capabilities of the platform argument as well as - * autocompilation given a board name. - */ -target C { - platform: { - name: "arduino", - board: "arduino:avr:leonardo" - } -} - -main reactor BlinkAutoCompile { - timer t1(0, 1 sec) - timer t2(500 msec, 1 sec) - - reaction(startup) {= pinMode(LED_BUILTIN, OUTPUT); =} - - reaction(t1) {= digitalWrite(LED_BUILTIN, HIGH); =} - - reaction(t2) {= digitalWrite(LED_BUILTIN, LOW); =} -} diff --git a/test/C/src/arduino/BlinkCustomPlatform.lf b/test/C/src/arduino/BlinkCustomPlatform.lf deleted file mode 100644 index a3c4d11e40..0000000000 --- a/test/C/src/arduino/BlinkCustomPlatform.lf +++ /dev/null @@ -1,24 +0,0 @@ -/** - * This example demonstrates a very simple blink program that will turn on and - * off an LED on the Arduino Board with a 50% duty cycle switching every - * half-second. - * - * This tests the overloading capabilities of the platform argument. - */ -target C { - platform: { - name: "arduino", - baud-rate: 9600 - } -} - -main reactor BlinkCustomPlatform { - timer t1(0, 1 sec) - timer t2(500 msec, 1 sec) - - reaction(startup) {= pinMode(LED_BUILTIN, OUTPUT); =} - - reaction(t1) {= digitalWrite(LED_BUILTIN, HIGH); =} - - reaction(t2) {= digitalWrite(LED_BUILTIN, LOW); =} -} diff --git a/test/C/src/arduino/DigitalReadSerial.lf b/test/C/src/arduino/DigitalReadSerial.lf index f7a53c5c2d..0ef88158e4 100644 --- a/test/C/src/arduino/DigitalReadSerial.lf +++ b/test/C/src/arduino/DigitalReadSerial.lf @@ -3,7 +3,10 @@ * Monitor */ target C { - platform: "Arduino" + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + } } main reactor DigitalReadSerial { diff --git a/test/C/src/arduino/Fade.lf b/test/C/src/arduino/Fade.lf index 8240a0ee89..5145c4a50e 100644 --- a/test/C/src/arduino/Fade.lf +++ b/test/C/src/arduino/Fade.lf @@ -6,7 +6,10 @@ * ~11. */ target C { - platform: "Arduino" + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + } } main reactor Fade { diff --git a/test/C/src/arduino/ReadAnalogVoltage.lf b/test/C/src/arduino/ReadAnalogVoltage.lf index ebb7a8f9c6..017115bf54 100644 --- a/test/C/src/arduino/ReadAnalogVoltage.lf +++ b/test/C/src/arduino/ReadAnalogVoltage.lf @@ -6,7 +6,10 @@ * ground. */ target C { - platform: "Arduino" + platform: { + name: "arduino", + board: "arduino:avr:leonardo" + } } main reactor ReadAnalogVoltage { From 0ecec595fd33ac1563d0378a5cdec97defaeec3f Mon Sep 17 00:00:00 2001 From: Anirudh Rengarajan <44007330+arengarajan99@users.noreply.github.com> Date: Fri, 27 Jan 2023 18:33:25 -0800 Subject: [PATCH 42/42] Added Helper Message for Programs that are compiled but not flashed --- org.lflang/src/org/lflang/util/ArduinoUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org.lflang/src/org/lflang/util/ArduinoUtil.java b/org.lflang/src/org/lflang/util/ArduinoUtil.java index 5e8b61842e..5ead7e196d 100644 --- a/org.lflang/src/org/lflang/util/ArduinoUtil.java +++ b/org.lflang/src/org/lflang/util/ArduinoUtil.java @@ -118,6 +118,9 @@ public void buildArduino(FileConfig fileConfig, TargetConfig targetConfig) { } else { errorReporter.reportError("Need to provide a port on which to automatically flash."); } + } else { + System.out.println("********"); + System.out.println("To flash your program, run the following command to see information about the board you plugged in:\n\n\tarduino-cli board list\n\nGrab the FQBN and PORT from the command and run the following command in the generated sources directory:\n\n\tarduino-cli upload -b -p \n"); } } }