1// Copyright 2016 Google Inc. 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 15package cc 16 17import ( 18 "fmt" 19 20 "android/soong/android" 21 "android/soong/bazel" 22) 23 24// 25// Objects (for crt*.o) 26// 27 28func init() { 29 android.RegisterModuleType("cc_object", ObjectFactory) 30 android.RegisterSdkMemberType(ccObjectSdkMemberType) 31 32 android.RegisterBp2BuildMutator("cc_object", ObjectBp2Build) 33} 34 35var ccObjectSdkMemberType = &librarySdkMemberType{ 36 SdkMemberTypeBase: android.SdkMemberTypeBase{ 37 PropertyName: "native_objects", 38 SupportsSdk: true, 39 }, 40 prebuiltModuleType: "cc_prebuilt_object", 41 linkTypes: nil, 42} 43 44type objectLinker struct { 45 *baseLinker 46 Properties ObjectLinkerProperties 47} 48 49type objectBazelHandler struct { 50 bazelHandler 51 52 module *Module 53} 54 55func (handler *objectBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool { 56 bazelCtx := ctx.Config().BazelContext 57 objPaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType) 58 if ok { 59 if len(objPaths) != 1 { 60 ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths) 61 return false 62 } 63 64 handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0])) 65 } 66 return ok 67} 68 69type ObjectLinkerProperties struct { 70 // list of modules that should only provide headers for this module. 71 Header_libs []string `android:"arch_variant,variant_prepend"` 72 73 // names of other cc_object modules to link into this module using partial linking 74 Objs []string `android:"arch_variant"` 75 76 // if set, add an extra objcopy --prefix-symbols= step 77 Prefix_symbols *string 78 79 // if set, the path to a linker script to pass to ld -r when combining multiple object files. 80 Linker_script *string `android:"path,arch_variant"` 81 82 // Indicates that this module is a CRT object. CRT objects will be split 83 // into a variant per-API level between min_sdk_version and current. 84 Crt *bool 85} 86 87func newObject() *Module { 88 module := newBaseModule(android.HostAndDeviceSupported, android.MultilibBoth) 89 module.sanitize = &sanitize{} 90 module.stl = &stl{} 91 return module 92} 93 94// cc_object runs the compiler without running the linker. It is rarely 95// necessary, but sometimes used to generate .s files from .c files to use as 96// input to a cc_genrule module. 97func ObjectFactory() android.Module { 98 module := newObject() 99 module.linker = &objectLinker{ 100 baseLinker: NewBaseLinker(module.sanitize), 101 } 102 module.compiler = NewBaseCompiler() 103 module.bazelHandler = &objectBazelHandler{module: module} 104 105 // Clang's address-significance tables are incompatible with ld -r. 106 module.compiler.appendCflags([]string{"-fno-addrsig"}) 107 108 module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType} 109 110 return module.Init() 111} 112 113// For bp2build conversion. 114type bazelObjectAttributes struct { 115 Srcs bazel.LabelListAttribute 116 Hdrs bazel.LabelListAttribute 117 Deps bazel.LabelListAttribute 118 Copts bazel.StringListAttribute 119 Asflags []string 120} 121 122type bazelObject struct { 123 android.BazelTargetModuleBase 124 bazelObjectAttributes 125} 126 127func (m *bazelObject) Name() string { 128 return m.BaseModuleName() 129} 130 131func (m *bazelObject) GenerateAndroidBuildActions(ctx android.ModuleContext) {} 132 133func BazelObjectFactory() android.Module { 134 module := &bazelObject{} 135 module.AddProperties(&module.bazelObjectAttributes) 136 android.InitBazelTargetModule(module) 137 return module 138} 139 140// ObjectBp2Build is the bp2build converter from cc_object modules to the 141// Bazel equivalent target, plus any necessary include deps for the cc_object. 142func ObjectBp2Build(ctx android.TopDownMutatorContext) { 143 m, ok := ctx.Module().(*Module) 144 if !ok || !m.ConvertWithBp2build(ctx) { 145 return 146 } 147 148 // a Module can be something other than a cc_object. 149 if ctx.ModuleType() != "cc_object" { 150 return 151 } 152 153 if m.compiler == nil { 154 // a cc_object must have access to the compiler decorator for its props. 155 ctx.ModuleErrorf("compiler must not be nil for a cc_object module") 156 } 157 158 // Set arch-specific configurable attributes 159 compilerAttrs := bp2BuildParseCompilerProps(ctx, m) 160 var asFlags []string 161 162 var deps bazel.LabelListAttribute 163 for _, props := range m.linker.linkerProps() { 164 if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok { 165 deps = bazel.MakeLabelListAttribute( 166 android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs)) 167 } 168 } 169 170 productVariableProps := android.ProductVariableProperties(ctx) 171 if props, exists := productVariableProps["Asflags"]; exists { 172 // TODO(b/183595873): consider deduplicating handling of product variable properties 173 for _, prop := range props { 174 flags, ok := prop.Property.([]string) 175 if !ok { 176 ctx.ModuleErrorf("Could not convert product variable asflag property") 177 return 178 } 179 // TODO(b/183595873) handle other product variable usages -- as selects? 180 if newFlags, subbed := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable); subbed { 181 asFlags = append(asFlags, newFlags...) 182 } 183 } 184 } 185 // TODO(b/183595872) warn/error if we're not handling product variables 186 187 attrs := &bazelObjectAttributes{ 188 Srcs: compilerAttrs.srcs, 189 Deps: deps, 190 Copts: compilerAttrs.copts, 191 Asflags: asFlags, 192 } 193 194 props := bazel.BazelTargetModuleProperties{ 195 Rule_class: "cc_object", 196 Bzl_load_location: "//build/bazel/rules:cc_object.bzl", 197 } 198 199 ctx.CreateBazelTargetModule(BazelObjectFactory, m.Name(), props, attrs) 200} 201 202func (object *objectLinker) appendLdflags(flags []string) { 203 panic(fmt.Errorf("appendLdflags on objectLinker not supported")) 204} 205 206func (object *objectLinker) linkerProps() []interface{} { 207 return []interface{}{&object.Properties} 208} 209 210func (*objectLinker) linkerInit(ctx BaseModuleContext) {} 211 212func (object *objectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { 213 deps.HeaderLibs = append(deps.HeaderLibs, object.Properties.Header_libs...) 214 deps.ObjFiles = append(deps.ObjFiles, object.Properties.Objs...) 215 return deps 216} 217 218func (object *objectLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { 219 flags.Global.LdFlags = append(flags.Global.LdFlags, ctx.toolchain().ToolchainClangLdflags()) 220 221 if lds := android.OptionalPathForModuleSrc(ctx, object.Properties.Linker_script); lds.Valid() { 222 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-T,"+lds.String()) 223 flags.LdFlagsDeps = append(flags.LdFlagsDeps, lds.Path()) 224 } 225 return flags 226} 227 228func (object *objectLinker) link(ctx ModuleContext, 229 flags Flags, deps PathDeps, objs Objects) android.Path { 230 231 objs = objs.Append(deps.Objs) 232 233 var outputFile android.Path 234 builderFlags := flagsToBuilderFlags(flags) 235 236 if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" { 237 outputFile = objs.objFiles[0] 238 239 if String(object.Properties.Prefix_symbols) != "" { 240 output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension) 241 transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), outputFile, 242 builderFlags, output) 243 outputFile = output 244 } 245 } else { 246 output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension) 247 outputFile = output 248 249 if String(object.Properties.Prefix_symbols) != "" { 250 input := android.PathForModuleOut(ctx, "unprefixed", ctx.ModuleName()+objectExtension) 251 transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input, 252 builderFlags, output) 253 output = input 254 } 255 256 transformObjsToObj(ctx, objs.objFiles, builderFlags, output, flags.LdFlagsDeps) 257 } 258 259 ctx.CheckbuildFile(outputFile) 260 return outputFile 261} 262 263func (object *objectLinker) unstrippedOutputFilePath() android.Path { 264 return nil 265} 266 267func (object *objectLinker) nativeCoverage() bool { 268 return true 269} 270 271func (object *objectLinker) coverageOutputFilePath() android.OptionalPath { 272 return android.OptionalPath{} 273} 274 275func (object *objectLinker) object() bool { 276 return true 277} 278 279func (object *objectLinker) isCrt() bool { 280 return Bool(object.Properties.Crt) 281} 282