Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
17bebd3c
Commit
17bebd3c
authored
Sep 15, 2011
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
go/build: handle cgo, //build comments
R=adg CC=golang-dev
https://golang.org/cl/5018044
parent
ce008f8c
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
377 additions
and
68 deletions
+377
-68
src/cmd/goinstall/main.go
src/cmd/goinstall/main.go
+7
-6
src/cmd/goinstall/make.go
src/cmd/goinstall/make.go
+3
-3
src/cmd/gotest/gotest.go
src/cmd/gotest/gotest.go
+1
-1
src/pkg/go/build/build_test.go
src/pkg/go/build/build_test.go
+17
-8
src/pkg/go/build/cgotest/cgotest.go
src/pkg/go/build/cgotest/cgotest.go
+3
-0
src/pkg/go/build/dir.go
src/pkg/go/build/dir.go
+344
-48
src/pkg/go/build/syslist_test.go
src/pkg/go/build/syslist_test.go
+2
-2
No files found.
src/cmd/goinstall/main.go
View file @
17bebd3c
...
@@ -13,7 +13,7 @@ import (
...
@@ -13,7 +13,7 @@ import (
"go/token"
"go/token"
"io/ioutil"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
// use for file system paths
"regexp"
"regexp"
"runtime"
"runtime"
"strings"
"strings"
...
@@ -190,7 +190,7 @@ func install(pkg, parent string) {
...
@@ -190,7 +190,7 @@ func install(pkg, parent string) {
}()
}()
// Don't allow trailing '/'
// Don't allow trailing '/'
if
_
,
f
:=
filepath
.
Split
(
pkg
);
f
==
""
{
if
strings
.
HasSuffix
(
pkg
,
"/"
)
{
errorf
(
"%s should not have trailing '/'
\n
"
,
pkg
)
errorf
(
"%s should not have trailing '/'
\n
"
,
pkg
)
return
return
}
}
...
@@ -225,16 +225,17 @@ func install(pkg, parent string) {
...
@@ -225,16 +225,17 @@ func install(pkg, parent string) {
terrorf
(
tree
,
"%s: %v
\n
"
,
pkg
,
err
)
terrorf
(
tree
,
"%s: %v
\n
"
,
pkg
,
err
)
return
return
}
}
dir
:=
filepath
.
Join
(
tree
.
SrcDir
(),
pkg
)
dir
:=
filepath
.
Join
(
tree
.
SrcDir
(),
filepath
.
FromSlash
(
pkg
)
)
// Install prerequisites.
// Install prerequisites.
dirInfo
,
err
:=
build
.
ScanDir
(
dir
,
parent
==
""
)
dirInfo
,
err
:=
build
.
ScanDir
(
dir
)
if
err
!=
nil
{
if
err
!=
nil
{
terrorf
(
tree
,
"%s: %v
\n
"
,
pkg
,
err
)
terrorf
(
tree
,
"%s: %v
\n
"
,
pkg
,
err
)
return
return
}
}
if
len
(
dirInfo
.
GoFiles
)
+
len
(
dirInfo
.
CgoFiles
)
==
0
{
// We reserve package main to identify commands.
terrorf
(
tree
,
"%s: package has no files
\n
"
,
pkg
)
if
parent
!=
""
&&
dirInfo
.
Package
==
"main"
{
terrorf
(
tree
,
"%s: found only package main in %s; cannot import"
,
pkg
,
dir
)
return
return
}
}
for
_
,
p
:=
range
dirInfo
.
Imports
{
for
_
,
p
:=
range
dirInfo
.
Imports
{
...
...
src/cmd/goinstall/make.go
View file @
17bebd3c
...
@@ -10,7 +10,7 @@ import (
...
@@ -10,7 +10,7 @@ import (
"bytes"
"bytes"
"go/build"
"go/build"
"os"
"os"
"path
/filepath"
"path
"
// use for import paths
"strings"
"strings"
"template"
"template"
)
)
...
@@ -44,10 +44,10 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
...
@@ -44,10 +44,10 @@ func makeMakefile(dir, pkg string, tree *build.Tree, isCmd bool) ([]byte, os.Err
targDir
:=
tree
.
PkgDir
()
targDir
:=
tree
.
PkgDir
()
if
isCmd
{
if
isCmd
{
// use the last part of the package name for targ
// use the last part of the package name for targ
_
,
targ
=
file
path
.
Split
(
pkg
)
_
,
targ
=
path
.
Split
(
pkg
)
targDir
=
tree
.
BinDir
()
targDir
=
tree
.
BinDir
()
}
}
dirInfo
,
err
:=
build
.
ScanDir
(
dir
,
isCmd
)
dirInfo
,
err
:=
build
.
ScanDir
(
dir
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
...
src/cmd/gotest/gotest.go
View file @
17bebd3c
...
@@ -165,7 +165,7 @@ func setEnvironment() {
...
@@ -165,7 +165,7 @@ func setEnvironment() {
func
getTestFileNames
()
{
func
getTestFileNames
()
{
names
:=
fileNames
names
:=
fileNames
if
len
(
names
)
==
0
{
if
len
(
names
)
==
0
{
info
,
err
:=
build
.
ScanDir
(
"."
,
true
)
info
,
err
:=
build
.
ScanDir
(
"."
)
if
err
!=
nil
{
if
err
!=
nil
{
Fatalf
(
"scanning directory: %v"
,
err
)
Fatalf
(
"scanning directory: %v"
,
err
)
}
}
...
...
src/pkg/go/build/build_test.go
View file @
17bebd3c
...
@@ -27,7 +27,7 @@ var buildPkgs = []struct {
...
@@ -27,7 +27,7 @@ var buildPkgs = []struct {
&
DirInfo
{
&
DirInfo
{
GoFiles
:
[]
string
{
"pkgtest.go"
},
GoFiles
:
[]
string
{
"pkgtest.go"
},
SFiles
:
[]
string
{
"sqrt_"
+
runtime
.
GOARCH
+
".s"
},
SFiles
:
[]
string
{
"sqrt_"
+
runtime
.
GOARCH
+
".s"
},
P
kgNam
e
:
"pkgtest"
,
P
ackag
e
:
"pkgtest"
,
Imports
:
[]
string
{
"os"
},
Imports
:
[]
string
{
"os"
},
TestImports
:
[]
string
{
"fmt"
,
"pkgtest"
},
TestImports
:
[]
string
{
"fmt"
,
"pkgtest"
},
TestGoFiles
:
sortstr
([]
string
{
"sqrt_test.go"
,
"sqrt_"
+
runtime
.
GOARCH
+
"_test.go"
}),
TestGoFiles
:
sortstr
([]
string
{
"sqrt_test.go"
,
"sqrt_"
+
runtime
.
GOARCH
+
"_test.go"
}),
...
@@ -38,7 +38,7 @@ var buildPkgs = []struct {
...
@@ -38,7 +38,7 @@ var buildPkgs = []struct {
"go/build/cmdtest"
,
"go/build/cmdtest"
,
&
DirInfo
{
&
DirInfo
{
GoFiles
:
[]
string
{
"main.go"
},
GoFiles
:
[]
string
{
"main.go"
},
P
kgNam
e
:
"main"
,
P
ackag
e
:
"main"
,
Imports
:
[]
string
{
"go/build/pkgtest"
},
Imports
:
[]
string
{
"go/build/pkgtest"
},
},
},
},
},
...
@@ -48,7 +48,9 @@ var buildPkgs = []struct {
...
@@ -48,7 +48,9 @@ var buildPkgs = []struct {
CgoFiles
:
[]
string
{
"cgotest.go"
},
CgoFiles
:
[]
string
{
"cgotest.go"
},
CFiles
:
[]
string
{
"cgotest.c"
},
CFiles
:
[]
string
{
"cgotest.c"
},
Imports
:
[]
string
{
"C"
,
"unsafe"
},
Imports
:
[]
string
{
"C"
,
"unsafe"
},
PkgName
:
"cgotest"
,
Package
:
"cgotest"
,
CgoLDFLAGS
:
[]
string
{
"-lregexp"
},
CgoPkgConfig
:
[]
string
{
"cairo"
,
"moscow"
},
},
},
},
},
}
}
...
@@ -56,11 +58,11 @@ var buildPkgs = []struct {
...
@@ -56,11 +58,11 @@ var buildPkgs = []struct {
const
cmdtestOutput
=
"3"
const
cmdtestOutput
=
"3"
func
TestBuild
(
t
*
testing
.
T
)
{
func
TestBuild
(
t
*
testing
.
T
)
{
var
ctxt
=
Context
{
GOOS
:
"darwin"
,
GOARCH
:
"amd64"
}
for
_
,
tt
:=
range
buildPkgs
{
for
_
,
tt
:=
range
buildPkgs
{
tree
:=
Path
[
0
]
// Goroot
tree
:=
Path
[
0
]
// Goroot
dir
:=
filepath
.
Join
(
tree
.
SrcDir
(),
tt
.
dir
)
dir
:=
filepath
.
Join
(
tree
.
SrcDir
(),
tt
.
dir
)
info
,
err
:=
ctxt
.
ScanDir
(
dir
)
info
,
err
:=
ScanDir
(
dir
,
true
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"ScanDir(%#q): %v"
,
tt
.
dir
,
err
)
t
.
Errorf
(
"ScanDir(%#q): %v"
,
tt
.
dir
,
err
)
continue
continue
...
@@ -70,6 +72,13 @@ func TestBuild(t *testing.T) {
...
@@ -70,6 +72,13 @@ func TestBuild(t *testing.T) {
continue
continue
}
}
if
tt
.
dir
==
"go/build/cgotest"
{
// Don't actually run cgo.
// Among other things our test depends
// on pkg-config, which is not present on all systems.
continue
}
s
,
err
:=
Build
(
tree
,
tt
.
dir
,
info
)
s
,
err
:=
Build
(
tree
,
tt
.
dir
,
info
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Build(%#q): %v"
,
tt
.
dir
,
err
)
t
.
Errorf
(
"Build(%#q): %v"
,
tt
.
dir
,
err
)
...
...
src/pkg/go/build/cgotest/cgotest.go
View file @
17bebd3c
...
@@ -6,6 +6,9 @@ package cgotest
...
@@ -6,6 +6,9 @@ package cgotest
/*
/*
char* greeting = "hello, world";
char* greeting = "hello, world";
#cgo darwin/amd64 LDFLAGS: -lregexp
#cgo linux CFLAGS: -m32
#cgo pkg-config: cairo moscow
*/
*/
// #include "cgotest.h"
// #include "cgotest.h"
import
"C"
import
"C"
...
...
src/pkg/go/build/dir.go
View file @
17bebd3c
...
@@ -5,16 +5,22 @@
...
@@ -5,16 +5,22 @@
package
build
package
build
import
(
import
(
"bytes"
"fmt"
"go/ast"
"go/doc"
"go/parser"
"go/parser"
"go/token"
"go/token"
"io/ioutil"
"io/ioutil"
"log"
"log"
"os"
"os"
"path"
"path/filepath"
"path/filepath"
"runtime"
"sort"
"sort"
"strconv"
"strconv"
"strings"
"strings"
"
runtim
e"
"
unicod
e"
)
)
// A Context specifies the supporting context for a build.
// A Context specifies the supporting context for a build.
...
@@ -22,14 +28,55 @@ type Context struct {
...
@@ -22,14 +28,55 @@ type Context struct {
GOARCH
string
// target architecture
GOARCH
string
// target architecture
GOOS
string
// target operating system
GOOS
string
// target operating system
// TODO(rsc,adg): GOPATH
// TODO(rsc,adg): GOPATH
// By default, ScanDir uses the operating system's
// file system calls to read directories and files.
// Callers can override those calls to provide other
// ways to read data by setting ReadDir and ReadFile.
// ScanDir does not make any assumptions about the
// format of the strings dir and file: they can be
// slash-separated, backslash-separated, even URLs.
// ReadDir returns a slice of *os.FileInfo, sorted by Name,
// describing the content of the named directory.
// The dir argument is the argument to ScanDir.
// If ReadDir is nil, ScanDir uses io.ReadDir.
ReadDir
func
(
dir
string
)
(
fi
[]
*
os
.
FileInfo
,
err
os
.
Error
)
// ReadFile returns the content of the file named file
// in the directory named dir. The dir argument is the
// argument to ScanDir, and the file argument is the
// Name field from an *os.FileInfo returned by ReadDir.
// The returned path is the full name of the file, to be
// used in error messages.
//
// If ReadFile is nil, ScanDir uses filepath.Join(dir, file)
// as the path and ioutil.ReadFile to read the data.
ReadFile
func
(
dir
,
file
string
)
(
path
string
,
content
[]
byte
,
err
os
.
Error
)
}
func
(
ctxt
*
Context
)
readDir
(
dir
string
)
([]
*
os
.
FileInfo
,
os
.
Error
)
{
if
f
:=
ctxt
.
ReadDir
;
f
!=
nil
{
return
f
(
dir
)
}
return
ioutil
.
ReadDir
(
dir
)
}
func
(
ctxt
*
Context
)
readFile
(
dir
,
file
string
)
(
string
,
[]
byte
,
os
.
Error
)
{
if
f
:=
ctxt
.
ReadFile
;
f
!=
nil
{
return
f
(
dir
,
file
)
}
p
:=
filepath
.
Join
(
dir
,
file
)
content
,
err
:=
ioutil
.
ReadFile
(
p
)
return
p
,
content
,
err
}
}
// The DefaultContext is the default Context for builds.
// The DefaultContext is the default Context for builds.
// It uses the GOARCH and GOOS environment variables
// It uses the GOARCH and GOOS environment variables
// if set, or else the compiled code's GOARCH and GOOS.
// if set, or else the compiled code's GOARCH and GOOS.
var
DefaultContext
=
Context
{
var
DefaultContext
=
Context
{
envOr
(
"GOARCH"
,
runtime
.
GOARCH
),
GOARCH
:
envOr
(
"GOARCH"
,
runtime
.
GOARCH
),
envOr
(
"GOOS"
,
runtime
.
GOOS
),
GOOS
:
envOr
(
"GOOS"
,
runtime
.
GOOS
),
}
}
func
envOr
(
name
,
def
string
)
string
{
func
envOr
(
name
,
def
string
)
string
{
...
@@ -41,36 +88,48 @@ func envOr(name, def string) string {
...
@@ -41,36 +88,48 @@ func envOr(name, def string) string {
}
}
type
DirInfo
struct
{
type
DirInfo
struct
{
Package
string
// Name of package in dir
PackageComment
*
ast
.
CommentGroup
// Package comments from GoFiles
ImportPath
string
// Import path of package in dir
Imports
[]
string
// All packages imported by GoFiles
// Source files
GoFiles
[]
string
// .go files in dir (excluding CgoFiles)
GoFiles
[]
string
// .go files in dir (excluding CgoFiles)
CgoFiles
[]
string
// .go files that import "C"
CFiles
[]
string
// .c files in dir
CFiles
[]
string
// .c files in dir
SFiles
[]
string
// .s files in dir
SFiles
[]
string
// .s files in dir
Imports
[]
string
// All packages imported by GoFiles
CgoFiles
[]
string
// .go files that import "C"
TestImports
[]
string
// All packages imported by (X)TestGoFiles
PkgName
string
// Name of package in dir
// Cgo directives
CgoPkgConfig
[]
string
// Cgo pkg-config directives
CgoCFLAGS
[]
string
// Cgo CFLAGS directives
CgoLDFLAGS
[]
string
// Cgo LDFLAGS directives
// Test information
TestGoFiles
[]
string
// _test.go files in package
TestGoFiles
[]
string
// _test.go files in package
XTestGoFiles
[]
string
// _test.go files outside package
XTestGoFiles
[]
string
// _test.go files outside package
TestImports
[]
string
// All packages imported by (X)TestGoFiles
}
}
func
(
d
*
DirInfo
)
IsCommand
()
bool
{
func
(
d
*
DirInfo
)
IsCommand
()
bool
{
return
d
.
PkgName
==
"main"
// TODO(rsc): This is at least a little bogus.
return
d
.
Package
==
"main"
}
}
// ScanDir calls DefaultContext.ScanDir.
// ScanDir calls DefaultContext.ScanDir.
func
ScanDir
(
dir
string
,
allowMain
bool
)
(
info
*
DirInfo
,
err
os
.
Error
)
{
func
ScanDir
(
dir
string
)
(
info
*
DirInfo
,
err
os
.
Error
)
{
return
DefaultContext
.
ScanDir
(
dir
,
allowMain
)
return
DefaultContext
.
ScanDir
(
dir
)
}
}
// ScanDir returns a structure with details about the Go content found
// ScanDir returns a structure with details about the Go content found
// in the given directory. The file lists exclude:
// in the given directory. The file lists exclude:
//
//
// - files in package main (unless
allowMain is true
)
// - files in package main (unless
no other package is found
)
// - files in package documentation
// - files in package documentation
// - files ending in _test.go
// - files ending in _test.go
// - files starting with _ or .
// - files starting with _ or .
//
//
func
(
ctxt
*
Context
)
ScanDir
(
dir
string
,
allowMain
bool
)
(
info
*
DirInfo
,
err
os
.
Error
)
{
func
(
ctxt
*
Context
)
ScanDir
(
dir
string
)
(
info
*
DirInfo
,
err
os
.
Error
)
{
dirs
,
err
:=
ioutil
.
R
eadDir
(
dir
)
dirs
,
err
:=
ctxt
.
r
eadDir
(
dir
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
...
@@ -80,16 +139,19 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -80,16 +139,19 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
testImported
:=
make
(
map
[
string
]
bool
)
testImported
:=
make
(
map
[
string
]
bool
)
fset
:=
token
.
NewFileSet
()
fset
:=
token
.
NewFileSet
()
for
_
,
d
:=
range
dirs
{
for
_
,
d
:=
range
dirs
{
if
!
d
.
IsRegular
()
{
continue
}
if
strings
.
HasPrefix
(
d
.
Name
,
"_"
)
||
if
strings
.
HasPrefix
(
d
.
Name
,
"_"
)
||
strings
.
HasPrefix
(
d
.
Name
,
"."
)
{
strings
.
HasPrefix
(
d
.
Name
,
"."
)
{
continue
continue
}
}
if
!
ctxt
.
goodOSArch
(
d
.
Name
)
{
if
!
ctxt
.
goodOSArch
File
(
d
.
Name
)
{
continue
continue
}
}
isTest
:=
false
isTest
:=
false
switch
file
path
.
Ext
(
d
.
Name
)
{
switch
path
.
Ext
(
d
.
Name
)
{
case
".go"
:
case
".go"
:
isTest
=
strings
.
HasSuffix
(
d
.
Name
,
"_test.go"
)
isTest
=
strings
.
HasSuffix
(
d
.
Name
,
"_test.go"
)
case
".c"
:
case
".c"
:
...
@@ -102,13 +164,22 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -102,13 +164,22 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
continue
continue
}
}
filename
:=
filepath
.
Join
(
dir
,
d
.
Name
)
filename
,
data
,
err
:=
ctxt
.
readFile
(
dir
,
d
.
Name
)
pf
,
err
:=
parser
.
ParseFile
(
fset
,
filename
,
nil
,
parser
.
ImportsOnly
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
pf
,
err
:=
parser
.
ParseFile
(
fset
,
filename
,
data
,
parser
.
ImportsOnly
|
parser
.
ParseComments
)
if
err
!=
nil
{
return
nil
,
err
}
// Skip if the //build comments don't match.
if
!
ctxt
.
shouldBuild
(
pf
)
{
continue
}
pkg
:=
string
(
pf
.
Name
.
Name
)
pkg
:=
string
(
pf
.
Name
.
Name
)
if
pkg
==
"main"
&&
!
allowMain
{
if
pkg
==
"main"
&&
di
.
Package
!=
""
&&
di
.
Package
!=
"main"
{
continue
continue
}
}
if
pkg
==
"documentation"
{
if
pkg
==
"documentation"
{
...
@@ -117,20 +188,37 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -117,20 +188,37 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
if
isTest
&&
strings
.
HasSuffix
(
pkg
,
"_test"
)
{
if
isTest
&&
strings
.
HasSuffix
(
pkg
,
"_test"
)
{
pkg
=
pkg
[
:
len
(
pkg
)
-
len
(
"_test"
)]
pkg
=
pkg
[
:
len
(
pkg
)
-
len
(
"_test"
)]
}
}
if
di
.
PkgName
==
""
{
di
.
PkgName
=
pkg
if
pkg
!=
di
.
Package
&&
di
.
Package
==
"main"
{
}
else
if
di
.
PkgName
!=
pkg
{
// Found non-main package but was recording
// Only if all files in the directory are in package main
// information about package main. Reset.
// do we return PkgName=="main".
di
=
DirInfo
{}
// A mix of main and another package reverts
}
// to the original (allowMain=false) behaviour.
if
di
.
Package
==
""
{
if
pkg
==
"main"
||
di
.
PkgName
==
"main"
{
di
.
Package
=
pkg
return
ScanDir
(
dir
,
false
)
}
else
if
pkg
!=
di
.
Package
{
return
nil
,
fmt
.
Errorf
(
"%s: found packages %s and %s"
,
dir
,
pkg
,
di
.
Package
)
}
if
pf
.
Doc
!=
nil
{
if
di
.
PackageComment
!=
nil
{
di
.
PackageComment
.
List
=
append
(
di
.
PackageComment
.
List
,
pf
.
Doc
.
List
...
)
}
else
{
di
.
PackageComment
=
pf
.
Doc
}
}
return
nil
,
os
.
NewError
(
"multiple package names in "
+
dir
)
}
}
// Record imports and information about cgo.
isCgo
:=
false
isCgo
:=
false
for
_
,
spec
:=
range
pf
.
Imports
{
for
_
,
decl
:=
range
pf
.
Decls
{
d
,
ok
:=
decl
.
(
*
ast
.
GenDecl
)
if
!
ok
{
continue
}
for
_
,
dspec
:=
range
d
.
Specs
{
spec
,
ok
:=
dspec
.
(
*
ast
.
ImportSpec
)
if
!
ok
{
continue
}
quoted
:=
string
(
spec
.
Path
.
Value
)
quoted
:=
string
(
spec
.
Path
.
Value
)
path
,
err
:=
strconv
.
Unquote
(
quoted
)
path
,
err
:=
strconv
.
Unquote
(
quoted
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -143,11 +231,21 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -143,11 +231,21 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
}
}
if
path
==
"C"
{
if
path
==
"C"
{
if
isTest
{
if
isTest
{
return
nil
,
os
.
NewError
(
"use of cgo in test "
+
filename
)
return
nil
,
fmt
.
Errorf
(
"%s: use of cgo in test not supported"
,
filename
)
}
cg
:=
spec
.
Doc
if
cg
==
nil
&&
len
(
d
.
Specs
)
==
1
{
cg
=
d
.
Doc
}
if
cg
!=
nil
{
if
err
:=
ctxt
.
saveCgo
(
filename
,
&
di
,
cg
);
err
!=
nil
{
return
nil
,
err
}
}
}
isCgo
=
true
isCgo
=
true
}
}
}
}
}
if
isCgo
{
if
isCgo
{
di
.
CgoFiles
=
append
(
di
.
CgoFiles
,
d
.
Name
)
di
.
CgoFiles
=
append
(
di
.
CgoFiles
,
d
.
Name
)
}
else
if
isTest
{
}
else
if
isTest
{
...
@@ -160,6 +258,9 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -160,6 +258,9 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
di
.
GoFiles
=
append
(
di
.
GoFiles
,
d
.
Name
)
di
.
GoFiles
=
append
(
di
.
GoFiles
,
d
.
Name
)
}
}
}
}
if
di
.
Package
==
""
{
return
nil
,
fmt
.
Errorf
(
"%s: no Go source files"
,
dir
)
}
di
.
Imports
=
make
([]
string
,
len
(
imported
))
di
.
Imports
=
make
([]
string
,
len
(
imported
))
i
:=
0
i
:=
0
for
p
:=
range
imported
{
for
p
:=
range
imported
{
...
@@ -172,13 +273,208 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -172,13 +273,208 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
di
.
TestImports
[
i
]
=
p
di
.
TestImports
[
i
]
=
p
i
++
i
++
}
}
// File name lists are sorted because
ioutil.
ReadDir sorts.
// File name lists are sorted because ReadDir sorts.
sort
.
Strings
(
di
.
Imports
)
sort
.
Strings
(
di
.
Imports
)
sort
.
Strings
(
di
.
TestImports
)
sort
.
Strings
(
di
.
TestImports
)
return
&
di
,
nil
return
&
di
,
nil
}
}
// goodOSArch returns false if the name contains a $GOOS or $GOARCH
// okayBuild reports whether it is okay to build this Go file,
// based on the //build comments leading up to the package clause.
//
// The file is accepted only if each such line lists something
// matching the file. For example:
//
// //build windows linux
//
// marks the file as applicable only on Windows and Linux.
func
(
ctxt
*
Context
)
shouldBuild
(
pf
*
ast
.
File
)
bool
{
for
_
,
com
:=
range
pf
.
Comments
{
if
com
.
Pos
()
>=
pf
.
Package
{
break
}
for
_
,
c
:=
range
com
.
List
{
if
strings
.
HasPrefix
(
c
.
Text
,
"//build"
)
{
f
:=
strings
.
Fields
(
c
.
Text
)
if
f
[
0
]
==
"//build"
{
ok
:=
false
for
_
,
tok
:=
range
f
[
1
:
]
{
if
ctxt
.
matchOSArch
(
tok
)
{
ok
=
true
break
}
}
if
!
ok
{
return
false
// this one doesn't match
}
}
}
}
}
return
true
// everything matches
}
// saveCgo saves the information from the #cgo lines in the import "C" comment.
// These lines set CFLAGS and LDFLAGS and pkg-config directives that affect
// the way cgo's C code is built.
//
// TODO(rsc): This duplicates code in cgo.
// Once the dust settles, remove this code from cgo.
func
(
ctxt
*
Context
)
saveCgo
(
filename
string
,
di
*
DirInfo
,
cg
*
ast
.
CommentGroup
)
os
.
Error
{
text
:=
doc
.
CommentText
(
cg
)
for
_
,
line
:=
range
strings
.
Split
(
text
,
"
\n
"
)
{
orig
:=
line
// Line is
// #cgo [GOOS/GOARCH...] LDFLAGS: stuff
//
line
=
strings
.
TrimSpace
(
line
)
if
len
(
line
)
<
5
||
line
[
:
4
]
!=
"#cgo"
||
(
line
[
4
]
!=
' '
&&
line
[
4
]
!=
'\t'
)
{
continue
}
// Split at colon.
line
=
strings
.
TrimSpace
(
line
[
4
:
])
i
:=
strings
.
Index
(
line
,
":"
)
if
i
<
0
{
return
fmt
.
Errorf
(
"%s: invalid #cgo line: %s"
,
filename
,
orig
)
}
line
,
argstr
:=
line
[
:
i
],
line
[
i
+
1
:
]
// Parse GOOS/GOARCH stuff.
f
:=
strings
.
Fields
(
line
)
if
len
(
f
)
<
1
{
return
fmt
.
Errorf
(
"%s: invalid #cgo line: %s"
,
filename
,
orig
)
}
cond
,
verb
:=
f
[
:
len
(
f
)
-
1
],
f
[
len
(
f
)
-
1
]
if
len
(
cond
)
>
0
{
ok
:=
false
for
_
,
c
:=
range
cond
{
if
ctxt
.
matchOSArch
(
c
)
{
ok
=
true
break
}
}
if
!
ok
{
continue
}
}
args
,
err
:=
splitQuoted
(
argstr
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"%s: invalid #cgo line: %s"
,
filename
,
orig
)
}
for
_
,
arg
:=
range
args
{
if
!
safeName
(
arg
)
{
return
fmt
.
Errorf
(
"%s: malformed #cgo argument: %s"
,
filename
,
arg
)
}
}
switch
verb
{
case
"CFLAGS"
:
di
.
CgoCFLAGS
=
append
(
di
.
CgoCFLAGS
,
args
...
)
case
"LDFLAGS"
:
di
.
CgoLDFLAGS
=
append
(
di
.
CgoLDFLAGS
,
args
...
)
case
"pkg-config"
:
di
.
CgoPkgConfig
=
append
(
di
.
CgoPkgConfig
,
args
...
)
default
:
return
fmt
.
Errorf
(
"%s: invalid #cgo verb: %s"
,
filename
,
orig
)
}
}
return
nil
}
var
safeBytes
=
[]
byte
(
"+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
)
func
safeName
(
s
string
)
bool
{
if
s
==
""
{
return
false
}
for
i
:=
0
;
i
<
len
(
s
);
i
++
{
if
c
:=
s
[
i
];
c
<
0x80
&&
bytes
.
IndexByte
(
safeBytes
,
c
)
<
0
{
return
false
}
}
return
true
}
// splitQuoted splits the string s around each instance of one or more consecutive
// white space characters while taking into account quotes and escaping, and
// returns an array of substrings of s or an empty list if s contains only white space.
// Single quotes and double quotes are recognized to prevent splitting within the
// quoted region, and are removed from the resulting substrings. If a quote in s
// isn't closed err will be set and r will have the unclosed argument as the
// last element. The backslash is used for escaping.
//
// For example, the following string:
//
// a b:"c d" 'e''f' "g\""
//
// Would be parsed as:
//
// []string{"a", "b:c d", "ef", `g"`}
//
func
splitQuoted
(
s
string
)
(
r
[]
string
,
err
os
.
Error
)
{
var
args
[]
string
arg
:=
make
([]
int
,
len
(
s
))
escaped
:=
false
quoted
:=
false
quote
:=
0
i
:=
0
for
_
,
rune
:=
range
s
{
switch
{
case
escaped
:
escaped
=
false
case
rune
==
'\\'
:
escaped
=
true
continue
case
quote
!=
0
:
if
rune
==
quote
{
quote
=
0
continue
}
case
rune
==
'"'
||
rune
==
'\'
'
:
quoted
=
true
quote
=
rune
continue
case
unicode
.
IsSpace
(
rune
)
:
if
quoted
||
i
>
0
{
quoted
=
false
args
=
append
(
args
,
string
(
arg
[
:
i
]))
i
=
0
}
continue
}
arg
[
i
]
=
rune
i
++
}
if
quoted
||
i
>
0
{
args
=
append
(
args
,
string
(
arg
[
:
i
]))
}
if
quote
!=
0
{
err
=
os
.
NewError
(
"unclosed quote"
)
}
else
if
escaped
{
err
=
os
.
NewError
(
"unfinished escaping"
)
}
return
args
,
err
}
// matchOSArch returns true if the name is one of:
//
// $GOOS
// $GOARCH
// $GOOS/$GOARCH
//
func
(
ctxt
*
Context
)
matchOSArch
(
name
string
)
bool
{
if
name
==
ctxt
.
GOOS
||
name
==
ctxt
.
GOARCH
{
return
true
}
i
:=
strings
.
Index
(
name
,
"/"
)
return
i
>=
0
&&
name
[
:
i
]
==
ctxt
.
GOOS
&&
name
[
i
+
1
:
]
==
ctxt
.
GOARCH
}
// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
// suffix which does not match the current system.
// suffix which does not match the current system.
// The recognized name formats are:
// The recognized name formats are:
//
//
...
@@ -189,7 +485,7 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
...
@@ -189,7 +485,7 @@ func (ctxt *Context) ScanDir(dir string, allowMain bool) (info *DirInfo, err os.
// name_$(GOARCH)_test.*
// name_$(GOARCH)_test.*
// name_$(GOOS)_$(GOARCH)_test.*
// name_$(GOOS)_$(GOARCH)_test.*
//
//
func
(
ctxt
*
Context
)
goodOSArch
(
name
string
)
bool
{
func
(
ctxt
*
Context
)
goodOSArch
File
(
name
string
)
bool
{
if
dot
:=
strings
.
Index
(
name
,
"."
);
dot
!=
-
1
{
if
dot
:=
strings
.
Index
(
name
,
"."
);
dot
!=
-
1
{
name
=
name
[
:
dot
]
name
=
name
[
:
dot
]
}
}
...
...
src/pkg/go/build/syslist_test.go
View file @
17bebd3c
...
@@ -55,8 +55,8 @@ var tests = []GoodFileTest{
...
@@ -55,8 +55,8 @@ var tests = []GoodFileTest{
func
TestGoodOSArch
(
t
*
testing
.
T
)
{
func
TestGoodOSArch
(
t
*
testing
.
T
)
{
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
if
DefaultContext
.
goodOSArch
(
test
.
name
)
!=
test
.
result
{
if
DefaultContext
.
goodOSArch
File
(
test
.
name
)
!=
test
.
result
{
t
.
Fatalf
(
"goodOSArch(%q) != %v"
,
test
.
name
,
test
.
result
)
t
.
Fatalf
(
"goodOSArch
File
(%q) != %v"
,
test
.
name
,
test
.
result
)
}
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment