From 3bb7697c95ab27f9cfa7b9d392064a9982ac1875 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Tue, 18 Aug 2015 19:58:29 +0200 Subject: [PATCH 1/2] Added optional .a linkage for libraries --- .../src/processing/app/debug/Compiler.java | 72 ++++++++++++++++++- .../processing/app/packages/UserLibrary.java | 12 ++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/arduino-core/src/processing/app/debug/Compiler.java b/arduino-core/src/processing/app/debug/Compiler.java index a3a42487fe8..87bbb2e0795 100644 --- a/arduino-core/src/processing/app/debug/Compiler.java +++ b/arduino-core/src/processing/app/debug/Compiler.java @@ -1070,8 +1070,76 @@ private void compileLibrary(UserLibrary lib, List includeFolders) if (lib.useRecursion()) { // libBuildFolder == {build.path}/LibName // libFolder == {lib.path}/src - recursiveCompileFilesInFolder(libBuildFolder, libFolder, includeFolders); - + + // Compile the library with .a linkage if a flag was set in library.properties + if(lib.alinkage()){ + + File afile = new File(libBuildFolder, lib.getName() + ".a"); + + createFolder(libBuildFolder); + List libraryObjectFiles = compileFiles(libBuildFolder, libFolder, true, includeFolders); + + // See if the .a file is already uptodate + if (afile.exists()) { + boolean changed = false; + for (File file : libraryObjectFiles) { + if (file.lastModified() > afile.lastModified()) { + changed = true; + break; + } + } + + // If none of the object files is newer than the .a file, don't + // bother rebuilding the .a file. There is a small corner case + // here: If a source file was removed, but no other source file + // was modified, this will not rebuild core.a even when it + // should. It's hard to fix and not a realistic case, so it + // shouldn't be a problem. + if (!changed) { + if (verbose) + System.out.println(I18n.format(tr("Using previously compiled file: {0}"), afile.getPath())); + + // this is no longer an object file, but will be added anyways. + objectFiles.add(afile); + return; + } + } + + // Delete the .a file, to prevent any previous code from lingering + afile.delete(); + + try { + for (File file : libraryObjectFiles) { + PreferencesMap dict = new PreferencesMap(prefs); + dict.put("ide_version", "" + BaseNoGui.REVISION); + dict.put("archive_file", afile.getName()); + dict.put("object_file", file.getAbsolutePath()); + dict.put("build.path", libBuildFolder.getAbsolutePath()); + + String[] cmdArray; + String cmd = prefs.getOrExcept("recipe.ar.pattern"); + try { + cmdArray = StringReplacer.formatAndSplit(cmd, dict, true); + } catch (Exception e) { + throw new RunnerException(e); + } + execAsynchronously(cmdArray); + } + + } catch (RunnerException e) { + afile.delete(); + throw e; + } + + // this is no longer an object file, but will be added anyways. + objectFiles.add(afile); + } + + // no alinkage, old, default .o file linkage + else{ + recursiveCompileFilesInFolder(libBuildFolder, libFolder, includeFolders); + } + } else { // libFolder == {lib.path}/ // utilityFolder == {lib.path}/utility diff --git a/arduino-core/src/processing/app/packages/UserLibrary.java b/arduino-core/src/processing/app/packages/UserLibrary.java index d8bfce03a13..110650cdb5f 100644 --- a/arduino-core/src/processing/app/packages/UserLibrary.java +++ b/arduino-core/src/processing/app/packages/UserLibrary.java @@ -58,6 +58,7 @@ public class UserLibrary extends ContributedLibrary { private List types; private List declaredTypes; private boolean onGoingDevelopment; + private boolean alinkage; private static final List MANDATORY_PROPERTIES = Arrays .asList("name", "version", "author", "maintainer", @@ -154,6 +155,12 @@ public static UserLibrary create(File libFolder) throws IOException { typesList.add(type.trim()); } + String alinkageString = properties.get("alinkage"); + boolean alinkage = false; + if(alinkageString != null && alinkageString.equals("true")) { + alinkage = true; + } + UserLibrary res = new UserLibrary(); res.setInstalledFolder(libFolder); res.setInstalled(true); @@ -170,6 +177,7 @@ public static UserLibrary create(File libFolder) throws IOException { res.layout = layout; res.declaredTypes = typesList; res.onGoingDevelopment = Files.exists(Paths.get(libFolder.getAbsolutePath(), Constants.LIBRARY_DEVELOPMENT_FLAG_FILE)); + res.alinkage = alinkage; return res; } @@ -274,6 +282,10 @@ public boolean onGoingDevelopment() { return onGoingDevelopment; } + public boolean alinkage() { + return alinkage; + } + protected enum LibraryLayout { FLAT, RECURSIVE } From e6090eac0f3fb27f05fd8e1fd491e34242edb742 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 23 Aug 2015 18:41:58 +0200 Subject: [PATCH 2/2] Moved .a compiling to a function Less code duplication --- .../src/processing/app/debug/Compiler.java | 128 ++++++------------ 1 file changed, 41 insertions(+), 87 deletions(-) diff --git a/arduino-core/src/processing/app/debug/Compiler.java b/arduino-core/src/processing/app/debug/Compiler.java index 87bbb2e0795..20b97047654 100644 --- a/arduino-core/src/processing/app/debug/Compiler.java +++ b/arduino-core/src/processing/app/debug/Compiler.java @@ -1074,65 +1074,12 @@ private void compileLibrary(UserLibrary lib, List includeFolders) // Compile the library with .a linkage if a flag was set in library.properties if(lib.alinkage()){ - File afile = new File(libBuildFolder, lib.getName() + ".a"); - - createFolder(libBuildFolder); - List libraryObjectFiles = compileFiles(libBuildFolder, libFolder, true, includeFolders); - - // See if the .a file is already uptodate - if (afile.exists()) { - boolean changed = false; - for (File file : libraryObjectFiles) { - if (file.lastModified() > afile.lastModified()) { - changed = true; - break; - } - } - - // If none of the object files is newer than the .a file, don't - // bother rebuilding the .a file. There is a small corner case - // here: If a source file was removed, but no other source file - // was modified, this will not rebuild core.a even when it - // should. It's hard to fix and not a realistic case, so it - // shouldn't be a problem. - if (!changed) { - if (verbose) - System.out.println(I18n.format(tr("Using previously compiled file: {0}"), afile.getPath())); - - // this is no longer an object file, but will be added anyways. - objectFiles.add(afile); - return; - } - } - - // Delete the .a file, to prevent any previous code from lingering - afile.delete(); - - try { - for (File file : libraryObjectFiles) { - PreferencesMap dict = new PreferencesMap(prefs); - dict.put("ide_version", "" + BaseNoGui.REVISION); - dict.put("archive_file", afile.getName()); - dict.put("object_file", file.getAbsolutePath()); - dict.put("build.path", libBuildFolder.getAbsolutePath()); - - String[] cmdArray; - String cmd = prefs.getOrExcept("recipe.ar.pattern"); - try { - cmdArray = StringReplacer.formatAndSplit(cmd, dict, true); - } catch (Exception e) { - throw new RunnerException(e); - } - execAsynchronously(cmdArray); - } + createFolder(libBuildFolder); + File afile = compileThroughAFile(libBuildFolder, libFolder, lib.getName(), includeFolders); - } catch (RunnerException e) { - afile.delete(); - throw e; - } - - // this is no longer an object file, but will be added anyways. - objectFiles.add(afile); + // This is not a .o object file, but a .a file with all .o files inside. + // This way libraries can be optimized better, similar as the core files. + objectFiles.add(afile); } // no alinkage, old, default .o file linkage @@ -1171,39 +1118,17 @@ private void compileFilesInFolder(File buildFolder, File srcFolder, List i objectFiles.addAll(objects); } - // 3. compile the core, outputting .o files to and then - // collecting them into the core.a library file. - // Also compiles the variant (if it supplies actual source files), - // which are included in the link directly (not through core.a) - void compileCore() - throws RunnerException, PreferencesMapException { + private File compileThroughAFile(File buildFolder, File srcFolder, String name, List includeFolders) + throws RunnerException, PreferencesMapException { + File afile = new File(buildFolder, name + ".a"); - File coreFolder = prefs.getFile("build.core.path"); - File variantFolder = prefs.getFile("build.variant.path"); - File buildFolder = new File(prefs.getFile("build.path"), "core"); - if (!buildFolder.exists() && !buildFolder.mkdirs()) { - throw new RunnerException("Unable to create folder " + buildFolder); - } - - List includeFolders = new ArrayList(); - includeFolders.add(coreFolder); // include core path only - if (variantFolder != null) - includeFolders.add(variantFolder); - - - if (variantFolder != null) - objectFiles.addAll(compileFiles(buildFolder, variantFolder, true, - includeFolders)); - - File afile = new File(buildFolder, "core.a"); - - List coreObjectFiles = compileFiles(buildFolder, coreFolder, true, + List aObjectFiles = compileFiles(buildFolder, srcFolder, true, includeFolders); // See if the .a file is already uptodate if (afile.exists()) { boolean changed = false; - for (File file : coreObjectFiles) { + for (File file : aObjectFiles) { if (file.lastModified() > afile.lastModified()) { changed = true; break; @@ -1219,7 +1144,7 @@ void compileCore() if (!changed) { if (verbose) System.out.println(I18n.format(tr("Using previously compiled file: {0}"), afile.getPath())); - return; + return afile; } } @@ -1227,7 +1152,7 @@ void compileCore() afile.delete(); try { - for (File file : coreObjectFiles) { + for (File file : aObjectFiles) { PreferencesMap dict = new PreferencesMap(prefs); dict.put("ide_version", "" + BaseNoGui.REVISION); @@ -1248,6 +1173,35 @@ void compileCore() afile.delete(); throw e; } + + return afile; + } + + // 3. compile the core, outputting .o files to and then + // collecting them into the core.a library file. + // Also compiles the variant (if it supplies actual source files), + // which are included in the link directly (not through core.a) + void compileCore() + throws RunnerException, PreferencesMapException { + + File coreFolder = prefs.getFile("build.core.path"); + File variantFolder = prefs.getFile("build.variant.path"); + File buildFolder = new File(prefs.getFile("build.path"), "core"); + if (!buildFolder.exists() && !buildFolder.mkdirs()) { + throw new RunnerException("Unable to create folder " + buildFolder); + } + + List includeFolders = new ArrayList(); + includeFolders.add(coreFolder); // include core path only + if (variantFolder != null) + includeFolders.add(variantFolder); + + + if (variantFolder != null) + objectFiles.addAll(compileFiles(buildFolder, variantFolder, true, + includeFolders)); + + compileThroughAFile(buildFolder, coreFolder, "core", includeFolders); } // 4. link it all together into the .elf file