compiler.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. // Copyright 2019 The Android Open Source Project
  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. package rust
  15. import (
  16. "android/soong/cc"
  17. "fmt"
  18. "path/filepath"
  19. "strings"
  20. "github.com/google/blueprint/proptools"
  21. "android/soong/android"
  22. "android/soong/rust/config"
  23. )
  24. type RustLinkage int
  25. const (
  26. DefaultLinkage RustLinkage = iota
  27. RlibLinkage
  28. DylibLinkage
  29. )
  30. func (compiler *baseCompiler) edition() string {
  31. return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
  32. }
  33. func (compiler *baseCompiler) setNoStdlibs() {
  34. compiler.Properties.No_stdlibs = proptools.BoolPtr(true)
  35. }
  36. func (compiler *baseCompiler) disableLints() {
  37. compiler.Properties.Lints = proptools.StringPtr("none")
  38. }
  39. func NewBaseCompiler(dir, dir64 string, location installLocation) *baseCompiler {
  40. return &baseCompiler{
  41. Properties: BaseCompilerProperties{},
  42. dir: dir,
  43. dir64: dir64,
  44. location: location,
  45. }
  46. }
  47. type installLocation int
  48. const (
  49. InstallInSystem installLocation = 0
  50. InstallInData = iota
  51. incorrectSourcesError = "srcs can only contain one path for a rust file and source providers prefixed by \":\""
  52. genSubDir = "out/"
  53. )
  54. type BaseCompilerProperties struct {
  55. // path to the source file that is the main entry point of the program (e.g. main.rs or lib.rs).
  56. // Only a single source file can be defined. Modules which generate source can be included by prefixing
  57. // the module name with ":", for example ":libfoo_bindgen"
  58. //
  59. // If no source file is defined, a single generated source module can be defined to be used as the main source.
  60. Srcs []string `android:"path,arch_variant"`
  61. // name of the lint set that should be used to validate this module.
  62. //
  63. // Possible values are "default" (for using a sensible set of lints
  64. // depending on the module's location), "android" (for the strictest
  65. // lint set that applies to all Android platform code), "vendor" (for
  66. // a relaxed set) and "none" (for ignoring all lint warnings and
  67. // errors). The default value is "default".
  68. Lints *string
  69. // flags to pass to rustc. To enable configuration options or features, use the "cfgs" or "features" properties.
  70. Flags []string `android:"arch_variant"`
  71. // flags to pass to the linker
  72. Ld_flags []string `android:"arch_variant"`
  73. // list of rust rlib crate dependencies
  74. Rlibs []string `android:"arch_variant"`
  75. // list of rust dylib crate dependencies
  76. Dylibs []string `android:"arch_variant"`
  77. // list of rust automatic crate dependencies
  78. Rustlibs []string `android:"arch_variant"`
  79. // list of rust proc_macro crate dependencies
  80. Proc_macros []string `android:"arch_variant"`
  81. // list of C shared library dependencies
  82. Shared_libs []string `android:"arch_variant"`
  83. // list of C static library dependencies. These dependencies do not normally propagate to dependents
  84. // and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library.
  85. Static_libs []string `android:"arch_variant"`
  86. // Similar to static_libs, but will bundle the static library dependency into a library. This is helpful
  87. // to avoid having to redeclare the dependency for dependents of this library, but in some cases may also
  88. // result in bloat if multiple dependencies all include the same static library whole.
  89. //
  90. // The common use case for this is when the static library is unlikely to be a dependency of other modules to avoid
  91. // having to redeclare the static library dependency for every dependent module.
  92. // If you are not sure what to, for rust_library modules most static dependencies should go in static_libraries,
  93. // and for rust_ffi modules most static dependencies should go into whole_static_libraries.
  94. //
  95. // For rust_ffi static variants, these libraries will be included in the resulting static library archive.
  96. //
  97. // For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will
  98. // include all of the static libraries symbols in any dylibs or binaries which use this rlib as well.
  99. Whole_static_libs []string `android:"arch_variant"`
  100. // list of Rust system library dependencies.
  101. //
  102. // This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates
  103. // like `core` and `alloc`.
  104. Stdlibs []string `android:"arch_variant"`
  105. // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
  106. // modules which create library variants (rust_bindgen). This must be the expected extern crate name used in
  107. // source, and is required to conform to an enforced format matching library output files (if the output file is
  108. // lib<someName><suffix>, the crate_name property must be <someName>).
  109. Crate_name string `android:"arch_variant"`
  110. // list of features to enable for this crate
  111. Features []string `android:"arch_variant"`
  112. // list of configuration options to enable for this crate. To enable features, use the "features" property.
  113. Cfgs []string `android:"arch_variant"`
  114. // specific rust edition that should be used if the default version is not desired
  115. Edition *string `android:"arch_variant"`
  116. // sets name of the output
  117. Stem *string `android:"arch_variant"`
  118. // append to name of output
  119. Suffix *string `android:"arch_variant"`
  120. // install to a subdirectory of the default install path for the module
  121. Relative_install_path *string `android:"arch_variant"`
  122. // whether to suppress inclusion of standard crates - defaults to false
  123. No_stdlibs *bool
  124. // Change the rustlibs linkage to select rlib linkage by default for device targets.
  125. // Also link libstd as an rlib as well on device targets.
  126. // Note: This is the default behavior for host targets.
  127. //
  128. // This is primarily meant for rust_binary and rust_ffi modules where the default
  129. // linkage of libstd might need to be overridden in some use cases. This should
  130. // generally be avoided with other module types since it may cause collisions at
  131. // linkage if all dependencies of the root binary module do not link against libstd
  132. // the same way.
  133. Prefer_rlib *bool `android:"arch_variant"`
  134. // Enables emitting certain Cargo environment variables. Only intended to be used for compatibility purposes.
  135. // Will set CARGO_CRATE_NAME to the crate_name property's value.
  136. // Will set CARGO_BIN_NAME to the output filename value without the extension.
  137. Cargo_env_compat *bool
  138. // If cargo_env_compat is true, sets the CARGO_PKG_VERSION env var to this value.
  139. Cargo_pkg_version *string
  140. }
  141. type baseCompiler struct {
  142. Properties BaseCompilerProperties
  143. // Install related
  144. dir string
  145. dir64 string
  146. subDir string
  147. relative string
  148. path android.InstallPath
  149. location installLocation
  150. sanitize *sanitize
  151. distFile android.OptionalPath
  152. // unstripped output file.
  153. unstrippedOutputFile android.Path
  154. // stripped output file.
  155. strippedOutputFile android.OptionalPath
  156. // If a crate has a source-generated dependency, a copy of the source file
  157. // will be available in cargoOutDir (equivalent to Cargo OUT_DIR).
  158. cargoOutDir android.ModuleOutPath
  159. }
  160. func (compiler *baseCompiler) Disabled() bool {
  161. return false
  162. }
  163. func (compiler *baseCompiler) SetDisabled() {
  164. panic("baseCompiler does not implement SetDisabled()")
  165. }
  166. func (compiler *baseCompiler) noStdlibs() bool {
  167. return Bool(compiler.Properties.No_stdlibs)
  168. }
  169. func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath {
  170. panic("baseCompiler does not implement coverageOutputZipPath()")
  171. }
  172. func (compiler *baseCompiler) preferRlib() bool {
  173. return Bool(compiler.Properties.Prefer_rlib)
  174. }
  175. func (compiler *baseCompiler) stdLinkage(ctx *depsContext) RustLinkage {
  176. // For devices, we always link stdlibs in as dylibs by default.
  177. if compiler.preferRlib() {
  178. return RlibLinkage
  179. } else if ctx.Device() {
  180. return DylibLinkage
  181. } else {
  182. return RlibLinkage
  183. }
  184. }
  185. var _ compiler = (*baseCompiler)(nil)
  186. func (compiler *baseCompiler) inData() bool {
  187. return compiler.location == InstallInData
  188. }
  189. func (compiler *baseCompiler) compilerProps() []interface{} {
  190. return []interface{}{&compiler.Properties}
  191. }
  192. func (compiler *baseCompiler) cfgsToFlags() []string {
  193. flags := []string{}
  194. for _, cfg := range compiler.Properties.Cfgs {
  195. flags = append(flags, "--cfg '"+cfg+"'")
  196. }
  197. return flags
  198. }
  199. func (compiler *baseCompiler) featuresToFlags() []string {
  200. flags := []string{}
  201. for _, feature := range compiler.Properties.Features {
  202. flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
  203. }
  204. return flags
  205. }
  206. func (compiler *baseCompiler) featureFlags(ctx ModuleContext, flags Flags) Flags {
  207. flags.RustFlags = append(flags.RustFlags, compiler.featuresToFlags()...)
  208. flags.RustdocFlags = append(flags.RustdocFlags, compiler.featuresToFlags()...)
  209. return flags
  210. }
  211. func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
  212. if ctx.RustModule().UseVndk() {
  213. compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vndk")
  214. if ctx.RustModule().InVendor() {
  215. compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vendor")
  216. } else if ctx.RustModule().InProduct() {
  217. compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_product")
  218. }
  219. }
  220. flags.RustFlags = append(flags.RustFlags, compiler.cfgsToFlags()...)
  221. flags.RustdocFlags = append(flags.RustdocFlags, compiler.cfgsToFlags()...)
  222. return flags
  223. }
  224. func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags) Flags {
  225. lintFlags, err := config.RustcLintsForDir(ctx.ModuleDir(), compiler.Properties.Lints)
  226. if err != nil {
  227. ctx.PropertyErrorf("lints", err.Error())
  228. }
  229. // linkage-related flags are disallowed.
  230. for _, s := range compiler.Properties.Ld_flags {
  231. if strings.HasPrefix(s, "-Wl,-l") || strings.HasPrefix(s, "-Wl,-L") {
  232. ctx.PropertyErrorf("ld_flags", "'-Wl,-l' and '-Wl,-L' flags cannot be manually specified")
  233. }
  234. }
  235. for _, s := range compiler.Properties.Flags {
  236. if strings.HasPrefix(s, "-l") || strings.HasPrefix(s, "-L") {
  237. ctx.PropertyErrorf("flags", "'-l' and '-L' flags cannot be manually specified")
  238. }
  239. if strings.HasPrefix(s, "--extern") {
  240. ctx.PropertyErrorf("flags", "'--extern' flag cannot be manually specified")
  241. }
  242. if strings.HasPrefix(s, "-Clink-args=") || strings.HasPrefix(s, "-C link-args=") {
  243. ctx.PropertyErrorf("flags", "'-C link-args' flag cannot be manually specified")
  244. }
  245. }
  246. flags.RustFlags = append(flags.RustFlags, lintFlags)
  247. flags.RustFlags = append(flags.RustFlags, compiler.Properties.Flags...)
  248. flags.RustFlags = append(flags.RustFlags, "--edition="+compiler.edition())
  249. flags.RustdocFlags = append(flags.RustdocFlags, "--edition="+compiler.edition())
  250. flags.LinkFlags = append(flags.LinkFlags, compiler.Properties.Ld_flags...)
  251. flags.GlobalRustFlags = append(flags.GlobalRustFlags, config.GlobalRustFlags...)
  252. flags.GlobalRustFlags = append(flags.GlobalRustFlags, ctx.toolchain().ToolchainRustFlags())
  253. flags.GlobalLinkFlags = append(flags.GlobalLinkFlags, ctx.toolchain().ToolchainLinkFlags())
  254. flags.EmitXrefs = ctx.Config().EmitXrefRules()
  255. if ctx.Host() && !ctx.Windows() {
  256. flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...)
  257. }
  258. return flags
  259. }
  260. func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
  261. panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
  262. }
  263. func (compiler *baseCompiler) rustdoc(ctx ModuleContext, flags Flags,
  264. deps PathDeps) android.OptionalPath {
  265. return android.OptionalPath{}
  266. }
  267. func (compiler *baseCompiler) initialize(ctx ModuleContext) {
  268. compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir)
  269. }
  270. func (compiler *baseCompiler) CargoOutDir() android.OptionalPath {
  271. return android.OptionalPathForPath(compiler.cargoOutDir)
  272. }
  273. func (compiler *baseCompiler) CargoEnvCompat() bool {
  274. return Bool(compiler.Properties.Cargo_env_compat)
  275. }
  276. func (compiler *baseCompiler) CargoPkgVersion() string {
  277. return String(compiler.Properties.Cargo_pkg_version)
  278. }
  279. func (compiler *baseCompiler) unstrippedOutputFilePath() android.Path {
  280. return compiler.unstrippedOutputFile
  281. }
  282. func (compiler *baseCompiler) strippedOutputFilePath() android.OptionalPath {
  283. return compiler.strippedOutputFile
  284. }
  285. func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
  286. deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
  287. deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
  288. deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...)
  289. deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
  290. deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
  291. deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...)
  292. deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
  293. deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...)
  294. if !Bool(compiler.Properties.No_stdlibs) {
  295. for _, stdlib := range config.Stdlibs {
  296. // If we're building for the build host, use the prebuilt stdlibs, unless the host
  297. // is linux_bionic which doesn't have prebuilts.
  298. if ctx.Host() && !ctx.Target().HostCross && ctx.Target().Os != android.LinuxBionic {
  299. stdlib = "prebuilt_" + stdlib
  300. }
  301. deps.Stdlibs = append(deps.Stdlibs, stdlib)
  302. }
  303. }
  304. return deps
  305. }
  306. func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps {
  307. bionicLibs := []string{}
  308. bionicLibs = append(bionicLibs, "liblog")
  309. bionicLibs = append(bionicLibs, "libc")
  310. bionicLibs = append(bionicLibs, "libm")
  311. bionicLibs = append(bionicLibs, "libdl")
  312. if static {
  313. deps.StaticLibs = append(deps.StaticLibs, bionicLibs...)
  314. } else {
  315. deps.SharedLibs = append(deps.SharedLibs, bionicLibs...)
  316. }
  317. if ctx.RustModule().StaticExecutable() {
  318. deps.StaticLibs = append(deps.StaticLibs, "libunwind")
  319. }
  320. if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
  321. deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
  322. }
  323. return deps
  324. }
  325. func muslDeps(ctx DepsContext, deps Deps, static bool) Deps {
  326. muslLibs := []string{"libc_musl"}
  327. if static {
  328. deps.StaticLibs = append(deps.StaticLibs, muslLibs...)
  329. } else {
  330. deps.SharedLibs = append(deps.SharedLibs, muslLibs...)
  331. }
  332. if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
  333. deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
  334. }
  335. return deps
  336. }
  337. func (compiler *baseCompiler) crateName() string {
  338. return compiler.Properties.Crate_name
  339. }
  340. func (compiler *baseCompiler) everInstallable() bool {
  341. // Most modules are installable, so return true by default.
  342. return true
  343. }
  344. func (compiler *baseCompiler) installDir(ctx ModuleContext) android.InstallPath {
  345. dir := compiler.dir
  346. if ctx.toolchain().Is64Bit() && compiler.dir64 != "" {
  347. dir = compiler.dir64
  348. }
  349. if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
  350. dir = filepath.Join(dir, ctx.Target().NativeBridgeRelativePath)
  351. }
  352. if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
  353. dir = filepath.Join(dir, ctx.Arch().ArchType.String())
  354. }
  355. if compiler.location == InstallInData && ctx.RustModule().UseVndk() {
  356. if ctx.RustModule().InProduct() {
  357. dir = filepath.Join(dir, "product")
  358. } else if ctx.RustModule().InVendor() {
  359. dir = filepath.Join(dir, "vendor")
  360. } else {
  361. ctx.ModuleErrorf("Unknown data+VNDK installation kind")
  362. }
  363. }
  364. return android.PathForModuleInstall(ctx, dir, compiler.subDir,
  365. compiler.relativeInstallPath(), compiler.relative)
  366. }
  367. func (compiler *baseCompiler) nativeCoverage() bool {
  368. return false
  369. }
  370. func (compiler *baseCompiler) install(ctx ModuleContext) {
  371. path := ctx.RustModule().OutputFile()
  372. compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path())
  373. }
  374. func (compiler *baseCompiler) getStem(ctx ModuleContext) string {
  375. return compiler.getStemWithoutSuffix(ctx) + String(compiler.Properties.Suffix)
  376. }
  377. func (compiler *baseCompiler) getStemWithoutSuffix(ctx BaseModuleContext) string {
  378. stem := ctx.ModuleName()
  379. if String(compiler.Properties.Stem) != "" {
  380. stem = String(compiler.Properties.Stem)
  381. }
  382. return stem
  383. }
  384. func (compiler *baseCompiler) relativeInstallPath() string {
  385. return String(compiler.Properties.Relative_install_path)
  386. }
  387. // Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
  388. func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) {
  389. if len(srcs) == 0 {
  390. ctx.PropertyErrorf("srcs", "srcs must not be empty")
  391. }
  392. // The srcs can contain strings with prefix ":".
  393. // They are dependent modules of this module, with android.SourceDepTag.
  394. // They are not the main source file compiled by rustc.
  395. numSrcs := 0
  396. srcIndex := 0
  397. for i, s := range srcs {
  398. if android.SrcIsModule(s) == "" {
  399. numSrcs++
  400. srcIndex = i
  401. }
  402. }
  403. if numSrcs > 1 {
  404. ctx.PropertyErrorf("srcs", incorrectSourcesError)
  405. }
  406. // If a main source file is not provided we expect only a single SourceProvider module to be defined
  407. // within srcs, with the expectation that the first source it provides is the entry point.
  408. if srcIndex != 0 {
  409. ctx.PropertyErrorf("srcs", "main source file must be the first in srcs")
  410. } else if numSrcs > 1 {
  411. ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.")
  412. }
  413. paths := android.PathsForModuleSrc(ctx, srcs)
  414. return paths[srcIndex], paths[1:]
  415. }