-
Notifications
You must be signed in to change notification settings - Fork 0
/
msvc.go
110 lines (93 loc) · 2.29 KB
/
msvc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// dcc - dependency-driven C/C++ compiler front end
//
// Copyright © A.Newman 2015.
//
// This source code is released under version 2 of the GNU Public License.
// See the file LICENSE for details.
//
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)
type msvcCompiler struct {
}
func (cl *msvcCompiler) Name() string {
return "cl"
}
func msvcScrapeShowIncludes(r io.Reader, deps io.Writer, nonDeps io.Writer, source string) {
const prefix = "Note: including file:"
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, prefix) {
filename := strings.TrimSpace(strings.TrimPrefix(line, prefix))
fmt.Fprintln(deps, filename)
} else if line != source {
fmt.Fprintln(nonDeps, line)
}
}
}
func (cl *msvcCompiler) Compile(source, object, deps string, options []string, stderr io.Writer) error {
r, w, err := os.Pipe()
if err != nil {
return err
}
defer r.Close()
defer w.Close()
depsFile, err := os.Create(deps)
if err != nil {
return err
}
fmt.Fprintln(depsFile, object)
go msvcScrapeShowIncludes(r, depsFile, os.Stdout, filepath.Base(source))
args := append([]string{}, options...)
args = append(args, "/nologo", "/showIncludes", "/c", source, "/Fo"+object)
cmd := exec.Command(cl.Name(), args...)
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, w, stderr
err = cmd.Run()
err2 := depsFile.Close()
if err != nil {
os.Remove(deps)
return err
}
if err2 != nil {
os.Remove(deps)
return err2
}
return err
}
func (cl *msvcCompiler) ReadDependencies(path string) (string, []string, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return "", nil, err
}
input := bufio.NewScanner(bytes.NewReader(data))
if !input.Scan() {
return "", nil, ErrUnexpectedEOF
}
target := input.Text()
var filenames = make([]string, 0, 1000)
for input.Scan() {
filename := input.Text()
filenames = append(filenames, filename)
}
return target, filenames, nil
}
// NewMsvcCompiler returns a CompilerDriver using Microsoft's
// cl.exe C/C++ compiler.
func NewMsvcCompiler() Compiler {
return &msvcCompiler{}
}
func (cl *msvcCompiler) DefineExecutableArgs(exeName string) []string {
args := make([]string, 1)
args[0] = fmt.Sprintf("/Fe%s", exeName)
return args
}