xref: /aosp_15_r20/external/bazelbuild-rules_go/go/private/actions/archive.bzl (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1# Copyright 2014 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load(
16    "//go/private:common.bzl",
17    "as_tuple",
18    "split_srcs",
19)
20load(
21    "//go/private:mode.bzl",
22    "LINKMODE_C_ARCHIVE",
23    "LINKMODE_C_SHARED",
24    "mode_string",
25)
26load(
27    "//go/private:providers.bzl",
28    "GoArchive",
29    "GoArchiveData",
30    "effective_importpath_pkgpath",
31    "get_archive",
32)
33load(
34    "//go/private/rules:cgo.bzl",
35    "cgo_configure",
36)
37load(
38    "//go/private/actions:compilepkg.bzl",
39    "emit_compilepkg",
40)
41
42def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_deps = None):
43    """See go/toolchains.rst#archive for full documentation."""
44
45    if source == None:
46        fail("source is a required parameter")
47
48    split = split_srcs(source.srcs)
49    testfilter = getattr(source.library, "testfilter", None)
50    pre_ext = ""
51    if go.mode.link == LINKMODE_C_ARCHIVE:
52        pre_ext = "_"  # avoid collision with go_binary output file with .a extension
53    elif testfilter == "exclude":
54        pre_ext = ".internal"
55    elif testfilter == "only":
56        pre_ext = ".external"
57    if _recompile_suffix:
58        pre_ext += _recompile_suffix
59    out_lib = go.declare_file(go, name = source.library.name, ext = pre_ext + ".a")
60
61    # store __.PKGDEF and nogo facts in .x
62    out_export = go.declare_file(go, name = source.library.name, ext = pre_ext + ".x")
63    out_cgo_export_h = None  # set if cgo used in c-shared or c-archive mode
64
65    direct = [get_archive(dep) for dep in source.deps]
66    runfiles = source.runfiles
67    data_files = runfiles.files
68
69    files = []
70    for a in direct:
71        files.append(a.runfiles)
72        if a.source.mode != go.mode:
73            fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode)))
74    runfiles.merge_all(files)
75
76    importmap = "main" if source.library.is_main else source.library.importmap
77    importpath, _ = effective_importpath_pkgpath(source.library)
78
79    if source.cgo and not go.mode.pure:
80        # TODO(jayconrod): do we need to do full Bourne tokenization here?
81        cppopts = [f for fs in source.cppopts for f in fs.split(" ")]
82        copts = [f for fs in source.copts for f in fs.split(" ")]
83        cxxopts = [f for fs in source.cxxopts for f in fs.split(" ")]
84        clinkopts = [f for fs in source.clinkopts for f in fs.split(" ")]
85        cgo = cgo_configure(
86            go,
87            srcs = split.go + split.c + split.asm + split.cxx + split.objc + split.headers,
88            cdeps = source.cdeps,
89            cppopts = cppopts,
90            copts = copts,
91            cxxopts = cxxopts,
92            clinkopts = clinkopts,
93        )
94        if go.mode.link in (LINKMODE_C_SHARED, LINKMODE_C_ARCHIVE):
95            out_cgo_export_h = go.declare_file(go, path = "_cgo_install.h")
96        cgo_deps = cgo.deps
97        runfiles = runfiles.merge(cgo.runfiles)
98        emit_compilepkg(
99            go,
100            sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers,
101            cover = source.cover,
102            embedsrcs = source.embedsrcs,
103            importpath = importpath,
104            importmap = importmap,
105            archives = direct,
106            out_lib = out_lib,
107            out_export = out_export,
108            out_cgo_export_h = out_cgo_export_h,
109            gc_goopts = source.gc_goopts,
110            cgo = True,
111            cgo_inputs = cgo.inputs,
112            cppopts = cgo.cppopts,
113            copts = cgo.copts,
114            cxxopts = cgo.cxxopts,
115            objcopts = cgo.objcopts,
116            objcxxopts = cgo.objcxxopts,
117            clinkopts = cgo.clinkopts,
118            testfilter = testfilter,
119        )
120    else:
121        cgo_deps = depset()
122        emit_compilepkg(
123            go,
124            sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers,
125            cover = source.cover,
126            embedsrcs = source.embedsrcs,
127            importpath = importpath,
128            importmap = importmap,
129            archives = direct,
130            out_lib = out_lib,
131            out_export = out_export,
132            gc_goopts = source.gc_goopts,
133            cgo = False,
134            testfilter = testfilter,
135            recompile_internal_deps = recompile_internal_deps,
136        )
137
138    data = GoArchiveData(
139        # TODO(#2578): reconsider the provider API. There's a lot of redundant
140        # information here. Some fields are tuples instead of lists or dicts
141        # since GoArchiveData is stored in a depset, and no value in a depset
142        # may be mutable. For now, new copied fields are private (named with
143        # a leading underscore) since they may change in the future.
144
145        # GoLibrary fields
146        name = source.library.name,
147        label = source.library.label,
148        importpath = source.library.importpath,
149        importmap = source.library.importmap,
150        importpath_aliases = source.library.importpath_aliases,
151        pathtype = source.library.pathtype,
152
153        # GoSource fields
154        srcs = as_tuple(source.srcs),
155        orig_srcs = as_tuple(source.orig_srcs),
156        _orig_src_map = tuple([source.orig_src_map.get(src, src) for src in source.srcs]),
157        _cover = as_tuple(source.cover),
158        _embedsrcs = as_tuple(source.embedsrcs),
159        _x_defs = tuple(source.x_defs.items()),
160        _gc_goopts = as_tuple(source.gc_goopts),
161        _cgo = source.cgo,
162        _cdeps = as_tuple(source.cdeps),
163        _cppopts = as_tuple(source.cppopts),
164        _copts = as_tuple(source.copts),
165        _cxxopts = as_tuple(source.cxxopts),
166        _clinkopts = as_tuple(source.clinkopts),
167        _cgo_exports = as_tuple(source.cgo_exports),
168
169        # Information on dependencies
170        _dep_labels = tuple([d.data.label for d in direct]),
171        _dep_importmaps = tuple([d.data.importmap for d in direct]),
172
173        # Information needed by dependents
174        file = out_lib,
175        export_file = out_export,
176        data_files = as_tuple(data_files),
177        _cgo_deps = as_tuple(cgo_deps),
178    )
179    x_defs = dict(source.x_defs)
180    for a in direct:
181        x_defs.update(a.x_defs)
182    cgo_exports_direct = list(source.cgo_exports)
183
184    # Ensure that the _cgo_export.h of the current target comes first when cgo_exports is iterated
185    # by prepending it and specifying the order explicitly. This is required as the CcInfo attached
186    # to the archive only exposes a single header rather than combining all headers.
187    if out_cgo_export_h:
188        cgo_exports_direct.insert(0, out_cgo_export_h)
189    cgo_exports = depset(direct = cgo_exports_direct, transitive = [a.cgo_exports for a in direct], order = "preorder")
190    return GoArchive(
191        source = source,
192        data = data,
193        direct = direct,
194        libs = depset(direct = [out_lib], transitive = [a.libs for a in direct]),
195        transitive = depset([data], transitive = [a.transitive for a in direct]),
196        x_defs = x_defs,
197        cgo_deps = depset(transitive = [cgo_deps] + [a.cgo_deps for a in direct]),
198        cgo_exports = cgo_exports,
199        runfiles = runfiles,
200        mode = go.mode,
201    )
202