github.com/bazelbuild/rules_go@v0.47.2-0.20240515105122-e7ddb9ea474e/go/private/actions/archive.bzl (about) 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 15 load( 16 "//go/private:common.bzl", 17 "as_tuple", 18 "split_srcs", 19 ) 20 load( 21 "//go/private:mode.bzl", 22 "LINKMODE_C_ARCHIVE", 23 "LINKMODE_C_SHARED", 24 "mode_string", 25 ) 26 load( 27 "//go/private:providers.bzl", 28 "GoArchive", 29 "GoArchiveData", 30 "effective_importpath_pkgpath", 31 "get_archive", 32 ) 33 load( 34 "//go/private/actions:compilepkg.bzl", 35 "emit_compilepkg", 36 ) 37 load( 38 "//go/private/rules:cgo.bzl", 39 "cgo_configure", 40 ) 41 42 def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_deps = None, is_external_pkg = False): 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 export information for compiling dependent packages separately 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 out_facts = None 65 nogo = go.get_nogo(go) 66 if nogo: 67 out_facts = go.declare_file(go, name = source.library.name, ext = pre_ext + ".facts") 68 69 direct = [get_archive(dep) for dep in source.deps] 70 runfiles = source.runfiles 71 data_files = runfiles.files 72 73 files = [] 74 for a in direct: 75 files.append(a.runfiles) 76 if a.source.mode != go.mode: 77 fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode))) 78 runfiles = runfiles.merge_all(files) 79 80 importmap = "main" if source.library.is_main else source.library.importmap 81 importpath, _ = effective_importpath_pkgpath(source.library) 82 83 if source.cgo and not go.mode.pure: 84 # TODO(jayconrod): do we need to do full Bourne tokenization here? 85 cppopts = [f for fs in source.cppopts for f in fs.split(" ")] 86 copts = [f for fs in source.copts for f in fs.split(" ")] 87 cxxopts = [f for fs in source.cxxopts for f in fs.split(" ")] 88 clinkopts = [f for fs in source.clinkopts for f in fs.split(" ")] 89 cgo = cgo_configure( 90 go, 91 srcs = split.go + split.c + split.asm + split.cxx + split.objc + split.headers + split.syso, 92 cdeps = source.cdeps, 93 cppopts = cppopts, 94 copts = copts, 95 cxxopts = cxxopts, 96 clinkopts = clinkopts, 97 ) 98 if go.mode.link in (LINKMODE_C_SHARED, LINKMODE_C_ARCHIVE): 99 out_cgo_export_h = go.declare_file(go, path = "_cgo_install.h") 100 cgo_deps = cgo.deps 101 runfiles = runfiles.merge(cgo.runfiles) 102 emit_compilepkg( 103 go, 104 sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers + split.syso, 105 cover = source.cover, 106 embedsrcs = source.embedsrcs, 107 importpath = importpath, 108 importmap = importmap, 109 archives = direct, 110 out_lib = out_lib, 111 out_export = out_export, 112 out_facts = out_facts, 113 nogo = nogo, 114 out_cgo_export_h = out_cgo_export_h, 115 gc_goopts = source.gc_goopts, 116 cgo = True, 117 cgo_inputs = cgo.inputs, 118 cppopts = cgo.cppopts, 119 copts = cgo.copts, 120 cxxopts = cgo.cxxopts, 121 objcopts = cgo.objcopts, 122 objcxxopts = cgo.objcxxopts, 123 clinkopts = cgo.clinkopts, 124 testfilter = testfilter, 125 is_external_pkg = is_external_pkg, 126 ) 127 else: 128 cgo_deps = depset() 129 emit_compilepkg( 130 go, 131 sources = split.go + split.c + split.asm + split.cxx + split.objc + split.headers + split.syso, 132 cover = source.cover, 133 embedsrcs = source.embedsrcs, 134 importpath = importpath, 135 importmap = importmap, 136 archives = direct, 137 out_lib = out_lib, 138 out_export = out_export, 139 out_facts = out_facts, 140 nogo = nogo, 141 gc_goopts = source.gc_goopts, 142 cgo = False, 143 testfilter = testfilter, 144 recompile_internal_deps = recompile_internal_deps, 145 is_external_pkg = is_external_pkg, 146 ) 147 148 data = GoArchiveData( 149 # TODO(#2578): reconsider the provider API. There's a lot of redundant 150 # information here. Some fields are tuples instead of lists or dicts 151 # since GoArchiveData is stored in a depset, and no value in a depset 152 # may be mutable. For now, new copied fields are private (named with 153 # a leading underscore) since they may change in the future. 154 155 # GoLibrary fields 156 name = source.library.name, 157 label = source.library.label, 158 importpath = source.library.importpath, 159 importmap = source.library.importmap, 160 importpath_aliases = source.library.importpath_aliases, 161 pathtype = source.library.pathtype, 162 163 # GoSource fields 164 srcs = as_tuple(source.srcs), 165 orig_srcs = as_tuple(source.orig_srcs), 166 _orig_src_map = tuple([source.orig_src_map.get(src, src) for src in source.srcs]), 167 _cover = as_tuple(source.cover), 168 _embedsrcs = as_tuple(source.embedsrcs), 169 _x_defs = tuple(source.x_defs.items()), 170 _gc_goopts = as_tuple(source.gc_goopts), 171 _cgo = source.cgo, 172 _cdeps = as_tuple(source.cdeps), 173 _cppopts = as_tuple(source.cppopts), 174 _copts = as_tuple(source.copts), 175 _cxxopts = as_tuple(source.cxxopts), 176 _clinkopts = as_tuple(source.clinkopts), 177 _cgo_exports = as_tuple(source.cgo_exports), 178 179 # Information on dependencies 180 _dep_labels = tuple([d.data.label for d in direct]), 181 _dep_importmaps = tuple([d.data.importmap for d in direct]), 182 183 # Information needed by dependents 184 file = out_lib, 185 export_file = out_export, 186 facts_file = out_facts, 187 data_files = as_tuple(data_files), 188 _cgo_deps = as_tuple(cgo_deps), 189 ) 190 x_defs = dict(source.x_defs) 191 for a in direct: 192 x_defs.update(a.x_defs) 193 cgo_exports_direct = list(source.cgo_exports) 194 195 # Ensure that the _cgo_export.h of the current target comes first when cgo_exports is iterated 196 # by prepending it and specifying the order explicitly. This is required as the CcInfo attached 197 # to the archive only exposes a single header rather than combining all headers. 198 if out_cgo_export_h: 199 cgo_exports_direct.insert(0, out_cgo_export_h) 200 cgo_exports = depset(direct = cgo_exports_direct, transitive = [a.cgo_exports for a in direct], order = "preorder") 201 return GoArchive( 202 source = source, 203 data = data, 204 direct = direct, 205 libs = depset(direct = [out_lib], transitive = [a.libs for a in direct]), 206 transitive = depset([data], transitive = [a.transitive for a in direct]), 207 x_defs = x_defs, 208 cgo_deps = depset(transitive = [cgo_deps] + [a.cgo_deps for a in direct]), 209 cgo_exports = cgo_exports, 210 runfiles = runfiles, 211 mode = go.mode, 212 )