diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index b4116e038..169aba346 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -37,7 +37,9 @@ import processing.app.helpers.Maps; import processing.app.helpers.PreferencesMap; import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyFilesWithExtension; -import processing.app.javax.swing.filechooser.FileNameExtensionFilter;import processing.app.tools.MapWithSubkeys; +import processing.app.javax.swing.filechooser.FileNameExtensionFilter;import processing.app.packages.Library; +import processing.app.packages.LibraryList; +import processing.app.tools.MapWithSubkeys; import processing.app.tools.ZipDeflater; import processing.core.*; import static processing.app.I18n._; @@ -89,10 +91,10 @@ public class Base { static private List librariesFolders; // maps library name to their library folder - static private Map libraries; + static private LibraryList libraries; // maps #included files to their library folder - static Map importToLibraryTable; + static Map importToLibraryTable; // classpath for all known libraries for p5 // (both those in the p5/libs folder and those with lib subfolders @@ -1041,26 +1043,18 @@ public class Base { } } - public Map getIDELibs() { + public LibraryList getIDELibs() { if (libraries == null) - return new HashMap(); - Map ideLibs = new HashMap(libraries); - for (String lib : libraries.keySet()) { - if (FileUtils.isSubDirectory(getSketchbookFolder(), libraries.get(lib))) - ideLibs.remove(lib); - } - return ideLibs; + return new LibraryList(); + LibraryList res = new LibraryList(libraries); + res.removeAll(getUserLibs()); + return res; } - public Map getUserLibs() { + public LibraryList getUserLibs() { if (libraries == null) - return new HashMap(); - Map userLibs = new HashMap(libraries); - for (String lib : libraries.keySet()) { - if (!FileUtils.isSubDirectory(getSketchbookFolder(), libraries.get(lib))) - userLibs.remove(lib); - } - return userLibs; + return new LibraryList(); + return libraries.filterLibrariesInSubfolder(getSketchbookFolder()); } public void rebuildImportMenu(JMenu importMenu, final Editor editor) { @@ -1080,8 +1074,8 @@ public class Base { // Split between user supplied libraries and IDE libraries TargetPlatform targetPlatform = getTargetPlatform(); if (targetPlatform != null) { - Map ideLibs = getIDELibs(); - Map userLibs = getUserLibs(); + LibraryList ideLibs = getIDELibs(); + LibraryList userLibs = getUserLibs(); try { // Find the current target. Get the platform, and then select the // correct name and core path. @@ -1121,44 +1115,33 @@ public class Base { if (found) menu.addSeparator(); // Add examples from libraries - Map ideLibs = getIDELibs(); - List names = new ArrayList(ideLibs.keySet()); - Collections.sort(names, String.CASE_INSENSITIVE_ORDER); - for (String name : names) { - File folder = ideLibs.get(name); - addSketchesSubmenu(menu, name, folder, false); - // Allows "fat" libraries to have examples in the root folder - if (folder.getName().equals(Base.getTargetPlatform().getName())) - addSketchesSubmenu(menu, name, folder.getParentFile(), false); - } + LibraryList ideLibs = getIDELibs(); + ideLibs.sort(); + for (Library lib : ideLibs) + addSketchesSubmenu(menu, lib, false); - Map userLibs = getUserLibs(); + LibraryList userLibs = getUserLibs(); if (userLibs.size()>0) { menu.addSeparator(); - names = new ArrayList(userLibs.keySet()); - Collections.sort(names, String.CASE_INSENSITIVE_ORDER); - for (String name : names) { - File folder = userLibs.get(name); - addSketchesSubmenu(menu, name, folder, false); - // Allows "fat" libraries to have examples in the root folder - if (folder.getName().equals(Base.getTargetPlatform().getName())) - addSketchesSubmenu(menu, name, folder.getParentFile(), false); - } + userLibs.sort(); + for (Library lib : userLibs) + addSketchesSubmenu(menu, lib, false); } } catch (IOException e) { e.printStackTrace(); } } - public Map scanLibraries(List folders) { - Map res = new HashMap(); + public LibraryList scanLibraries(List folders) throws IOException { + LibraryList res = new LibraryList(); for (File folder : folders) - res.putAll(scanLibraries(folder)); + res.addOrReplaceAll(scanLibraries(folder)); return res; } - public Map scanLibraries(File folder) { - Map res = new HashMap(); + public LibraryList scanLibraries(File folder) throws IOException { + LibraryList res = new LibraryList(); + String list[] = folder.list(new OnlyDirs()); // if a bad folder or something like that, this might come back null if (list == null) @@ -1175,41 +1158,14 @@ public class Base { continue; } - subfolder = scanFatLibrary(subfolder); - + Library lib = Library.create(subfolder); // (also replace previously found libs with the same name) - if (subfolder != null) - res.put(libName, subfolder); + if (lib != null) + res.addOrReplace(lib); } return res; } - /** - * Scans inside a "FAT" (multi-platform) library folder to see if it contains - * a version suitable for the actual selected architecture. If a suitable - * version is found the folder containing that version is returned, otherwise - * null is returned.
- *
- * If a non-"FAT" library is detected, we assume that the library is suitable - * for the current architecture and the libFolder parameter is returned.
- * - * @param libFolder - * @return - */ - public File scanFatLibrary(File libFolder) { - // A library is considered "fat" if it contains a file called - // "library.properties" - File libraryPropFile = new File(libFolder, "library.properties"); - if (!libraryPropFile.exists() || !libraryPropFile.isFile()) - return libFolder; - - // Search for a subfolder for actual architecture, return null if not found - File archSubfolder = new File(libFolder, Base.getTargetPlatform().getName()); - if (!archSubfolder.exists() || !archSubfolder.isDirectory()) - return null; - return archSubfolder; - } - public void onBoardOrPortChange() { TargetPlatform targetPlatform = getTargetPlatform(); if (targetPlatform == null) @@ -1228,18 +1184,25 @@ public class Base { // Scan for libraries in each library folder. // Libraries located in the latest folders on the list can override // other libraries with the same name. - libraries = scanLibraries(librariesFolders); - + try { + libraries = scanLibraries(librariesFolders); + } catch (IOException e) { + showWarning(_("Error"), _("Error reading preferences"), e); + } + String currentArch = Base.getTargetPlatform().getName(); + libraries = libraries.filterByArchitecture(currentArch); + // Populate importToLibraryTable - importToLibraryTable = new HashMap(); - for (File subfolder : libraries.values()) { + importToLibraryTable = new HashMap(); + for (Library lib : libraries) { try { - String packages[] = headerListFromIncludePath(subfolder); - for (String pkg : packages) { - importToLibraryTable.put(pkg, subfolder); + String headers[] = headerListFromIncludePath(lib.getSrcFolder()); + for (String header : headers) { + importToLibraryTable.put(header, lib); } } catch (IOException e) { - showWarning(_("Error"), I18n.format("Unable to list header files in {0}", subfolder), e); + showWarning(_("Error"), I18n + .format("Unable to list header files in {0}", lib.getSrcFolder()), e); } } @@ -1517,6 +1480,13 @@ public class Base { return ifound; // actually ignored, but.. } + private boolean addSketchesSubmenu(JMenu menu, Library lib, + boolean replaceExisting) + throws IOException { + return addSketchesSubmenu(menu, lib.getName(), lib.getFolder(), + replaceExisting); + } + private boolean addSketchesSubmenu(JMenu menu, String name, File folder, final boolean replaceExisting) throws IOException { @@ -1583,29 +1553,28 @@ public class Base { return found; } - protected void addLibraries(JMenu menu, Map libs) throws IOException { + protected void addLibraries(JMenu menu, LibraryList libs) throws IOException { - List list = new ArrayList(libs.keySet()); - Collections.sort(list, String.CASE_INSENSITIVE_ORDER); + LibraryList list = new LibraryList(libs); + list.sort(); - ActionListener listener = new ActionListener() { - public void actionPerformed(ActionEvent event) { - String jarPath = event.getActionCommand(); - try { - activeEditor.getSketch().importLibrary(jarPath); - } catch (IOException e) { - showWarning(_("Error"), I18n.format("Unable to list header files in {0}", jarPath), e); + for (Library lib : list) { + @SuppressWarnings("serial") + AbstractAction action = new AbstractAction(lib.getName()) { + public void actionPerformed(ActionEvent event) { + Library l = (Library) getValue("library"); + try { + activeEditor.getSketch().importLibrary(l); + } catch (IOException e) { + showWarning(_("Error"), I18n.format("Unable to list header files in {0}", l.getSrcFolder()), e); + } } - } - }; - - for (String name : list) { - File folder = libs.get(name); - + }; + action.putValue("library", lib); + // Add new element at the bottom - JMenuItem item = new JMenuItem(name); - item.addActionListener(listener); - item.setActionCommand(folder.getAbsolutePath()); + JMenuItem item = new JMenuItem(action); + item.putClientProperty("library", lib); menu.add(item); // XXX: DAM: should recurse here so that library folders can be nested @@ -1877,7 +1846,7 @@ public class Base { } - static public Map getLibraries() { + static public LibraryList getLibraries() { return libraries; } diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index 6d84c70b9..fe65a9761 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -29,6 +29,8 @@ import processing.app.debug.RunnerException; import processing.app.debug.Sizer; import processing.app.debug.Uploader; import processing.app.helpers.PreferencesMap; +import processing.app.packages.Library; +import processing.app.packages.LibraryList; import processing.app.preproc.*; import processing.core.*; import static processing.app.I18n._; @@ -87,16 +89,10 @@ public class Sketch { /** Class path determined during build. */ private String classPath; - /** - * This is *not* the "Processing" libraries path, this is the Java libraries - * path, as in java.library.path=BlahBlah, which identifies search paths for - * DLLs or JNILIBs. - */ - private String libraryPath; /** * List of library folders. */ - private ArrayList importedLibraries; + private LibraryList importedLibraries; /** * path is location of the main .pde file, because this is also @@ -1120,15 +1116,19 @@ public class Sketch { } + public void importLibrary(Library lib) throws IOException { + importLibrary(lib.getSrcFolder()); + } + /** * Add import statements to the current tab for all of packages inside * the specified jar file. */ - public void importLibrary(String jarPath) throws IOException { + public void importLibrary(File jarPath) throws IOException { // make sure the user didn't hide the sketch folder ensureExistence(); - String list[] = Base.headerListFromIncludePath(new File(jarPath)); + String list[] = Base.headerListFromIncludePath(jarPath); // import statements into the main sketch file (code[0]) // if the current code is a .java file, insert into current @@ -1421,18 +1421,14 @@ public class Sketch { // grab the imports from the code just preproc'd - importedLibraries = new ArrayList(); - //Remember to clear library path before building it. - libraryPath = ""; + importedLibraries = new LibraryList(); for (String item : preprocessor.getExtraImports()) { - File libFolder = (File) Base.importToLibraryTable.get(item); - //If needed can Debug libraryPath here + Library lib = Base.importToLibraryTable.get(item); + //If needed can Debug libraryPath here - if (libFolder != null && !importedLibraries.contains(libFolder)) { - importedLibraries.add(libFolder); - //classPath += Compiler.contentsToClassPath(libFolder); - libraryPath += File.pathSeparator + libFolder.getAbsolutePath(); + if (lib != null && !importedLibraries.contains(lib)) { + importedLibraries.add(lib); } } @@ -1462,7 +1458,7 @@ public class Sketch { } - public ArrayList getImportedLibraries() { + public LibraryList getImportedLibraries() { return importedLibraries; } @@ -1887,11 +1883,6 @@ public class Sketch { } - public String getLibraryPath() { - return libraryPath; - } - - public SketchCode[] getCode() { return code; } diff --git a/app/src/processing/app/debug/Compiler.java b/app/src/processing/app/debug/Compiler.java index 1bd8b8c25..80cbe9ed6 100644 --- a/app/src/processing/app/debug/Compiler.java +++ b/app/src/processing/app/debug/Compiler.java @@ -40,6 +40,8 @@ import processing.app.Sketch; import processing.app.SketchCode; import processing.app.helpers.PreferencesMap; import processing.app.helpers.StringReplacer; +import processing.app.helpers.filefilters.OnlyDirs; +import processing.app.packages.Library; import processing.core.PApplet; public class Compiler implements MessageConsumer { @@ -55,7 +57,8 @@ public class Compiler implements MessageConsumer { private PreferencesMap prefs; private boolean verbose; private boolean sketchIsCompiled; - + private String targetArch; + private RunnerException exception; /** @@ -83,8 +86,9 @@ public class Compiler implements MessageConsumer { includePaths.add(prefs.get("build.core.path")); if (prefs.get("build.variant.path").length() != 0) includePaths.add(prefs.get("build.variant.path")); - for (File file : sketch.getImportedLibraries()) - includePaths.add(file.getPath()); + for (Library lib : sketch.getImportedLibraries()) + for (File folder : lib.getSrcFolders(targetArch)) + includePaths.add(folder.getPath()); // 1. compile the sketch (already in the buildPath) sketch.setCompilingProgress(30); @@ -129,7 +133,7 @@ public class Compiler implements MessageConsumer { } TargetPlatform targetPlatform = Base.getTargetPlatform(); - + // Merge all the global preference configuration in order of priority PreferencesMap p = new PreferencesMap(); p.putAll(Preferences.getMap()); @@ -142,6 +146,8 @@ public class Compiler implements MessageConsumer { p.put("build.path", _buildPath); p.put("build.project_name", _primaryClassName); + targetArch = targetPlatform.getName(); + p.put("build.arch", targetArch.toUpperCase()); if (!p.containsKey("compiler.path")) p.put("compiler.path", Base.getAvrBasePath()); @@ -578,26 +584,49 @@ public class Compiler implements MessageConsumer { // 2. compile the libraries, outputting .o files to: // // void compileLibraries(List includePaths) throws RunnerException { - - for (File libraryFolder : sketch.getImportedLibraries()) { - String outputPath = prefs.get("build.path"); - File outputFolder = new File(outputPath, libraryFolder.getName()); - File utilityFolder = new File(libraryFolder, "utility"); - createFolder(outputFolder); - // this library can use includes in its utility/ folder - includePaths.add(utilityFolder.getAbsolutePath()); - - objectFiles.addAll(compileFiles(outputFolder.getAbsolutePath(), - libraryFolder, false, includePaths)); - outputFolder = new File(outputFolder, "utility"); - createFolder(outputFolder); - objectFiles.addAll(compileFiles(outputFolder.getAbsolutePath(), - utilityFolder, false, includePaths)); - // other libraries should not see this library's utility/ folder - includePaths.remove(includePaths.size() - 1); + File outputPath = new File(prefs.get("build.path")); + for (Library lib : sketch.getImportedLibraries()) { + for (File folder : lib.getSrcFolders(targetArch)) { + if (lib.isPre15Lib()) { + compileLibrary(outputPath, folder, includePaths); + } else { + recursiveCompileLibrary(outputPath, folder, includePaths); + } + } } } - + + private void recursiveCompileLibrary(File outputPath, File libraryFolder, List includePaths) throws RunnerException { + File newOutputPath = compileFilesInFolder(outputPath, libraryFolder, includePaths); + for (File subFolder : libraryFolder.listFiles(new OnlyDirs())) { + recursiveCompileLibrary(newOutputPath, subFolder, includePaths); + } + } + + private File compileFilesInFolder(File outputPath, File libraryFolder, List includePaths) throws RunnerException { + File outputFolder = new File(outputPath, libraryFolder.getName()); + createFolder(outputFolder); + objectFiles.addAll(compileFiles(outputFolder.getAbsolutePath(), libraryFolder, false, includePaths)); + return outputFolder; + } + + private void compileLibrary(File outputPath, File libraryFolder, List includePaths) throws RunnerException { + File outputFolder = new File(outputPath, libraryFolder.getName()); + File utilityFolder = new File(libraryFolder, "utility"); + createFolder(outputFolder); + // this library can use includes in its utility/ folder + includePaths.add(utilityFolder.getAbsolutePath()); + + objectFiles.addAll(compileFiles(outputFolder.getAbsolutePath(), + libraryFolder, false, includePaths)); + outputFolder = new File(outputFolder, "utility"); + createFolder(outputFolder); + objectFiles.addAll(compileFiles(outputFolder.getAbsolutePath(), + utilityFolder, false, includePaths)); + // other libraries should not see this library's utility/ folder + includePaths.remove(includePaths.size() - 1); + } + // 3. compile the core, outputting .o files to and then // collecting them into the core.a library file. void compileCore() diff --git a/app/src/processing/app/helpers/StringMatchers.java b/app/src/processing/app/helpers/StringMatchers.java new file mode 100644 index 000000000..686d9b2ab --- /dev/null +++ b/app/src/processing/app/helpers/StringMatchers.java @@ -0,0 +1,21 @@ +package processing.app.helpers; + +public class StringMatchers { + + /** + * Tries to match input with pattern. The pattern can use the + * "*" and "?" globs to match any-char-sequence and any-char respectively. + * + * @param input + * The string to be checked + * @param pattern + * The pattern to match + * @return true if the input matches the pattern, + * false otherwise. + */ + public static boolean wildcardMatch(String input, String pattern) { + String regex = pattern.replace("?", ".?").replace("*", ".*?"); + return input.matches(regex); + } + +} diff --git a/app/src/processing/app/packages/Library.java b/app/src/processing/app/packages/Library.java new file mode 100644 index 000000000..6779c88e8 --- /dev/null +++ b/app/src/processing/app/packages/Library.java @@ -0,0 +1,230 @@ +package processing.app.packages; + +import processing.app.helpers.PreferencesMap; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import static processing.app.helpers.StringMatchers.wildcardMatch; + +public class Library { + + private String name; + private String version; + private String author; + private String email; + private String url; + private String sentence; + private String paragraph; + private List coreDependencies; + private List dependencies; + private File folder, srcFolder, archFolder; + private List architectures; + private boolean pre15Lib; + + private static final List MANDATORY_PROPERTIES = Arrays + .asList(new String[] { "architectures", "author", "core-dependencies", + "dependencies", "email", "name", "paragraph", "sentence", "url", + "version" }); + private static final List OPTIONAL_FOLDERS = Arrays + .asList(new String[] { "arch", "examples", "extras", "src" }); + private static final List OPTIONAL_FILES = Arrays + .asList(new String[] { "keywords.txt", "library.properties" }); + + /** + * Scans inside a folder and create a Library object out of it. Automatically + * detects pre-1.5 libraries. Automatically fills metadata from + * library.properties file if found. + * + * @param libFolder + * @return + */ + static public Library create(File libFolder) throws IOException { + // A library is considered "new" if it contains a file called + // "library.properties" + File check = new File(libFolder, "library.properties"); + if (!check.exists() || !check.isFile()) + return createPre15Library(libFolder); + else + return createLibrary(libFolder); + } + + private static Library createLibrary(File libFolder) throws IOException { + // Parse metadata + File propertiesFile = new File(libFolder, "library.properties"); + PreferencesMap properties = new PreferencesMap(); + properties.load(propertiesFile); + + // Library sanity checks + // --------------------- + + // 1. Check mandatory properties + for (String p : MANDATORY_PROPERTIES) + if (!properties.containsKey(p)) + throw new IOException("Missing '" + p + "' from library"); + + // 2. Check mandatory folders + File srcFolder = new File(libFolder, "src"); + if (!srcFolder.exists() || !srcFolder.isDirectory()) + throw new IOException("Missing 'src' folder"); + + // 3. check if root folder contains prohibited stuff + for (File file : libFolder.listFiles()) { + if (file.isDirectory()) { + if (!OPTIONAL_FOLDERS.contains(file.getName())) + throw new IOException("Invalid folder '" + file.getName() + "'."); + } else { + if (!OPTIONAL_FILES.contains(file.getName())) + throw new IOException("Invalid file '" + file.getName() + "'."); + } + } + + // Extract metadata info + List archs = new ArrayList(); + for (String arch : properties.get("architectures").split(",")) + archs.add(arch.trim()); + + List coreDeps = new ArrayList(); + for (String dep : properties.get("core-dependencies").split(",")) + coreDeps.add(dep.trim()); + + List dependencies = new ArrayList(); + for (String dependency : properties.get("dependencies").split(",")) { + dependency = dependency.trim(); + if (!dependency.equals("")) { + dependencies.add(dependency); + } + } + + Library res = new Library(); + res.folder = libFolder; + res.srcFolder = srcFolder; + res.archFolder = new File(libFolder, "arch"); + res.name = properties.get("name").trim(); + res.author = properties.get("author").trim(); + res.email = properties.get("email").trim(); + res.sentence = properties.get("sentence").trim(); + res.paragraph = properties.get("paragraph").trim(); + res.url = properties.get("url").trim(); + res.architectures = archs; + res.coreDependencies = coreDeps; + res.dependencies = dependencies; + res.version = properties.get("version").trim(); + res.pre15Lib = false; + return res; + } + + private static Library createPre15Library(File libFolder) { + // construct an old style library + Library res = new Library(); + res.folder = libFolder; + res.srcFolder = libFolder; + res.name = libFolder.getName(); + res.architectures = Arrays.asList(new String[]{"*"}); + res.pre15Lib = true; + return res; + } + + public List getSrcFolders(String reqArch) { + if (!supportsArchitecture(reqArch)) + return null; + List res = new ArrayList(); + res.add(srcFolder); + File archSpecificFolder = new File(archFolder, reqArch); + if (archSpecificFolder.exists() && archSpecificFolder.isDirectory()) { + res.add(archSpecificFolder); + } else { + // If specific architecture folder is not found try with "default" + archSpecificFolder = new File(archFolder, "default"); + if (archSpecificFolder.exists() && archSpecificFolder.isDirectory()) + res.add(archSpecificFolder); + } + return res; + } + + public boolean supportsArchitecture(String reqArch) { + for (String arch : architectures) + if (wildcardMatch(reqArch, arch)) + return true; + return false; + } + + public static final Comparator CASE_INSENSITIVE_ORDER = new Comparator() { + @Override + public int compare(Library o1, Library o2) { + return o1.getName().compareToIgnoreCase(o2.getName()); + } + }; + + public File getSrcFolder() { + return srcFolder; + } + + public String getName() { + return name; + } + + public boolean isPre15Lib() { + return pre15Lib; + } + + public File getFolder() { + return folder; + } + + public List getArchitectures() { + return architectures; + } + + public String getAuthor() { + return author; + } + + public List getCoreDependencies() { + return coreDependencies; + } + + public List getDependencies() { + return dependencies; + } + + public String getEmail() { + return email; + } + + public String getParagraph() { + return paragraph; + } + + public String getSentence() { + return sentence; + } + + public String getUrl() { + return url; + } + + public String getVersion() { + return version; + } + + @Override + public String toString() { + String res = "Library:"; + res += " (name=" + name + ")"; + res += " (architectures=" + architectures + ")"; + res += " (author=" + author + ")"; + res += " (core-dependencies=" + coreDependencies + ")"; + res += " (dependencies=" + dependencies + ")"; + res += " (email=" + email + ")"; + res += " (paragraph=" + paragraph + ")"; + res += " (sentence=" + sentence + ")"; + res += " (url=" + url + ")"; + res += " (version=" + version + ")"; + return res; + } +} diff --git a/app/src/processing/app/packages/LibraryList.java b/app/src/processing/app/packages/LibraryList.java new file mode 100644 index 000000000..343ff4bde --- /dev/null +++ b/app/src/processing/app/packages/LibraryList.java @@ -0,0 +1,70 @@ +package processing.app.packages; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import processing.app.helpers.FileUtils; + +@SuppressWarnings("serial") +public class LibraryList extends ArrayList { + + public LibraryList(LibraryList libs) { + super(libs); + } + + public LibraryList() { + super(); + } + + public Library getByName(String name) { + for (Library l : this) + if (l.getName().equals(name)) + return l; + return null; + } + + public void addOrReplace(Library lib) { + Library l = getByName(lib.getName()); + if (l != null) + remove(l); + add(lib); + } + + public void addOrReplaceAll(Collection c) { + for (Library l : c) + addOrReplace(l); + } + + public void sort() { + Collections.sort(this, Library.CASE_INSENSITIVE_ORDER); + } + + public Library search(String name, String arch) { + for (Library lib : this) { + if (!lib.getName().equals(name)) + continue; + if (!lib.supportsArchitecture(arch)) + continue; + return lib; + } + return null; + } + + public LibraryList filterByArchitecture(String reqArch) { + LibraryList res = new LibraryList(); + for (Library lib : this) + if (lib.supportsArchitecture(reqArch)) + res.add(lib); + return res; + } + + public LibraryList filterLibrariesInSubfolder(File subFolder) { + LibraryList res = new LibraryList(); + for (Library lib : this) + if (FileUtils.isSubDirectory(subFolder, lib.getFolder())) + res.add(lib); + return res; + } +} diff --git a/app/src/processing/app/syntax/PdeKeywords.java b/app/src/processing/app/syntax/PdeKeywords.java index 2edc312a7..ead926ec9 100644 --- a/app/src/processing/app/syntax/PdeKeywords.java +++ b/app/src/processing/app/syntax/PdeKeywords.java @@ -25,6 +25,7 @@ package processing.app.syntax; import processing.app.*; +import processing.app.packages.Library; import java.io.*; import java.util.*; @@ -59,8 +60,8 @@ public class PdeKeywords extends CTokenMarker { keywordColoring = new KeywordMap(false); keywordToReference = new Hashtable(); getKeywords(Base.getLibStream("keywords.txt")); - for (File lib : Base.getLibraries().values()) { - File keywords = new File(lib, "keywords.txt"); + for (Library lib : Base.getLibraries()) { + File keywords = new File(lib.getFolder(), "keywords.txt"); if (keywords.exists()) getKeywords(new FileInputStream(keywords)); } } catch (Exception e) { diff --git a/build/shared/revisions.txt b/build/shared/revisions.txt index 83ed21c4c..9ec12e161 100644 --- a/build/shared/revisions.txt +++ b/build/shared/revisions.txt @@ -4,6 +4,8 @@ ARDUINO 1.5.3 BETA [ide] * Removed useless baud rates from serial monitor * Fixed some minor IDE UI bugs (Shigeru Kanemoto) +* Added support for new 1.5 Library format (https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification) +* Pass board type from boards.txt (https://github.com/arduino/Arduino/issues/308) [arduino core] * sam: Fixed delayMicrosecond() when interrupts are disabled diff --git a/hardware/arduino/avr/boards.txt b/hardware/arduino/avr/boards.txt index b62eb10e0..f28192094 100644 --- a/hardware/arduino/avr/boards.txt +++ b/hardware/arduino/avr/boards.txt @@ -20,6 +20,7 @@ uno.bootloader.file=optiboot/optiboot_atmega328.hex uno.build.mcu=atmega328p uno.build.f_cpu=16000000L +uno.build.board=ARDUINO_UNO uno.build.core=arduino uno.build.variant=standard @@ -36,6 +37,7 @@ atmega328diecimila.bootloader.unlock_bits=0x3F atmega328diecimila.bootloader.lock_bits=0x0F atmega328diecimila.build.f_cpu=16000000L +atmega328diecimila.build.board=ARDUINO_DUEMILANOVE atmega328diecimila.build.core=arduino atmega328diecimila.build.variant=standard @@ -75,6 +77,7 @@ nano.bootloader.unlock_bits=0x3F nano.bootloader.lock_bits=0x0F nano.build.f_cpu=16000000L +nano.build.board=ARDUINO_NANO nano.build.core=arduino nano.build.variant=eightanaloginputs @@ -124,6 +127,7 @@ mega2560.bootloader.lock_bits=0x0F mega2560.build.mcu=atmega2560 mega2560.build.f_cpu=16000000L +mega2560.build.board=ARDUINO_MEGA2560 mega2560.build.core=arduino mega2560.build.variant=mega @@ -147,6 +151,7 @@ mega.bootloader.lock_bits=0x0F mega.build.mcu=atmega1280 mega.build.f_cpu=16000000L +mega.build.board=ARDUINO_MEGA mega.build.core=arduino mega.build.variant=mega @@ -173,6 +178,7 @@ leonardo.build.mcu=atmega32u4 leonardo.build.f_cpu=16000000L leonardo.build.vid=0x2341 leonardo.build.pid=0x8036 +leonardo.build.board=ARDUINO_LEONARDO leonardo.build.core=arduino leonardo.build.variant=leonardo leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} @@ -200,6 +206,7 @@ micro.build.mcu=atmega32u4 micro.build.f_cpu=16000000L micro.build.vid=0x2341 micro.build.pid=0x8037 +micro.build.board=ARDUINO_MICRO micro.build.core=arduino micro.build.variant=micro micro.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} @@ -227,6 +234,7 @@ esplora.build.mcu=atmega32u4 esplora.build.f_cpu=16000000L esplora.build.vid=0x2341 esplora.build.pid=0x803c +esplora.build.board=ARDUINO_ESPLORA esplora.build.core=arduino esplora.build.variant=leonardo esplora.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} @@ -244,6 +252,7 @@ mini.bootloader.unlock_bits=0x3F mini.bootloader.lock_bits=0x0F mini.build.f_cpu=16000000L +mini.build.board=ARDUINO_MINI mini.build.core=arduino mini.build.variant=eightanaloginputs @@ -291,6 +300,7 @@ ethernet.bootloader.lock_bits=0x0F ethernet.build.variant=standard ethernet.build.mcu=atmega328p ethernet.build.f_cpu=16000000L +ethernet.build.board=ARDUINO_ETHERNET ethernet.build.core=arduino ############################################################## @@ -312,6 +322,7 @@ fio.bootloader.lock_bits=0x0F fio.build.mcu=atmega328p fio.build.f_cpu=8000000L +fio.build.board=ARDUINO_FIO fio.build.core=arduino fio.build.variant=eightanaloginputs @@ -330,6 +341,7 @@ bt.bootloader.unlock_bits=0x3F bt.bootloader.lock_bits=0x0F bt.build.f_cpu=16000000L +bt.build.board=ARDUINO_BT bt.build.core=arduino bt.build.variant=eightanaloginputs @@ -377,6 +389,7 @@ LilyPadUSB.build.mcu=atmega32u4 LilyPadUSB.build.f_cpu=8000000L LilyPadUSB.build.vid=0x1B4F LilyPadUSB.build.pid=0x9208 +LilyPadUSB.build.board=ARDUINO_LILYPAD_USB LilyPadUSB.build.core=arduino LilyPadUSB.build.variant=leonardo LilyPadUSB.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} @@ -393,6 +406,7 @@ lilypad.bootloader.unlock_bits=0x3F lilypad.bootloader.lock_bits=0x0F lilypad.build.f_cpu=8000000L +lilypad.build.board=ARDUINO_LILYPAD lilypad.build.core=arduino lilypad.build.variant=standard @@ -433,6 +447,7 @@ pro.bootloader.tool=avrdude pro.bootloader.unlock_bits=0x3F pro.bootloader.lock_bits=0x0F +pro.build.board=ARDUINO_PRO pro.build.core=arduino pro.build.variant=standard @@ -506,6 +521,7 @@ atmegang.bootloader.lock_bits=0x0F atmegang.build.mcu=atmegang atmegang.build.f_cpu=16000000L +atmegang.build.board=ARDUINO_NG atmegang.build.core=arduino atmegang.build.variant=standard diff --git a/hardware/arduino/avr/platform.txt b/hardware/arduino/avr/platform.txt index d439ddd5c..a6cd314c1 100644 --- a/hardware/arduino/avr/platform.txt +++ b/hardware/arduino/avr/platform.txt @@ -27,10 +27,10 @@ build.extra_flags= # -------------------- ## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} -D{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} -D{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Create archives recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{build.path}/{archive_file}" "{object_file}" diff --git a/hardware/arduino/sam/boards.txt b/hardware/arduino/sam/boards.txt index 5d6f386cd..d3629e596 100644 --- a/hardware/arduino/sam/boards.txt +++ b/hardware/arduino/sam/boards.txt @@ -8,6 +8,7 @@ arduino_due_x_dbg.upload.wait_for_upload_port=false arduino_due_x_dbg.upload.native_usb=false arduino_due_x_dbg.build.mcu=cortex-m3 arduino_due_x_dbg.build.f_cpu=84000000L +arduino_due_x_dbg.build.board=ARDUINO_DUE arduino_due_x_dbg.build.core=arduino arduino_due_x_dbg.build.extra_flags=-D__SAM3X8E__ -mthumb -DUSB_PID={build.pid} -DUSB_VID={build.vid} -DUSBCON arduino_due_x_dbg.build.ldscript=linker_scripts/gcc/flash.ld @@ -25,6 +26,7 @@ arduino_due_x.upload.wait_for_upload_port=true arduino_due_x.upload.native_usb=true arduino_due_x.build.mcu=cortex-m3 arduino_due_x.build.f_cpu=84000000L +arduino_due_x.build.board=ARDUINO_DUE arduino_due_x.build.core=arduino arduino_due_x.build.extra_flags=-D__SAM3X8E__ -mthumb -DUSB_PID={build.pid} -DUSB_VID={build.vid} -DUSBCON arduino_due_x.build.ldscript=linker_scripts/gcc/flash.ld diff --git a/hardware/arduino/sam/platform.txt b/hardware/arduino/sam/platform.txt index fedb29e12..3594610ea 100644 --- a/hardware/arduino/sam/platform.txt +++ b/hardware/arduino/sam/platform.txt @@ -30,10 +30,10 @@ compiler.libsam.c.flags="-I{build.system.path}/libsam" "-I{build.system.path}/CM # --------------------- ## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}" +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} -D{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}" +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} -D{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}" ## Create archives recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{build.path}/{archive_file}" "{object_file}"