32
32
import java .io .*;
33
33
import java .util .*;
34
34
import java .util .zip .*;
35
+ import java .text .MessageFormat ;
35
36
36
37
37
38
public class Compiler implements MessageConsumer {
@@ -43,9 +44,22 @@ public class Compiler implements MessageConsumer {
43
44
Sketch sketch ;
44
45
String buildPath ;
45
46
String primaryClassName ;
46
- boolean verbose ;
47
+ String platform ;
48
+ String board ;
47
49
50
+ boolean verbose ;
51
+
48
52
RunnerException exception ;
53
+
54
+ HashMap <String , String > configPreferences ;
55
+ HashMap <String , String > boardPreferences ;
56
+ HashMap <String , String > platformPreferences ;
57
+
58
+ String avrBasePath ;
59
+ String corePath ;
60
+
61
+ List <File > objectFiles ;
62
+ ArrayList <String > includePaths ;
49
63
50
64
public Compiler () { }
51
65
@@ -70,9 +84,47 @@ public boolean compile(Sketch sketch,
70
84
// the pms object isn't used for anything but storage
71
85
MessageStream pms = new MessageStream (this );
72
86
73
- String avrBasePath = Base .getAvrBasePath ();
74
87
Map <String , String > boardPreferences = Base .getBoardPreferences ();
75
- String core = boardPreferences .get ("build.core" );
88
+
89
+ //Check for null platform, and use system default if not found
90
+ platform = boardPreferences .get ("platform" );
91
+ if (platform == null )
92
+ {
93
+ platformPreferences = new HashMap (Base .getPlatformPreferences ());
94
+ }
95
+ else
96
+ {
97
+ platformPreferences = new HashMap (Base .getPlatformPreferences (platform ));
98
+ }
99
+
100
+
101
+ //Put all the global preference configuration into one Master configpreferences
102
+ configPreferences = mergePreferences ( Preferences .getMap (), platformPreferences , boardPreferences );
103
+ avrBasePath = configPreferences .get ("compiler.path" );
104
+ if (avrBasePath == null )
105
+ {
106
+ avrBasePath = Base .getAvrBasePath ();
107
+ }
108
+ else
109
+ {
110
+ //Put in the system path in the compiler path if available
111
+ MessageFormat compileFormat = new MessageFormat (avrBasePath );
112
+ String basePath = System .getProperty ("user.dir" );
113
+ if (Base .isMacOS ()) {
114
+ //logger.debug("basePath: " + basePath);
115
+ basePath += "/Arduino.app/Contents/Resources/Java" ;
116
+ }
117
+ Object [] Args = {basePath };
118
+ avrBasePath = compileFormat .format ( Args );
119
+
120
+ }
121
+ this .board = configPreferences .get ("board" );
122
+ if (this .board == "" )
123
+ {
124
+ this .board = "_UNKNOWN" ;
125
+ }
126
+
127
+ String core = configPreferences .get ("build.core" );
76
128
if (core == null ) {
77
129
RunnerException re = new RunnerException ("No board selected; please choose a board from the Tools > Board menu." );
78
130
re .hideStackTrace ();
@@ -91,7 +143,7 @@ public boolean compile(Sketch sketch,
91
143
corePath = coreFolder .getAbsolutePath ();
92
144
}
93
145
94
- String pins = boardPreferences .get ("build.pins" );
146
+ String pins = configPreferences .get ("build.pins" );
95
147
String pinsPath = null ;
96
148
97
149
if (pins != null ) {
@@ -111,21 +163,23 @@ public boolean compile(Sketch sketch,
111
163
112
164
// 0. include paths for core + all libraries
113
165
114
- List includePaths = new ArrayList ();
166
+ ArrayList < String > includePaths = new ArrayList ();
115
167
includePaths .add (corePath );
116
168
if (pinsPath != null ) includePaths .add (pinsPath );
117
169
for (File file : sketch .getImportedLibraries ()) {
118
170
includePaths .add (file .getPath ());
119
171
}
120
172
121
173
// 1. compile the sketch (already in the buildPath)
122
-
174
+ compileSketch (avrBasePath , buildPath , includePaths , configPreferences );
175
+ /*
123
176
objectFiles.addAll(
124
177
compileFiles(avrBasePath, buildPath, includePaths,
125
178
findFilesInPath(buildPath, "S", false),
126
179
findFilesInPath(buildPath, "c", false),
127
180
findFilesInPath(buildPath, "cpp", false),
128
181
boardPreferences));
182
+ */
129
183
130
184
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
131
185
@@ -280,9 +334,9 @@ public boolean compile(Sketch sketch,
280
334
281
335
282
336
private List <File > compileFiles (String avrBasePath ,
283
- String buildPath , List < File > includePaths ,
284
- List <File > sSources ,
285
- List <File > cSources , List <File > cppSources ,
337
+ String buildPath , ArrayList < String > includePaths ,
338
+ ArrayList <File > sSources ,
339
+ ArrayList <File > cSources , ArrayList <File > cppSources ,
286
340
Map <String , String > boardPreferences )
287
341
throws RunnerException {
288
342
@@ -580,6 +634,171 @@ static public ArrayList<File> findFilesInFolder(File folder, String extension,
580
634
}
581
635
582
636
637
+ // 1. compile the sketch (already in the buildPath)
638
+ void compileSketch (String avrBasePath , String buildPath , ArrayList <String > includePaths , HashMap <String , String > configPreferences )
639
+ throws RunnerException
640
+ {
641
+ //logger.debug("compileSketch: start");
642
+ this .objectFiles .addAll (compileFiles (avrBasePath , buildPath , includePaths ,
643
+ findFilesInPath (buildPath , "S" , false ),
644
+ findFilesInPath (buildPath , "c" , false ),
645
+ findFilesInPath (buildPath , "cpp" , false ),
646
+ configPreferences ));
647
+ }
648
+
649
+ // 2. compile the libraries, outputting .o files to:
650
+ // <buildPath>/<library>/
651
+ void compileLibraries (String avrBasePath , String buildPath , ArrayList <String > includePaths , HashMap <String , String > configPreferences )
652
+ throws RunnerException
653
+ {
654
+ //logger.debug("compileLibraries: start");
655
+ for (File libraryFolder : sketch .getImportedLibraries ())
656
+ {
657
+ File outputFolder = new File (buildPath , libraryFolder .getName ());
658
+ File utilityFolder = new File (libraryFolder , "utility" );
659
+ createFolder (outputFolder );
660
+ // this library can use includes in its utility/ folder
661
+ this .includePaths .add (utilityFolder .getAbsolutePath ());
662
+ this .objectFiles .addAll (compileFiles (avrBasePath ,
663
+ outputFolder .getAbsolutePath (), includePaths ,
664
+ findFilesInFolder (libraryFolder , "S" , false ),
665
+ findFilesInFolder (libraryFolder , "c" , false ),
666
+ findFilesInFolder (libraryFolder , "cpp" , false ),
667
+ configPreferences ));
668
+ outputFolder = new File (outputFolder , "utility" );
669
+ createFolder (outputFolder );
670
+ this .objectFiles .addAll (compileFiles (avrBasePath ,
671
+ outputFolder .getAbsolutePath (), includePaths ,
672
+ findFilesInFolder (utilityFolder , "S" , false ),
673
+ findFilesInFolder (utilityFolder , "c" , false ),
674
+ findFilesInFolder (utilityFolder , "cpp" , false ),
675
+ configPreferences ));
676
+ // other libraries should not see this library's utility/ folder
677
+ this .includePaths .remove (includePaths .size () - 1 );
678
+ }
679
+ }
680
+
681
+ // 3. compile the core, outputting .o files to <buildPath> and then
682
+ // collecting them into the core.a library file.
683
+ void compileCore (String avrBasePath , String buildPath , String corePath , HashMap <String , String > configPreferences )
684
+ throws RunnerException
685
+ {
686
+ //logger.debug("compileCore(...) start");
687
+
688
+ ArrayList <String > includePaths = new ArrayList ();
689
+ includePaths .add (corePath ); //include core path only
690
+ String baseCommandString = configPreferences .get ("recipe.ar.pattern" );
691
+ String commandString = "" ;
692
+ MessageFormat compileFormat = new MessageFormat (baseCommandString );
693
+
694
+ List <File > coreObjectFiles = compileFiles (
695
+ avrBasePath ,
696
+ buildPath ,
697
+ includePaths ,
698
+ findFilesInPath (corePath , "S" , true ),
699
+ findFilesInPath (corePath , "c" , true ),
700
+ findFilesInPath (corePath , "cpp" , true ),
701
+ configPreferences );
702
+
703
+ for (File file : coreObjectFiles ) {
704
+ //List commandAR = new ArrayList(baseCommandAR);
705
+ //commandAR = commandAR + file.getAbsolutePath();
706
+
707
+ Object [] Args = {
708
+ avrBasePath ,
709
+ configPreferences .get ("compiler.ar.cmd" ),
710
+ configPreferences .get ("compiler.ar.flags" ),
711
+ //corePath,
712
+ buildPath + File .separator ,
713
+ "core.a" ,
714
+ //objectName
715
+ file .getAbsolutePath ()
716
+ };
717
+ commandString = compileFormat .format ( Args );
718
+ execAsynchronously (commandString );
719
+ }
720
+ }
721
+
722
+ // 4. link it all together into the .elf file
723
+ void compileLink (String avrBasePath , String buildPath , String corePath , ArrayList <String > includePaths , HashMap <String , String > configPreferences )
724
+ throws RunnerException
725
+ {
726
+ //logger.debug("compileLink: start");
727
+ String baseCommandString = configPreferences .get ("recipe.c.combine.pattern" );
728
+ String commandString = "" ;
729
+ MessageFormat compileFormat = new MessageFormat (baseCommandString );
730
+ String objectFileList = "" ;
731
+
732
+ for (File file : objectFiles ) {
733
+ objectFileList = objectFileList + file .getAbsolutePath () + "::" ;
734
+ }
735
+
736
+ Object [] Args = {
737
+ avrBasePath ,
738
+ configPreferences .get ("compiler.c.elf.cmd" ),
739
+ configPreferences .get ("compiler.c.elf.flags" ),
740
+ configPreferences .get ("compiler.cpudef" ),
741
+ configPreferences .get ("build.mcu" ),
742
+ buildPath + File .separator ,
743
+ primaryClassName ,
744
+ objectFileList ,
745
+ buildPath + File .separator + "core.a" ,
746
+ buildPath ,
747
+ corePath ,
748
+ configPreferences .get ("ldscript" ),
749
+ };
750
+ commandString = compileFormat .format ( Args );
751
+ execAsynchronously (commandString );
752
+ }
753
+
754
+ // 5. extract EEPROM data (from EEMEM directive) to .eep file.
755
+ void compileEep (String avrBasePath , String buildPath , ArrayList <String > includePaths , HashMap <String , String > configPreferences )
756
+ throws RunnerException
757
+ {
758
+ //logger.debug("compileEep: start");
759
+ String baseCommandString = configPreferences .get ("recipe.objcopy.eep.pattern" );
760
+ String commandString = "" ;
761
+ MessageFormat compileFormat = new MessageFormat (baseCommandString );
762
+ String objectFileList = "" ;
763
+
764
+ Object [] Args = {
765
+ avrBasePath ,
766
+ configPreferences .get ("compiler.objcopy.cmd" ),
767
+ configPreferences .get ("compiler.objcopy.eep.flags" ),
768
+ buildPath + File .separator + primaryClassName ,
769
+ buildPath + File .separator + primaryClassName
770
+ };
771
+ commandString = compileFormat .format ( Args );
772
+
773
+ execAsynchronously (commandString );
774
+ }
775
+
776
+ // 6. build the .hex file
777
+ void compileHex (String avrBasePath , String buildPath , ArrayList <String > includePaths , HashMap <String , String > configPreferences )
778
+ throws RunnerException
779
+ {
780
+ //logger.debug("compileHex: start");
781
+ String baseCommandString = configPreferences .get ("recipe.objcopy.hex.pattern" );
782
+ String commandString = "" ;
783
+ MessageFormat compileFormat = new MessageFormat (baseCommandString );
784
+ String objectFileList = "" ;
785
+
786
+ Object [] Args = {
787
+ avrBasePath ,
788
+ configPreferences .get ("compiler.elf2hex.cmd" ),
789
+ configPreferences .get ("compiler.elf2hex.flags" ),
790
+ buildPath + File .separator + primaryClassName ,
791
+ buildPath + File .separator + primaryClassName
792
+ };
793
+ commandString = compileFormat .format ( Args );
794
+
795
+ execAsynchronously (commandString );
796
+
797
+ }
798
+
799
+
800
+
801
+
583
802
//merge all the preferences file in the correct order of precedence
584
803
HashMap mergePreferences (Map Preferences , Map platformPreferences , Map boardPreferences )
585
804
{
0 commit comments