Skip to content

1.5 Library specification rev. 2 #1765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 9, 2014
2 changes: 0 additions & 2 deletions app/src/processing/app/Base.java
Original file line number Diff line number Diff line change
Expand Up @@ -1323,8 +1323,6 @@ public void onBoardOrPortChange() {
} catch (IOException e) {
showWarning(_("Error"), _("Error loading libraries"), e);
}
String currentArch = Base.getTargetPlatform().getId();
libraries = libraries.filterByArchitecture(currentArch);

// Populate importToLibraryTable
importToLibraryTable = new HashMap<String, Library>();
Expand Down
1 change: 0 additions & 1 deletion app/src/processing/app/Sketch.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import processing.core.*;
import static processing.app.I18n._;

import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;
Expand Down
214 changes: 113 additions & 101 deletions app/src/processing/app/debug/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -88,30 +89,46 @@ public boolean compile(boolean _verbose) throws RunnerException {

// 0. include paths for core + all libraries
sketch.setCompilingProgress(20);
List<String> includePaths = new ArrayList<String>();
includePaths.add(prefs.get("build.core.path"));
if (prefs.get("build.variant.path").length() != 0)
includePaths.add(prefs.get("build.variant.path"));
List<File> includeFolders = new ArrayList<File>();
includeFolders.add(prefs.getFile("build.core.path"));
if (prefs.getFile("build.variant.path") != null)
includeFolders.add(prefs.getFile("build.variant.path"));
for (Library lib : sketch.getImportedLibraries()) {
if (verbose)
System.out.println(I18n
.format(_("Using library {0} in folder: {1} {2}"), lib.getName(),
lib.getFolder(), lib.isPre15Lib() ? "(pre-1.5)" : ""));
for (File folder : lib.getSrcFolders(targetArch))
includePaths.add(folder.getPath());
lib.getFolder(), lib.isLegacy() ? "(legacy)" : ""));
includeFolders.add(lib.getSrcFolder());
}
if (verbose)
System.out.println();

List<String> archs = new ArrayList<String>();
archs.add(Base.getTargetPlatform().getId());
if (prefs.containsKey("architecture.override_check")) {
String[] overrides = prefs.get("architecture.override_check").split(",");
archs.addAll(Arrays.asList(overrides));
}
for (Library lib : sketch.getImportedLibraries()) {
if (!lib.supportsArchitecture(archs)) {
System.err.println(I18n
.format(_("WARNING: library {0} claims to run on {1} "
+ "architecture(s) and may be incompatible with your"
+ " current board which runs on {2} architecture(s)."), lib
.getName(), lib.getArchitectures(), archs));
System.err.println();
}
}

// 1. compile the sketch (already in the buildPath)
sketch.setCompilingProgress(30);
compileSketch(includePaths);
compileSketch(includeFolders);
sketchIsCompiled = true;

// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
// Doesn't really use configPreferences
sketch.setCompilingProgress(40);
compileLibraries(includePaths);
compileLibraries(includeFolders);

// 3. compile the core, outputting .o files to <buildPath> and then
// collecting them into the core.a library file.
Expand All @@ -120,15 +137,15 @@ public boolean compile(boolean _verbose) throws RunnerException {

// 4. link it all together into the .elf file
sketch.setCompilingProgress(60);
compileLink(includePaths);
compileLink();

// 5. extract EEPROM data (from EEMEM directive) to .eep file.
sketch.setCompilingProgress(70);
compileEep(includePaths);
compileEep();

// 6. build the .hex file
sketch.setCompilingProgress(80);
compileHex(includePaths);
compileHex();

sketch.setCompilingProgress(90);
return true;
Expand Down Expand Up @@ -218,45 +235,38 @@ private PreferencesMap createBuildPreferences(String _buildPath,
return p;
}

private List<File> compileFiles(String outputPath, File sourcePath,
boolean recurse, List<String> includePaths)
private List<File> compileFiles(File outputPath, File sourcePath,
boolean recurse, List<File> includeFolders)
throws RunnerException {
List<File> sSources = findFilesInFolder(sourcePath, "S", recurse);
List<File> cSources = findFilesInFolder(sourcePath, "c", recurse);
List<File> cppSources = findFilesInFolder(sourcePath, "cpp", recurse);
List<File> objectPaths = new ArrayList<File>();

for (File file : sSources) {
String objectPath = outputPath + File.separator + file.getName() + ".o";
objectPaths.add(new File(objectPath));
String[] cmd = getCommandCompilerS(includePaths, file.getAbsolutePath(),
objectPath);
File objectFile = new File(outputPath, file.getName() + ".o");
objectPaths.add(objectFile);
String[] cmd = getCommandCompilerS(includeFolders, file, objectFile);
execAsynchronously(cmd);
}

for (File file : cSources) {
String objectPath = outputPath + File.separator + file.getName() + ".o";
String dependPath = outputPath + File.separator + file.getName() + ".d";
File objectFile = new File(objectPath);
File dependFile = new File(dependPath);
File objectFile = new File(outputPath, file.getName() + ".o");
File dependFile = new File(outputPath, file.getName() + ".d");
objectPaths.add(objectFile);
if (isAlreadyCompiled(file, objectFile, dependFile, prefs))
continue;
String[] cmd = getCommandCompilerC(includePaths, file.getAbsolutePath(),
objectPath);
String[] cmd = getCommandCompilerC(includeFolders, file, objectFile);
execAsynchronously(cmd);
}

for (File file : cppSources) {
String objectPath = outputPath + File.separator + file.getName() + ".o";
String dependPath = outputPath + File.separator + file.getName() + ".d";
File objectFile = new File(objectPath);
File dependFile = new File(dependPath);
File objectFile = new File(outputPath, file.getName() + ".o");
File dependFile = new File(outputPath, file.getName() + ".d");
objectPaths.add(objectFile);
if (isAlreadyCompiled(file, objectFile, dependFile, prefs))
continue;
String[] cmd = getCommandCompilerCPP(includePaths,
file.getAbsolutePath(), objectPath);
String[] cmd = getCommandCompilerCPP(includeFolders, file, objectFile);
execAsynchronously(cmd);
}

Expand Down Expand Up @@ -511,15 +521,15 @@ public void message(String s) {
System.err.print(s);
}

private String[] getCommandCompilerS(List<String> includePaths,
String sourceName, String objectName)
private String[] getCommandCompilerS(List<File> includeFolders,
File sourceFile, File objectFile)
throws RunnerException {
String includes = preparePaths(includePaths);
String includes = prepareIncludes(includeFolders);
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + Base.REVISION);
dict.put("includes", includes);
dict.put("source_file", sourceName);
dict.put("object_file", objectName);
dict.put("source_file", sourceFile.getAbsolutePath());
dict.put("object_file", objectFile.getAbsolutePath());

try {
String cmd = prefs.get("recipe.S.o.pattern");
Expand All @@ -529,16 +539,16 @@ private String[] getCommandCompilerS(List<String> includePaths,
}
}

private String[] getCommandCompilerC(List<String> includePaths,
String sourceName, String objectName)
private String[] getCommandCompilerC(List<File> includeFolders,
File sourceFile, File objectFile)
throws RunnerException {
String includes = preparePaths(includePaths);
String includes = prepareIncludes(includeFolders);

PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + Base.REVISION);
dict.put("includes", includes);
dict.put("source_file", sourceName);
dict.put("object_file", objectName);
dict.put("source_file", sourceFile.getAbsolutePath());
dict.put("object_file", objectFile.getAbsolutePath());

String cmd = prefs.get("recipe.c.o.pattern");
try {
Expand All @@ -548,16 +558,16 @@ private String[] getCommandCompilerC(List<String> includePaths,
}
}

private String[] getCommandCompilerCPP(List<String> includePaths,
String sourceName, String objectName)
private String[] getCommandCompilerCPP(List<File> includeFolders,
File sourceFile, File objectFile)
throws RunnerException {
String includes = preparePaths(includePaths);
String includes = prepareIncludes(includeFolders);

PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + Base.REVISION);
dict.put("includes", includes);
dict.put("source_file", sourceName);
dict.put("object_file", objectName);
dict.put("source_file", sourceFile.getAbsolutePath());
dict.put("object_file", objectFile.getAbsolutePath());

String cmd = prefs.get("recipe.cpp.o.pattern");
try {
Expand Down Expand Up @@ -606,79 +616,81 @@ static public List<File> findFilesInFolder(File folder, String extension,
}

// 1. compile the sketch (already in the buildPath)
void compileSketch(List<String> includePaths) throws RunnerException {
String buildPath = prefs.get("build.path");
objectFiles.addAll(compileFiles(buildPath, new File(buildPath), false,
includePaths));
void compileSketch(List<File> includeFolders) throws RunnerException {
File buildPath = prefs.getFile("build.path");
objectFiles.addAll(compileFiles(buildPath, buildPath, false, includeFolders));
}

// 2. compile the libraries, outputting .o files to:
// <buildPath>/<library>/
void compileLibraries(List<String> includePaths) throws RunnerException {
File outputPath = new File(prefs.get("build.path"));
void compileLibraries(List<File> includeFolders) throws RunnerException {
for (Library lib : sketch.getImportedLibraries()) {
for (File folder : lib.getSrcFolders(targetArch)) {
if (lib.isPre15Lib()) {
compileLibrary(outputPath, folder, includePaths);
} else {
recursiveCompileLibrary(outputPath, folder, includePaths);
}
}
compileLibrary(lib, includeFolders);
}
}

private void recursiveCompileLibrary(File outputPath, File libraryFolder, List<String> includePaths) throws RunnerException {
File newOutputPath = compileFilesInFolder(outputPath, libraryFolder, includePaths);
for (File subFolder : libraryFolder.listFiles(new OnlyDirs())) {
recursiveCompileLibrary(newOutputPath, subFolder, includePaths);
private void compileLibrary(Library lib, List<File> includeFolders)
throws RunnerException {
File libFolder = lib.getSrcFolder();
File libBuildFolder = prefs.getFile(("build.path"), lib.getName());

if (lib.useRecursion()) {
// libBuildFolder == {build.path}/LibName
// libFolder == {lib.path}/src
recursiveCompileFilesInFolder(libBuildFolder, libFolder, includeFolders);

} else {
// libFolder == {lib.path}/
// utilityFolder == {lib.path}/utility
// libBuildFolder == {build.path}/LibName
// utilityBuildFolder == {build.path}/LibName/utility
File utilityFolder = new File(libFolder, "utility");
File utilityBuildFolder = new File(libBuildFolder, "utility");

includeFolders.add(utilityFolder);
compileFilesInFolder(libBuildFolder, libFolder, includeFolders);
compileFilesInFolder(utilityBuildFolder, utilityFolder, includeFolders);

// other libraries should not see this library's utility/ folder
includeFolders.remove(utilityFolder);
}
}

private File compileFilesInFolder(File outputPath, File libraryFolder, List<String> includePaths) throws RunnerException {
File outputFolder = new File(outputPath, libraryFolder.getName());
createFolder(outputFolder);
objectFiles.addAll(compileFiles(outputFolder.getAbsolutePath(), libraryFolder, false, includePaths));
return outputFolder;
private void recursiveCompileFilesInFolder(File srcBuildFolder, File srcFolder, List<File> includeFolders) throws RunnerException {
compileFilesInFolder(srcBuildFolder, srcFolder, includeFolders);
for (File subFolder : srcFolder.listFiles(new OnlyDirs())) {
File subBuildFolder = new File(srcBuildFolder, subFolder.getName());
recursiveCompileFilesInFolder(subBuildFolder, subFolder, includeFolders);
}
}

private void compileLibrary(File outputPath, File libraryFolder, List<String> 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);
private void compileFilesInFolder(File buildFolder, File srcFolder, List<File> includeFolders) throws RunnerException {
createFolder(buildFolder);
List<File> objects = compileFiles(buildFolder, srcFolder, false, includeFolders);
objectFiles.addAll(objects);
}

// 3. compile the core, outputting .o files to <buildPath> and then
// collecting them into the core.a library file.
void compileCore()
throws RunnerException {

String corePath = prefs.get("build.core.path");
String variantPath = prefs.get("build.variant.path");
String buildPath = prefs.get("build.path");
File coreFolder = prefs.getFile("build.core.path");
File variantFolder = prefs.getFile("build.variant.path");
File buildFolder = prefs.getFile("build.path");

List<String> includePaths = new ArrayList<String>();
includePaths.add(corePath); // include core path only
if (variantPath.length() != 0)
includePaths.add(variantPath);
List<File> includeFolders = new ArrayList<File>();
includeFolders.add(coreFolder); // include core path only
if (variantFolder != null)
includeFolders.add(variantFolder);

List<File> coreObjectFiles = compileFiles(buildPath, new File(corePath),
true, includePaths);
if (variantPath.length() != 0)
coreObjectFiles.addAll(compileFiles(buildPath, new File(variantPath),
true, includePaths));
List<File> objectFiles = compileFiles(buildFolder, coreFolder, true,
includeFolders);
if (variantFolder != null)
objectFiles.addAll(compileFiles(buildFolder, variantFolder, true,
includeFolders));

for (File file : coreObjectFiles) {
for (File file : objectFiles) {

PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + Base.REVISION);
Expand All @@ -697,7 +709,7 @@ void compileCore()
}

// 4. link it all together into the .elf file
void compileLink(List<String> includePaths)
void compileLink()
throws RunnerException {

// TODO: Make the --relax thing in configuration files.
Expand Down Expand Up @@ -731,7 +743,7 @@ void compileLink(List<String> includePaths)
}

// 5. extract EEPROM data (from EEMEM directive) to .eep file.
void compileEep(List<String> includePaths) throws RunnerException {
void compileEep() throws RunnerException {
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + Base.REVISION);

Expand All @@ -746,7 +758,7 @@ void compileEep(List<String> includePaths) throws RunnerException {
}

// 6. build the .hex file
void compileHex(List<String> includePaths) throws RunnerException {
void compileHex() throws RunnerException {
PreferencesMap dict = new PreferencesMap(prefs);
dict.put("ide_version", "" + Base.REVISION);

Expand All @@ -760,10 +772,10 @@ void compileHex(List<String> includePaths) throws RunnerException {
execAsynchronously(cmdArray);
}

private static String preparePaths(List<String> includePaths) {
private static String prepareIncludes(List<File> includeFolders) {
String res = "";
for (String p : includePaths)
res += " \"-I" + p + '"';
for (File p : includeFolders)
res += " \"-I" + p.getAbsolutePath() + '"';

// Remove first space
return res.substring(1);
Expand Down
Loading