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