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