Merge "Add clippy-driver build rule"
This commit is contained in:
@@ -9,24 +9,26 @@ bootstrap_go_package {
|
|||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"androidmk.go",
|
"androidmk.go",
|
||||||
"compiler.go",
|
|
||||||
"coverage.go",
|
|
||||||
"binary.go",
|
"binary.go",
|
||||||
"builder.go",
|
"builder.go",
|
||||||
|
"clippy.go",
|
||||||
|
"compiler.go",
|
||||||
|
"coverage.go",
|
||||||
"library.go",
|
"library.go",
|
||||||
"prebuilt.go",
|
"prebuilt.go",
|
||||||
"proc_macro.go",
|
"proc_macro.go",
|
||||||
"project_json.go",
|
"project_json.go",
|
||||||
"rust.go",
|
"rust.go",
|
||||||
"test.go",
|
"test.go",
|
||||||
"testing.go",
|
"testing.go",
|
||||||
],
|
],
|
||||||
testSrcs: [
|
testSrcs: [
|
||||||
"binary_test.go",
|
"binary_test.go",
|
||||||
|
"clippy_test.go",
|
||||||
"compiler_test.go",
|
"compiler_test.go",
|
||||||
"coverage_test.go",
|
"coverage_test.go",
|
||||||
"library_test.go",
|
"library_test.go",
|
||||||
"project_json_test.go",
|
"project_json_test.go",
|
||||||
"rust_test.go",
|
"rust_test.go",
|
||||||
"test_test.go",
|
"test_test.go",
|
||||||
],
|
],
|
||||||
|
@@ -39,6 +39,18 @@ var (
|
|||||||
},
|
},
|
||||||
"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
|
"rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd")
|
||||||
|
|
||||||
|
_ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
|
||||||
|
clippyDriver = pctx.AndroidStaticRule("clippy",
|
||||||
|
blueprint.RuleParams{
|
||||||
|
Command: "$clippyCmd " +
|
||||||
|
// Because clippy-driver uses rustc as backend, we need to have some output even during the linting.
|
||||||
|
// Use the metadata output as it has the smallest footprint.
|
||||||
|
"--emit metadata -o $out $in ${libFlags} " +
|
||||||
|
"$clippyFlags $rustcFlags",
|
||||||
|
CommandDeps: []string{"$clippyCmd"},
|
||||||
|
},
|
||||||
|
"rustcFlags", "libFlags", "clippyFlags")
|
||||||
|
|
||||||
zip = pctx.AndroidStaticRule("zip",
|
zip = pctx.AndroidStaticRule("zip",
|
||||||
blueprint.RuleParams{
|
blueprint.RuleParams{
|
||||||
Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp",
|
Command: "cat $out.rsp | tr ' ' '\\n' | tr -d \\' | sort -u > ${out}.tmp && ${SoongZipCmd} -o ${out} -C $$OUT_DIR -l ${out}.tmp",
|
||||||
@@ -125,10 +137,14 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
|
|||||||
rustcFlags = append(rustcFlags, "--target="+targetTriple)
|
rustcFlags = append(rustcFlags, "--target="+targetTriple)
|
||||||
linkFlags = append(linkFlags, "-target "+targetTriple)
|
linkFlags = append(linkFlags, "-target "+targetTriple)
|
||||||
}
|
}
|
||||||
// TODO once we have static libraries in the host prebuilt .bp, this
|
// TODO(b/159718669): Once we have defined static libraries in the host
|
||||||
// should be unconditionally added.
|
// prebuilts Blueprint file, sysroot should be unconditionally sourced
|
||||||
if !(ctx.Host() && ctx.TargetPrimary()) {
|
// from /dev/null. Explicitly set sysroot to avoid clippy-driver to
|
||||||
// If we're not targeting the host primary arch, do not use an implicit sysroot
|
// internally call rustc.
|
||||||
|
if ctx.Host() && ctx.TargetPrimary() {
|
||||||
|
rustcFlags = append(rustcFlags, "--sysroot=${config.RustPath}")
|
||||||
|
} else {
|
||||||
|
// If we're not targeting the host primary arch, do not use a sysroot.
|
||||||
rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
|
rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
|
||||||
}
|
}
|
||||||
// Collect linker flags
|
// Collect linker flags
|
||||||
@@ -179,6 +195,25 @@ func transformSrctoCrate(ctx android.ModuleContext, main android.Path, deps Path
|
|||||||
output.coverageFile = gcnoFile
|
output.coverageFile = gcnoFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags.Clippy {
|
||||||
|
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
|
||||||
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
Rule: clippyDriver,
|
||||||
|
Description: "clippy " + main.Rel(),
|
||||||
|
Output: clippyFile,
|
||||||
|
ImplicitOutputs: nil,
|
||||||
|
Inputs: inputs,
|
||||||
|
Implicits: implicits,
|
||||||
|
Args: map[string]string{
|
||||||
|
"rustcFlags": strings.Join(rustcFlags, " "),
|
||||||
|
"libFlags": strings.Join(libFlags, " "),
|
||||||
|
"clippyFlags": strings.Join(flags.ClippyFlags, " "),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// Declare the clippy build as an implicit dependency of the original crate.
|
||||||
|
implicits = append(implicits, clippyFile)
|
||||||
|
}
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
Rule: rustc,
|
Rule: rustc,
|
||||||
Description: "rustc " + main.Rel(),
|
Description: "rustc " + main.Rel(),
|
||||||
|
42
rust/clippy.go
Normal file
42
rust/clippy.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rust
|
||||||
|
|
||||||
|
import (
|
||||||
|
"android/soong/rust/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClippyProperties struct {
|
||||||
|
// whether to run clippy.
|
||||||
|
Clippy *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type clippy struct {
|
||||||
|
Properties ClippyProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *clippy) props() []interface{} {
|
||||||
|
return []interface{}{&c.Properties}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *clippy) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
|
||||||
|
if c.Properties.Clippy != nil && !*c.Properties.Clippy {
|
||||||
|
return flags, deps
|
||||||
|
}
|
||||||
|
enabled, lints := config.ClippyLintsForDir(ctx.ModuleDir())
|
||||||
|
flags.Clippy = enabled
|
||||||
|
flags.ClippyFlags = append(flags.ClippyFlags, lints)
|
||||||
|
return flags, deps
|
||||||
|
}
|
46
rust/clippy_test.go
Normal file
46
rust/clippy_test.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package rust
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClippy(t *testing.T) {
|
||||||
|
ctx := testRust(t, `
|
||||||
|
rust_library {
|
||||||
|
name: "libfoo",
|
||||||
|
srcs: ["foo.rs"],
|
||||||
|
crate_name: "foo",
|
||||||
|
}
|
||||||
|
rust_library {
|
||||||
|
name: "libfoobar",
|
||||||
|
srcs: ["foo.rs"],
|
||||||
|
crate_name: "foobar",
|
||||||
|
clippy: false,
|
||||||
|
}`)
|
||||||
|
|
||||||
|
ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Output("libfoo.so")
|
||||||
|
fooClippy := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").MaybeRule("clippy")
|
||||||
|
if fooClippy.Rule.String() != "android/soong/rust.clippy" {
|
||||||
|
t.Errorf("Clippy output (default) for libfoo was not generated: %+v", fooClippy)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_shared").Output("libfoobar.so")
|
||||||
|
foobarClippy := ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_shared").MaybeRule("clippy")
|
||||||
|
if foobarClippy.Rule != nil {
|
||||||
|
t.Errorf("Clippy output for libfoobar is not empty")
|
||||||
|
}
|
||||||
|
}
|
@@ -9,6 +9,7 @@ bootstrap_go_package {
|
|||||||
"arm_device.go",
|
"arm_device.go",
|
||||||
"arm64_device.go",
|
"arm64_device.go",
|
||||||
"global.go",
|
"global.go",
|
||||||
|
"clippy.go",
|
||||||
"toolchain.go",
|
"toolchain.go",
|
||||||
"allowed_list.go",
|
"allowed_list.go",
|
||||||
"x86_darwin_host.go",
|
"x86_darwin_host.go",
|
||||||
|
80
rust/config/clippy.go
Normal file
80
rust/config/clippy.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright 2020 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultLints = []string{
|
||||||
|
"-D missing-docs",
|
||||||
|
"-D clippy::missing-safety-doc",
|
||||||
|
}
|
||||||
|
defaultVendorLints = []string{
|
||||||
|
"",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Default Rust lints. These apply to all Google-authored modules.
|
||||||
|
pctx.VariableFunc("ClippyDefaultLints", func(ctx android.PackageVarContext) string {
|
||||||
|
if override := ctx.Config().Getenv("CLIPPY_DEFAULT_LINTS"); override != "" {
|
||||||
|
return override
|
||||||
|
}
|
||||||
|
return strings.Join(defaultLints, " ")
|
||||||
|
})
|
||||||
|
|
||||||
|
// Rust lints that only applies to external code.
|
||||||
|
pctx.VariableFunc("ClippyVendorLints", func(ctx android.PackageVarContext) string {
|
||||||
|
if override := ctx.Config().Getenv("CLIPPY_VENDOR_LINTS"); override != "" {
|
||||||
|
return override
|
||||||
|
}
|
||||||
|
return strings.Join(defaultVendorLints, " ")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathBasedClippyConfig struct {
|
||||||
|
PathPrefix string
|
||||||
|
Enabled bool
|
||||||
|
ClippyConfig string
|
||||||
|
}
|
||||||
|
|
||||||
|
const clippyNone = ""
|
||||||
|
const clippyDefault = "${config.ClippyDefaultLints}"
|
||||||
|
const clippyVendor = "${config.ClippyVendorLints}"
|
||||||
|
|
||||||
|
// This is a map of local path prefixes to a boolean indicating if the lint
|
||||||
|
// rule should be generated and if so, the set of lints to use. The first entry
|
||||||
|
// matching will be used. If no entry is matching, clippyDefault will be used.
|
||||||
|
var DefaultLocalTidyChecks = []PathBasedClippyConfig{
|
||||||
|
{"external/", false, clippyNone},
|
||||||
|
{"hardware/", true, clippyVendor},
|
||||||
|
{"prebuilts/", false, clippyNone},
|
||||||
|
{"vendor/google", true, clippyDefault},
|
||||||
|
{"vendor/", true, clippyVendor},
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClippyLintsForDir returns the Clippy lints to be used for a repository.
|
||||||
|
func ClippyLintsForDir(dir string) (bool, string) {
|
||||||
|
for _, pathCheck := range DefaultLocalTidyChecks {
|
||||||
|
if strings.HasPrefix(dir, pathCheck.PathPrefix) {
|
||||||
|
return pathCheck.Enabled, pathCheck.ClippyConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, clippyDefault
|
||||||
|
}
|
11
rust/rust.go
11
rust/rust.go
@@ -49,8 +49,10 @@ type Flags struct {
|
|||||||
GlobalLinkFlags []string // Flags that apply globally to linker
|
GlobalLinkFlags []string // Flags that apply globally to linker
|
||||||
RustFlags []string // Flags that apply to rust
|
RustFlags []string // Flags that apply to rust
|
||||||
LinkFlags []string // Flags that apply to linker
|
LinkFlags []string // Flags that apply to linker
|
||||||
|
ClippyFlags []string // Flags that apply to clippy-driver, during the linting
|
||||||
Toolchain config.Toolchain
|
Toolchain config.Toolchain
|
||||||
Coverage bool
|
Coverage bool
|
||||||
|
Clippy bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseProperties struct {
|
type BaseProperties struct {
|
||||||
@@ -75,6 +77,7 @@ type Module struct {
|
|||||||
|
|
||||||
compiler compiler
|
compiler compiler
|
||||||
coverage *coverage
|
coverage *coverage
|
||||||
|
clippy *clippy
|
||||||
cachedToolchain config.Toolchain
|
cachedToolchain config.Toolchain
|
||||||
subAndroidMkOnce map[subAndroidMkProvider]bool
|
subAndroidMkOnce map[subAndroidMkProvider]bool
|
||||||
outputFile android.OptionalPath
|
outputFile android.OptionalPath
|
||||||
@@ -306,6 +309,7 @@ func DefaultsFactory(props ...interface{}) android.Module {
|
|||||||
&PrebuiltProperties{},
|
&PrebuiltProperties{},
|
||||||
&TestProperties{},
|
&TestProperties{},
|
||||||
&cc.CoverageProperties{},
|
&cc.CoverageProperties{},
|
||||||
|
&ClippyProperties{},
|
||||||
)
|
)
|
||||||
|
|
||||||
android.InitDefaultsModule(module)
|
android.InitDefaultsModule(module)
|
||||||
@@ -456,6 +460,9 @@ func (mod *Module) Init() android.Module {
|
|||||||
if mod.coverage != nil {
|
if mod.coverage != nil {
|
||||||
mod.AddProperties(mod.coverage.props()...)
|
mod.AddProperties(mod.coverage.props()...)
|
||||||
}
|
}
|
||||||
|
if mod.clippy != nil {
|
||||||
|
mod.AddProperties(mod.clippy.props()...)
|
||||||
|
}
|
||||||
|
|
||||||
android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
|
android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
|
||||||
|
|
||||||
@@ -487,6 +494,7 @@ func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib)
|
|||||||
func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
||||||
module := newBaseModule(hod, multilib)
|
module := newBaseModule(hod, multilib)
|
||||||
module.coverage = &coverage{}
|
module.coverage = &coverage{}
|
||||||
|
module.clippy = &clippy{}
|
||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,6 +584,9 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
if mod.coverage != nil {
|
if mod.coverage != nil {
|
||||||
flags, deps = mod.coverage.flags(ctx, flags, deps)
|
flags, deps = mod.coverage.flags(ctx, flags, deps)
|
||||||
}
|
}
|
||||||
|
if mod.clippy != nil {
|
||||||
|
flags, deps = mod.clippy.flags(ctx, flags, deps)
|
||||||
|
}
|
||||||
|
|
||||||
if mod.compiler != nil {
|
if mod.compiler != nil {
|
||||||
outputFile := mod.compiler.compile(ctx, flags, deps)
|
outputFile := mod.compiler.compile(ctx, flags, deps)
|
||||||
|
Reference in New Issue
Block a user