blob: 9b96e17aa6c82aa851fe12b0a8d4dcb01457031d [file]
# Copyright 2014 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
load(
"@bazel_skylib//lib:sets.bzl",
"sets",
)
load(
"@io_bazel_rules_go//go/private:common.bzl",
"as_tuple",
"split_srcs",
)
load(
"@io_bazel_rules_go//go/private:mode.bzl",
"mode_string",
)
load(
"@io_bazel_rules_go//go/private:providers.bzl",
"GoArchive",
"GoArchiveData",
"get_archive",
)
def emit_archive(go, source = None):
"""See go/toolchains.rst#archive for full documentation."""
if source == None:
fail("source is a required parameter")
covered = bool(go.cover and go.coverdata and source.cover)
if covered:
source = go.cover(go, source)
split = split_srcs(source.srcs)
lib_name = source.library.importmap + ".a"
out_lib = go.declare_file(go, path = lib_name)
out_export = None
if go.nogo:
# TODO(#1847): write nogo data into a new section in the .a file instead
# of writing a separate file.
out_export = go.declare_file(go, path = lib_name[:-len(".a")] + ".x")
searchpath = out_lib.path[:-len(lib_name)]
testfilter = getattr(source.library, "testfilter", None)
direct = [get_archive(dep) for dep in source.deps]
runfiles = source.runfiles
data_files = runfiles.files
for a in direct:
runfiles = runfiles.merge(a.runfiles)
if a.source.mode != go.mode:
fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode)))
if covered:
direct.append(go.coverdata)
asmhdr = None
if split.asm:
asmhdr = go.declare_file(go, "go_asm.h")
if len(split.asm) == 0 and not source.cgo_archives:
go.compile(
go,
sources = split.go,
importpath = source.library.importmap,
archives = direct,
out_lib = out_lib,
out_export = out_export,
gc_goopts = source.gc_goopts,
testfilter = testfilter,
)
else:
# Assembly files must be passed to the compiler as sources. We need
# to run the assembler to produce a symabis file that gets passed to
# the compiler. The compiler builder does all this so it doesn't
# need to be a separate action (but individual .o files are still
# produced with separate actions).
partial_lib = go.declare_file(go, path = lib_name + "~partial", ext = ".a")
go.compile(
go,
sources = split.go + split.asm + split.headers,
importpath = source.library.importmap,
archives = direct,
out_lib = partial_lib,
out_export = out_export,
gc_goopts = source.gc_goopts,
testfilter = testfilter,
asmhdr = asmhdr,
)
# include other .s as inputs, since they may be #included.
# This may result in multiple copies of symbols defined in included
# files, but go build allows it, so we do, too.
asm_headers = split.headers + split.asm + [asmhdr]
extra_objects = []
for src in split.asm:
extra_objects.append(go.asm(go, source = src, hdrs = asm_headers))
go.pack(
go,
in_lib = partial_lib,
out_lib = out_lib,
objects = extra_objects,
archives = source.cgo_archives,
)
data = GoArchiveData(
name = source.library.name,
label = source.library.label,
importpath = source.library.importpath,
importmap = source.library.importmap,
pathtype = source.library.pathtype,
file = out_lib,
export_file = out_export,
srcs = as_tuple(source.srcs),
orig_srcs = as_tuple(source.orig_srcs),
data_files = as_tuple(data_files),
searchpath = searchpath,
)
x_defs = dict(source.x_defs)
for a in direct:
x_defs.update(a.x_defs)
return GoArchive(
source = source,
data = data,
direct = direct,
searchpaths = sets.union([searchpath], *[a.searchpaths for a in direct]),
libs = sets.union([out_lib], *[a.libs for a in direct]),
transitive = sets.union([data], *[a.transitive for a in direct]),
x_defs = x_defs,
cgo_deps = sets.union(source.cgo_deps, *[a.cgo_deps for a in direct]),
cgo_exports = sets.union(source.cgo_exports, *[a.cgo_exports for a in direct]),
runfiles = runfiles,
mode = go.mode,
)