Skip to content

Commit

Permalink
Emit nogo facts into a separate archive (#3789)
Browse files Browse the repository at this point in the history
* Use `-linkobj` to directly generate `.x` and `.a`

* Extract nogo facts into a separate file

* Address review comments
  • Loading branch information
fmeum authored Jan 20, 2024
1 parent 54c12e5 commit 30099a6
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 451 deletions.
11 changes: 10 additions & 1 deletion go/private/actions/archive.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,13 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
pre_ext += _recompile_suffix
out_lib = go.declare_file(go, name = source.library.name, ext = pre_ext + ".a")

# store __.PKGDEF and nogo facts in .x
# store export information for compiling dependent packages separately
out_export = go.declare_file(go, name = source.library.name, ext = pre_ext + ".x")
out_cgo_export_h = None # set if cgo used in c-shared or c-archive mode
out_facts = None
nogo = go.get_nogo(go)
if nogo:
out_facts = go.declare_file(go, name = source.library.name, ext = pre_ext + ".facts")

direct = [get_archive(dep) for dep in source.deps]
runfiles = source.runfiles
Expand Down Expand Up @@ -105,6 +109,8 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
archives = direct,
out_lib = out_lib,
out_export = out_export,
out_facts = out_facts,
nogo = nogo,
out_cgo_export_h = out_cgo_export_h,
gc_goopts = source.gc_goopts,
cgo = True,
Expand All @@ -129,6 +135,8 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
archives = direct,
out_lib = out_lib,
out_export = out_export,
out_facts = out_facts,
nogo = nogo,
gc_goopts = source.gc_goopts,
cgo = False,
testfilter = testfilter,
Expand Down Expand Up @@ -173,6 +181,7 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
# Information needed by dependents
file = out_lib,
export_file = out_export,
facts_file = out_facts,
data_files = as_tuple(data_files),
_cgo_deps = as_tuple(cgo_deps),
)
Expand Down
25 changes: 22 additions & 3 deletions go/private/actions/compilepkg.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ def _archive(v):
v.data.export_file.path if v.data.export_file else v.data.file.path,
)

def _facts(v):
facts_file = v.data.facts_file
if not facts_file:
return None
importpaths = [v.data.importpath]
importpaths.extend(v.data.importpath_aliases)
return "{}={}={}".format(
":".join(importpaths),
v.data.importmap,
facts_file.path,
)

def _embedroot_arg(src):
return src.root.path

Expand Down Expand Up @@ -55,6 +67,8 @@ def emit_compilepkg(
clinkopts = [],
out_lib = None,
out_export = None,
out_facts = None,
nogo = None,
out_cgo_export_h = None,
gc_goopts = [],
testfilter = None, # TODO: remove when test action compiles packages
Expand All @@ -64,6 +78,8 @@ def emit_compilepkg(
fail("sources is a required parameter")
if out_lib == None:
fail("out_lib is a required parameter")
if bool(nogo) != bool(out_facts):
fail("nogo must be specified if and only if out_facts is specified")

inputs = (sources + embedsrcs + [go.package_list] +
[archive.data.export_file for archive in archives] +
Expand Down Expand Up @@ -108,10 +124,13 @@ def emit_compilepkg(
args.add("-p", importmap)
args.add("-package_list", go.package_list)

args.add("-o", out_lib)
args.add("-x", out_export)
nogo = go.get_nogo(go)
args.add("-lo", out_lib)
args.add("-o", out_export)
if nogo:
args.add_all(archives, before_each = "-facts", map_each = _facts)
inputs.extend([archive.data.facts_file for archive in archives if archive.data.facts_file])
args.add("-out_facts", out_facts)
outputs.append(out_facts)
args.add("-nogo", nogo)
inputs.append(nogo)
if out_cgo_export_h:
Expand Down
10 changes: 9 additions & 1 deletion go/providers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,15 @@ rule. Instead, it's referenced in the ``data`` field of GoArchive_.
+--------------------------------+-----------------------------------------------------------------+
| :param:`file` | :type:`File` |
+--------------------------------+-----------------------------------------------------------------+
| The archive file produced when this library is compiled. |
| The archive file for the linker produced when this library is compiled. |
+--------------------------------+-----------------------------------------------------------------+
| :param:`export_file` | :type:`File` |
+--------------------------------+-----------------------------------------------------------------+
| The archive file for compilation of dependent libraries produced when this library is compiled. |
+--------------------------------+-----------------------------------------------------------------+
| :param:`facts_file` | :type:`File` |
+--------------------------------+-----------------------------------------------------------------+
| The serialized facts for this library produced when nogo ran for this library. |
+--------------------------------+-----------------------------------------------------------------+
| :param:`srcs` | :type:`tuple of File` |
+--------------------------------+-----------------------------------------------------------------+
Expand Down
2 changes: 0 additions & 2 deletions go/tools/builders/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ filegroup(
"generate_test_main.go",
"importcfg.go",
"link.go",
"pack.go",
"read.go",
"replicate.go",
"stdlib.go",
Expand All @@ -97,7 +96,6 @@ go_source(
"nogo_typeparams_go117.go",
"nogo_typeparams_go118.go",
"nolint.go",
"pack.go",
],
# //go/tools/builders:nogo_srcs is considered a different target by
# Bazel's visibility check than
Expand Down
12 changes: 12 additions & 0 deletions go/tools/builders/ar.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ import (
"strings"
)

const (
// arHeader appears at the beginning of archives created by "ar" and
// "go tool pack" on all platforms.
arHeader = "!<arch>\n"

// entryLength is the size in bytes of the metadata preceding each file
// in an archive.
entryLength = 60
)

var zeroBytes = []byte("0 ")

type header struct {
NameRaw [16]byte
ModTimeRaw [12]byte
Expand Down
33 changes: 33 additions & 0 deletions go/tools/builders/cgo2.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
)

Expand Down Expand Up @@ -395,3 +397,34 @@ func (e cgoError) Error() string {
fmt.Fprintf(b, "Ensure that 'cgo = True' is set and the C/C++ toolchain is configured.")
return b.String()
}

func copyFile(inPath, outPath string) error {
inFile, err := os.Open(inPath)
if err != nil {
return err
}
defer inFile.Close()
outFile, err := os.OpenFile(outPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
if err != nil {
return err
}
defer outFile.Close()
_, err = io.Copy(outFile, inFile)
return err
}

func linkFile(inPath, outPath string) error {
inPath, err := filepath.Abs(inPath)
if err != nil {
return err
}
return os.Symlink(inPath, outPath)
}

func copyOrLinkFile(inPath, outPath string) error {
if runtime.GOOS == "windows" {
return copyFile(inPath, outPath)
} else {
return linkFile(inPath, outPath)
}
}
Loading

0 comments on commit 30099a6

Please sign in to comment.