Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions internal/client/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os/user"
"path/filepath"
"runtime"
"strings"
"sync"
"syscall"
"time"
Expand Down Expand Up @@ -274,15 +275,17 @@ func (daemon *Daemon) FallbackToLocalCxx(req DaemonSockRequest, reason error) Da
return reply
}

func (daemon *Daemon) GetOrCreateIncludesCache(cxxName string) *IncludesCache {
func (daemon *Daemon) GetOrCreateIncludesCache(cxxName string, cxxArgs []string) *IncludesCache {
cxxCacheName := cxxName + strings.Join(cxxArgs, " ")

daemon.mu.Lock()
includesCache := daemon.includesCache[cxxName]
includesCache := daemon.includesCache[cxxCacheName]
if includesCache == nil {
var err error
if includesCache, err = MakeIncludesCache(cxxName); err != nil {
if includesCache, err = MakeIncludesCache(cxxName, cxxArgs); err != nil {
logClient.Error("failed to calc default include dirs for", cxxName, err)
}
daemon.includesCache[cxxName] = includesCache
daemon.includesCache[cxxCacheName] = includesCache
}
daemon.mu.Unlock()
return includesCache
Expand Down
4 changes: 2 additions & 2 deletions internal/client/includes-cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ type IncludesCache struct {
mu sync.RWMutex
}

func MakeIncludesCache(cxxName string) (*IncludesCache, error) {
cxxDefIDirs, err := GetDefaultCxxIncludeDirsOnLocal(cxxName)
func MakeIncludesCache(cxxName string, cxxArgs []string) (*IncludesCache, error) {
cxxDefIDirs, err := GetDefaultCxxIncludeDirsOnLocal(cxxName, cxxArgs)

return &IncludesCache{
cxxName: cxxName,
Expand Down
8 changes: 6 additions & 2 deletions internal/client/includes-collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,12 @@ func CollectDependentIncludesByCxxM(includesCache *IncludesCache, cwd string, cx
// GetDefaultCxxIncludeDirsOnLocal retrieves default include dirs on a local machine.
// This is done by -Wp,-v option for a no input file.
// This result is cached once nocc-daemon is started.
func GetDefaultCxxIncludeDirsOnLocal(cxxName string) (IncludeDirs, error) {
cxxWpCommand := exec.Command(cxxName, "-Wp,-v", "-x", "c++", "/dev/null", "-fsyntax-only")
func GetDefaultCxxIncludeDirsOnLocal(cxxName string, cxxArgs []string) (IncludeDirs, error) {
cxxCmdLine := make([]string, 0, len(cxxArgs)+5)
cxxCmdLine = append(cxxCmdLine, cxxArgs...)
cxxCmdLine = append(cxxCmdLine, "-Wp,-v", "-x", "c++", "/dev/null", "-fsyntax-only")
Comment on lines +125 to +126
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be replaced?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And for what and why?


cxxWpCommand := exec.Command(cxxName, cxxCmdLine...)
var cxxWpStderr bytes.Buffer
cxxWpCommand.Stderr = &cxxWpStderr
if err := cxxWpCommand.Run(); err != nil {
Expand Down
48 changes: 35 additions & 13 deletions internal/client/invocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ type Invocation struct {
sessionID uint32 // incremental while a daemon is alive

// cmdLine is parsed to the following fields:
cppInFile string // input file as specified in cmd line (.cpp for compilation, .h for pch generation)
objOutFile string // output file as specified in cmd line (.o for compilation, .gch/.pch for pch generation)
cxxName string // g++ / clang / etc.
cxxArgs []string // args like -Wall, -fpch-preprocess and many more, except:
cxxIDirs IncludeDirs // -I / -iquote / -isystem go here
depsFlags DepCmdFlags // -MD -MF file and others, used for .d files generation (not passed to server)
cppInFile string // input file as specified in cmd line (.cpp for compilation, .h for pch generation)
objOutFile string // output file as specified in cmd line (.o for compilation, .gch/.pch for pch generation)
cxxName string // g++ / clang / etc.
cxxArgs []string // args like -Wall, -fpch-preprocess and many more, except:
cxxArgsIncludes []string // TODO
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO mark is present but not explained

cxxIDirs IncludeDirs // -I / -iquote / -isystem go here
depsFlags DepCmdFlags // -MD -MF file and others, used for .d files generation (not passed to server)

waitUploads int32 // files still waiting for upload to finish; 0 releases wgUpload; see Invocation.DoneUploadFile
doneRecv int32 // 1 if o file received or failed receiving; 1 releases wgRecv; see Invocation.DoneRecvObj
Expand Down Expand Up @@ -73,13 +74,14 @@ func pathAbs(cwd string, relPath string) string {

func ParseCmdLineInvocation(daemon *Daemon, cwd string, cmdLine []string) (invocation *Invocation) {
invocation = &Invocation{
createTime: time.Now(),
sessionID: atomic.AddUint32(&daemon.totalInvocations, 1),
cxxName: cmdLine[0],
cxxArgs: make([]string, 0, 10),
cxxIDirs: MakeIncludeDirs(),
summary: MakeInvocationSummary(),
includesCache: daemon.GetOrCreateIncludesCache(cmdLine[0]),
createTime: time.Now(),
sessionID: atomic.AddUint32(&daemon.totalInvocations, 1),
cxxName: cmdLine[0],
cxxArgs: make([]string, 0, 10),
cxxArgsIncludes: make([]string, 0, 1),
cxxIDirs: MakeIncludeDirs(),
summary: MakeInvocationSummary(),
includesCache: nil, // TODO
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

}

parseArgFile := func(key string, arg string, argIndex *int) (string, bool) {
Expand Down Expand Up @@ -113,6 +115,21 @@ func ParseCmdLineInvocation(daemon *Daemon, cwd string, cmdLine []string) (invoc
return ""
}

parsePartsArgString := func(arg string, argIndex *int) string {
parts := strings.SplitN(arg, "=", 2)
if len(parts) == 2 {
return parts[1]
}

if *argIndex+1 < len(cmdLine) {
*argIndex++
return cmdLine[*argIndex]
} else {
invocation.err = fmt.Errorf("unsupported command-line: no argument after %s", arg)
return ""
}
}

for i := 1; i < len(cmdLine); i++ {
arg := cmdLine[i]
if len(arg) == 0 {
Expand Down Expand Up @@ -183,6 +200,9 @@ func ParseCmdLineInvocation(daemon *Daemon, cwd string, cmdLine []string) (invoc
invocation.cxxArgs = append(invocation.cxxArgs, "-Xclang", xArg)
i++
continue
} else if HasPrefixOrEqualOption(arg, "-stdlib") || HasPrefixOrEqualOption(arg, "--stdlib") {
invocation.cxxArgsIncludes = append(invocation.cxxArgsIncludes, parsePartsArgString(arg, &i))
continue
}
} else if isSourceFileName(arg) || isHeaderFileName(arg) {
if invocation.cppInFile != "" {
Expand All @@ -198,6 +218,8 @@ func ParseCmdLineInvocation(daemon *Daemon, cwd string, cmdLine []string) (invoc
invocation.cxxArgs = append(invocation.cxxArgs, arg)
}

invocation.includesCache = daemon.GetOrCreateIncludesCache(invocation.cxxName, invocation.cxxArgsIncludes)

if invocation.err != nil {
return
}
Expand Down
14 changes: 14 additions & 0 deletions internal/client/options-parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package client

import (
"fmt"
"strings"
)

func HasPrefixOrEqualOption(optionName string, flagValue string) bool {
if flagValue == optionName || strings.HasPrefix(flagValue, fmt.Sprintf("%s=", optionName)) {
return true
}

return false
}
61 changes: 61 additions & 0 deletions internal/client/options-parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package client

import "testing"

func TestOther(t *testing.T) {
tests := []struct {
optionName string
flag string
isPrefix bool
}{
{
optionName: "-option",
flag: "-option=args",
isPrefix: true,
},
{
optionName: "--option",
flag: "--option=args",
isPrefix: true,
},
{
optionName: "-option",
flag: "-option",
isPrefix: true,
},
{
optionName: "--option",
flag: "--option",
isPrefix: true,
},

// Negative
{
optionName: "options",
flag: "-options",
isPrefix: false,
},
{
optionName: "-options",
flag: "--options",
isPrefix: false,
},
{
optionName: "--options",
flag: "-options",
isPrefix: false,
},
{
optionName: "-option",
flag: "-options=args",
isPrefix: false,
},
}

for _, tt := range tests {
isPrefix := HasPrefixOrEqualOption(tt.optionName, tt.flag)
if isPrefix != tt.isPrefix {
t.Errorf("want: '%t', got: '%t' (optionName: '%s', flag: '%s')", tt.isPrefix, isPrefix, tt.optionName, tt.flag)
}
}
}