Merge "Generate NDK sysroots from the platform build."
This commit is contained in:
commit
c6b4e452b4
|
@ -134,6 +134,10 @@ bootstrap_go_package {
|
|||
"cc/toolchain.go",
|
||||
"cc/util.go",
|
||||
|
||||
"cc/ndk_headers.go",
|
||||
"cc/ndk_library.go",
|
||||
"cc/ndk_sysroot.go",
|
||||
|
||||
"cc/arm_device.go",
|
||||
"cc/arm64_device.go",
|
||||
"cc/mips_device.go",
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
|
@ -183,3 +184,22 @@ func (installer *baseInstaller) AndroidMk(ctx AndroidMkContext, ret *android.And
|
|||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *stubCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
|
||||
ret.SubName = "." + strconv.Itoa(c.properties.ApiLevel)
|
||||
}
|
||||
|
||||
func (installer *stubInstaller) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
|
||||
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) error {
|
||||
path, file := filepath.Split(installer.installPath)
|
||||
stem := strings.TrimSuffix(file, filepath.Ext(file))
|
||||
fmt.Fprintln(w, "LOCAL_MODULE_PATH := "+path)
|
||||
fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
|
||||
|
||||
// Prevent make from installing the libraries to obj/lib (since we have
|
||||
// dozens of libraries with the same name, they'll clobber each other
|
||||
// and the real versions of the libraries from the platform).
|
||||
fmt.Fprintln(w, "LOCAL_COPY_TO_INTERMEDIATE_LIBRARIES := false")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
|
113
cc/cc.go
113
cc/cc.go
|
@ -58,6 +58,7 @@ func init() {
|
|||
// the Go initialization order because this package depends on common, so common's init
|
||||
// functions will run first.
|
||||
android.RegisterBottomUpMutator("link", linkageMutator)
|
||||
android.RegisterBottomUpMutator("ndk_api", ndkApiMutator)
|
||||
android.RegisterBottomUpMutator("test_per_src", testPerSrcMutator)
|
||||
android.RegisterBottomUpMutator("deps", depsMutator)
|
||||
|
||||
|
@ -70,6 +71,10 @@ func init() {
|
|||
|
||||
var (
|
||||
HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
|
||||
|
||||
// These libraries have migrated over to the new ndk_library, which is added
|
||||
// as a variation dependency via depsMutator.
|
||||
ndkMigratedLibs = []string{}
|
||||
)
|
||||
|
||||
// Flags used by lots of devices. Putting them in package static variables will save bytes in
|
||||
|
@ -555,6 +560,8 @@ var (
|
|||
crtBeginDepTag = dependencyTag{name: "crtbegin"}
|
||||
crtEndDepTag = dependencyTag{name: "crtend"}
|
||||
reuseObjTag = dependencyTag{name: "reuse objects"}
|
||||
ndkStubDepTag = dependencyTag{name: "ndk stub", library: true}
|
||||
ndkLateStubDepTag = dependencyTag{name: "ndk late stub", library: true}
|
||||
)
|
||||
|
||||
// Module contains the properties and members used by all C/C++ module types, and implements
|
||||
|
@ -883,20 +890,40 @@ func (c *Module) depsMutator(actx android.BottomUpMutatorContext) {
|
|||
c.Properties.AndroidMkSharedLibs = append(c.Properties.AndroidMkSharedLibs, deps.SharedLibs...)
|
||||
c.Properties.AndroidMkSharedLibs = append(c.Properties.AndroidMkSharedLibs, deps.LateSharedLibs...)
|
||||
|
||||
variantNdkLibs := []string{}
|
||||
variantLateNdkLibs := []string{}
|
||||
if ctx.sdk() {
|
||||
version := "." + ctx.sdkVersion()
|
||||
version := ctx.sdkVersion()
|
||||
|
||||
rewriteNdkLibs := func(list []string) []string {
|
||||
for i, entry := range list {
|
||||
// Rewrites the names of shared libraries into the names of the NDK
|
||||
// libraries where appropriate. This returns two slices.
|
||||
//
|
||||
// The first is a list of non-variant shared libraries (either rewritten
|
||||
// NDK libraries to the modules in prebuilts/ndk, or not rewritten
|
||||
// because they are not NDK libraries).
|
||||
//
|
||||
// The second is a list of ndk_library modules. These need to be
|
||||
// separated because they are a variation dependency and must be added
|
||||
// in a different manner.
|
||||
rewriteNdkLibs := func(list []string) ([]string, []string) {
|
||||
variantLibs := []string{}
|
||||
nonvariantLibs := []string{}
|
||||
for _, entry := range list {
|
||||
if inList(entry, ndkPrebuiltSharedLibraries) {
|
||||
list[i] = "ndk_" + entry + version
|
||||
if !inList(entry, ndkMigratedLibs) {
|
||||
nonvariantLibs = append(nonvariantLibs, entry+".ndk."+version)
|
||||
} else {
|
||||
variantLibs = append(variantLibs, entry+ndkLibrarySuffix)
|
||||
}
|
||||
} else {
|
||||
nonvariantLibs = append(variantLibs, entry)
|
||||
}
|
||||
}
|
||||
return list
|
||||
return nonvariantLibs, variantLibs
|
||||
}
|
||||
|
||||
deps.SharedLibs = rewriteNdkLibs(deps.SharedLibs)
|
||||
deps.LateSharedLibs = rewriteNdkLibs(deps.LateSharedLibs)
|
||||
deps.SharedLibs, variantNdkLibs = rewriteNdkLibs(deps.SharedLibs)
|
||||
deps.LateSharedLibs, variantLateNdkLibs = rewriteNdkLibs(deps.LateSharedLibs)
|
||||
}
|
||||
|
||||
actx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, wholeStaticDepTag,
|
||||
|
@ -935,6 +962,12 @@ func (c *Module) depsMutator(actx android.BottomUpMutatorContext) {
|
|||
if deps.CrtEnd != "" {
|
||||
actx.AddDependency(c, crtEndDepTag, deps.CrtEnd)
|
||||
}
|
||||
|
||||
version := ctx.sdkVersion()
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{"ndk_api", version}, {"link", "shared"}}, ndkStubDepTag, variantNdkLibs...)
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{"ndk_api", version}, {"link", "shared"}}, ndkLateStubDepTag, variantLateNdkLibs...)
|
||||
}
|
||||
|
||||
func depsMutator(ctx android.BottomUpMutatorContext) {
|
||||
|
@ -990,6 +1023,11 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
// These are allowed, but don't set sdk_version
|
||||
return true
|
||||
}
|
||||
if _, ok := to.linker.(*stubLinker); ok {
|
||||
// These aren't real libraries, but are the stub shared libraries that are included in
|
||||
// the NDK.
|
||||
return true
|
||||
}
|
||||
return to.Properties.Sdk_version != ""
|
||||
}
|
||||
|
||||
|
@ -1073,9 +1111,9 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||
var depPtr *android.Paths
|
||||
|
||||
switch tag {
|
||||
case sharedDepTag, sharedExportDepTag:
|
||||
case ndkStubDepTag, sharedDepTag, sharedExportDepTag:
|
||||
depPtr = &depPaths.SharedLibs
|
||||
case lateSharedDepTag:
|
||||
case lateSharedDepTag, ndkLateStubDepTag:
|
||||
depPtr = &depPaths.LateSharedLibs
|
||||
case staticDepTag, staticExportDepTag:
|
||||
depPtr = &depPaths.StaticLibs
|
||||
|
@ -1190,6 +1228,30 @@ func (compiler *baseCompiler) flags(ctx ModuleContext, flags Flags) Flags {
|
|||
}...)
|
||||
}
|
||||
|
||||
if ctx.sdk() {
|
||||
// The NDK headers are installed to a common sysroot. While a more
|
||||
// typical Soong approach would be to only make the headers for the
|
||||
// library you're using available, we're trying to emulate the NDK
|
||||
// behavior here, and the NDK always has all the NDK headers available.
|
||||
flags.GlobalFlags = append(flags.GlobalFlags,
|
||||
"-isystem "+getCurrentIncludePath(ctx).String(),
|
||||
"-isystem "+getCurrentIncludePath(ctx).Join(ctx, toolchain.ClangTriple()).String())
|
||||
|
||||
// Traditionally this has come from android/api-level.h, but with the
|
||||
// libc headers unified it must be set by the build system since we
|
||||
// don't have per-API level copies of that header now.
|
||||
flags.GlobalFlags = append(flags.GlobalFlags,
|
||||
"-D__ANDROID_API__="+ctx.sdkVersion())
|
||||
|
||||
// Until the full NDK has been migrated to using ndk_headers, we still
|
||||
// need to add the legacy sysroot includes to get the full set of
|
||||
// headers.
|
||||
legacyIncludes := fmt.Sprintf(
|
||||
"prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/include",
|
||||
ctx.sdkVersion(), ctx.Arch().ArchType.String())
|
||||
flags.GlobalFlags = append(flags.GlobalFlags, "-isystem "+legacyIncludes)
|
||||
}
|
||||
|
||||
instructionSet := compiler.Properties.Instruction_set
|
||||
if flags.RequiredInstructionSet != "" {
|
||||
instructionSet = flags.RequiredInstructionSet
|
||||
|
@ -1310,11 +1372,22 @@ func (compiler *baseCompiler) flags(ctx ModuleContext, flags Flags) Flags {
|
|||
return flags
|
||||
}
|
||||
|
||||
func ndkPathDeps(ctx ModuleContext) android.Paths {
|
||||
if ctx.sdk() {
|
||||
// The NDK sysroot timestamp file depends on all the NDK sysroot files
|
||||
// (headers and libraries).
|
||||
return android.Paths{getNdkSysrootTimestampFile(ctx)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
|
||||
pathDeps := deps.GeneratedHeaders
|
||||
pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
|
||||
// Compile files listed in c.Properties.Srcs into objects
|
||||
objFiles := compiler.compileObjs(ctx, flags, "",
|
||||
compiler.Properties.Srcs, compiler.Properties.Exclude_srcs,
|
||||
deps.GeneratedSources, deps.GeneratedHeaders)
|
||||
deps.GeneratedSources, pathDeps)
|
||||
|
||||
if ctx.Failed() {
|
||||
return nil
|
||||
|
@ -1595,14 +1668,17 @@ func (library *libraryCompiler) compile(ctx ModuleContext, flags Flags, deps Pat
|
|||
objFiles = library.baseCompiler.compile(ctx, flags, deps)
|
||||
library.reuseObjFiles = objFiles
|
||||
|
||||
pathDeps := deps.GeneratedHeaders
|
||||
pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
|
||||
|
||||
if library.linker.static() {
|
||||
objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceStaticLibrary,
|
||||
library.Properties.Static.Srcs, library.Properties.Static.Exclude_srcs,
|
||||
nil, deps.GeneratedHeaders)...)
|
||||
nil, pathDeps)...)
|
||||
} else {
|
||||
objFiles = append(objFiles, library.compileObjs(ctx, flags, android.DeviceSharedLibrary,
|
||||
library.Properties.Shared.Srcs, library.Properties.Shared.Exclude_srcs,
|
||||
nil, deps.GeneratedHeaders)...)
|
||||
nil, pathDeps)...)
|
||||
}
|
||||
|
||||
return objFiles
|
||||
|
@ -1626,6 +1702,10 @@ type libraryLinker struct {
|
|||
|
||||
// For whole_static_libs
|
||||
objFiles android.Paths
|
||||
|
||||
// Uses the module's name if empty, but can be overridden. Does not include
|
||||
// shlib suffix.
|
||||
libName string
|
||||
}
|
||||
|
||||
var _ linker = (*libraryLinker)(nil)
|
||||
|
@ -1646,7 +1726,10 @@ func (library *libraryLinker) props() []interface{} {
|
|||
}
|
||||
|
||||
func (library *libraryLinker) getLibName(ctx ModuleContext) string {
|
||||
name := ctx.ModuleName()
|
||||
name := library.libName
|
||||
if name == "" {
|
||||
name = ctx.ModuleName()
|
||||
}
|
||||
|
||||
if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
|
||||
if !strings.HasSuffix(name, "-host") {
|
||||
|
@ -2634,10 +2717,6 @@ func ndkPrebuiltLibraryFactory() (blueprint.Module, []interface{}) {
|
|||
func (ndk *ndkPrebuiltLibraryLinker) link(ctx ModuleContext, flags Flags,
|
||||
deps PathDeps, objFiles android.Paths) android.Path {
|
||||
// A null build step, but it sets up the output path.
|
||||
if !strings.HasPrefix(ctx.ModuleName(), "ndk_lib") {
|
||||
ctx.ModuleErrorf("NDK prebuilts must have an ndk_lib prefixed name")
|
||||
}
|
||||
|
||||
ndk.exportIncludes(ctx, "-isystem")
|
||||
|
||||
return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(),
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2016 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.
|
||||
#
|
||||
"""Generates source for stub shared libraries for the NDK."""
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
ALL_ARCHITECTURES = (
|
||||
'arm',
|
||||
'arm64',
|
||||
'mips',
|
||||
'mips64',
|
||||
'x86',
|
||||
'x86_64',
|
||||
)
|
||||
|
||||
|
||||
class Scope(object):
|
||||
"""Enum for version script scope.
|
||||
|
||||
Top: Top level of the file.
|
||||
Global: In a version and visibility section where symbols should be visible
|
||||
to the NDK.
|
||||
Local: In a visibility section of a public version where symbols should be
|
||||
hidden to the NDK.
|
||||
Private: In a version where symbols should not be visible to the NDK.
|
||||
"""
|
||||
Top = 1
|
||||
Global = 2
|
||||
Local = 3
|
||||
Private = 4
|
||||
|
||||
|
||||
class Stack(object):
|
||||
"""Basic stack implementation."""
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
|
||||
def push(self, obj):
|
||||
"""Push an item on to the stack."""
|
||||
self.stack.append(obj)
|
||||
|
||||
def pop(self):
|
||||
"""Remove and return the item on the top of the stack."""
|
||||
return self.stack.pop()
|
||||
|
||||
@property
|
||||
def top(self):
|
||||
"""Return the top of the stack."""
|
||||
return self.stack[-1]
|
||||
|
||||
|
||||
def version_is_private(version):
|
||||
"""Returns True if the version name should be treated as private."""
|
||||
return version.endswith('_PRIVATE') or version.endswith('_PLATFORM')
|
||||
|
||||
|
||||
def enter_version(scope, line, version_file):
|
||||
"""Enters a new version block scope."""
|
||||
if scope.top != Scope.Top:
|
||||
raise RuntimeError('Encountered nested version block.')
|
||||
|
||||
# Entering a new version block. By convention symbols with versions ending
|
||||
# with "_PRIVATE" or "_PLATFORM" are not included in the NDK.
|
||||
version_name = line.split('{')[0].strip()
|
||||
if version_is_private(version_name):
|
||||
scope.push(Scope.Private)
|
||||
else:
|
||||
scope.push(Scope.Global) # By default symbols are visible.
|
||||
version_file.write(line)
|
||||
|
||||
|
||||
def leave_version(scope, line, version_file):
|
||||
"""Leave a version block scope."""
|
||||
# There is no close to a visibility section, just the end of the version or
|
||||
# a new visiblity section.
|
||||
assert scope.top in (Scope.Global, Scope.Local, Scope.Private)
|
||||
if scope.top != Scope.Private:
|
||||
version_file.write(line)
|
||||
scope.pop()
|
||||
assert scope.top == Scope.Top
|
||||
|
||||
|
||||
def enter_visibility(scope, line, version_file):
|
||||
"""Enters a new visibility block scope."""
|
||||
leave_visibility(scope)
|
||||
version_file.write(line)
|
||||
visibility = line.split(':')[0].strip()
|
||||
if visibility == 'local':
|
||||
scope.push(Scope.Local)
|
||||
elif visibility == 'global':
|
||||
scope.push(Scope.Global)
|
||||
else:
|
||||
raise RuntimeError('Unknown visiblity label: ' + visibility)
|
||||
|
||||
|
||||
def leave_visibility(scope):
|
||||
"""Leaves a visibility block scope."""
|
||||
assert scope.top in (Scope.Global, Scope.Local)
|
||||
scope.pop()
|
||||
assert scope.top == Scope.Top
|
||||
|
||||
|
||||
def handle_top_scope(scope, line, version_file):
|
||||
"""Processes a line in the top level scope."""
|
||||
if '{' in line:
|
||||
enter_version(scope, line, version_file)
|
||||
else:
|
||||
raise RuntimeError('Unexpected contents at top level: ' + line)
|
||||
|
||||
|
||||
def handle_private_scope(scope, line, version_file):
|
||||
"""Eats all input."""
|
||||
if '}' in line:
|
||||
leave_version(scope, line, version_file)
|
||||
|
||||
|
||||
def handle_local_scope(scope, line, version_file):
|
||||
"""Passes through input."""
|
||||
if ':' in line:
|
||||
enter_visibility(scope, line, version_file)
|
||||
elif '}' in line:
|
||||
leave_version(scope, line, version_file)
|
||||
else:
|
||||
version_file.write(line)
|
||||
|
||||
|
||||
def symbol_in_arch(tags, arch):
|
||||
"""Returns true if the symbol is present for the given architecture."""
|
||||
has_arch_tags = False
|
||||
for tag in tags:
|
||||
if tag == arch:
|
||||
return True
|
||||
if tag in ALL_ARCHITECTURES:
|
||||
has_arch_tags = True
|
||||
|
||||
# If there were no arch tags, the symbol is available for all
|
||||
# architectures. If there were any arch tags, the symbol is only available
|
||||
# for the tagged architectures.
|
||||
return not has_arch_tags
|
||||
|
||||
|
||||
def symbol_in_version(tags, arch, version):
|
||||
"""Returns true if the symbol is present for the given version."""
|
||||
introduced_tag = None
|
||||
arch_specific = False
|
||||
for tag in tags:
|
||||
# If there is an arch-specific tag, it should override the common one.
|
||||
if tag.startswith('introduced=') and not arch_specific:
|
||||
introduced_tag = tag
|
||||
elif tag.startswith('introduced-' + arch + '='):
|
||||
introduced_tag = tag
|
||||
arch_specific = True
|
||||
|
||||
if introduced_tag is None:
|
||||
# We found no "introduced" tags, so the symbol has always been
|
||||
# available.
|
||||
return True
|
||||
|
||||
# The tag is a key=value pair, and we only care about the value now.
|
||||
_, _, version_str = introduced_tag.partition('=')
|
||||
return version >= int(version_str)
|
||||
|
||||
|
||||
def handle_global_scope(scope, line, src_file, version_file, arch, api):
|
||||
"""Emits present symbols to the version file and stub source file."""
|
||||
if ':' in line:
|
||||
enter_visibility(scope, line, version_file)
|
||||
return
|
||||
if '}' in line:
|
||||
leave_version(scope, line, version_file)
|
||||
return
|
||||
|
||||
if ';' not in line:
|
||||
raise RuntimeError('Expected ; to terminate symbol: ' + line)
|
||||
if '*' in line:
|
||||
raise RuntimeError('Wildcard global symbols are not permitted.')
|
||||
|
||||
# Line is now in the format "<symbol-name>; # tags"
|
||||
# Tags are whitespace separated.
|
||||
symbol_name, _, rest = line.strip().partition(';')
|
||||
_, _, all_tags = rest.partition('#')
|
||||
tags = re.split(r'\s+', all_tags)
|
||||
|
||||
if not symbol_in_arch(tags, arch):
|
||||
return
|
||||
if not symbol_in_version(tags, arch, api):
|
||||
return
|
||||
|
||||
if 'var' in tags:
|
||||
src_file.write('int {} = 0;\n'.format(symbol_name))
|
||||
else:
|
||||
src_file.write('void {}() {{}}\n'.format(symbol_name))
|
||||
version_file.write(line)
|
||||
|
||||
|
||||
def generate(symbol_file, src_file, version_file, arch, api):
|
||||
"""Generates the stub source file and version script."""
|
||||
scope = Stack()
|
||||
scope.push(Scope.Top)
|
||||
for line in symbol_file:
|
||||
if line.strip() == '' or line.strip().startswith('#'):
|
||||
version_file.write(line)
|
||||
elif scope.top == Scope.Top:
|
||||
handle_top_scope(scope, line, version_file)
|
||||
elif scope.top == Scope.Private:
|
||||
handle_private_scope(scope, line, version_file)
|
||||
elif scope.top == Scope.Local:
|
||||
handle_local_scope(scope, line, version_file)
|
||||
elif scope.top == Scope.Global:
|
||||
handle_global_scope(scope, line, src_file, version_file, arch, api)
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Parses and returns command line arguments."""
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('--api', type=int, help='API level being targeted.')
|
||||
parser.add_argument(
|
||||
'--arch', choices=ALL_ARCHITECTURES,
|
||||
help='Architecture being targeted.')
|
||||
|
||||
parser.add_argument(
|
||||
'symbol_file', type=os.path.realpath, help='Path to symbol file.')
|
||||
parser.add_argument(
|
||||
'stub_src', type=os.path.realpath,
|
||||
help='Path to output stub source file.')
|
||||
parser.add_argument(
|
||||
'version_script', type=os.path.realpath,
|
||||
help='Path to output version script.')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
"""Program entry point."""
|
||||
args = parse_args()
|
||||
|
||||
with open(args.symbol_file) as symbol_file:
|
||||
with open(args.stub_src, 'w') as src_file:
|
||||
with open(args.version_script, 'w') as version_file:
|
||||
generate(symbol_file, src_file, version_file, args.arch,
|
||||
args.api)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -50,6 +50,8 @@ func makeVarsProvider(ctx android.MakeVarsContext) {
|
|||
ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " "))
|
||||
ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " "))
|
||||
|
||||
ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " "))
|
||||
|
||||
hostTargets := ctx.Config().Targets[android.Host]
|
||||
makeVarsToolchain(ctx, "", hostTargets[0])
|
||||
if len(hostTargets) > 1 {
|
||||
|
@ -198,6 +200,7 @@ func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
|
|||
ctx.Strict(makePrefix+"STRIP", gccCmd(toolchain, "strip"))
|
||||
ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
|
||||
ctx.Strict(makePrefix+"NDK_GCC_VERSION", toolchain.GccVersion())
|
||||
ctx.Strict(makePrefix+"NDK_TRIPLE", toolchain.ClangTriple())
|
||||
}
|
||||
|
||||
ctx.Strict(makePrefix+"TOOLCHAIN_ROOT", toolchain.GccRoot())
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// 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 cc
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
// Returns the NDK base include path for use with sdk_version current. Usable with -I.
|
||||
func getCurrentIncludePath(ctx android.ModuleContext) android.OutputPath {
|
||||
return getNdkSysrootBase(ctx).Join(ctx, "usr/include")
|
||||
}
|
||||
|
||||
type headerProperies struct {
|
||||
// Base directory of the headers being installed. As an example:
|
||||
//
|
||||
// ndk_headers {
|
||||
// name: "foo",
|
||||
// from: "include",
|
||||
// to: "",
|
||||
// srcs: ["include/foo/bar/baz.h"],
|
||||
// }
|
||||
//
|
||||
// Will install $SYSROOT/usr/include/foo/bar/baz.h. If `from` were instead
|
||||
// "include/foo", it would have installed $SYSROOT/usr/include/bar/baz.h.
|
||||
From string
|
||||
|
||||
// Install path within the sysroot. This is relative to usr/include.
|
||||
To string
|
||||
|
||||
// List of headers to install. Glob compatible. Common case is "include/**/*.h".
|
||||
Srcs []string
|
||||
}
|
||||
|
||||
type headerModule struct {
|
||||
android.ModuleBase
|
||||
|
||||
properties headerProperies
|
||||
|
||||
installPaths []string
|
||||
}
|
||||
|
||||
func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
srcFiles := ctx.ExpandSources(m.properties.Srcs, nil)
|
||||
for _, header := range srcFiles {
|
||||
// Output path is the sysroot base + "usr/include" + to directory + directory component
|
||||
// of the file without the leading from directory stripped.
|
||||
//
|
||||
// Given:
|
||||
// sysroot base = "ndk/sysroot"
|
||||
// from = "include/foo"
|
||||
// to = "bar"
|
||||
// header = "include/foo/woodly/doodly.h"
|
||||
// output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
|
||||
|
||||
// full/platform/path/to/include/foo
|
||||
fullFromPath := android.PathForModuleSrc(ctx, m.properties.From)
|
||||
|
||||
// full/platform/path/to/include/foo/woodly
|
||||
headerDir := filepath.Dir(header.String())
|
||||
|
||||
// woodly
|
||||
strippedHeaderDir, err := filepath.Rel(fullFromPath.String(), headerDir)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s", headerDir,
|
||||
fullFromPath.String(), err)
|
||||
}
|
||||
|
||||
// full/platform/path/to/sysroot/usr/include/bar/woodly
|
||||
installDir := getCurrentIncludePath(ctx).Join(ctx, m.properties.To, strippedHeaderDir)
|
||||
|
||||
// full/platform/path/to/sysroot/usr/include/bar/woodly/doodly.h
|
||||
installPath := ctx.InstallFile(installDir, header)
|
||||
m.installPaths = append(m.installPaths, installPath.String())
|
||||
}
|
||||
|
||||
if len(m.installPaths) == 0 {
|
||||
ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs)
|
||||
}
|
||||
}
|
||||
|
||||
func ndkHeadersFactory() (blueprint.Module, []interface{}) {
|
||||
module := &headerModule{}
|
||||
return android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst,
|
||||
&module.properties)
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// 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 cc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
var (
|
||||
toolPath = pctx.SourcePathVariable("toolPath", "build/soong/cc/gen_stub_libs.py")
|
||||
|
||||
genStubSrc = pctx.StaticRule("genStubSrc",
|
||||
blueprint.RuleParams{
|
||||
Command: "$toolPath --arch $arch --api $apiLevel $in $out",
|
||||
Description: "genStubSrc $out",
|
||||
CommandDeps: []string{"$toolPath"},
|
||||
}, "arch", "apiLevel")
|
||||
|
||||
ndkLibrarySuffix = ".ndk"
|
||||
)
|
||||
|
||||
// Creates a stub shared library based on the provided version file.
|
||||
//
|
||||
// The name of the generated file will be based on the module name by stripping
|
||||
// the ".ndk" suffix from the module name. Module names must end with ".ndk"
|
||||
// (as a convention to allow soong to guess the NDK name of a dependency when
|
||||
// needed). "libfoo.ndk" will generate "libfoo.so.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ndk_library {
|
||||
// name: "libfoo.ndk",
|
||||
// symbol_file: "libfoo.map.txt",
|
||||
// first_version: "9",
|
||||
// }
|
||||
//
|
||||
type libraryProperties struct {
|
||||
// Relative path to the symbol map.
|
||||
// An example file can be seen here: TODO(danalbert): Make an example.
|
||||
Symbol_file string
|
||||
|
||||
// The first API level a library was available. A library will be generated
|
||||
// for every API level beginning with this one.
|
||||
First_version string
|
||||
|
||||
// Private property for use by the mutator that splits per-API level.
|
||||
ApiLevel int `blueprint:"mutated"`
|
||||
}
|
||||
|
||||
type stubCompiler struct {
|
||||
baseCompiler
|
||||
|
||||
properties libraryProperties
|
||||
}
|
||||
|
||||
// OMG GO
|
||||
func intMin(a int, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
func generateStubApiVariants(mctx android.BottomUpMutatorContext, c *stubCompiler) {
|
||||
minVersion := 9 // Minimum version supported by the NDK.
|
||||
// TODO(danalbert): Use PlatformSdkVersion when possible.
|
||||
// This is an interesting case because for the moment we actually need 24
|
||||
// even though the latest released version in aosp is 23. prebuilts/ndk/r11
|
||||
// has android-24 versions of libraries, and as platform libraries get
|
||||
// migrated the libraries in prebuilts will need to depend on them.
|
||||
//
|
||||
// Once everything is all moved over to the new stuff (when there isn't a
|
||||
// prebuilts/ndk any more) then this should be fixable, but for now I think
|
||||
// it needs to remain as-is.
|
||||
maxVersion := 24
|
||||
firstArchVersions := map[string]int{
|
||||
"arm": 9,
|
||||
"arm64": 21,
|
||||
"mips": 9,
|
||||
"mips64": 21,
|
||||
"x86": 9,
|
||||
"x86_64": 21,
|
||||
}
|
||||
|
||||
// If the NDK drops support for a platform version, we don't want to have to
|
||||
// fix up every module that was using it as its minimum version. Clip to the
|
||||
// supported version here instead.
|
||||
firstVersion, err := strconv.Atoi(c.properties.First_version)
|
||||
if err != nil {
|
||||
mctx.ModuleErrorf("Invalid first_version value (must be int): %q",
|
||||
c.properties.First_version)
|
||||
}
|
||||
if firstVersion < minVersion {
|
||||
firstVersion = minVersion
|
||||
}
|
||||
|
||||
arch := mctx.Arch().ArchType.String()
|
||||
firstArchVersion, ok := firstArchVersions[arch]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("Arch %q not found in firstArchVersions", arch))
|
||||
}
|
||||
firstGenVersion := intMin(firstVersion, firstArchVersion)
|
||||
versionStrs := make([]string, maxVersion-firstGenVersion+1)
|
||||
for version := firstGenVersion; version <= maxVersion; version++ {
|
||||
versionStrs[version-firstGenVersion] = strconv.Itoa(version)
|
||||
}
|
||||
|
||||
modules := mctx.CreateVariations(versionStrs...)
|
||||
for i, module := range modules {
|
||||
module.(*Module).compiler.(*stubCompiler).properties.ApiLevel = firstGenVersion + i
|
||||
}
|
||||
}
|
||||
|
||||
func ndkApiMutator(mctx android.BottomUpMutatorContext) {
|
||||
if m, ok := mctx.Module().(*Module); ok {
|
||||
if compiler, ok := m.compiler.(*stubCompiler); ok {
|
||||
generateStubApiVariants(mctx, compiler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *stubCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Paths {
|
||||
arch := ctx.Arch().ArchType.String()
|
||||
|
||||
if !strings.HasSuffix(ctx.ModuleName(), ndkLibrarySuffix) {
|
||||
ctx.ModuleErrorf("ndk_library modules names must be suffixed with %q\n",
|
||||
ndkLibrarySuffix)
|
||||
}
|
||||
libName := strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix)
|
||||
fileBase := fmt.Sprintf("%s.%s.%d", libName, arch, c.properties.ApiLevel)
|
||||
stubSrcName := fileBase + ".c"
|
||||
stubSrcPath := android.PathForModuleGen(ctx, stubSrcName)
|
||||
versionScriptName := fileBase + ".map"
|
||||
versionScriptPath := android.PathForModuleGen(ctx, versionScriptName)
|
||||
symbolFilePath := android.PathForModuleSrc(ctx, c.properties.Symbol_file)
|
||||
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
|
||||
Rule: genStubSrc,
|
||||
Outputs: []android.WritablePath{stubSrcPath, versionScriptPath},
|
||||
Input: symbolFilePath,
|
||||
Args: map[string]string{
|
||||
"arch": arch,
|
||||
"apiLevel": strconv.Itoa(c.properties.ApiLevel),
|
||||
},
|
||||
})
|
||||
|
||||
flags.CFlags = append(flags.CFlags,
|
||||
// We're knowingly doing some otherwise unsightly things with builtin
|
||||
// functions here. We're just generating stub libraries, so ignore it.
|
||||
"-Wno-incompatible-library-redeclaration",
|
||||
"-Wno-builtin-requires-header",
|
||||
"-Wno-invalid-noreturn",
|
||||
|
||||
// These libraries aren't actually used. Don't worry about unwinding
|
||||
// (avoids the need to link an unwinder into a fake library).
|
||||
"-fno-unwind-tables",
|
||||
)
|
||||
|
||||
subdir := ""
|
||||
srcs := []string{}
|
||||
excludeSrcs := []string{}
|
||||
extraSrcs := []android.Path{stubSrcPath}
|
||||
extraDeps := []android.Path{}
|
||||
return c.baseCompiler.compileObjs(ctx, flags, subdir, srcs, excludeSrcs,
|
||||
extraSrcs, extraDeps)
|
||||
}
|
||||
|
||||
type stubLinker struct {
|
||||
libraryLinker
|
||||
}
|
||||
|
||||
func (linker *stubLinker) deps(ctx BaseModuleContext, deps Deps) Deps {
|
||||
return Deps{}
|
||||
}
|
||||
|
||||
func (linker *stubLinker) flags(ctx ModuleContext, flags Flags) Flags {
|
||||
linker.libraryLinker.libName = strings.TrimSuffix(ctx.ModuleName(),
|
||||
ndkLibrarySuffix)
|
||||
return linker.libraryLinker.flags(ctx, flags)
|
||||
}
|
||||
|
||||
type stubInstaller struct {
|
||||
baseInstaller
|
||||
|
||||
compiler *stubCompiler
|
||||
|
||||
installPath string
|
||||
}
|
||||
|
||||
var _ installer = (*stubInstaller)(nil)
|
||||
|
||||
func (installer *stubInstaller) install(ctx ModuleContext, path android.Path) {
|
||||
arch := ctx.Target().Arch.ArchType.Name
|
||||
apiLevel := installer.compiler.properties.ApiLevel
|
||||
|
||||
// arm64 isn't actually a multilib toolchain, so unlike the other LP64
|
||||
// architectures it's just installed to lib.
|
||||
libDir := "lib"
|
||||
if ctx.toolchain().Is64Bit() && arch != "arm64" {
|
||||
libDir = "lib64"
|
||||
}
|
||||
|
||||
installDir := getNdkInstallBase(ctx).Join(ctx, fmt.Sprintf(
|
||||
"platforms/android-%d/arch-%s/usr/%s", apiLevel, arch, libDir))
|
||||
installer.installPath = ctx.InstallFile(installDir, path).String()
|
||||
}
|
||||
|
||||
func newStubLibrary() *Module {
|
||||
module := newModule(android.DeviceSupported, android.MultilibBoth)
|
||||
module.stl = nil
|
||||
|
||||
linker := &stubLinker{}
|
||||
linker.dynamicProperties.BuildShared = true
|
||||
linker.dynamicProperties.BuildStatic = false
|
||||
linker.stripper.StripProperties.Strip.None = true
|
||||
module.linker = linker
|
||||
|
||||
compiler := &stubCompiler{}
|
||||
module.compiler = compiler
|
||||
module.installer = &stubInstaller{baseInstaller{
|
||||
dir: "lib",
|
||||
dir64: "lib64",
|
||||
}, compiler, ""}
|
||||
|
||||
return module
|
||||
}
|
||||
|
||||
func ndkLibraryFactory() (blueprint.Module, []interface{}) {
|
||||
module := newStubLibrary()
|
||||
return android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth,
|
||||
&module.compiler.(*stubCompiler).properties)
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// 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 cc
|
||||
|
||||
// The platform needs to provide the following artifacts for the NDK:
|
||||
// 1. Bionic headers.
|
||||
// 2. Platform API headers.
|
||||
// 3. NDK stub shared libraries.
|
||||
// 4. Bionic static libraries.
|
||||
//
|
||||
// TODO(danalbert): All of the above need to include NOTICE files.
|
||||
//
|
||||
// Components 1 and 2: Headers
|
||||
// The bionic and platform API headers are generalized into a single
|
||||
// `ndk_headers` rule. This rule has a `from` property that indicates a base
|
||||
// directory from which headers are to be taken, and a `to` property that
|
||||
// indicates where in the sysroot they should reside relative to usr/include.
|
||||
// There is also a `srcs` property that is glob compatible for specifying which
|
||||
// headers to include.
|
||||
//
|
||||
// Component 3: Stub Libraries
|
||||
// The shared libraries in the NDK are not the actual shared libraries they
|
||||
// refer to (to prevent people from accidentally loading them), but stub
|
||||
// libraries with dummy implementations of everything for use at build time
|
||||
// only.
|
||||
//
|
||||
// Since we don't actually need to know anything about the stub libraries aside
|
||||
// from a list of functions and globals to be exposed, we can create these for
|
||||
// every platform level in the current tree. This is handled by the
|
||||
// ndk_library rule.
|
||||
//
|
||||
// Component 4: Static Libraries
|
||||
// The NDK only provides static libraries for bionic, not the platform APIs.
|
||||
// Since these need to be the actual implementation, we can't build old versions
|
||||
// in the current platform tree. As such, legacy versions are checked in
|
||||
// prebuilt to development/ndk, and a current version is built and archived as
|
||||
// part of the platform build. The platfrom already builds these libraries, our
|
||||
// NDK build rules only need to archive them for retrieval so they can be added
|
||||
// to the prebuilts.
|
||||
//
|
||||
// TODO(danalbert): Write `ndk_static_library` rule.
|
||||
|
||||
import (
|
||||
"github.com/google/blueprint"
|
||||
|
||||
"android/soong"
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
func init() {
|
||||
soong.RegisterModuleType("ndk_headers", ndkHeadersFactory)
|
||||
soong.RegisterModuleType("ndk_library", ndkLibraryFactory)
|
||||
soong.RegisterSingletonType("ndk", NdkSingleton)
|
||||
|
||||
pctx.Import("android/soong/common")
|
||||
}
|
||||
|
||||
func getNdkInstallBase(ctx android.ModuleContext) android.OutputPath {
|
||||
return android.PathForOutput(ctx, "ndk")
|
||||
}
|
||||
|
||||
// Returns the main install directory for the NDK sysroot. Usable with --sysroot.
|
||||
func getNdkSysrootBase(ctx android.ModuleContext) android.OutputPath {
|
||||
return getNdkInstallBase(ctx).Join(ctx, "sysroot")
|
||||
}
|
||||
|
||||
func getNdkSysrootTimestampFile(ctx android.PathContext) android.Path {
|
||||
return android.PathForOutput(ctx, "ndk.timestamp")
|
||||
}
|
||||
|
||||
func NdkSingleton() blueprint.Singleton {
|
||||
return &ndkSingleton{}
|
||||
}
|
||||
|
||||
type ndkSingleton struct{}
|
||||
|
||||
func (n *ndkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
|
||||
installPaths := []string{}
|
||||
ctx.VisitAllModules(func(module blueprint.Module) {
|
||||
if m, ok := module.(*headerModule); ok {
|
||||
installPaths = append(installPaths, m.installPaths...)
|
||||
}
|
||||
})
|
||||
|
||||
ctx.VisitAllModules(func(module blueprint.Module) {
|
||||
if m, ok := module.(*Module); ok {
|
||||
if installer, ok := m.installer.(*stubInstaller); ok {
|
||||
installPaths = append(installPaths, installer.installPath)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// There's a dummy "ndk" rule defined in ndk/Android.mk that depends on
|
||||
// this. `m ndk` will build the sysroots.
|
||||
ctx.Build(pctx, blueprint.BuildParams{
|
||||
Rule: android.Touch,
|
||||
Outputs: []string{getNdkSysrootTimestampFile(ctx).String()},
|
||||
Implicits: installPaths,
|
||||
})
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
[MASTER]
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Profiled execution.
|
||||
profile=no
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time. See also the "--disable" option for examples.
|
||||
#enable=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=design
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||
# (visual studio) and html. You can also give a reporter class, eg
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Put messages in a separate file for each module / package specified on the
|
||||
# command line instead of printing them on stdout. Reports (if any) will be
|
||||
# written in a file name "pylint_global.[txt|html]".
|
||||
files-output=no
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=yes
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Add a comment according to your evaluation note. This is used by the global
|
||||
# evaluation report (RP0004).
|
||||
comment=no
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details
|
||||
#msg-template=
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Required attributes for module, separated by a comma
|
||||
required-attributes=
|
||||
|
||||
# List of builtins function names that should not be used, separated by a comma
|
||||
bad-functions=map,filter,apply,input
|
||||
|
||||
# Regular expression which should only match correct module names
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Regular expression which should only match correct module level names
|
||||
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
# Regular expression which should only match correct class names
|
||||
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Regular expression which should only match correct function names
|
||||
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct method names
|
||||
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct instance attribute names
|
||||
attr-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct argument names
|
||||
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct variable names
|
||||
variable-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct attribute names in class
|
||||
# bodies
|
||||
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Regular expression which should only match correct list comprehension /
|
||||
# generator expression variable names
|
||||
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=i,j,k,ex,Run,_
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,bar,baz,toto,tutu,tata
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=__.*__
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# List of classes names for which member attributes should not be checked
|
||||
# (useful for classes with attributes dynamically set).
|
||||
ignored-classes=SQLObject
|
||||
|
||||
# When zope mode is activated, add a predefined set of Zope acquired attributes
|
||||
# to generated-members.
|
||||
zope=no
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E0201 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=REQUEST,acl_users,aq_parent
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,XXX,TODO
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching the beginning of the name of dummy variables
|
||||
# (i.e. not used).
|
||||
dummy-variables-rgx=_|dummy
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=80
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled
|
||||
no-space-check=trailing-comma,dict-separator
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=regsub,TERMIOS,Bastion,rexec
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=5
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore
|
||||
ignored-argument-names=_.*
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of return / yield for function / method body
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of branch for function / method body
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of statements in function / method body
|
||||
max-statements=50
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of interface methods to ignore, separated by a comma. This is used for
|
||||
# instance to not check methods defines in Zope's Interface base class.
|
||||
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=Exception
|
Loading…
Reference in New Issue