Skip to content

Commit be29229

Browse files
authored
Merge pull request #1098 from nevkontakte/better-builds
Build package cleanups and minor improvements
2 parents 0f5af05 + 181d09f commit be29229

File tree

2 files changed

+140
-94
lines changed

2 files changed

+140
-94
lines changed

build/build.go

Lines changed: 33 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import (
3737
// DefaultGOROOT is the default GOROOT value for builds.
3838
//
3939
// It uses the GOPHERJS_GOROOT environment variable if it is set,
40-
// or else the default GOROOT value of the system Go distrubtion.
40+
// or else the default GOROOT value of the system Go distribution.
4141
var DefaultGOROOT = func() string {
4242
if goroot, ok := os.LookupEnv("GOPHERJS_GOROOT"); ok {
4343
// GopherJS-specific GOROOT value takes precedence.
@@ -47,6 +47,8 @@ var DefaultGOROOT = func() string {
4747
return build.Default.GOROOT
4848
}()
4949

50+
// ImportCError is returned when GopherJS attempts to build a package that uses
51+
// CGo.
5052
type ImportCError struct {
5153
pkgPath string
5254
}
@@ -115,49 +117,6 @@ func importWithSrcDir(xctx XContext, path string, srcDir string, mode build.Impo
115117
return nil, err
116118
}
117119

118-
switch path {
119-
case "os":
120-
pkg.GoFiles = excludeExecutable(pkg.GoFiles) // Need to exclude executable implementation files, because some of them contain package scope variables that perform (indirectly) syscalls on init.
121-
// Prefer the dirent_${GOOS}.go version, to make the build pass on both linux
122-
// and darwin.
123-
// In the long term, our builds should produce the same output regardless
124-
// of the host OS: https://github.com/gopherjs/gopherjs/issues/693.
125-
pkg.GoFiles = exclude(pkg.GoFiles, "dirent_js.go")
126-
case "runtime":
127-
pkg.GoFiles = []string{} // Package sources are completely replaced in natives.
128-
case "runtime/internal/sys":
129-
pkg.GoFiles = []string{fmt.Sprintf("zgoos_%s.go", xctx.GOOS()), "zversion.go"}
130-
case "runtime/pprof":
131-
pkg.GoFiles = nil
132-
case "internal/poll":
133-
pkg.GoFiles = exclude(pkg.GoFiles, "fd_poll_runtime.go")
134-
case "sync":
135-
// GopherJS completely replaces sync.Pool implementation with a simpler one,
136-
// since it always executes in a single-threaded environment.
137-
pkg.GoFiles = exclude(pkg.GoFiles, "pool.go")
138-
case "crypto/rand":
139-
pkg.GoFiles = []string{"rand.go", "util.go"}
140-
pkg.TestGoFiles = exclude(pkg.TestGoFiles, "rand_linux_test.go") // Don't want linux-specific tests (since linux-specific package files are excluded too).
141-
case "crypto/x509":
142-
// GopherJS doesn't support loading OS root certificates regardless of the
143-
// OS. The substitution below allows to avoid build dependency on Mac OS
144-
// implementation, which won't be used anyway.
145-
//
146-
// Just like above, https://github.com/gopherjs/gopherjs/issues/693 is
147-
// probably the best long-term option.
148-
pkg.GoFiles = include(
149-
exclude(pkg.GoFiles, fmt.Sprintf("root_%s.go", xctx.GOOS())),
150-
"root_unix.go", "root_js.go")
151-
case "syscall/js":
152-
// Reuse upstream tests to ensure conformance, but completely replace
153-
// implementation.
154-
pkg.XTestGoFiles = append(pkg.TestGoFiles, "js_test.go")
155-
}
156-
157-
if len(pkg.CgoFiles) > 0 {
158-
return nil, &ImportCError{path}
159-
}
160-
161120
if pkg.IsCommand() {
162121
pkg.PkgObj = filepath.Join(pkg.BinDir, filepath.Base(pkg.ImportPath)+".js")
163122
}
@@ -378,6 +337,7 @@ func parseAndAugment(xctx XContext, pkg *PackageData, isTest bool, fileSet *toke
378337
return files, nil
379338
}
380339

340+
// Options controls build process behavior.
381341
type Options struct {
382342
GOROOT string
383343
GOPATH string
@@ -391,13 +351,15 @@ type Options struct {
391351
BuildTags []string
392352
}
393353

354+
// PrintError message to the terminal.
394355
func (o *Options) PrintError(format string, a ...interface{}) {
395356
if o.Color {
396357
format = "\x1B[31m" + format + "\x1B[39m"
397358
}
398359
fmt.Fprintf(os.Stderr, format, a...)
399360
}
400361

362+
// PrintSuccess message to the terminal.
401363
func (o *Options) PrintSuccess(format string, a ...interface{}) {
402364
if o.Color {
403365
format = "\x1B[32m" + format + "\x1B[39m"
@@ -455,6 +417,10 @@ func (p *PackageData) XTestPackage() *PackageData {
455417
}
456418
}
457419

420+
// Session manages internal state GopherJS requires to perform a build.
421+
//
422+
// This is the main interface to GopherJS build system. Session lifetime is
423+
// roughly equivalent to a single GopherJS tool invocation.
458424
type Session struct {
459425
options *Options
460426
xctx XContext
@@ -463,6 +429,7 @@ type Session struct {
463429
Watcher *fsnotify.Watcher
464430
}
465431

432+
// NewSession creates a new GopherJS build session.
466433
func NewSession(options *Options) (*Session, error) {
467434
if options.GOROOT == "" {
468435
options.GOROOT = DefaultGOROOT
@@ -499,9 +466,10 @@ func NewSession(options *Options) (*Session, error) {
499466
return s, nil
500467
}
501468

502-
// BuildContext returns the session's build context.
469+
// XContext returns the session's build context.
503470
func (s *Session) XContext() XContext { return s.xctx }
504471

472+
// InstallSuffix returns the suffix added to the generated output file.
505473
func (s *Session) InstallSuffix() string {
506474
if s.options.Minify {
507475
return "min"
@@ -514,30 +482,10 @@ func (s *Session) GoRelease() string {
514482
return compiler.GoRelease(s.options.GOROOT)
515483
}
516484

517-
func (s *Session) BuildDir(packagePath string, importPath string, pkgObj string) error {
518-
if s.Watcher != nil {
519-
s.Watcher.Add(packagePath)
520-
}
521-
pkg, err := s.xctx.Import(".", packagePath, 0)
522-
if err != nil {
523-
return err
524-
}
525-
526-
archive, err := s.BuildPackage(pkg)
527-
if err != nil {
528-
return err
529-
}
530-
if pkgObj == "" {
531-
pkgObj = filepath.Base(packagePath) + ".js"
532-
}
533-
if pkg.IsCommand() && !pkg.UpToDate {
534-
if err := s.WriteCommandPackage(archive, pkgObj); err != nil {
535-
return err
536-
}
537-
}
538-
return nil
539-
}
540-
485+
// BuildFiles passed to the GopherJS tool as if they were a package.
486+
//
487+
// A ephemeral package will be created with only the provided files. This
488+
// function is intended for use with, for example, `gopherjs run main.go`.
541489
func (s *Session) BuildFiles(filenames []string, pkgObj string, packagePath string) error {
542490
pkg := &PackageData{
543491
Package: &build.Package{
@@ -566,11 +514,18 @@ func (s *Session) BuildFiles(filenames []string, pkgObj string, packagePath stri
566514
return s.WriteCommandPackage(archive, pkgObj)
567515
}
568516

517+
// BuildImportPath loads and compiles package with the given import path.
518+
//
519+
// Relative paths are interpreted relative to the current working dir.
569520
func (s *Session) BuildImportPath(path string) (*compiler.Archive, error) {
570521
_, archive, err := s.buildImportPathWithSrcDir(path, "")
571522
return archive, err
572523
}
573524

525+
// buildImportPathWithSrcDir builds the package specified by the import path.
526+
//
527+
// Relative import paths are interpreted relative to the passed srcDir. If
528+
// srcDir is empty, current working directory is assumed.
574529
func (s *Session) buildImportPathWithSrcDir(path string, srcDir string) (*PackageData, *compiler.Archive, error) {
575530
pkg, err := importWithSrcDir(s.xctx, path, srcDir, 0, s.InstallSuffix())
576531
if s.Watcher != nil && pkg != nil { // add watch even on error
@@ -588,6 +543,7 @@ func (s *Session) buildImportPathWithSrcDir(path string, srcDir string) (*Packag
588543
return pkg, archive, nil
589544
}
590545

546+
// BuildPackage compiles an already loaded package.
591547
func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
592548
if archive, ok := s.Archives[pkg.ImportPath]; ok {
593549
return archive, nil
@@ -608,23 +564,7 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
608564
}
609565

610566
for _, importedPkgPath := range pkg.Imports {
611-
// Ignore all imports that aren't mentioned in import specs of pkg.
612-
// For example, this ignores imports such as runtime/internal/sys and runtime/internal/atomic.
613-
ignored := true
614-
for _, pos := range pkg.ImportPos[importedPkgPath] {
615-
importFile := filepath.Base(pos.Filename)
616-
for _, file := range pkg.GoFiles {
617-
if importFile == file {
618-
ignored = false
619-
break
620-
}
621-
}
622-
if !ignored {
623-
break
624-
}
625-
}
626-
627-
if importedPkgPath == "unsafe" || ignored {
567+
if importedPkgPath == "unsafe" {
628568
continue
629569
}
630570
importedPkg, _, err := s.buildImportPathWithSrcDir(importedPkgPath, pkg.Dir)
@@ -732,6 +672,7 @@ func (s *Session) BuildPackage(pkg *PackageData) (*compiler.Archive, error) {
732672
return archive, nil
733673
}
734674

675+
// writeLibraryPackage writes a compiled package archive to disk at pkgObj path.
735676
func (s *Session) writeLibraryPackage(archive *compiler.Archive, pkgObj string) error {
736677
if err := os.MkdirAll(filepath.Dir(pkgObj), 0777); err != nil {
737678
return err
@@ -746,6 +687,7 @@ func (s *Session) writeLibraryPackage(archive *compiler.Archive, pkgObj string)
746687
return compiler.WriteArchive(archive, objFile)
747688
}
748689

690+
// WriteCommandPackage writes the final JavaScript output file at pkgObj path.
749691
func (s *Session) WriteCommandPackage(archive *compiler.Archive, pkgObj string) error {
750692
if err := os.MkdirAll(filepath.Dir(pkgObj), 0777); err != nil {
751693
return err
@@ -786,6 +728,7 @@ func (s *Session) WriteCommandPackage(archive *compiler.Archive, pkgObj string)
786728
return compiler.WriteProgramCode(deps, sourceMapFilter, s.GoRelease())
787729
}
788730

731+
// NewMappingCallback creates a new callback for source map generation.
789732
func NewMappingCallback(m *sourcemap.Map, goroot, gopath string, localMap bool) func(generatedLine, generatedColumn int, originalPos token.Position) {
790733
return func(generatedLine, generatedColumn int, originalPos token.Position) {
791734
if !originalPos.IsValid() {
@@ -810,6 +753,8 @@ func NewMappingCallback(m *sourcemap.Map, goroot, gopath string, localMap bool)
810753
}
811754
}
812755

756+
// jsFilesFromDir finds and loads any *.inc.js packages in the build context
757+
// directory.
813758
func jsFilesFromDir(bctx *build.Context, dir string) ([]string, error) {
814759
files, err := buildutil.ReadDir(bctx, dir)
815760
if err != nil {
@@ -837,6 +782,8 @@ func hasGopathPrefix(file, gopath string) (hasGopathPrefix bool, prefixLen int)
837782
return false, 0
838783
}
839784

785+
// WaitForChange watches file system events and returns if either when one of
786+
// the source files is modified.
840787
func (s *Session) WaitForChange() {
841788
s.options.PrintSuccess("watching for changes...\n")
842789
for {

0 commit comments

Comments
 (0)