@@ -3,188 +3,103 @@ package handler
33import (
44 "bufio"
55 "bytes"
6+ "encoding/json"
67 "io/ioutil"
78 "log"
89 "os"
910 "os/exec"
1011 "path/filepath"
1112 "strings"
1213
14+ "github.com/arduino/arduino-cli/arduino/libraries"
15+ "github.com/arduino/arduino-cli/executils"
16+ "github.com/arduino/go-paths-helper"
1317 "github.com/arduino/go-properties-orderedmap"
1418 "github.com/pkg/errors"
1519)
1620
17- func generateCpp (inoCode []byte , sourcePath , fqbn string ) (cppPath string , cppCode []byte , err error ) {
18- // The CLI expects the `theSketchName.ino` file to be in `some/path/theSketchName` folder.
19- // Expected folder structure: `/path/to/temp/ino2cpp-${random}/theSketchName/theSketchName.ino`.
20- rawRootTempDir , err := ioutil .TempDir ("" , "ino2cpp-" )
21- if err != nil {
22- err = errors .Wrap (err , "Error while creating temporary directory." )
23- return
24- }
25- rootTempDir , err := filepath .EvalSymlinks (rawRootTempDir )
26- if err != nil {
27- err = errors .Wrap (err , "Error while resolving symbolic links of temporary directory." )
28- return
29- }
30-
31- sketchName := filepath .Base (sourcePath )
32- if strings .HasSuffix (sketchName , ".ino" ) {
33- sketchName = sketchName [:len (sketchName )- len (".ino" )]
34- }
35- sketchTempPath := filepath .Join (rootTempDir , sketchName )
36- createDirIfNotExist (sketchTempPath )
37-
38- // Write source file to temp dir
39- sketchFileName := sketchName + ".ino"
40- inoPath := filepath .Join (sketchTempPath , sketchFileName )
41- err = ioutil .WriteFile (inoPath , inoCode , 0600 )
42- if err != nil {
43- err = errors .Wrap (err , "Error while writing source file to temporary directory." )
44- return
45- }
46- if enableLogging {
47- log .Println ("Source file written to" , inoPath )
48- }
49-
50- // Copy all header files to temp dir
51- err = copyHeaderFiles (filepath .Dir (sourcePath ), rootTempDir )
52- if err != nil {
53- return
54- }
55-
56- // Generate compile_flags.txt
57- cppPath = filepath .Join (sketchTempPath , sketchFileName + ".cpp" )
58- flagsPath , err := generateCompileFlags (sketchTempPath , inoPath , sourcePath , fqbn )
59- if err != nil {
60- return
61- }
62- if enableLogging {
63- log .Println ("Compile flags written to" , flagsPath )
64- }
65-
66- // Generate target file
67- cppCode , err = generateTargetFile (sketchTempPath , inoPath , cppPath , fqbn )
68- return
69- }
70-
71- func createDirIfNotExist (dir string ) {
72- if _ , err := os .Stat (dir ); os .IsNotExist (err ) {
73- err = os .MkdirAll (dir , os .ModePerm )
74- if err != nil {
75- panic (err )
76- }
77- }
78- }
79-
80- func copyHeaderFiles (sourceDir string , destDir string ) error {
81- fileInfos , err := ioutil .ReadDir (sourceDir )
82- if err != nil {
83- return err
84- }
85- for _ , fileInfo := range fileInfos {
86- if ! fileInfo .IsDir () && strings .HasSuffix (fileInfo .Name (), ".h" ) {
87- input , err := ioutil .ReadFile (filepath .Join (sourceDir , fileInfo .Name ()))
88- if err != nil {
89- return err
90- }
91-
92- err = ioutil .WriteFile (filepath .Join (destDir , fileInfo .Name ()), input , 0644 )
93- if err != nil {
94- return err
95- }
96- }
97- }
98- return nil
99- }
21+ // func generateCpp(sourcePath, fqbn string) (*paths.Path, []byte, error) {
22+ // // Generate target file
23+ // if cppPath, err := generateBuildEnvironment(paths.New(sourcePath), fqbn); err != nil {
24+ // return nil, nil, err
25+ // } else if cppCode, err := cppPath.ReadFile(); err != nil {
26+ // return nil, nil, err
27+ // } else {
28+ // return cppPath, cppCode, err
29+ // }
30+ // }
10031
10132func updateCpp (inoCode []byte , sourcePath , fqbn string , fqbnChanged bool , cppPath string ) (cppCode []byte , err error ) {
102- tempDir := filepath .Dir (cppPath )
103- inoPath := strings .TrimSuffix (cppPath , ".cpp" )
104- if inoCode != nil {
105- // Write source file to temp dir
106- err = ioutil .WriteFile (inoPath , inoCode , 0600 )
107- if err != nil {
108- err = errors .Wrap (err , "Error while writing source file to temporary directory." )
109- return
110- }
111- if enableLogging {
112- log .Println ("Source file written to" , inoPath )
113- }
114- }
33+ // tempDir := filepath.Dir(cppPath)
34+ // inoPath := strings.TrimSuffix(cppPath, ".cpp")
35+ // if inoCode != nil {
36+ // // Write source file to temp dir
37+ // err = ioutil.WriteFile(inoPath, inoCode, 0600)
38+ // if err != nil {
39+ // err = errors.Wrap(err, "Error while writing source file to temporary directory.")
40+ // return
41+ // }
42+ // if enableLogging {
43+ // log.Println("Source file written to", inoPath)
44+ // }
45+ // }
11546
116- if fqbnChanged {
117- // Generate compile_flags.txt
118- var flagsPath string
119- flagsPath , err = generateCompileFlags (tempDir , inoPath , sourcePath , fqbn )
120- if err != nil {
121- return
122- }
123- if enableLogging {
124- log .Println ("Compile flags written to" , flagsPath )
125- }
126- }
47+ // if fqbnChanged {
48+ // // Generate compile_flags.txt
49+ // var flagsPath string
50+ // flagsPath, err = generateCompileFlags(tempDir, inoPath, sourcePath, fqbn)
51+ // if err != nil {
52+ // return
53+ // }
54+ // if enableLogging {
55+ // log.Println("Compile flags written to", flagsPath)
56+ // }
57+ // }
12758
128- // Generate target file
129- cppCode , err = generateTargetFile (tempDir , inoPath , cppPath , fqbn )
59+ // // Generate target file
60+ // cppCode, err = generateTargetFile(tempDir, inoPath, cppPath, fqbn)
13061 return
13162}
13263
133- func generateCompileFlags (tempDir , inoPath , sourcePath , fqbn string ) (string , error ) {
134- var cliArgs []string
135- if len (fqbn ) > 0 {
136- cliArgs = []string {"compile" , "--fqbn" , fqbn , "--show-properties" , inoPath }
137- } else {
138- cliArgs = []string {"compile" , "--show-properties" , inoPath }
139- }
140- propertiesCmd := exec .Command (globalCliPath , cliArgs ... )
141- output , err := propertiesCmd .Output ()
142- if err != nil {
143- err = logCommandErr (propertiesCmd , output , err , errMsgFilter (tempDir ))
144- return "" , err
145- }
146- buildProps , err := properties .LoadFromBytes (output )
64+ func generateBuildEnvironment (sketchDir * paths.Path , fqbn string ) (* paths.Path , error ) {
65+ // XXX: do this from IDE or via gRPC
66+ args := []string {globalCliPath ,
67+ "compile" ,
68+ "--fqbn" , fqbn ,
69+ "--only-compilation-database" ,
70+ "--clean" ,
71+ "--format" , "json" ,
72+ sketchDir .String (),
73+ }
74+ cmd , err := executils .NewProcess (args ... )
14775 if err != nil {
148- return "" , errors .Wrap ( err , "Error while reading build properties." )
76+ return nil , errors .Errorf ( "running %s: %s" , strings . Join ( args , " " ), err )
14977 }
150- flagsPath := filepath .Join (tempDir , "compile_flags.txt" )
151- outFile , err := os .OpenFile (flagsPath , os .O_WRONLY | os .O_CREATE , 0600 )
152- if err != nil {
153- return flagsPath , errors .Wrap (err , "Error while creating output file for compile flags." )
78+ cmdOutput := & bytes.Buffer {}
79+ cmd .RedirectStdoutTo (cmdOutput )
80+ cmd .SetDirFromPath (sketchDir )
81+ log .Println ("running: " , strings .Join (args , " " ))
82+ if err := cmd .Run (); err != nil {
83+ return nil , errors .Errorf ("running %s: %s" , strings .Join (args , " " ), err )
15484 }
155- defer outFile .Close ()
15685
157- printer := Printer {Writer : bufio .NewWriter (outFile )}
158- printCompileFlags (buildProps , & printer , fqbn )
159- printLibraryPaths (sourcePath , & printer )
160- printer .Flush ()
161- return flagsPath , printer .Err
162- }
163-
164- func generateTargetFile (tempDir , inoPath , cppPath , fqbn string ) (cppCode []byte , err error ) {
165- var cliArgs []string
166- if len (fqbn ) > 0 {
167- cliArgs = []string {"compile" , "--fqbn" , fqbn , "--preprocess" , inoPath }
168- } else {
169- cliArgs = []string {"compile" , "--preprocess" , inoPath }
86+ type cmdBuilderRes struct {
87+ BuildPath * paths.Path `json:"build_path"`
88+ UsedLibraries []* libraries.Library
17089 }
171- preprocessCmd := exec .Command (globalCliPath , cliArgs ... )
172- cppCode , err = preprocessCmd .Output ()
173- if err != nil {
174- err = logCommandErr (preprocessCmd , cppCode , err , errMsgFilter (tempDir ))
175- return
90+ type cmdRes struct {
91+ CompilerOut string `json:"compiler_out"`
92+ CompilerErr string `json:"compiler_err"`
93+ BuilderResult cmdBuilderRes `json:"builder_result"`
17694 }
177-
178- // Filter lines beginning with ERROR or WARNING
179- cppCode = []byte (filterErrorsAndWarnings (cppCode ))
180-
181- err = ioutil .WriteFile (cppPath , cppCode , 0600 )
182- if err != nil {
183- err = errors .Wrap (err , "Error while writing target file to temporary directory." )
184- } else if enableLogging {
185- log .Println ("Target file written to" , cppPath )
95+ var res cmdRes
96+ if err := json .Unmarshal (cmdOutput .Bytes (), & res ); err != nil {
97+ return nil , errors .Errorf ("parsing arduino-cli output: %s" , err )
18698 }
187- return
99+
100+ // Return only the build path
101+ log .Println ("arduino-cli output:" , cmdOutput )
102+ return res .BuilderResult .BuildPath , nil
188103}
189104
190105func filterErrorsAndWarnings (cppCode []byte ) string {
0 commit comments