1616package preprocessor
1717
1818import (
19+ "bytes"
1920 "context"
2021 "fmt"
2122 "strconv"
2223 "strings"
2324
25+ "github.com/arduino/arduino-cli/arduino/builder"
2426 "github.com/arduino/arduino-cli/arduino/builder/cpp"
2527 "github.com/arduino/arduino-cli/arduino/builder/preprocessor/ctags"
2628 "github.com/arduino/arduino-cli/arduino/sketch"
@@ -34,30 +36,73 @@ import (
3436var tr = i18n .Tr
3537var DebugPreprocessor bool
3638
37- func CTags (sourceFile * paths.Path , targetFile * paths.Path , sketch * sketch.Sketch , lineOffset int , buildProperties * properties.Map ) ([]byte , error ) {
38- ctagsOutput , ctagsStdErr , err := RunCTags (sourceFile , buildProperties )
39+ func PreprocessSketchWithCtags (sketch * sketch.Sketch , buildPath * paths.Path , includes paths.PathList , lineOffset int , buildProperties * properties.Map , onlyUpdateCompilationDatabase bool ) ([]byte , []byte , error ) {
40+ // Create a temporary working directory
41+ tmpDir , err := paths .MkTempDir ("" , "" )
3942 if err != nil {
40- return ctagsStdErr , err
43+ return nil , nil , err
44+ }
45+ defer tmpDir .RemoveAll ()
46+ ctagsTarget := tmpDir .Join ("sketch_merged.cpp" )
47+
48+ normalOutput := & bytes.Buffer {}
49+ verboseOutput := & bytes.Buffer {}
50+
51+ // Run GCC preprocessor
52+ sourceFile := buildPath .Join ("sketch" , sketch .MainFile .Base ()+ ".cpp" )
53+ gccStdout , gccStderr , err := GCC (sourceFile , ctagsTarget , includes , buildProperties )
54+ verboseOutput .Write (gccStdout )
55+ verboseOutput .Write (gccStderr )
56+ normalOutput .Write (gccStderr )
57+ if err != nil {
58+ if ! onlyUpdateCompilationDatabase {
59+ return normalOutput .Bytes (), verboseOutput .Bytes (), errors .WithStack (err )
60+ }
61+
62+ // Do not bail out if we are generating the compile commands database
63+ normalOutput .WriteString (fmt .Sprintf ("%s: %s" ,
64+ tr ("An error occurred adding prototypes" ),
65+ tr ("the compilation database may be incomplete or inaccurate" )))
66+ if err := sourceFile .CopyTo (ctagsTarget ); err != nil {
67+ return normalOutput .Bytes (), verboseOutput .Bytes (), errors .WithStack (err )
68+ }
69+ }
70+
71+ if src , err := ctagsTarget .ReadFile (); err != nil {
72+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
73+ } else {
74+ filteredSource := builder .FilterSketchSource (sketch , bytes .NewReader (src ), false )
75+ if err := ctagsTarget .WriteFile ([]byte (filteredSource )); err != nil {
76+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
77+ }
78+ }
79+
80+ // Run CTags on gcc-preprocessed source
81+ ctagsOutput , ctagsStdErr , err := RunCTags (ctagsTarget , buildProperties )
82+ verboseOutput .Write (ctagsStdErr )
83+ if err != nil {
84+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
4185 }
4286
43- // func PrototypesAdder(sketch *sketch.Sketch, source string, ctagsStdout []byte, lineOffset int) string {
87+ // Parse CTags output
4488 parser := & ctags.CTagsParser {}
4589 prototypes , firstFunctionLine := parser .Parse (ctagsOutput , sketch .MainFile )
4690 if firstFunctionLine == - 1 {
4791 firstFunctionLine = 0
4892 }
4993
94+ // Add prototypes to the original sketch source
5095 var source string
51- if sourceData , err := targetFile .ReadFile (); err != nil {
52- return nil , err
96+ if sourceData , err := sourceFile .ReadFile (); err != nil {
97+ return normalOutput . Bytes (), verboseOutput . Bytes () , err
5398 } else {
5499 source = string (sourceData )
55100 }
56101 source = strings .Replace (source , "\r \n " , "\n " , - 1 )
57102 source = strings .Replace (source , "\r " , "\n " , - 1 )
58103 sourceRows := strings .Split (source , "\n " )
59104 if isFirstFunctionOutsideOfSource (firstFunctionLine , sourceRows ) {
60- return nil , nil
105+ return normalOutput . Bytes (), verboseOutput . Bytes () , nil
61106 }
62107
63108 insertionLine := firstFunctionLine + lineOffset - 1
@@ -81,8 +126,9 @@ func CTags(sourceFile *paths.Path, targetFile *paths.Path, sketch *sketch.Sketch
81126 fmt .Println ("#END OF PREPROCESSED SOURCE" )
82127 }
83128
84- err = targetFile .WriteFile ([]byte (preprocessedSource ))
85- return ctagsStdErr , err
129+ // Write back arduino-preprocess output to the sourceFile
130+ err = sourceFile .WriteFile ([]byte (preprocessedSource ))
131+ return normalOutput .Bytes (), verboseOutput .Bytes (), err
86132}
87133
88134func composePrototypeSection (line int , prototypes []* ctags.Prototype ) string {
0 commit comments