blob: b002dc5ec6224a7503905986fa46844a98a71684 [file] [log] [blame]
# 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(
"@io_bazel_rules_go//go/private:common.bzl",
"as_tuple",
"split_srcs",
)
load(
"@io_bazel_rules_go//go/private:mode.bzl",
"LINKMODE_C_ARCHIVE",
"LINKMODE_C_SHARED",
"mode_string",
)
load(
"@io_bazel_rules_go//go/private:providers.bzl",
"GoArchive",
"GoArchiveData",
"effective_importpath_pkgpath",
"get_archive",
)
load(
"@io_bazel_rules_go//go/private:rules/cgo.bzl",
"cgo_configure",
)
load(
"@io_bazel_rules_go//go/private:actions/compilepkg.bzl",
"emit_compilepkg",
)
def emit_archive(go, source = None, _recompile_suffix = ""):
"""See go/toolchains.rst#archive for full documentation."""
if source == None:
fail("source is a required parameter")
split = split_srcs(source.srcs)
testfilter = getattr(source.library, "testfilter", None)
pre_ext = ""
if go.mode.link == LINKMODE_C_ARCHIVE:
pre_ext = "_" # avoid collision with go_binary output file with .a extension
elif testfilter == "exclude":
pre_ext = ".internal"
elif testfilter == "only":
pre_ext = ".external"
if _recompile_suffix:
pre_ext += _recompile_suffix
out_lib = go.declare_file(go, ext = pre_ext + ".a")
# store __.PKGDEF and nogo facts in .x
out_export = go.declare_file(go, ext = pre_ext + ".x")
out_cgo_export_h = None # set if cgo used in c-shared or c-archive mode
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)))
importmap = "main" if source.library.is_main else source.library.importmap
importpath, _ = effective_importpath_pkgpath(source.library)
if source.cgo and not go.mode.pure:
# TODO(jayconrod): do we need to do full Bourne tokenization here?
cppopts = [f for fs in source.cppopts for f in fs.split(" ")]
copts = [f for fs in source.copts for f in fs.split(" ")]
cxxopts = [f for fs in source.cxxopts for f in fs.split(" ")]
clinkopts = [f for fs in source.clinkopts for f in fs.split(" ")]
cgo = cgo_configure(
go,
srcs = split.go + split.c + split.asm + split.cxx + split.objc + split.headers,
cdeps = source.cdeps,
cppopts = cppopts,
copts = copts,
cxxopts = cxxopts,
clinkopts = clinkopts,
)
if go.mode.link in (LINKMODE_C_SHARED, LINKMODE_C_ARCHIVE):
out_cgo_export_h = go.declare_file(go, path = "_cgo_install.h")
cgo_deps = cgo.deps
runfiles = runfiles.merge(cgo.runfiles)
emit_compilepkg(
go,
sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers,
cover = source.cover,
importpath = importpath,
importmap = importmap,
archives = direct,
out_lib = out_lib,
out_export = out_export,
out_cgo_export_h = out_cgo_export_h,
gc_goopts = source.gc_goopts,
cgo = True,
cgo_inputs = cgo.inputs,
cppopts = cgo.cppopts,
copts = cgo.copts,
cxxopts = cgo.cxxopts,
objcopts = cgo.objcopts,
objcxxopts = cgo.objcxxopts,
clinkopts = cgo.clinkopts,
testfilter = testfilter,
)
else:
cgo_deps = depset()
emit_compilepkg(
go,
sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers,
cover = source.cover,
importpath = importpath,
importmap = importmap,
archives = direct,
out_lib = out_lib,
out_export = out_export,
gc_goopts = source.gc_goopts,
cgo = False,
testfilter = testfilter,
)
data = GoArchiveData(
# TODO(#2578): reconsider the provider API. There's a lot of redundant
# information here. Some fields are tuples instead of lists or dicts
# since GoArchiveData is stored in a depset, and no value in a depset
# may be mutable. For now, new copied fields are private (named with
# a leading underscore) since they may change in the future.
# GoLibrary fields
name = source.library.name,
label = source.library.label,
importpath = source.library.importpath,
importmap = source.library.importmap,
importpath_aliases = source.library.importpath_aliases,
pathtype = source.library.pathtype,
# GoSource fields
srcs = as_tuple(source.srcs),
orig_srcs = as_tuple(source.orig_srcs),
_orig_src_map = tuple([source.orig_src_map.get(src, src) for src in source.srcs]),
_cover = as_tuple(source.cover),
_x_defs = tuple(source.x_defs.items()),
_gc_goopts = as_tuple(source.gc_goopts),
_cgo = source.cgo,
_cdeps = as_tuple(source.cdeps),
_cppopts = as_tuple(source.cppopts),
_copts = as_tuple(source.copts),
_cxxopts = as_tuple(source.cxxopts),
_clinkopts = as_tuple(source.clinkopts),
_cgo_exports = as_tuple(source.cgo_exports),
# Information on dependencies
_dep_labels = tuple([d.data.label for d in direct]),
_dep_importmaps = tuple([d.data.importmap for d in direct]),
# Information needed by dependents
file = out_lib,
export_file = out_export,
data_files = as_tuple(data_files),
_cgo_deps = as_tuple(cgo_deps),
)
x_defs = dict(source.x_defs)
for a in direct:
x_defs.update(a.x_defs)
cgo_exports_direct = list(source.cgo_exports)
if out_cgo_export_h:
cgo_exports_direct.append(out_cgo_export_h)
cgo_exports = depset(direct = cgo_exports_direct, transitive = [a.cgo_exports for a in direct])
return GoArchive(
source = source,
data = data,
direct = direct,
libs = depset(direct = [out_lib], transitive = [a.libs for a in direct]),
transitive = depset([data], transitive = [a.transitive for a in direct]),
x_defs = x_defs,
cgo_deps = depset(transitive = [cgo_deps] + [a.cgo_deps for a in direct]),
cgo_exports = cgo_exports,
runfiles = runfiles,
mode = go.mode,
)