2016-07-29 21:48:20 +02:00
// 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 (
2019-06-03 12:10:47 +02:00
"fmt"
2019-04-10 07:33:58 +02:00
"io"
2019-02-25 03:05:47 +01:00
"path/filepath"
2018-11-02 10:23:15 +01:00
"regexp"
2021-02-04 18:28:22 +01:00
"strconv"
2016-07-29 21:48:20 +02:00
"strings"
2018-11-02 10:23:15 +01:00
"sync"
2016-07-29 21:48:20 +02:00
"android/soong/android"
2024-01-08 04:55:45 +01:00
bp2build: handle system_shared_libs
- If no system_shared_libs is specified, bp2build writes no attribute
value. In this case, the bazel library macros determine the correct
default behavior.
- If any system_shared_libs is specified for any variant, then bp2build
writes the value verbatim. This includes if an empty list is specified,
as this should override defaulting behavior.
Note this defaulting behavior is incomplete and will be incorrect in
corner cases. For example, if, in an Android.bp, system_shared_libs is
specified for os.linux_bionic but not for os.android, then the bazel
default for os.android will be incorrect. However, there are no current
modules in AOSP which fit this case.
As a related fix, supports static struct for cc_library_static.
Also, removes some elements from the bp2build denylist.
Test: mixed_droid CI
Change-Id: Iee5feeaaf05e8e7209c7a90c913173832ad7bf91
2021-08-04 03:01:05 +02:00
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
2022-09-09 03:38:47 +02:00
"github.com/google/blueprint/proptools"
2016-07-29 21:48:20 +02:00
)
2022-01-12 18:00:49 +01:00
// LibraryProperties is a collection of properties shared by cc library rules/cc.
2016-07-30 02:28:03 +02:00
type LibraryProperties struct {
2016-07-29 21:48:20 +02:00
// local file name to pass to the linker as -unexported_symbols_list
2019-03-05 07:35:41 +01:00
Unexported_symbols_list * string ` android:"path,arch_variant" `
2016-07-29 21:48:20 +02:00
// local file name to pass to the linker as -force_symbols_not_weak_list
2019-03-05 07:35:41 +01:00
Force_symbols_not_weak_list * string ` android:"path,arch_variant" `
2016-07-29 21:48:20 +02:00
// local file name to pass to the linker as -force_symbols_weak_list
2019-03-05 07:35:41 +01:00
Force_symbols_weak_list * string ` android:"path,arch_variant" `
2016-07-29 21:48:20 +02:00
// rename host libraries to prevent overlap with system installed libraries
Unique_host_soname * bool
2016-11-03 22:28:51 +01:00
Aidl struct {
// export headers generated from .aidl sources
2017-11-07 19:57:05 +01:00
Export_aidl_headers * bool
2016-11-03 22:28:51 +01:00
}
2016-10-21 01:11:43 +02:00
Proto struct {
// export headers generated from .proto sources
2017-11-07 19:57:05 +01:00
Export_proto_headers * bool
2016-10-21 01:11:43 +02:00
}
2017-10-13 09:29:00 +02:00
2019-02-08 13:00:45 +01:00
Sysprop struct {
// Whether platform owns this sysprop library.
Platform * bool
2019-03-05 04:40:24 +01:00
} ` blueprint:"mutated" `
2019-02-08 13:00:45 +01:00
2017-11-07 19:57:05 +01:00
Static_ndk_lib * bool
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
2020-12-31 12:39:48 +01:00
// Generate stubs to make this library accessible to APEXes.
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
Stubs struct {
// Relative path to the symbol map. The symbol map provides the list of
// symbols that are exported for stubs variant of this library.
2019-03-05 07:35:41 +01:00
Symbol_file * string ` android:"path" `
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
// List versions to generate stubs libs for. The version name "current" is always
// implicitly added.
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
Versions [ ] string
2022-11-14 13:21:24 +01:00
// Whether to not require the implementation of the library to be installed if a
// client of the stubs is installed. Defaults to true; set to false if the
// implementation is made available by some other means, e.g. in a Microdroid
// virtual machine.
Implementation_installable * bool
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
}
2018-11-07 13:43:34 +01:00
// set the name of the output
Stem * string ` android:"arch_variant" `
2019-08-16 23:22:10 +02:00
// set suffix of the name of the output
Suffix * string ` android:"arch_variant" `
2022-12-26 08:54:36 +01:00
// Properties for ABI compatibility checker.
Header_abi_checker headerAbiCheckerProperties
2019-08-16 23:22:10 +02:00
Target struct {
2020-10-29 08:49:43 +01:00
Vendor , Product struct {
2019-08-16 23:22:10 +02:00
// set suffix of the name of the output
Suffix * string ` android:"arch_variant" `
2022-12-26 08:54:36 +01:00
Header_abi_checker headerAbiCheckerProperties
2023-12-01 06:21:13 +01:00
// Disable stubs for vendor/product variants
// This is a workaround to keep `stubs` only for "core" variant (not product/vendor).
// It would be nice if we could put `stubs` into a `target: { core: {} }`
// block but it's not supported in soong yet. This could be removed/simplified once we have
// a better syntax.
No_stubs bool
2022-12-26 08:54:36 +01:00
}
Platform struct {
Header_abi_checker headerAbiCheckerProperties
2019-08-16 23:22:10 +02:00
}
}
2018-11-07 13:43:34 +01:00
// Names of modules to be overridden. Listed modules can only be other shared libraries
// (in Make or Soong).
// This does not completely prevent installation of the overridden libraries, but if both
// binaries would be installed by default (in PRODUCT_PACKAGES) the other library will be removed
// from PRODUCT_PACKAGES.
Overrides [ ] string
2019-01-16 17:18:02 +01:00
2019-08-06 23:19:59 +02:00
// Inject boringssl hash into the shared library. This is only intended for use by external/boringssl.
Inject_bssl_hash * bool ` android:"arch_variant" `
2020-10-14 03:43:54 +02:00
2020-12-17 01:46:01 +01:00
// If this is an LLNDK library, properties to describe the LLNDK stubs. Will be copied from
// the module pointed to by llndk_stubs if it is set.
Llndk llndkLibraryProperties
2021-04-27 22:06:04 +02:00
// If this is a vendor public library, properties to describe the vendor public library stubs.
Vendor_public_library vendorPublicLibraryProperties
2017-02-15 00:28:44 +01:00
}
2016-10-21 01:11:43 +02:00
2020-11-20 18:42:07 +01:00
// StaticProperties is a properties stanza to affect only attributes of the "static" variants of a
// library module.
2019-09-24 23:55:04 +02:00
type StaticProperties struct {
Static StaticOrSharedProperties ` android:"arch_variant" `
}
2020-11-20 18:42:07 +01:00
// SharedProperties is a properties stanza to affect only attributes of the "shared" variants of a
// library module.
2019-09-24 23:55:04 +02:00
type SharedProperties struct {
Shared StaticOrSharedProperties ` android:"arch_variant" `
}
2020-11-20 18:42:07 +01:00
// StaticOrSharedProperties is an embedded struct representing properties to affect attributes of
// either only the "static" variants or only the "shared" variants of a library module. These override
// the base properties of the same name.
// Use `StaticProperties` or `SharedProperties`, depending on which variant is needed.
// `StaticOrSharedProperties` exists only to avoid duplication.
2019-09-24 23:55:04 +02:00
type StaticOrSharedProperties struct {
2020-07-25 00:35:40 +02:00
Srcs [ ] string ` android:"path,arch_variant" `
2021-09-18 02:18:39 +02:00
Tidy_disabled_srcs [ ] string ` android:"path,arch_variant" `
2022-02-17 21:54:45 +01:00
Tidy_timeout_srcs [ ] string ` android:"path,arch_variant" `
2020-07-25 00:35:40 +02:00
Sanitized Sanitized ` android:"arch_variant" `
2019-09-24 23:55:04 +02:00
Cflags [ ] string ` android:"arch_variant" `
2021-07-22 20:39:44 +02:00
Enabled * bool ` android:"arch_variant" `
Whole_static_libs [ ] string ` android:"arch_variant" `
Static_libs [ ] string ` android:"arch_variant" `
Shared_libs [ ] string ` android:"arch_variant" `
System_shared_libs [ ] string ` android:"arch_variant" `
2019-09-24 23:55:04 +02:00
Export_shared_lib_headers [ ] string ` android:"arch_variant" `
Export_static_lib_headers [ ] string ` android:"arch_variant" `
2019-10-07 08:47:24 +02:00
Apex_available [ ] string ` android:"arch_variant" `
2021-10-28 22:25:54 +02:00
Installable * bool ` android:"arch_variant" `
2019-09-24 23:55:04 +02:00
}
2017-02-15 00:28:44 +01:00
type LibraryMutatedProperties struct {
2016-07-30 02:28:03 +02:00
// Build a static variant
BuildStatic bool ` blueprint:"mutated" `
// Build a shared variant
BuildShared bool ` blueprint:"mutated" `
// This variant is shared
VariantIsShared bool ` blueprint:"mutated" `
// This variant is static
VariantIsStatic bool ` blueprint:"mutated" `
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
// This variant is a stubs lib
BuildStubs bool ` blueprint:"mutated" `
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
// This variant is the latest version
IsLatestVersion bool ` blueprint:"mutated" `
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
// Version of the stubs lib
StubsVersion string ` blueprint:"mutated" `
2020-08-19 03:35:15 +02:00
// List of all stubs versions associated with an implementation lib
AllStubsVersions [ ] string ` blueprint:"mutated" `
2016-07-30 02:28:03 +02:00
}
type FlagExporterProperties struct {
// list of directories relative to the Blueprints file that will
2016-11-03 23:53:42 +01:00
// be added to the include path (using -I) for this module and any module that links
2017-10-18 01:15:50 +02:00
// against this module. Directories listed in export_include_dirs do not need to be
// listed in local_include_dirs.
2021-06-29 02:51:12 +02:00
Export_include_dirs [ ] string ` android:"arch_variant,variant_prepend" `
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
2019-10-22 13:31:18 +02:00
// list of directories that will be added to the system include path
// using -isystem for this module and any module that links against this module.
2021-06-29 02:51:12 +02:00
Export_system_include_dirs [ ] string ` android:"arch_variant,variant_prepend" `
2019-10-22 13:31:18 +02:00
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
Target struct {
2020-10-29 08:49:43 +01:00
Vendor , Product struct {
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
// list of exported include directories, like
2020-10-29 08:49:43 +01:00
// export_include_dirs, that will be applied to
// vendor or product variant of this library.
// This will overwrite any other declarations.
2018-01-05 23:42:54 +01:00
Override_export_include_dirs [ ] string
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
}
}
2016-07-29 21:48:20 +02:00
}
func init ( ) {
2019-12-19 16:02:40 +01:00
RegisterLibraryBuildComponents ( android . InitRegistrationContext )
}
func RegisterLibraryBuildComponents ( ctx android . RegistrationContext ) {
ctx . RegisterModuleType ( "cc_library_static" , LibraryStaticFactory )
ctx . RegisterModuleType ( "cc_library_shared" , LibrarySharedFactory )
ctx . RegisterModuleType ( "cc_library" , LibraryFactory )
ctx . RegisterModuleType ( "cc_library_host_static" , LibraryHostStaticFactory )
ctx . RegisterModuleType ( "cc_library_host_shared" , LibraryHostSharedFactory )
2016-07-29 21:48:20 +02:00
}
2019-03-25 23:32:39 +01:00
// cc_library creates both static and/or shared libraries for a device and/or
// host. By default, a cc_library has a single variant that targets the device.
// Specifying `host_supported: true` also creates a library that targets the
// host.
2017-11-03 01:00:50 +01:00
func LibraryFactory ( ) android . Module {
2016-12-09 23:46:15 +01:00
module , _ := NewLibrary ( android . HostAndDeviceSupported )
2019-12-13 20:50:38 +01:00
// Can be used as both a static and a shared library.
module . sdkMemberTypes = [ ] android . SdkMemberType {
sharedLibrarySdkMemberType ,
staticLibrarySdkMemberType ,
2020-03-12 11:24:35 +01:00
staticAndSharedLibrarySdkMemberType ,
2019-12-13 20:50:38 +01:00
}
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-25 23:32:39 +01:00
// cc_library_static creates a static library for a device and/or host binary.
2017-11-03 01:00:50 +01:00
func LibraryStaticFactory ( ) android . Module {
2016-12-09 23:46:15 +01:00
module , library := NewLibrary ( android . HostAndDeviceSupported )
library . BuildOnlyStatic ( )
2019-12-13 20:50:38 +01:00
module . sdkMemberTypes = [ ] android . SdkMemberType { staticLibrarySdkMemberType }
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-25 23:32:39 +01:00
// cc_library_shared creates a shared library for a device and/or host.
2017-11-03 01:00:50 +01:00
func LibrarySharedFactory ( ) android . Module {
2016-12-09 23:46:15 +01:00
module , library := NewLibrary ( android . HostAndDeviceSupported )
library . BuildOnlyShared ( )
2019-12-13 20:50:38 +01:00
module . sdkMemberTypes = [ ] android . SdkMemberType { sharedLibrarySdkMemberType }
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-25 23:32:39 +01:00
// cc_library_host_static creates a static library that is linkable to a host
// binary.
2017-11-03 01:00:50 +01:00
func LibraryHostStaticFactory ( ) android . Module {
2016-12-09 23:46:15 +01:00
module , library := NewLibrary ( android . HostSupported )
library . BuildOnlyStatic ( )
2019-12-13 20:50:38 +01:00
module . sdkMemberTypes = [ ] android . SdkMemberType { staticLibrarySdkMemberType }
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2019-03-25 23:32:39 +01:00
// cc_library_host_shared creates a shared library that is usable on a host.
2017-11-03 01:00:50 +01:00
func LibraryHostSharedFactory ( ) android . Module {
2016-12-09 23:46:15 +01:00
module , library := NewLibrary ( android . HostSupported )
library . BuildOnlyShared ( )
2019-12-13 20:50:38 +01:00
module . sdkMemberTypes = [ ] android . SdkMemberType { sharedLibrarySdkMemberType }
2016-07-29 21:48:20 +02:00
return module . Init ( )
}
2020-11-20 18:42:07 +01:00
// flagExporter is a separated portion of libraryDecorator pertaining to exported
// include paths and flags. Keeping this dependency-related information separate
// from the rest of library information is helpful in keeping data more structured
// and explicit.
2016-07-29 21:48:20 +02:00
type flagExporter struct {
Properties FlagExporterProperties
2024-05-14 03:03:34 +02:00
dirs android . Paths // Include directories to be included with -I
systemDirs android . Paths // System include directories to be included with -isystem
flags [ ] string // Exported raw flags.
deps android . Paths
headers android . Paths
rustRlibDeps [ ] RustRlibDep
2016-07-29 21:48:20 +02:00
}
2020-11-20 18:42:07 +01:00
// exportedIncludes returns the effective include paths for this module and
// any module that links against this module. This is obtained from
// the export_include_dirs property in the appropriate target stanza.
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
func ( f * flagExporter ) exportedIncludes ( ctx ModuleContext ) android . Paths {
2020-10-29 10:24:11 +01:00
if ctx . inVendor ( ) && f . Properties . Target . Vendor . Override_export_include_dirs != nil {
2018-01-05 23:42:54 +01:00
return android . PathsForModuleSrc ( ctx , f . Properties . Target . Vendor . Override_export_include_dirs )
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
}
2020-10-29 10:24:11 +01:00
if ctx . inProduct ( ) && f . Properties . Target . Product . Override_export_include_dirs != nil {
return android . PathsForModuleSrc ( ctx , f . Properties . Target . Product . Override_export_include_dirs )
}
return android . PathsForModuleSrc ( ctx , f . Properties . Export_include_dirs )
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
}
2024-04-02 06:38:47 +02:00
func ( f * flagExporter ) exportedSystemIncludes ( ctx ModuleContext ) android . Paths {
return android . PathsForModuleSrc ( ctx , f . Properties . Export_system_include_dirs )
}
2020-11-20 18:42:07 +01:00
// exportIncludes registers the include directories and system include directories to be exported
// transitively to modules depending on this module.
2019-06-03 12:10:47 +02:00
func ( f * flagExporter ) exportIncludes ( ctx ModuleContext ) {
2019-10-22 13:19:51 +02:00
f . dirs = append ( f . dirs , f . exportedIncludes ( ctx ) ... )
2019-10-22 13:31:18 +02:00
f . systemDirs = append ( f . systemDirs , android . PathsForModuleSrc ( ctx , f . Properties . Export_system_include_dirs ) ... )
2019-06-03 12:10:47 +02:00
}
2020-11-20 18:42:07 +01:00
// exportIncludesAsSystem registers the include directories and system include directories to be
// exported transitively both as system include directories to modules depending on this module.
2019-06-03 12:10:47 +02:00
func ( f * flagExporter ) exportIncludesAsSystem ( ctx ModuleContext ) {
2019-10-22 13:31:18 +02:00
// all dirs are force exported as system
2019-10-22 13:19:51 +02:00
f . systemDirs = append ( f . systemDirs , f . exportedIncludes ( ctx ) ... )
2019-10-22 13:31:18 +02:00
f . systemDirs = append ( f . systemDirs , android . PathsForModuleSrc ( ctx , f . Properties . Export_system_include_dirs ) ... )
2019-06-03 12:10:47 +02:00
}
2020-11-20 18:42:07 +01:00
// reexportDirs registers the given directories as include directories to be exported transitively
// to modules depending on this module.
2019-10-22 13:19:51 +02:00
func ( f * flagExporter ) reexportDirs ( dirs ... android . Path ) {
2019-06-03 12:10:47 +02:00
f . dirs = append ( f . dirs , dirs ... )
}
2020-11-20 18:42:07 +01:00
// reexportSystemDirs registers the given directories as system include directories
// to be exported transitively to modules depending on this module.
2019-10-22 13:19:51 +02:00
func ( f * flagExporter ) reexportSystemDirs ( dirs ... android . Path ) {
2019-06-03 12:10:47 +02:00
f . systemDirs = append ( f . systemDirs , dirs ... )
2016-07-29 21:48:20 +02:00
}
2020-11-20 18:42:07 +01:00
// reexportFlags registers the flags to be exported transitively to modules depending on this
// module.
2019-06-03 12:10:47 +02:00
func ( f * flagExporter ) reexportFlags ( flags ... string ) {
2020-02-11 16:54:35 +01:00
if android . PrefixInList ( flags , "-I" ) || android . PrefixInList ( flags , "-isystem" ) {
panic ( fmt . Errorf ( "Exporting invalid flag %q: " +
"use reexportDirs or reexportSystemDirs to export directories" , flag ) )
2019-06-03 12:10:47 +02:00
}
2016-07-29 21:48:20 +02:00
f . flags = append ( f . flags , flags ... )
}
2019-06-03 12:10:47 +02:00
func ( f * flagExporter ) reexportDeps ( deps ... android . Path ) {
f . deps = append ( f . deps , deps ... )
}
2024-05-14 03:03:34 +02:00
func ( f * flagExporter ) reexportRustStaticDeps ( deps ... RustRlibDep ) {
f . rustRlibDeps = append ( f . rustRlibDeps , deps ... )
}
2019-12-06 05:15:38 +01:00
// addExportedGeneratedHeaders does nothing but collects generated header files.
// This can be differ to exportedDeps which may contain phony files to minimize ninja.
func ( f * flagExporter ) addExportedGeneratedHeaders ( headers ... android . Path ) {
f . headers = append ( f . headers , headers ... )
}
2020-09-18 23:15:30 +02:00
func ( f * flagExporter ) setProvider ( ctx android . ModuleContext ) {
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , FlagExporterInfoProvider , FlagExporterInfo {
2021-04-27 20:48:30 +02:00
// Comes from Export_include_dirs property, and those of exported transitive deps
IncludeDirs : android . FirstUniquePaths ( f . dirs ) ,
// Comes from Export_system_include_dirs property, and those of exported transitive deps
2021-04-21 03:21:50 +02:00
SystemIncludeDirs : android . FirstUniquePaths ( f . systemDirs ) ,
2021-04-27 20:48:30 +02:00
// Used in very few places as a one-off way of adding extra defines.
Flags : f . flags ,
// Used sparingly, for extra files that need to be explicitly exported to dependers,
// or for phony files to minimize ninja.
Deps : f . deps ,
2024-05-14 03:03:34 +02:00
// Used for exporting rlib deps of static libraries to dependents.
RustRlibDeps : f . rustRlibDeps ,
2021-04-27 20:48:30 +02:00
// For exported generated headers, such as exported aidl headers, proto headers, or
// sysprop headers.
GeneratedHeaders : f . headers ,
2020-09-18 23:15:30 +02:00
} )
2019-06-03 12:10:47 +02:00
}
2016-07-30 02:28:03 +02:00
// libraryDecorator wraps baseCompiler, baseLinker and baseInstaller to provide library-specific
// functionality: static vs. shared linkage, reusing object files for shared libraries
type libraryDecorator struct {
2017-02-15 00:28:44 +01:00
Properties LibraryProperties
2019-09-24 23:55:04 +02:00
StaticProperties StaticProperties
SharedProperties SharedProperties
2017-02-15 00:28:44 +01:00
MutatedProperties LibraryMutatedProperties
2016-07-29 21:48:20 +02:00
// For reusing static library objects for shared library
2019-06-03 12:10:47 +02:00
reuseObjects Objects
2017-05-03 20:01:58 +02:00
2016-10-01 02:10:16 +02:00
// table-of-contents file to optimize out relinking when possible
tocFile android . OptionalPath
2016-07-29 21:48:20 +02:00
2016-07-30 02:28:03 +02:00
flagExporter
2021-04-12 21:42:51 +02:00
flagExporterInfo * FlagExporterInfo
stripper Stripper
2016-07-30 02:28:03 +02:00
// For whole_static_libs
2022-02-11 22:11:55 +01:00
objects Objects
wholeStaticLibsFromPrebuilts android . Paths
2016-07-30 02:28:03 +02:00
// Uses the module's name if empty, but can be overridden. Does not include
// shlib suffix.
libName string
2017-02-08 22:45:53 +01:00
sabi * sabi
2017-02-10 01:16:31 +01:00
// Output archive of gcno coverage information files
coverageOutputFile android . OptionalPath
2017-02-08 22:45:53 +01:00
// Source Abi Diff
2022-10-27 08:55:42 +02:00
sAbiDiff android . Paths
2022-07-05 11:49:50 +02:00
2017-11-29 02:34:01 +01:00
// Location of the static library in the sysroot. Empty if the library is
// not included in the NDK.
ndkSysrootPath android . Path
2018-09-05 01:28:17 +02:00
// Location of the linked, unstripped library for shared libraries
unstrippedOutputFile android . Path
2023-12-12 00:40:29 +01:00
// Location of the linked, stripped library for shared libraries, strip: "all"
strippedAllOutputFile android . Path
2018-09-05 01:28:17 +02:00
2018-11-19 18:33:29 +01:00
// Location of the file that should be copied to dist dir when requested
2020-06-15 07:24:19 +02:00
distFile android . Path
2018-11-19 18:33:29 +01:00
2020-09-29 03:28:02 +02:00
versionScriptPath android . OptionalPath
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
2020-12-21 18:11:10 +01:00
postInstallCmds [ ] string
2019-02-25 03:05:47 +01:00
2018-11-13 05:19:56 +01:00
// If useCoreVariant is true, the vendor variant of a VNDK library is
// not installed.
2020-01-08 23:32:28 +01:00
useCoreVariant bool
checkSameCoreVariant bool
2018-11-13 05:19:56 +01:00
2020-09-30 20:41:33 +02:00
skipAPIDefine bool
2020-04-01 21:38:01 +02:00
// Decorated interfaces
2016-07-30 02:28:03 +02:00
* baseCompiler
* baseLinker
* baseInstaller
2020-03-03 14:06:32 +01:00
2021-08-17 07:54:00 +02:00
apiListCoverageXmlPath android . ModuleOutPath
2020-03-03 14:06:32 +01:00
}
2020-11-20 18:42:07 +01:00
// linkerProps returns the list of properties structs relevant for this library. (For example, if
// the library is cc_shared_library, then static-library properties are omitted.)
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) linkerProps ( ) [ ] interface { } {
var props [ ] interface { }
props = append ( props , library . baseLinker . linkerProps ( ) ... )
2019-09-24 23:55:04 +02:00
props = append ( props ,
2016-07-30 02:28:03 +02:00
& library . Properties ,
2017-02-15 00:28:44 +01:00
& library . MutatedProperties ,
2016-07-30 02:28:03 +02:00
& library . flagExporter . Properties ,
2018-09-05 19:43:13 +02:00
& library . stripper . StripProperties )
2019-09-24 23:55:04 +02:00
if library . MutatedProperties . BuildShared {
props = append ( props , & library . SharedProperties )
}
if library . MutatedProperties . BuildStatic {
props = append ( props , & library . StaticProperties )
}
return props
2016-07-30 02:28:03 +02:00
}
2020-11-20 18:42:07 +01:00
// linkerFlags takes a Flags struct and augments it to contain linker flags that are defined by this
// library, or that are implied by attributes of this library (such as whether this library is a
// shared library).
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) linkerFlags ( ctx ModuleContext , flags Flags ) Flags {
flags = library . baseLinker . linkerFlags ( ctx , flags )
2016-07-29 21:48:20 +02:00
// MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because
// all code is position independent, and then those warnings get promoted to
// errors.
2017-04-04 21:59:48 +02:00
if ! ctx . Windows ( ) {
2019-11-04 18:37:55 +01:00
flags . Global . CFlags = append ( flags . Global . CFlags , "-fPIC" )
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
if library . static ( ) {
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , library . StaticProperties . Static . Cflags ... )
2017-02-15 00:28:44 +01:00
} else if library . shared ( ) {
2019-11-04 18:37:55 +01:00
flags . Local . CFlags = append ( flags . Local . CFlags , library . SharedProperties . Shared . Cflags ... )
2016-07-29 21:48:20 +02:00
}
2017-02-15 00:28:44 +01:00
if library . shared ( ) {
2016-07-30 02:28:03 +02:00
libName := library . getLibName ( ctx )
var f [ ] string
2016-06-14 02:19:03 +02:00
if ctx . toolchain ( ) . Bionic ( ) {
2016-07-30 02:28:03 +02:00
f = append ( f ,
"-nostdlib" ,
"-Wl,--gc-sections" ,
)
}
if ctx . Darwin ( ) {
f = append ( f ,
"-dynamiclib" ,
"-install_name @rpath/" + libName + flags . Toolchain . ShlibSuffix ( ) ,
)
2016-10-20 19:47:21 +02:00
if ctx . Arch ( ) . ArchType == android . X86 {
f = append ( f ,
"-read_only_relocs suppress" ,
)
}
2016-07-30 02:28:03 +02:00
} else {
2019-06-08 02:58:59 +02:00
f = append ( f , "-shared" )
if ! ctx . Windows ( ) {
f = append ( f , "-Wl,-soname," + libName + flags . Toolchain . ShlibSuffix ( ) )
}
2016-07-30 02:28:03 +02:00
}
2019-11-04 18:37:55 +01:00
flags . Global . LdFlags = append ( flags . Global . LdFlags , f ... )
2016-07-30 02:28:03 +02:00
}
2016-07-29 21:48:20 +02:00
return flags
}
2020-11-20 18:42:07 +01:00
// compilerFlags takes a Flags and augments it to contain compile flags from global values,
// per-target values, module type values, per-module Blueprints properties, extra flags from
// `flags`, and generated sources from `deps`.
2017-11-16 23:33:08 +01:00
func ( library * libraryDecorator ) compilerFlags ( ctx ModuleContext , flags Flags , deps PathDeps ) Flags {
Split /system and /vendor modules, allow multi-installation
Nothing changes if BOARD_VNDK_VERSION isn't set.
When the VNDK is enabled (BOARD_VNDK_VERSION in Make), this will split
/system and /vendor modules into two different variant spaces that can't
link to each other. There are a few interfaces between the two variant
spaces:
The `llndk_library` stubs will be available in the /vendor variant, but
won't be installed, so at runtime the /system variant will be used.
Setting `vendor_available: true` will split a module into both variants.
The /system (or "core") variant will compile just like today. The
/vendor ("vendor") variant will compile against everything else in the
vendor space (so LL-NDK instead of libc/liblog/etc). There will be two
copies of these libraries installed onto the final device.
Since the available runtime interfaces for vendor modules may be
reduced, and your dependencies may not expose their private interfaces,
we allow the vendor variants to reduce their compilation set, and export
a different set of headers:
cc_library {
name: "libfoo",
srcs: ["common.cpp", "private_impl.cpp"],
export_include_dirs: ["include"],
target: {
vendor: {
export_include_dirs: ["include_vndk"],
exclude_srcs: ["private_impl.cpp"],
srcs: ["vendor_only.cpp"],
},
},
}
So the "core" variant would compile with both "common.cpp" and
"private_impl.cpp", and export "include".
The "vendor" variant would compile "common.cpp" and "vendor_only.cpp",
and export "include_vndk".
Bug: 36426473
Bug: 36079834
Test: out/soong/build.ninja, out/soong/Android- only changes due to _core addition and
.llndk -> .vendor
Test: attempt to compile with BOARD_VNDK_VERSION:=current
Change-Id: Idef28764043bf6c33dc0d2e7e2026c38867ff769
2017-04-06 21:43:22 +02:00
exportIncludeDirs := library . flagExporter . exportedIncludes ( ctx )
2016-11-03 23:53:42 +01:00
if len ( exportIncludeDirs ) > 0 {
2017-04-26 23:55:27 +02:00
f := includeDirsToFlags ( exportIncludeDirs )
2019-11-04 18:37:55 +01:00
flags . Local . CommonFlags = append ( flags . Local . CommonFlags , f )
flags . Local . YasmFlags = append ( flags . Local . YasmFlags , f )
2016-11-03 23:53:42 +01:00
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
flags = library . baseCompiler . compilerFlags ( ctx , flags , deps )
2020-12-17 01:46:01 +01:00
if ctx . IsLlndk ( ) {
// LLNDK libraries ignore most of the properties on the cc_library and use the
// LLNDK-specific properties instead.
// Wipe all the module-local properties, leaving only the global properties.
flags . Local = LocalOrGlobalFlags { }
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
if library . buildStubs ( ) {
2018-12-13 10:37:29 +01:00
// Remove -include <file> when compiling stubs. Otherwise, the force included
// headers might cause conflicting types error with the symbols in the
// generated stubs source code. e.g.
// double acos(double); // in header
// void acos() {} // in the generated source code
removeInclude := func ( flags [ ] string ) [ ] string {
ret := flags [ : 0 ]
for _ , f := range flags {
if strings . HasPrefix ( f , "-include " ) {
continue
}
ret = append ( ret , f )
}
return ret
}
2019-11-04 18:37:55 +01:00
flags . Local . CommonFlags = removeInclude ( flags . Local . CommonFlags )
flags . Local . CFlags = removeInclude ( flags . Local . CFlags )
2018-12-13 10:37:29 +01:00
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
flags = addStubLibraryCompilerFlags ( flags )
}
return flags
2016-11-03 23:53:42 +01:00
}
2022-12-26 08:54:36 +01:00
func ( library * libraryDecorator ) getHeaderAbiCheckerProperties ( ctx android . BaseModuleContext ) headerAbiCheckerProperties {
m := ctx . Module ( ) . ( * Module )
variantProps := & library . Properties . Target . Platform . Header_abi_checker
if m . InVendor ( ) {
variantProps = & library . Properties . Target . Vendor . Header_abi_checker
} else if m . InProduct ( ) {
variantProps = & library . Properties . Target . Product . Header_abi_checker
}
props := library . Properties . Header_abi_checker
err := proptools . AppendProperties ( & props , variantProps , nil )
if err != nil {
ctx . ModuleErrorf ( "Cannot merge headerAbiCheckerProperties: %s" , err . Error ( ) )
}
return props
2019-04-10 07:33:58 +02:00
}
2016-09-27 02:33:01 +02:00
func ( library * libraryDecorator ) compile ( ctx ModuleContext , flags Flags , deps PathDeps ) Objects {
2020-12-17 01:46:01 +01:00
if ctx . IsLlndk ( ) {
2024-03-11 07:46:48 +01:00
vendorApiLevel := ctx . Config ( ) . VendorApiLevel ( )
if vendorApiLevel == "" {
// TODO(b/321892570): Some tests relying on old fixtures which
// doesn't set vendorApiLevel. Needs to fix them.
vendorApiLevel = ctx . Config ( ) . PlatformSdkVersion ( ) . String ( )
2020-12-17 01:46:01 +01:00
}
2024-03-11 07:46:48 +01:00
// This is the vendor variant of an LLNDK library, build the LLNDK stubs.
2020-07-30 23:32:55 +02:00
nativeAbiResult := parseNativeAbiDefinition ( ctx ,
String ( library . Properties . Llndk . Symbol_file ) ,
2024-03-11 07:46:48 +01:00
android . ApiLevelOrPanic ( ctx , vendorApiLevel ) , "--llndk" )
2020-07-30 23:32:55 +02:00
objs := compileStubLibrary ( ctx , flags , nativeAbiResult . stubSrc )
2020-12-17 01:46:01 +01:00
if ! Bool ( library . Properties . Llndk . Unversioned ) {
2020-07-30 23:32:55 +02:00
library . versionScriptPath = android . OptionalPathForPath (
nativeAbiResult . versionScript )
2020-12-17 01:46:01 +01:00
}
return objs
}
2021-04-27 22:06:04 +02:00
if ctx . IsVendorPublicLibrary ( ) {
2020-07-30 23:32:55 +02:00
nativeAbiResult := parseNativeAbiDefinition ( ctx ,
String ( library . Properties . Vendor_public_library . Symbol_file ) ,
android . FutureApiLevel , "" )
objs := compileStubLibrary ( ctx , flags , nativeAbiResult . stubSrc )
2021-04-27 22:06:04 +02:00
if ! Bool ( library . Properties . Vendor_public_library . Unversioned ) {
2020-07-30 23:32:55 +02:00
library . versionScriptPath = android . OptionalPathForPath ( nativeAbiResult . versionScript )
2021-04-27 22:06:04 +02:00
}
return objs
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
if library . buildStubs ( ) {
2021-02-04 13:05:47 +01:00
symbolFile := String ( library . Properties . Stubs . Symbol_file )
if symbolFile != "" && ! strings . HasSuffix ( symbolFile , ".map.txt" ) {
ctx . PropertyErrorf ( "symbol_file" , "%q doesn't have .map.txt suffix" , symbolFile )
return Objects { }
}
2022-07-17 04:30:47 +02:00
// b/239274367 --apex and --systemapi filters symbols tagged with # apex and #
// systemapi, respectively. The former is for symbols defined in platform libraries
// and the latter is for symbols defined in APEXes.
2023-01-19 00:54:13 +01:00
// A single library can contain either # apex or # systemapi, but not both.
// The stub generator (ndkstubgen) is additive, so passing _both_ of these to it should be a no-op.
// However, having this distinction helps guard accidental
// promotion or demotion of API and also helps the API review process b/191371676
2022-07-17 04:30:47 +02:00
var flag string
if ctx . Module ( ) . ( android . ApexModule ) . NotInPlatform ( ) {
flag = "--apex"
} else {
2022-07-17 10:32:56 +02:00
flag = "--systemapi"
2022-07-17 04:30:47 +02:00
}
2022-09-26 14:16:09 +02:00
// b/184712170, unless the lib is an NDK library, exclude all public symbols from
// the stub so that it is mandated that all symbols are explicitly marked with
// either apex or systemapi.
if ! ctx . Module ( ) . ( * Module ) . IsNdk ( ctx . Config ( ) ) {
flag = flag + " --no-ndk"
}
2020-07-30 23:32:55 +02:00
nativeAbiResult := parseNativeAbiDefinition ( ctx , symbolFile ,
2022-07-17 04:30:47 +02:00
android . ApiLevelOrPanic ( ctx , library . MutatedProperties . StubsVersion ) , flag )
2020-07-30 23:32:55 +02:00
objs := compileStubLibrary ( ctx , flags , nativeAbiResult . stubSrc )
library . versionScriptPath = android . OptionalPathForPath (
nativeAbiResult . versionScript )
2021-08-17 07:54:00 +02:00
// Parse symbol file to get API list for coverage
2021-09-29 01:37:50 +02:00
if library . stubsVersion ( ) == "current" && ctx . PrimaryArch ( ) && ! ctx . inRecovery ( ) && ! ctx . inProduct ( ) && ! ctx . inVendor ( ) {
2021-08-17 07:54:00 +02:00
library . apiListCoverageXmlPath = parseSymbolFileForAPICoverage ( ctx , symbolFile )
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
return objs
}
2016-12-13 21:50:57 +01:00
if ! library . buildShared ( ) && ! library . buildStatic ( ) {
if len ( library . baseCompiler . Properties . Srcs ) > 0 {
ctx . PropertyErrorf ( "srcs" , "cc_library_headers must not have any srcs" )
}
2019-09-24 23:55:04 +02:00
if len ( library . StaticProperties . Static . Srcs ) > 0 {
2016-12-13 21:50:57 +01:00
ctx . PropertyErrorf ( "static.srcs" , "cc_library_headers must not have any srcs" )
}
2019-09-24 23:55:04 +02:00
if len ( library . SharedProperties . Shared . Srcs ) > 0 {
2016-12-13 21:50:57 +01:00
ctx . PropertyErrorf ( "shared.srcs" , "cc_library_headers must not have any srcs" )
}
return Objects { }
}
2020-12-14 04:42:16 +01:00
if library . sabi . shouldCreateSourceAbiDump ( ) {
2024-03-29 13:10:36 +01:00
dirs := library . exportedIncludeDirsForAbiCheck ( ctx )
flags . SAbiFlags = make ( [ ] string , 0 , len ( dirs ) )
for _ , dir := range dirs {
flags . SAbiFlags = append ( flags . SAbiFlags , "-I" + dir )
2017-02-08 22:45:53 +01:00
}
2020-12-21 18:11:10 +01:00
totalLength := len ( library . baseCompiler . Properties . Srcs ) + len ( deps . GeneratedSources ) +
2019-09-24 23:55:04 +02:00
len ( library . SharedProperties . Shared . Srcs ) + len ( library . StaticProperties . Static . Srcs )
2020-12-21 18:11:10 +01:00
if totalLength > 0 {
2017-02-08 22:45:53 +01:00
flags . SAbiDump = true
}
}
2016-09-27 02:33:01 +02:00
objs := library . baseCompiler . compile ( ctx , flags , deps )
library . reuseObjects = objs
2016-10-26 19:03:47 +02:00
buildFlags := flagsToBuilderFlags ( flags )
2016-07-29 21:48:20 +02:00
2016-07-30 02:28:03 +02:00
if library . static ( ) {
2019-09-24 23:55:04 +02:00
srcs := android . PathsForModuleSrc ( ctx , library . StaticProperties . Static . Srcs )
2021-09-18 02:18:39 +02:00
objs = objs . Append ( compileObjs ( ctx , buildFlags , android . DeviceStaticLibrary , srcs ,
android . PathsForModuleSrc ( ctx , library . StaticProperties . Static . Tidy_disabled_srcs ) ,
2022-02-17 21:54:45 +01:00
android . PathsForModuleSrc ( ctx , library . StaticProperties . Static . Tidy_timeout_srcs ) ,
2021-09-18 02:18:39 +02:00
library . baseCompiler . pathDeps , library . baseCompiler . cFlagsDeps ) )
2017-02-15 00:28:44 +01:00
} else if library . shared ( ) {
2019-09-24 23:55:04 +02:00
srcs := android . PathsForModuleSrc ( ctx , library . SharedProperties . Shared . Srcs )
2021-09-18 02:18:39 +02:00
objs = objs . Append ( compileObjs ( ctx , buildFlags , android . DeviceSharedLibrary , srcs ,
android . PathsForModuleSrc ( ctx , library . SharedProperties . Shared . Tidy_disabled_srcs ) ,
2022-02-17 21:54:45 +01:00
android . PathsForModuleSrc ( ctx , library . SharedProperties . Shared . Tidy_timeout_srcs ) ,
2021-09-18 02:18:39 +02:00
library . baseCompiler . pathDeps , library . baseCompiler . cFlagsDeps ) )
2016-07-29 21:48:20 +02:00
}
2016-09-27 02:33:01 +02:00
return objs
2016-07-29 21:48:20 +02:00
}
type libraryInterface interface {
2020-10-02 00:58:11 +02:00
versionedInterface
2016-07-29 21:48:20 +02:00
static ( ) bool
2019-05-14 11:52:49 +02:00
shared ( ) bool
2016-09-27 02:33:01 +02:00
objs ( ) Objects
2020-09-18 23:15:30 +02:00
reuseObjs ( ) Objects
2016-10-01 02:10:16 +02:00
toc ( ) android . OptionalPath
2016-07-29 21:48:20 +02:00
2016-07-30 02:28:03 +02:00
// Returns true if the build options for the module have selected a static or shared build
buildStatic ( ) bool
buildShared ( ) bool
// Sets whether a specific variant is static or shared
2017-02-15 00:28:44 +01:00
setStatic ( )
setShared ( )
2019-04-10 07:33:58 +02:00
2022-12-26 08:54:36 +01:00
// Gets the ABI properties for vendor, product, or platform variant
getHeaderAbiCheckerProperties ( ctx android . BaseModuleContext ) headerAbiCheckerProperties
2020-12-14 04:42:16 +01:00
2019-04-10 07:33:58 +02:00
// Write LOCAL_ADDITIONAL_DEPENDENCIES for ABI diff
androidMkWriteAdditionalDependenciesForSourceAbiDiff ( w io . Writer )
2019-10-07 08:47:24 +02:00
availableFor ( string ) bool
2021-09-29 01:37:50 +02:00
getAPIListCoverageXMLPath ( ) android . ModuleOutPath
2021-10-28 22:25:54 +02:00
installable ( ) * bool
2016-07-29 21:48:20 +02:00
}
2020-09-29 02:32:47 +02:00
type versionedInterface interface {
buildStubs ( ) bool
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
setBuildStubs ( isLatest bool )
2020-09-29 02:32:47 +02:00
hasStubsVariants ( ) bool
2022-11-14 13:21:24 +01:00
isStubsImplementationRequired ( ) bool
2020-09-29 02:32:47 +02:00
setStubsVersion ( string )
stubsVersion ( ) string
2020-10-02 00:58:11 +02:00
stubsVersions ( ctx android . BaseMutatorContext ) [ ] string
2020-09-29 02:32:47 +02:00
setAllStubsVersions ( [ ] string )
allStubsVersions ( ) [ ] string
2020-10-14 03:43:54 +02:00
implementationModuleName ( name string ) string
2020-12-17 01:46:01 +01:00
hasLLNDKStubs ( ) bool
2021-04-27 03:37:44 +02:00
hasLLNDKHeaders ( ) bool
2021-04-27 22:06:04 +02:00
hasVendorPublicLibrary ( ) bool
2020-09-29 02:32:47 +02:00
}
var _ libraryInterface = ( * libraryDecorator ) ( nil )
var _ versionedInterface = ( * libraryDecorator ) ( nil )
2020-10-29 10:24:11 +01:00
func ( library * libraryDecorator ) getLibNameHelper ( baseModuleName string , inVendor bool , inProduct bool ) string {
2016-07-29 21:48:20 +02:00
name := library . libName
if name == "" {
2018-11-07 13:43:34 +01:00
name = String ( library . Properties . Stem )
if name == "" {
2019-10-30 10:43:49 +01:00
name = baseModuleName
2018-11-07 13:43:34 +01:00
}
2016-07-29 21:48:20 +02:00
}
2019-08-16 23:22:10 +02:00
suffix := ""
2020-10-29 10:24:11 +01:00
if inVendor {
2019-08-16 23:22:10 +02:00
suffix = String ( library . Properties . Target . Vendor . Suffix )
2020-10-29 10:24:11 +01:00
} else if inProduct {
suffix = String ( library . Properties . Target . Product . Suffix )
2019-08-16 23:22:10 +02:00
}
if suffix == "" {
suffix = String ( library . Properties . Suffix )
}
2019-10-30 10:43:49 +01:00
return name + suffix
}
2020-11-20 18:42:07 +01:00
// getLibName returns the actual canonical name of the library (the name which
// should be passed to the linker via linker flags).
2019-10-30 10:43:49 +01:00
func ( library * libraryDecorator ) getLibName ( ctx BaseModuleContext ) string {
2020-10-29 10:24:11 +01:00
name := library . getLibNameHelper ( ctx . baseModuleName ( ) , ctx . inVendor ( ) , ctx . inProduct ( ) )
2019-08-16 23:22:10 +02:00
2016-07-29 21:48:20 +02:00
if ctx . Host ( ) && Bool ( library . Properties . Unique_host_soname ) {
if ! strings . HasSuffix ( name , "-host" ) {
name = name + "-host"
}
}
2019-07-04 07:38:27 +02:00
return name
2016-07-29 21:48:20 +02:00
}
2018-11-02 10:23:15 +01:00
var versioningMacroNamesListMutex sync . Mutex
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) linkerInit ( ctx BaseModuleContext ) {
location := InstallInSystem
2018-07-26 23:00:24 +02:00
if library . baseLinker . sanitize . inSanitizerDir ( ) {
2017-03-30 07:00:18 +02:00
location = InstallInSanitizerDir
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
library . baseInstaller . location = location
library . baseLinker . linkerInit ( ctx )
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
// Let baseLinker know whether this variant is for stubs or not, so that
// it can omit things that are not required for linking stubs.
library . baseLinker . dynamicProperties . BuildStubs = library . buildStubs ( )
2018-11-02 10:23:15 +01:00
if library . buildStubs ( ) {
macroNames := versioningMacroNamesList ( ctx . Config ( ) )
myName := versioningMacroName ( ctx . ModuleName ( ) )
versioningMacroNamesListMutex . Lock ( )
defer versioningMacroNamesListMutex . Unlock ( )
if ( * macroNames ) [ myName ] == "" {
( * macroNames ) [ myName ] = ctx . ModuleName ( )
} else if ( * macroNames ) [ myName ] != ctx . ModuleName ( ) {
ctx . ModuleErrorf ( "Macro name %q for versioning conflicts with macro name from module %q " , myName , ( * macroNames ) [ myName ] )
}
}
2016-07-29 21:48:20 +02:00
}
2018-12-05 16:28:14 +01:00
func ( library * libraryDecorator ) compilerDeps ( ctx DepsContext , deps Deps ) Deps {
2020-12-17 01:46:01 +01:00
if ctx . IsLlndk ( ) {
// LLNDK libraries ignore most of the properties on the cc_library and use the
// LLNDK-specific properties instead.
return deps
}
2018-12-05 16:28:14 +01:00
deps = library . baseCompiler . compilerDeps ( ctx , deps )
return deps
}
2016-12-14 02:06:13 +01:00
func ( library * libraryDecorator ) linkerDeps ( ctx DepsContext , deps Deps ) Deps {
2020-12-17 01:46:01 +01:00
if ctx . IsLlndk ( ) {
// LLNDK libraries ignore most of the properties on the cc_library and use the
// LLNDK-specific properties instead.
2021-03-02 20:00:07 +01:00
deps . HeaderLibs = append ( [ ] string ( nil ) , library . Properties . Llndk . Export_llndk_headers ... )
deps . ReexportHeaderLibHeaders = append ( [ ] string ( nil ) , library . Properties . Llndk . Export_llndk_headers ... )
2020-12-17 01:46:01 +01:00
return deps
}
2021-04-27 22:06:04 +02:00
if ctx . IsVendorPublicLibrary ( ) {
headers := library . Properties . Vendor_public_library . Export_public_headers
deps . HeaderLibs = append ( [ ] string ( nil ) , headers ... )
deps . ReexportHeaderLibHeaders = append ( [ ] string ( nil ) , headers ... )
return deps
}
2020-12-17 01:46:01 +01:00
2018-12-04 00:25:46 +01:00
if library . static ( ) {
2020-03-24 02:19:52 +01:00
// Compare with nil because an empty list needs to be propagated.
2019-09-24 23:55:04 +02:00
if library . StaticProperties . Static . System_shared_libs != nil {
library . baseLinker . Properties . System_shared_libs = library . StaticProperties . Static . System_shared_libs
2018-12-04 00:25:46 +01:00
}
} else if library . shared ( ) {
2020-03-24 02:19:52 +01:00
// Compare with nil because an empty list needs to be propagated.
2019-09-24 23:55:04 +02:00
if library . SharedProperties . Shared . System_shared_libs != nil {
library . baseLinker . Properties . System_shared_libs = library . SharedProperties . Shared . System_shared_libs
2018-12-04 00:25:46 +01:00
}
}
2016-08-01 22:20:05 +02:00
deps = library . baseLinker . linkerDeps ( ctx , deps )
2016-07-30 02:28:03 +02:00
2016-07-29 21:48:20 +02:00
if library . static ( ) {
2016-07-30 02:28:03 +02:00
deps . WholeStaticLibs = append ( deps . WholeStaticLibs ,
2019-09-24 23:55:04 +02:00
library . StaticProperties . Static . Whole_static_libs ... )
deps . StaticLibs = append ( deps . StaticLibs , library . StaticProperties . Static . Static_libs ... )
deps . SharedLibs = append ( deps . SharedLibs , library . StaticProperties . Static . Shared_libs ... )
2019-01-22 23:41:08 +01:00
2019-09-24 23:55:04 +02:00
deps . ReexportSharedLibHeaders = append ( deps . ReexportSharedLibHeaders , library . StaticProperties . Static . Export_shared_lib_headers ... )
deps . ReexportStaticLibHeaders = append ( deps . ReexportStaticLibHeaders , library . StaticProperties . Static . Export_static_lib_headers ... )
2017-02-15 00:28:44 +01:00
} else if library . shared ( ) {
2023-01-30 23:53:04 +01:00
if library . baseLinker . Properties . crt ( ) {
2021-06-22 02:34:47 +02:00
deps . CrtBegin = append ( deps . CrtBegin , ctx . toolchain ( ) . CrtBeginSharedLibrary ( ) ... )
deps . CrtEnd = append ( deps . CrtEnd , ctx . toolchain ( ) . CrtEndSharedLibrary ( ) ... )
2024-01-29 22:01:51 +01:00
}
if library . baseLinker . Properties . crtPadSegment ( ) {
deps . CrtEnd = append ( deps . CrtEnd , ctx . toolchain ( ) . CrtPadSegmentSharedLibrary ( ) ... )
2016-07-29 21:48:20 +02:00
}
2019-09-24 23:55:04 +02:00
deps . WholeStaticLibs = append ( deps . WholeStaticLibs , library . SharedProperties . Shared . Whole_static_libs ... )
deps . StaticLibs = append ( deps . StaticLibs , library . SharedProperties . Shared . Static_libs ... )
deps . SharedLibs = append ( deps . SharedLibs , library . SharedProperties . Shared . Shared_libs ... )
2019-01-22 23:41:08 +01:00
2019-09-24 23:55:04 +02:00
deps . ReexportSharedLibHeaders = append ( deps . ReexportSharedLibHeaders , library . SharedProperties . Shared . Export_shared_lib_headers ... )
deps . ReexportStaticLibHeaders = append ( deps . ReexportStaticLibHeaders , library . SharedProperties . Shared . Export_static_lib_headers ... )
2024-03-27 09:31:16 +01:00
deps . LlndkHeaderLibs = append ( deps . LlndkHeaderLibs , library . Properties . Llndk . Export_llndk_headers ... )
2016-07-29 21:48:20 +02:00
}
2020-10-29 10:24:11 +01:00
if ctx . inVendor ( ) {
2017-10-13 02:17:01 +02:00
deps . WholeStaticLibs = removeListFromList ( deps . WholeStaticLibs , library . baseLinker . Properties . Target . Vendor . Exclude_static_libs )
deps . SharedLibs = removeListFromList ( deps . SharedLibs , library . baseLinker . Properties . Target . Vendor . Exclude_shared_libs )
deps . StaticLibs = removeListFromList ( deps . StaticLibs , library . baseLinker . Properties . Target . Vendor . Exclude_static_libs )
2019-01-30 17:02:22 +01:00
deps . ReexportSharedLibHeaders = removeListFromList ( deps . ReexportSharedLibHeaders , library . baseLinker . Properties . Target . Vendor . Exclude_shared_libs )
deps . ReexportStaticLibHeaders = removeListFromList ( deps . ReexportStaticLibHeaders , library . baseLinker . Properties . Target . Vendor . Exclude_static_libs )
2017-10-13 02:17:01 +02:00
}
2020-10-29 10:24:11 +01:00
if ctx . inProduct ( ) {
deps . WholeStaticLibs = removeListFromList ( deps . WholeStaticLibs , library . baseLinker . Properties . Target . Product . Exclude_static_libs )
deps . SharedLibs = removeListFromList ( deps . SharedLibs , library . baseLinker . Properties . Target . Product . Exclude_shared_libs )
deps . StaticLibs = removeListFromList ( deps . StaticLibs , library . baseLinker . Properties . Target . Product . Exclude_static_libs )
deps . ReexportSharedLibHeaders = removeListFromList ( deps . ReexportSharedLibHeaders , library . baseLinker . Properties . Target . Product . Exclude_shared_libs )
deps . ReexportStaticLibHeaders = removeListFromList ( deps . ReexportStaticLibHeaders , library . baseLinker . Properties . Target . Product . Exclude_static_libs )
}
2018-01-31 16:54:12 +01:00
if ctx . inRecovery ( ) {
deps . WholeStaticLibs = removeListFromList ( deps . WholeStaticLibs , library . baseLinker . Properties . Target . Recovery . Exclude_static_libs )
deps . SharedLibs = removeListFromList ( deps . SharedLibs , library . baseLinker . Properties . Target . Recovery . Exclude_shared_libs )
deps . StaticLibs = removeListFromList ( deps . StaticLibs , library . baseLinker . Properties . Target . Recovery . Exclude_static_libs )
2019-01-30 17:02:22 +01:00
deps . ReexportSharedLibHeaders = removeListFromList ( deps . ReexportSharedLibHeaders , library . baseLinker . Properties . Target . Recovery . Exclude_shared_libs )
deps . ReexportStaticLibHeaders = removeListFromList ( deps . ReexportStaticLibHeaders , library . baseLinker . Properties . Target . Recovery . Exclude_static_libs )
2018-01-31 16:54:12 +01:00
}
2020-01-22 02:04:13 +01:00
if ctx . inRamdisk ( ) {
deps . WholeStaticLibs = removeListFromList ( deps . WholeStaticLibs , library . baseLinker . Properties . Target . Ramdisk . Exclude_static_libs )
deps . SharedLibs = removeListFromList ( deps . SharedLibs , library . baseLinker . Properties . Target . Ramdisk . Exclude_shared_libs )
deps . StaticLibs = removeListFromList ( deps . StaticLibs , library . baseLinker . Properties . Target . Ramdisk . Exclude_static_libs )
deps . ReexportSharedLibHeaders = removeListFromList ( deps . ReexportSharedLibHeaders , library . baseLinker . Properties . Target . Ramdisk . Exclude_shared_libs )
deps . ReexportStaticLibHeaders = removeListFromList ( deps . ReexportStaticLibHeaders , library . baseLinker . Properties . Target . Ramdisk . Exclude_static_libs )
}
2020-10-27 23:01:21 +01:00
if ctx . inVendorRamdisk ( ) {
deps . WholeStaticLibs = removeListFromList ( deps . WholeStaticLibs , library . baseLinker . Properties . Target . Vendor_ramdisk . Exclude_static_libs )
deps . SharedLibs = removeListFromList ( deps . SharedLibs , library . baseLinker . Properties . Target . Vendor_ramdisk . Exclude_shared_libs )
deps . StaticLibs = removeListFromList ( deps . StaticLibs , library . baseLinker . Properties . Target . Vendor_ramdisk . Exclude_static_libs )
deps . ReexportSharedLibHeaders = removeListFromList ( deps . ReexportSharedLibHeaders , library . baseLinker . Properties . Target . Vendor_ramdisk . Exclude_shared_libs )
deps . ReexportStaticLibHeaders = removeListFromList ( deps . ReexportStaticLibHeaders , library . baseLinker . Properties . Target . Vendor_ramdisk . Exclude_static_libs )
}
2018-02-06 23:40:13 +01:00
2016-07-29 21:48:20 +02:00
return deps
}
2020-03-06 13:30:43 +01:00
func ( library * libraryDecorator ) linkerSpecifiedDeps ( specifiedDeps specifiedDeps ) specifiedDeps {
specifiedDeps = library . baseLinker . linkerSpecifiedDeps ( specifiedDeps )
var properties StaticOrSharedProperties
if library . static ( ) {
properties = library . StaticProperties . Static
} else if library . shared ( ) {
properties = library . SharedProperties . Shared
}
specifiedDeps . sharedLibs = append ( specifiedDeps . sharedLibs , properties . Shared_libs ... )
2020-03-24 02:19:52 +01:00
// Must distinguish nil and [] in system_shared_libs - ensure that [] in
// either input list doesn't come out as nil.
if specifiedDeps . systemSharedLibs == nil {
specifiedDeps . systemSharedLibs = properties . System_shared_libs
} else {
specifiedDeps . systemSharedLibs = append ( specifiedDeps . systemSharedLibs , properties . System_shared_libs ... )
}
2020-03-06 13:30:43 +01:00
specifiedDeps . sharedLibs = android . FirstUniqueStrings ( specifiedDeps . sharedLibs )
2020-03-24 02:19:52 +01:00
if len ( specifiedDeps . systemSharedLibs ) > 0 {
// Skip this if systemSharedLibs is either nil or [], to ensure they are
// retained.
specifiedDeps . systemSharedLibs = android . FirstUniqueStrings ( specifiedDeps . systemSharedLibs )
}
2020-03-06 13:30:43 +01:00
return specifiedDeps
}
2023-12-19 00:29:41 +01:00
func ( library * libraryDecorator ) moduleInfoJSON ( ctx ModuleContext , moduleInfoJSON * android . ModuleInfoJSON ) {
if library . static ( ) {
moduleInfoJSON . Class = [ ] string { "STATIC_LIBRARIES" }
moduleInfoJSON . Uninstallable = true
} else if library . shared ( ) {
moduleInfoJSON . Class = [ ] string { "SHARED_LIBRARIES" }
} else if library . header ( ) {
moduleInfoJSON . Class = [ ] string { "HEADER_LIBRARIES" }
moduleInfoJSON . Uninstallable = true
}
if library . buildStubs ( ) && library . stubsVersion ( ) != "" {
moduleInfoJSON . SubName += "." + library . stubsVersion ( )
}
// If a library providing a stub is included in an APEX, the private APIs of the library
// is accessible only inside the APEX. From outside of the APEX, clients can only use the
// public APIs via the stub. To enforce this, the (latest version of the) stub gets the
// name of the library. The impl library instead gets the `.bootstrap` suffix to so that
// they can be exceptionally used directly when APEXes are not available (e.g. during the
// very early stage in the boot process).
if len ( library . Properties . Stubs . Versions ) > 0 && ! ctx . Host ( ) && ctx . notInPlatform ( ) &&
! ctx . inRamdisk ( ) && ! ctx . inVendorRamdisk ( ) && ! ctx . inRecovery ( ) && ! ctx . useVndk ( ) && ! ctx . static ( ) {
if library . buildStubs ( ) && library . isLatestStubVersion ( ) {
moduleInfoJSON . SubName = ""
}
if ! library . buildStubs ( ) {
moduleInfoJSON . SubName = ".bootstrap"
}
}
library . baseLinker . moduleInfoJSON ( ctx , moduleInfoJSON )
}
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) linkStatic ( ctx ModuleContext ,
2016-09-27 02:33:01 +02:00
flags Flags , deps PathDeps , objs Objects ) android . Path {
2016-07-29 21:48:20 +02:00
2016-09-27 02:33:01 +02:00
library . objects = deps . WholeStaticLibObjs . Copy ( )
library . objects = library . objects . Append ( objs )
2022-02-11 22:11:55 +01:00
library . wholeStaticLibsFromPrebuilts = android . CopyOfPaths ( deps . WholeStaticLibsFromPrebuilts )
2016-07-29 21:48:20 +02:00
2019-07-04 07:38:27 +02:00
fileName := ctx . ModuleName ( ) + staticLibraryExtension
2018-02-15 23:12:26 +01:00
outputFile := android . PathForModuleOut ( ctx , fileName )
2017-02-10 01:16:31 +01:00
builderFlags := flagsToBuilderFlags ( flags )
2016-07-29 21:48:20 +02:00
2018-11-19 18:33:29 +01:00
if Bool ( library . baseLinker . Properties . Use_version_lib ) {
if ctx . Host ( ) {
versionedOutputFile := outputFile
outputFile = android . PathForModuleOut ( ctx , "unversioned" , fileName )
library . injectVersionSymbol ( ctx , outputFile , versionedOutputFile )
} else {
versionedOutputFile := android . PathForModuleOut ( ctx , "versioned" , fileName )
2020-06-15 07:24:19 +02:00
library . distFile = versionedOutputFile
2018-11-19 18:33:29 +01:00
library . injectVersionSymbol ( ctx , outputFile , versionedOutputFile )
}
2018-02-15 23:12:26 +01:00
}
2022-01-09 04:56:09 +01:00
transformObjToStaticLib ( ctx , library . objects . objFiles , deps . WholeStaticLibsFromPrebuilts , builderFlags , outputFile , nil , objs . tidyDepFiles )
2017-02-10 01:16:31 +01:00
2020-11-23 23:02:44 +01:00
library . coverageOutputFile = transformCoverageFilesToZip ( ctx , library . objects , ctx . ModuleName ( ) )
2016-07-29 21:48:20 +02:00
ctx . CheckbuildFile ( outputFile )
2020-12-10 21:30:21 +01:00
if library . static ( ) {
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , StaticLibraryInfoProvider , StaticLibraryInfo {
2022-02-11 22:11:55 +01:00
StaticLibrary : outputFile ,
ReuseObjects : library . reuseObjects ,
Objects : library . objects ,
WholeStaticLibsFromPrebuilts : library . wholeStaticLibsFromPrebuilts ,
2020-12-10 21:30:21 +01:00
2022-04-21 21:50:51 +02:00
TransitiveStaticLibrariesForOrdering : android . NewDepSetBuilder [ android . Path ] ( android . TOPOLOGICAL ) .
2020-12-10 21:30:21 +01:00
Direct ( outputFile ) .
Transitive ( deps . TranstiveStaticLibrariesForOrdering ) .
Build ( ) ,
} )
}
if library . header ( ) {
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , HeaderLibraryInfoProvider , HeaderLibraryInfo { } )
2020-12-10 21:30:21 +01:00
}
2020-09-18 23:15:30 +02:00
2016-07-29 21:48:20 +02:00
return outputFile
}
2021-12-06 03:02:50 +01:00
func ndkSharedLibDeps ( ctx ModuleContext ) android . Paths {
if ctx . Module ( ) . ( * Module ) . IsSdkVariant ( ) {
// The NDK sysroot timestamp file depends on all the NDK
// sysroot header and shared library files.
return android . Paths { getNdkBaseTimestampFile ( ctx ) }
}
return nil
}
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) linkShared ( ctx ModuleContext ,
2016-09-27 02:33:01 +02:00
flags Flags , deps PathDeps , objs Objects ) android . Path {
2016-07-29 21:48:20 +02:00
var linkerDeps android . Paths
2017-09-01 08:38:27 +02:00
linkerDeps = append ( linkerDeps , flags . LdFlagsDeps ... )
2021-12-06 03:02:50 +01:00
linkerDeps = append ( linkerDeps , ndkSharedLibDeps ( ctx ) ... )
2016-07-29 21:48:20 +02:00
2018-02-06 23:40:13 +01:00
unexportedSymbols := ctx . ExpandOptionalSource ( library . Properties . Unexported_symbols_list , "unexported_symbols_list" )
forceNotWeakSymbols := ctx . ExpandOptionalSource ( library . Properties . Force_symbols_not_weak_list , "force_symbols_not_weak_list" )
forceWeakSymbols := ctx . ExpandOptionalSource ( library . Properties . Force_symbols_weak_list , "force_symbols_weak_list" )
2016-07-29 21:48:20 +02:00
if ! ctx . Darwin ( ) {
if unexportedSymbols . Valid ( ) {
ctx . PropertyErrorf ( "unexported_symbols_list" , "Only supported on Darwin" )
}
if forceNotWeakSymbols . Valid ( ) {
ctx . PropertyErrorf ( "force_symbols_not_weak_list" , "Only supported on Darwin" )
}
if forceWeakSymbols . Valid ( ) {
ctx . PropertyErrorf ( "force_symbols_weak_list" , "Only supported on Darwin" )
}
} else {
if unexportedSymbols . Valid ( ) {
2019-11-04 18:37:55 +01:00
flags . Local . LdFlags = append ( flags . Local . LdFlags , "-Wl,-unexported_symbols_list," + unexportedSymbols . String ( ) )
2016-07-29 21:48:20 +02:00
linkerDeps = append ( linkerDeps , unexportedSymbols . Path ( ) )
}
if forceNotWeakSymbols . Valid ( ) {
2019-11-04 18:37:55 +01:00
flags . Local . LdFlags = append ( flags . Local . LdFlags , "-Wl,-force_symbols_not_weak_list," + forceNotWeakSymbols . String ( ) )
2016-07-29 21:48:20 +02:00
linkerDeps = append ( linkerDeps , forceNotWeakSymbols . Path ( ) )
}
if forceWeakSymbols . Valid ( ) {
2019-11-04 18:37:55 +01:00
flags . Local . LdFlags = append ( flags . Local . LdFlags , "-Wl,-force_symbols_weak_list," + forceWeakSymbols . String ( ) )
2016-07-29 21:48:20 +02:00
linkerDeps = append ( linkerDeps , forceWeakSymbols . Path ( ) )
}
}
2020-09-29 03:28:02 +02:00
if library . versionScriptPath . Valid ( ) {
2019-01-12 05:39:10 +01:00
linkerScriptFlags := "-Wl,--version-script," + library . versionScriptPath . String ( )
2019-11-04 18:37:55 +01:00
flags . Local . LdFlags = append ( flags . Local . LdFlags , linkerScriptFlags )
2020-09-29 03:28:02 +02:00
linkerDeps = append ( linkerDeps , library . versionScriptPath . Path ( ) )
2019-01-12 05:39:10 +01:00
}
2016-07-29 21:48:20 +02:00
fileName := library . getLibName ( ctx ) + flags . Toolchain . ShlibSuffix ( )
outputFile := android . PathForModuleOut ( ctx , fileName )
2020-09-18 23:15:30 +02:00
unstrippedOutputFile := outputFile
2016-07-29 21:48:20 +02:00
2019-06-08 02:58:59 +02:00
var implicitOutputs android . WritablePaths
if ctx . Windows ( ) {
importLibraryPath := android . PathForModuleOut ( ctx , pathtools . ReplaceExtension ( fileName , "lib" ) )
2019-11-04 18:37:55 +01:00
flags . Local . LdFlags = append ( flags . Local . LdFlags , "-Wl,--out-implib=" + importLibraryPath . String ( ) )
2019-06-08 02:58:59 +02:00
implicitOutputs = append ( implicitOutputs , importLibraryPath )
}
2016-07-29 21:48:20 +02:00
builderFlags := flagsToBuilderFlags ( flags )
2021-10-20 05:24:49 +02:00
if ctx . Darwin ( ) && deps . DarwinSecondArchOutput . Valid ( ) {
fatOutputFile := outputFile
outputFile = android . PathForModuleOut ( ctx , "pre-fat" , fileName )
transformDarwinUniversalBinary ( ctx , fatOutputFile , outputFile , deps . DarwinSecondArchOutput . Path ( ) )
}
2018-09-11 01:50:05 +02:00
// Optimize out relinking against shared libraries whose interface hasn't changed by
// depending on a table of contents file instead of the library itself.
2019-10-02 07:05:35 +02:00
tocFile := outputFile . ReplaceExtension ( ctx , flags . Toolchain . ShlibSuffix ( ) [ 1 : ] + ".toc" )
2018-09-11 01:50:05 +02:00
library . tocFile = android . OptionalPathForPath ( tocFile )
2021-11-03 20:30:18 +01:00
TransformSharedObjectToToc ( ctx , outputFile , tocFile )
2016-09-15 00:04:48 +02:00
2020-08-19 14:53:01 +02:00
stripFlags := flagsToStripFlags ( flags )
2020-12-15 02:01:55 +01:00
needsStrip := library . stripper . NeedsStrip ( ctx )
if library . buildStubs ( ) {
// No need to strip stubs libraries
needsStrip = false
}
if needsStrip {
2018-11-08 01:28:49 +01:00
if ctx . Darwin ( ) {
2020-08-19 14:53:01 +02:00
stripFlags . StripUseGnuStrip = true
2018-11-08 01:28:49 +01:00
}
2016-07-29 21:48:20 +02:00
strippedOutputFile := outputFile
outputFile = android . PathForModuleOut ( ctx , "unstripped" , fileName )
2020-08-19 14:53:01 +02:00
library . stripper . StripExecutableOrSharedLib ( ctx , outputFile , strippedOutputFile , stripFlags )
2016-07-29 21:48:20 +02:00
}
2018-09-05 01:28:17 +02:00
library . unstrippedOutputFile = outputFile
2019-09-05 23:26:33 +02:00
outputFile = maybeInjectBoringSSLHash ( ctx , outputFile , library . Properties . Inject_bssl_hash , fileName )
2019-08-06 23:19:59 +02:00
2018-11-19 18:33:29 +01:00
if Bool ( library . baseLinker . Properties . Use_version_lib ) {
if ctx . Host ( ) {
versionedOutputFile := outputFile
outputFile = android . PathForModuleOut ( ctx , "unversioned" , fileName )
library . injectVersionSymbol ( ctx , outputFile , versionedOutputFile )
} else {
versionedOutputFile := android . PathForModuleOut ( ctx , "versioned" , fileName )
2020-06-15 07:24:19 +02:00
library . distFile = versionedOutputFile
2018-11-19 18:33:29 +01:00
2020-08-19 14:53:01 +02:00
if library . stripper . NeedsStrip ( ctx ) {
2018-11-19 18:33:29 +01:00
out := android . PathForModuleOut ( ctx , "versioned-stripped" , fileName )
2020-06-15 07:24:19 +02:00
library . distFile = out
2020-08-19 14:53:01 +02:00
library . stripper . StripExecutableOrSharedLib ( ctx , versionedOutputFile , out , stripFlags )
2018-11-19 18:33:29 +01:00
}
library . injectVersionSymbol ( ctx , outputFile , versionedOutputFile )
}
2018-02-15 23:12:26 +01:00
}
2023-12-12 00:40:29 +01:00
// Generate an output file for dist as if strip: "all" is set on the module.
// Currently this is for layoutlib release process only.
for _ , dist := range ctx . Module ( ) . ( * Module ) . Dists ( ) {
if dist . Tag != nil && * dist . Tag == "stripped_all" {
strippedAllOutputFile := android . PathForModuleOut ( ctx , "stripped_all" , fileName )
transformStrip ( ctx , outputFile , strippedAllOutputFile , StripFlags { Toolchain : flags . Toolchain } )
library . strippedAllOutputFile = strippedAllOutputFile
break
}
}
2019-01-18 06:37:08 +01:00
sharedLibs := deps . EarlySharedLibs
sharedLibs = append ( sharedLibs , deps . SharedLibs ... )
2016-07-29 21:48:20 +02:00
sharedLibs = append ( sharedLibs , deps . LateSharedLibs ... )
2019-01-18 06:37:08 +01:00
linkerDeps = append ( linkerDeps , deps . EarlySharedLibsDeps ... )
2016-10-01 02:10:16 +02:00
linkerDeps = append ( linkerDeps , deps . SharedLibsDeps ... )
linkerDeps = append ( linkerDeps , deps . LateSharedLibsDeps ... )
2024-05-14 03:03:34 +02:00
if generatedLib := generateRustStaticlib ( ctx , deps . RustRlibDeps ) ; generatedLib != nil {
deps . StaticLibs = append ( deps . StaticLibs , generatedLib )
}
2020-11-23 23:02:44 +01:00
transformObjToDynamicBinary ( ctx , objs . objFiles , sharedLibs ,
2024-05-14 03:03:34 +02:00
deps . StaticLibs , deps . LateStaticLibs , deps . WholeStaticLibs , linkerDeps , deps . CrtBegin ,
deps . CrtEnd , false , builderFlags , outputFile , implicitOutputs , objs . tidyDepFiles )
2016-07-29 21:48:20 +02:00
2017-02-10 01:16:31 +01:00
objs . coverageFiles = append ( objs . coverageFiles , deps . StaticLibObjs . coverageFiles ... )
objs . coverageFiles = append ( objs . coverageFiles , deps . WholeStaticLibObjs . coverageFiles ... )
2017-02-08 22:45:53 +01:00
objs . sAbiDumpFiles = append ( objs . sAbiDumpFiles , deps . StaticLibObjs . sAbiDumpFiles ... )
objs . sAbiDumpFiles = append ( objs . sAbiDumpFiles , deps . WholeStaticLibObjs . sAbiDumpFiles ... )
2020-11-23 23:02:44 +01:00
library . coverageOutputFile = transformCoverageFilesToZip ( ctx , objs , library . getLibName ( ctx ) )
2024-03-29 12:12:35 +01:00
library . linkSAbiDumpFiles ( ctx , deps , objs , fileName , unstrippedOutputFile )
2020-09-18 23:15:30 +02:00
2022-04-21 21:50:51 +02:00
var transitiveStaticLibrariesForOrdering * android . DepSet [ android . Path ]
2020-09-18 23:15:30 +02:00
if static := ctx . GetDirectDepsWithTag ( staticVariantTag ) ; len ( static ) > 0 {
2023-12-13 22:47:44 +01:00
s , _ := android . OtherModuleProvider ( ctx , static [ 0 ] , StaticLibraryInfoProvider )
2021-06-08 21:37:09 +02:00
transitiveStaticLibrariesForOrdering = s . TransitiveStaticLibrariesForOrdering
2020-09-18 23:15:30 +02:00
}
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , SharedLibraryInfoProvider , SharedLibraryInfo {
2021-06-08 21:37:09 +02:00
TableOfContents : android . OptionalPathForPath ( tocFile ) ,
SharedLibrary : unstrippedOutputFile ,
TransitiveStaticLibrariesForOrdering : transitiveStaticLibrariesForOrdering ,
Target : ctx . Target ( ) ,
2020-09-18 23:15:30 +02:00
} )
2023-04-20 15:13:25 +02:00
addStubDependencyProviders ( ctx )
return unstrippedOutputFile
}
func addStubDependencyProviders ( ctx ModuleContext ) {
2020-09-18 23:15:30 +02:00
stubs := ctx . GetDirectDepsWithTag ( stubImplDepTag )
if len ( stubs ) > 0 {
2020-11-20 18:42:07 +01:00
var stubsInfo [ ] SharedStubLibrary
2020-09-18 23:15:30 +02:00
for _ , stub := range stubs {
2023-12-13 22:47:44 +01:00
stubInfo , _ := android . OtherModuleProvider ( ctx , stub , SharedLibraryInfoProvider )
flagInfo , _ := android . OtherModuleProvider ( ctx , stub , FlagExporterInfoProvider )
2020-11-20 18:42:07 +01:00
stubsInfo = append ( stubsInfo , SharedStubLibrary {
2020-10-24 02:22:06 +02:00
Version : moduleLibraryInterface ( stub ) . stubsVersion ( ) ,
2020-09-18 23:15:30 +02:00
SharedLibraryInfo : stubInfo ,
FlagExporterInfo : flagInfo ,
} )
}
2023-12-14 00:19:49 +01:00
android . SetProvider ( ctx , SharedLibraryStubsProvider , SharedLibraryStubsInfo {
2020-11-20 18:42:07 +01:00
SharedStubLibraries : stubsInfo ,
2023-04-20 15:13:25 +02:00
IsLLNDK : ctx . IsLlndk ( ) ,
2020-09-18 23:15:30 +02:00
} )
}
2016-07-29 21:48:20 +02:00
}
2019-01-31 04:21:23 +01:00
func ( library * libraryDecorator ) unstrippedOutputFilePath ( ) android . Path {
return library . unstrippedOutputFile
}
2023-12-12 00:40:29 +01:00
func ( library * libraryDecorator ) strippedAllOutputFilePath ( ) android . Path {
return library . strippedAllOutputFile
}
2020-08-19 14:53:01 +02:00
func ( library * libraryDecorator ) disableStripping ( ) {
library . stripper . StripProperties . Strip . None = BoolPtr ( true )
}
2019-03-25 18:21:31 +01:00
func ( library * libraryDecorator ) nativeCoverage ( ) bool {
if library . header ( ) || library . buildStubs ( ) {
return false
}
return true
}
2019-08-09 07:44:36 +02:00
func ( library * libraryDecorator ) coverageOutputFilePath ( ) android . OptionalPath {
return library . coverageOutputFile
}
2024-03-29 13:10:36 +01:00
func ( library * libraryDecorator ) exportedIncludeDirsForAbiCheck ( ctx ModuleContext ) [ ] string {
exportIncludeDirs := library . flagExporter . exportedIncludes ( ctx ) . Strings ( )
exportIncludeDirs = append ( exportIncludeDirs , library . sabi . Properties . ReexportedIncludes ... )
2024-04-02 06:38:47 +02:00
exportSystemIncludeDirs := library . flagExporter . exportedSystemIncludes ( ctx ) . Strings ( )
exportSystemIncludeDirs = append ( exportSystemIncludeDirs , library . sabi . Properties . ReexportedSystemIncludes ... )
// The ABI checker does not distinguish normal and system headers.
return append ( exportIncludeDirs , exportSystemIncludeDirs ... )
2024-03-29 13:10:36 +01:00
}
2024-03-29 12:12:35 +01:00
func ( library * libraryDecorator ) llndkIncludeDirsForAbiCheck ( ctx ModuleContext , deps PathDeps ) [ ] string {
2024-04-02 06:38:47 +02:00
var includeDirs , systemIncludeDirs [ ] string
2024-03-29 12:12:35 +01:00
// The ABI checker does not need the preprocess which adds macro guards to function declarations.
2024-04-02 06:38:47 +02:00
preprocessedDirs := android . PathsForModuleSrc ( ctx , library . Properties . Llndk . Export_preprocessed_headers ) . Strings ( )
if Bool ( library . Properties . Llndk . Export_headers_as_system ) {
systemIncludeDirs = append ( systemIncludeDirs , preprocessedDirs ... )
} else {
includeDirs = append ( includeDirs , preprocessedDirs ... )
}
2024-03-29 12:12:35 +01:00
if library . Properties . Llndk . Override_export_include_dirs != nil {
includeDirs = append ( includeDirs , android . PathsForModuleSrc (
ctx , library . Properties . Llndk . Override_export_include_dirs ) . Strings ( ) ... )
} else {
includeDirs = append ( includeDirs , library . flagExporter . exportedIncludes ( ctx ) . Strings ( ) ... )
// Ignore library.sabi.Properties.ReexportedIncludes because
// LLNDK does not reexport the implementation's dependencies, such as export_header_libs.
}
2024-04-02 06:38:47 +02:00
systemIncludeDirs = append ( systemIncludeDirs ,
library . flagExporter . exportedSystemIncludes ( ctx ) . Strings ( ) ... )
2024-03-29 12:12:35 +01:00
if Bool ( library . Properties . Llndk . Export_headers_as_system ) {
systemIncludeDirs = append ( systemIncludeDirs , includeDirs ... )
includeDirs = nil
}
// Header libs.
includeDirs = append ( includeDirs , deps . LlndkIncludeDirs . Strings ( ) ... )
systemIncludeDirs = append ( systemIncludeDirs , deps . LlndkSystemIncludeDirs . Strings ( ) ... )
// The ABI checker does not distinguish normal and system headers.
return append ( includeDirs , systemIncludeDirs ... )
}
func ( library * libraryDecorator ) linkLlndkSAbiDumpFiles ( ctx ModuleContext ,
deps PathDeps , sAbiDumpFiles android . Paths , soFile android . Path , libFileName string ,
2024-04-15 09:43:21 +02:00
excludeSymbolVersions , excludeSymbolTags [ ] string ,
vendorApiLevel string ) android . Path {
2024-03-29 12:12:35 +01:00
// NDK symbols in version 34 are LLNDK symbols. Those in version 35 are not.
return transformDumpToLinkedDump ( ctx ,
sAbiDumpFiles , soFile , libFileName + ".llndk" ,
library . llndkIncludeDirsForAbiCheck ( ctx , deps ) ,
android . OptionalPathForModuleSrc ( ctx , library . Properties . Llndk . Symbol_file ) ,
append ( [ ] string { "*_PLATFORM" , "*_PRIVATE" } , excludeSymbolVersions ... ) ,
append ( [ ] string { "platform-only" } , excludeSymbolTags ... ) ,
2024-04-15 09:43:21 +02:00
[ ] string { "llndk=" + vendorApiLevel } , "34" , true /* isLlndk */ )
2024-03-29 12:12:35 +01:00
}
2024-04-14 13:08:17 +02:00
func ( library * libraryDecorator ) linkApexSAbiDumpFiles ( ctx ModuleContext ,
deps PathDeps , sAbiDumpFiles android . Paths , soFile android . Path , libFileName string ,
2024-04-15 09:43:21 +02:00
excludeSymbolVersions , excludeSymbolTags [ ] string ,
sdkVersion string ) android . Path {
2024-04-14 13:08:17 +02:00
return transformDumpToLinkedDump ( ctx ,
sAbiDumpFiles , soFile , libFileName + ".apex" ,
library . exportedIncludeDirsForAbiCheck ( ctx ) ,
android . OptionalPathForModuleSrc ( ctx , library . Properties . Stubs . Symbol_file ) ,
append ( [ ] string { "*_PLATFORM" , "*_PRIVATE" } , excludeSymbolVersions ... ) ,
append ( [ ] string { "platform-only" } , excludeSymbolTags ... ) ,
2024-04-15 09:43:21 +02:00
[ ] string { "apex" , "systemapi" } , sdkVersion , false /* isLlndk */ )
2024-04-14 13:08:17 +02:00
}
2022-11-23 07:39:46 +01:00
func getRefAbiDumpFile ( ctx android . ModuleInstallPathContext ,
versionedDumpDir , fileName string ) android . OptionalPath {
2022-08-30 12:37:21 +02:00
currentArchType := ctx . Arch ( ) . ArchType
primaryArchType := ctx . Config ( ) . DevicePrimaryArchType ( )
archName := currentArchType . String ( )
if currentArchType != primaryArchType {
archName += "_" + primaryArchType . String ( )
}
2022-10-27 08:55:42 +02:00
return android . ExistentPathForSource ( ctx , versionedDumpDir , archName , "source-based" ,
2022-11-23 07:39:46 +01:00
fileName + ".lsdump" )
2022-08-30 12:37:21 +02:00
}
2024-02-05 10:37:27 +01:00
// Return the previous and current SDK versions for cross-version ABI diff.
2024-04-14 13:08:17 +02:00
func crossVersionAbiDiffSdkVersions ( ctx ModuleContext , dumpDir string ) ( int , int ) {
2022-07-05 11:49:50 +02:00
sdkVersionInt := ctx . Config ( ) . PlatformSdkVersion ( ) . FinalInt ( )
if ctx . Config ( ) . PlatformSdkFinal ( ) {
2024-04-14 13:08:17 +02:00
return sdkVersionInt - 1 , sdkVersionInt
2022-07-05 11:49:50 +02:00
} else {
// The platform SDK version can be upgraded before finalization while the corresponding abi dumps hasn't
// been generated. Thus the Cross-Version Check chooses PLATFORM_SDK_VERION - 1 as previous version.
// This situation could be identified by checking the existence of the PLATFORM_SDK_VERION dump directory.
2024-04-14 13:08:17 +02:00
versionedDumpDir := android . ExistentPathForSource ( ctx ,
dumpDir , ctx . Config ( ) . PlatformSdkVersion ( ) . String ( ) )
2022-10-27 08:55:42 +02:00
if versionedDumpDir . Valid ( ) {
2024-04-14 13:08:17 +02:00
return sdkVersionInt , sdkVersionInt + 1
2022-07-05 11:49:50 +02:00
} else {
2024-04-14 13:08:17 +02:00
return sdkVersionInt - 1 , sdkVersionInt
2022-07-05 11:49:50 +02:00
}
}
}
2024-02-05 10:37:27 +01:00
// Return the SDK version for same-version ABI diff.
func currRefAbiDumpSdkVersion ( ctx ModuleContext ) string {
2024-01-08 11:38:42 +01:00
if ctx . Config ( ) . PlatformSdkFinal ( ) {
2022-11-10 09:56:27 +01:00
// After sdk finalization, the ABI of the latest API level must be consistent with the source code,
// so choose PLATFORM_SDK_VERSION as the current version.
return ctx . Config ( ) . PlatformSdkVersion ( ) . String ( )
} else {
return "current"
}
}
2022-10-27 08:55:42 +02:00
// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
2024-03-29 13:10:36 +01:00
func ( library * libraryDecorator ) sourceAbiDiff ( ctx android . ModuleContext ,
sourceDump , referenceDump android . Path ,
2024-05-02 09:37:30 +02:00
baseName , nameExt string , isLlndk , allowExtensions bool ,
2022-10-27 08:55:42 +02:00
sourceVersion , errorMessage string ) {
extraFlags := [ ] string { "-target-version" , sourceVersion }
2022-12-26 08:54:36 +01:00
headerAbiChecker := library . getHeaderAbiCheckerProperties ( ctx )
if Bool ( headerAbiChecker . Check_all_apis ) {
2022-10-27 08:55:42 +02:00
extraFlags = append ( extraFlags , "-check-all-apis" )
} else {
extraFlags = append ( extraFlags ,
"-allow-unreferenced-changes" ,
"-allow-unreferenced-elf-symbol-changes" )
}
2024-05-02 09:37:30 +02:00
if isLlndk {
2022-10-27 08:55:42 +02:00
extraFlags = append ( extraFlags , "-consider-opaque-types-different" )
}
if allowExtensions {
extraFlags = append ( extraFlags , "-allow-extensions" )
}
2022-12-26 08:54:36 +01:00
extraFlags = append ( extraFlags , headerAbiChecker . Diff_flags ... )
2022-10-27 08:55:42 +02:00
library . sAbiDiff = append (
library . sAbiDiff ,
transformAbiDumpToAbiDiff ( ctx , sourceDump , referenceDump ,
baseName , nameExt , extraFlags , errorMessage ) )
}
2024-03-29 13:10:36 +01:00
func ( library * libraryDecorator ) crossVersionAbiDiff ( ctx android . ModuleContext ,
sourceDump , referenceDump android . Path ,
2024-02-19 08:15:30 +01:00
baseName , nameExt string , isLlndk bool , sourceVersion , prevDumpDir string ) {
2022-10-27 08:55:42 +02:00
2024-02-19 08:15:30 +01:00
errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/main/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the difference between your source code and the ABI dumps in " + prevDumpDir
2022-10-27 08:55:42 +02:00
2024-02-19 08:15:30 +01:00
library . sourceAbiDiff ( ctx , sourceDump , referenceDump , baseName , nameExt ,
2024-05-02 09:37:30 +02:00
isLlndk , true /* allowExtensions */ , sourceVersion , errorMessage )
2022-10-27 08:55:42 +02:00
}
2024-03-29 13:10:36 +01:00
func ( library * libraryDecorator ) sameVersionAbiDiff ( ctx android . ModuleContext ,
sourceDump , referenceDump android . Path ,
2024-02-19 08:15:30 +01:00
baseName , nameExt string , isLlndk bool , lsdumpTagName string ) {
2022-10-27 08:55:42 +02:00
libName := strings . TrimSuffix ( baseName , filepath . Ext ( baseName ) )
2024-02-19 08:15:30 +01:00
errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py --lib " + libName + " --lib-variant " + lsdumpTagName
targetRelease := ctx . Config ( ) . Getenv ( "TARGET_RELEASE" )
if targetRelease != "" {
errorMessage += " --release " + targetRelease
}
2022-10-27 08:55:42 +02:00
2024-03-29 13:10:36 +01:00
library . sourceAbiDiff ( ctx , sourceDump , referenceDump , baseName , nameExt ,
2024-05-02 09:37:30 +02:00
isLlndk , false /* allowExtensions */ , "current" , errorMessage )
2022-10-27 08:55:42 +02:00
}
2024-03-29 13:10:36 +01:00
func ( library * libraryDecorator ) optInAbiDiff ( ctx android . ModuleContext ,
sourceDump , referenceDump android . Path ,
2024-02-19 08:15:30 +01:00
baseName , nameExt string , refDumpDir string , lsdumpTagName string ) {
2022-11-17 07:29:43 +01:00
libName := strings . TrimSuffix ( baseName , filepath . Ext ( baseName ) )
2024-02-19 08:15:30 +01:00
errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py --lib " + libName + " --lib-variant " + lsdumpTagName + " --ref-dump-dir $$ANDROID_BUILD_TOP/" + refDumpDir
targetRelease := ctx . Config ( ) . Getenv ( "TARGET_RELEASE" )
if targetRelease != "" {
errorMessage += " --release " + targetRelease
}
2023-06-29 10:51:27 +02:00
// Most opt-in libraries do not have dumps for all default architectures.
if ctx . Config ( ) . HasDeviceProduct ( ) {
2024-02-19 08:15:30 +01:00
errorMessage += " --product " + ctx . Config ( ) . DeviceProduct ( )
2023-06-29 10:51:27 +02:00
}
2022-11-17 07:29:43 +01:00
2024-03-29 13:10:36 +01:00
library . sourceAbiDiff ( ctx , sourceDump , referenceDump , baseName , nameExt ,
2024-05-02 09:37:30 +02:00
false /* isLlndk */ , false /* allowExtensions */ , "current" , errorMessage )
2022-11-17 07:29:43 +01:00
}
2024-03-29 12:12:35 +01:00
func ( library * libraryDecorator ) linkSAbiDumpFiles ( ctx ModuleContext , deps PathDeps , objs Objects , fileName string , soFile android . Path ) {
2020-12-14 04:42:16 +01:00
if library . sabi . shouldCreateSourceAbiDump ( ) {
2024-03-29 13:10:36 +01:00
exportedIncludeDirs := library . exportedIncludeDirsForAbiCheck ( ctx )
2022-12-26 08:54:36 +01:00
headerAbiChecker := library . getHeaderAbiCheckerProperties ( ctx )
2024-02-05 10:37:27 +01:00
currSdkVersion := currRefAbiDumpSdkVersion ( ctx )
currVendorVersion := ctx . Config ( ) . VendorApiLevel ( )
2024-03-29 12:12:35 +01:00
// Generate source dumps.
implDump := transformDumpToLinkedDump ( ctx ,
2024-03-29 13:10:36 +01:00
objs . sAbiDumpFiles , soFile , fileName ,
exportedIncludeDirs ,
2019-08-27 07:02:19 +02:00
android . OptionalPathForModuleSrc ( ctx , library . symbolFileForAbiCheck ( ctx ) ) ,
2022-12-26 08:54:36 +01:00
headerAbiChecker . Exclude_symbol_versions ,
2023-09-25 09:26:30 +02:00
headerAbiChecker . Exclude_symbol_tags ,
2024-04-15 09:43:21 +02:00
[ ] string { } /* includeSymbolTags */ , currSdkVersion , false /* isLlndk */ )
2018-07-10 09:01:19 +02:00
2024-04-14 13:08:17 +02:00
var llndkDump , apexVariantDump android . Path
2024-03-29 12:12:35 +01:00
tags := classifySourceAbiDump ( ctx )
2024-02-19 08:15:30 +01:00
optInTags := [ ] lsdumpTag { }
2024-03-29 12:12:35 +01:00
for _ , tag := range tags {
2024-04-15 09:43:21 +02:00
if tag == llndkLsdumpTag && currVendorVersion != "" {
2024-03-29 12:12:35 +01:00
if llndkDump == nil {
// TODO(b/323447559): Evaluate if replacing sAbiDumpFiles with implDump is faster
llndkDump = library . linkLlndkSAbiDumpFiles ( ctx ,
deps , objs . sAbiDumpFiles , soFile , fileName ,
headerAbiChecker . Exclude_symbol_versions ,
2024-04-15 09:43:21 +02:00
headerAbiChecker . Exclude_symbol_tags ,
currVendorVersion )
2024-03-29 12:12:35 +01:00
}
addLsdumpPath ( string ( tag ) + ":" + llndkDump . String ( ) )
2024-04-14 13:08:17 +02:00
} else if tag == apexLsdumpTag {
if apexVariantDump == nil {
apexVariantDump = library . linkApexSAbiDumpFiles ( ctx ,
deps , objs . sAbiDumpFiles , soFile , fileName ,
headerAbiChecker . Exclude_symbol_versions ,
headerAbiChecker . Exclude_symbol_tags ,
currSdkVersion )
}
addLsdumpPath ( string ( tag ) + ":" + apexVariantDump . String ( ) )
2024-03-29 12:12:35 +01:00
} else {
2024-02-19 08:15:30 +01:00
if tag . dirName ( ) == "" {
optInTags = append ( optInTags , tag )
}
2024-03-29 12:12:35 +01:00
addLsdumpPath ( string ( tag ) + ":" + implDump . String ( ) )
}
}
// Diff source dumps and reference dumps.
for _ , tag := range tags {
2024-02-06 08:43:17 +01:00
dumpDirName := tag . dirName ( )
if dumpDirName == "" {
continue
}
dumpDir := filepath . Join ( "prebuilts" , "abi-dumps" , dumpDirName )
isLlndk := ( tag == llndkLsdumpTag )
2024-04-14 13:08:17 +02:00
isApex := ( tag == apexLsdumpTag )
2024-02-06 08:43:17 +01:00
binderBitness := ctx . DeviceConfig ( ) . BinderBitness ( )
nameExt := ""
if isLlndk {
nameExt = "llndk"
2024-04-14 13:08:17 +02:00
} else if isApex {
nameExt = "apex"
2024-02-06 08:43:17 +01:00
}
// Check against the previous version.
2024-02-05 10:37:27 +01:00
var prevVersion , currVersion string
2024-03-29 12:12:35 +01:00
sourceDump := implDump
2024-02-05 10:37:27 +01:00
// If this release config does not define VendorApiLevel, fall back to the old policy.
if isLlndk && currVendorVersion != "" {
prevVersion = ctx . Config ( ) . PrevVendorApiLevel ( )
currVersion = currVendorVersion
2024-03-29 12:12:35 +01:00
// LLNDK dumps are generated by different rules after trunk stable.
if android . IsTrunkStableVendorApiLevel ( prevVersion ) {
sourceDump = llndkDump
}
2024-02-05 10:37:27 +01:00
} else {
2024-04-14 13:08:17 +02:00
prevVersionInt , currVersionInt := crossVersionAbiDiffSdkVersions ( ctx , dumpDir )
prevVersion = strconv . Itoa ( prevVersionInt )
currVersion = strconv . Itoa ( currVersionInt )
// APEX dumps are generated by different rules after trunk stable.
if isApex && prevVersionInt > 34 {
sourceDump = apexVariantDump
}
2024-02-05 10:37:27 +01:00
}
2024-02-06 08:43:17 +01:00
prevDumpDir := filepath . Join ( dumpDir , prevVersion , binderBitness )
prevDumpFile := getRefAbiDumpFile ( ctx , prevDumpDir , fileName )
if prevDumpFile . Valid ( ) {
2024-03-29 13:10:36 +01:00
library . crossVersionAbiDiff ( ctx , sourceDump , prevDumpFile . Path ( ) ,
2024-02-19 08:15:30 +01:00
fileName , nameExt + prevVersion , isLlndk , currVersion , prevDumpDir )
2024-02-06 08:43:17 +01:00
}
// Check against the current version.
2024-03-29 12:12:35 +01:00
sourceDump = implDump
2024-02-05 10:37:27 +01:00
if isLlndk && currVendorVersion != "" {
currVersion = currVendorVersion
2024-03-29 12:12:35 +01:00
if android . IsTrunkStableVendorApiLevel ( currVersion ) {
sourceDump = llndkDump
}
2024-02-05 10:37:27 +01:00
} else {
currVersion = currSdkVersion
2024-04-14 13:08:17 +02:00
if isApex && ( ! ctx . Config ( ) . PlatformSdkFinal ( ) ||
ctx . Config ( ) . PlatformSdkVersion ( ) . FinalInt ( ) > 34 ) {
sourceDump = apexVariantDump
}
2024-02-05 10:37:27 +01:00
}
2024-02-06 08:43:17 +01:00
currDumpDir := filepath . Join ( dumpDir , currVersion , binderBitness )
currDumpFile := getRefAbiDumpFile ( ctx , currDumpDir , fileName )
if currDumpFile . Valid ( ) {
2024-03-29 13:10:36 +01:00
library . sameVersionAbiDiff ( ctx , sourceDump , currDumpFile . Path ( ) ,
2024-02-19 08:15:30 +01:00
fileName , nameExt , isLlndk , string ( tag ) )
2024-02-06 08:43:17 +01:00
}
2017-02-08 22:45:53 +01:00
}
2024-02-19 08:15:30 +01:00
// Assert that a module is tagged with at most one of platformLsdumpTag, productLsdumpTag, or vendorLsdumpTag.
if len ( headerAbiChecker . Ref_dump_dirs ) > 0 && len ( optInTags ) != 1 {
ctx . ModuleErrorf ( "Expect exactly one opt-in lsdump tag when ref_dump_dirs are specified: %s" , optInTags )
return
}
2024-04-22 05:47:57 +02:00
// Ensure that a module tagged with only platformLsdumpTag has ref_dump_dirs.
// Android.bp in vendor projects should be cleaned up before this is enforced for vendorLsdumpTag and productLsdumpTag.
if len ( headerAbiChecker . Ref_dump_dirs ) == 0 && len ( tags ) == 1 && tags [ 0 ] == platformLsdumpTag {
ctx . ModuleErrorf ( "header_abi_checker is explicitly enabled, but no ref_dump_dirs are specified." )
}
2022-11-17 07:29:43 +01:00
// Check against the opt-in reference dumps.
2022-12-26 08:54:36 +01:00
for i , optInDumpDir := range headerAbiChecker . Ref_dump_dirs {
2022-11-17 07:29:43 +01:00
optInDumpDirPath := android . PathForModuleSrc ( ctx , optInDumpDir )
// Ref_dump_dirs are not versioned.
// They do not contain subdir for binder bitness because 64-bit binder has been mandatory.
optInDumpFile := getRefAbiDumpFile ( ctx , optInDumpDirPath . String ( ) , fileName )
if ! optInDumpFile . Valid ( ) {
continue
}
2024-03-29 13:10:36 +01:00
library . optInAbiDiff ( ctx ,
2024-03-29 12:12:35 +01:00
implDump , optInDumpFile . Path ( ) ,
2024-02-19 08:15:30 +01:00
fileName , "opt" + strconv . Itoa ( i ) , optInDumpDirPath . String ( ) , string ( optInTags [ 0 ] ) )
2022-11-17 07:29:43 +01:00
}
2017-02-08 22:45:53 +01:00
}
}
2021-05-14 13:15:55 +02:00
func processLLNDKHeaders ( ctx ModuleContext , srcHeaderDir string , outDir android . ModuleGenPath ) ( timestamp android . Path , installPaths android . WritablePaths ) {
2020-12-17 01:46:01 +01:00
srcDir := android . PathForModuleSrc ( ctx , srcHeaderDir )
srcFiles := ctx . GlobFiles ( filepath . Join ( srcDir . String ( ) , "**/*.h" ) , nil )
for _ , header := range srcFiles {
headerDir := filepath . Dir ( header . String ( ) )
relHeaderDir , err := filepath . Rel ( srcDir . String ( ) , headerDir )
if err != nil {
ctx . ModuleErrorf ( "filepath.Rel(%q, %q) failed: %s" ,
srcDir . String ( ) , headerDir , err )
continue
}
installPaths = append ( installPaths , outDir . Join ( ctx , relHeaderDir , header . Base ( ) ) )
}
2021-05-14 13:15:55 +02:00
return processHeadersWithVersioner ( ctx , srcDir , outDir , srcFiles , installPaths ) , installPaths
2020-12-17 01:46:01 +01:00
}
2020-11-20 18:42:07 +01:00
// link registers actions to link this library, and sets various fields
// on this library to reflect information that should be exported up the build
// tree (for example, exported flags and include paths).
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) link ( ctx ModuleContext ,
2016-09-27 02:33:01 +02:00
flags Flags , deps PathDeps , objs Objects ) android . Path {
2016-07-29 21:48:20 +02:00
2020-12-17 01:46:01 +01:00
if ctx . IsLlndk ( ) {
if len ( library . Properties . Llndk . Export_preprocessed_headers ) > 0 {
// This is the vendor variant of an LLNDK library with preprocessed headers.
genHeaderOutDir := android . PathForModuleGen ( ctx , "include" )
var timestampFiles android . Paths
for _ , dir := range library . Properties . Llndk . Export_preprocessed_headers {
2021-05-14 13:15:55 +02:00
timestampFile , installPaths := processLLNDKHeaders ( ctx , dir , genHeaderOutDir )
timestampFiles = append ( timestampFiles , timestampFile )
library . addExportedGeneratedHeaders ( installPaths . Paths ( ) ... )
2020-12-17 01:46:01 +01:00
}
if Bool ( library . Properties . Llndk . Export_headers_as_system ) {
library . reexportSystemDirs ( genHeaderOutDir )
} else {
library . reexportDirs ( genHeaderOutDir )
}
library . reexportDeps ( timestampFiles ... )
}
2021-03-02 20:00:07 +01:00
// override the module's export_include_dirs with llndk.override_export_include_dirs
// if it is set.
if override := library . Properties . Llndk . Override_export_include_dirs ; override != nil {
library . flagExporter . Properties . Export_include_dirs = override
}
2020-12-17 01:46:01 +01:00
if Bool ( library . Properties . Llndk . Export_headers_as_system ) {
library . flagExporter . Properties . Export_system_include_dirs = append (
library . flagExporter . Properties . Export_system_include_dirs ,
library . flagExporter . Properties . Export_include_dirs ... )
library . flagExporter . Properties . Export_include_dirs = nil
}
}
2021-04-27 22:06:04 +02:00
if ctx . IsVendorPublicLibrary ( ) {
// override the module's export_include_dirs with vendor_public_library.override_export_include_dirs
// if it is set.
if override := library . Properties . Vendor_public_library . Override_export_include_dirs ; override != nil {
library . flagExporter . Properties . Export_include_dirs = override
}
}
2020-11-20 18:42:07 +01:00
// Linking this library consists of linking `deps.Objs` (.o files in dependencies
// of this library), together with `objs` (.o files created by compiling this
// library).
2017-11-16 23:29:11 +01:00
objs = deps . Objs . Copy ( ) . Append ( objs )
2016-07-29 21:48:20 +02:00
var out android . Path
2017-02-15 00:28:44 +01:00
if library . static ( ) || library . header ( ) {
2016-09-27 02:33:01 +02:00
out = library . linkStatic ( ctx , flags , deps , objs )
2016-07-29 21:48:20 +02:00
} else {
2016-09-27 02:33:01 +02:00
out = library . linkShared ( ctx , flags , deps , objs )
2016-07-29 21:48:20 +02:00
}
2020-11-20 18:42:07 +01:00
// Export include paths and flags to be propagated up the tree.
2019-06-03 12:10:47 +02:00
library . exportIncludes ( ctx )
library . reexportDirs ( deps . ReexportedDirs ... )
library . reexportSystemDirs ( deps . ReexportedSystemDirs ... )
library . reexportFlags ( deps . ReexportedFlags ... )
library . reexportDeps ( deps . ReexportedDeps ... )
2019-12-06 05:15:38 +01:00
library . addExportedGeneratedHeaders ( deps . ReexportedGeneratedHeaders ... )
2016-07-29 21:48:20 +02:00
2024-05-14 03:03:34 +02:00
if library . static ( ) && len ( deps . ReexportedRustRlibDeps ) > 0 {
library . reexportRustStaticDeps ( deps . ReexportedRustRlibDeps ... )
}
2020-11-20 18:42:07 +01:00
// Optionally export aidl headers.
2017-11-07 19:57:05 +01:00
if Bool ( library . Properties . Aidl . Export_aidl_headers ) {
2023-04-28 17:21:25 +02:00
if library . baseCompiler . hasAidl ( deps ) {
2023-05-16 22:03:20 +02:00
if library . baseCompiler . hasSrcExt ( ".aidl" ) {
dir := android . PathForModuleGen ( ctx , "aidl" )
library . reexportDirs ( dir )
}
if len ( deps . AidlLibraryInfos ) > 0 {
dir := android . PathForModuleGen ( ctx , "aidl_library" )
library . reexportDirs ( dir )
}
2019-12-06 05:15:38 +01:00
2021-02-19 14:49:08 +01:00
library . reexportDeps ( library . baseCompiler . aidlOrderOnlyDeps ... )
library . addExportedGeneratedHeaders ( library . baseCompiler . aidlHeaders ... )
2016-11-03 22:28:51 +01:00
}
}
2020-11-20 18:42:07 +01:00
// Optionally export proto headers.
2017-11-07 19:57:05 +01:00
if Bool ( library . Properties . Proto . Export_proto_headers ) {
2016-11-03 22:28:51 +01:00
if library . baseCompiler . hasSrcExt ( ".proto" ) {
2019-10-22 13:19:51 +02:00
var includes android . Paths
2019-03-28 22:45:07 +01:00
if flags . proto . CanonicalPathFromRoot {
2019-10-22 13:19:51 +02:00
includes = append ( includes , flags . proto . SubDir )
2017-05-03 20:01:58 +02:00
}
2019-10-22 13:19:51 +02:00
includes = append ( includes , flags . proto . Dir )
2019-06-03 12:10:47 +02:00
library . reexportDirs ( includes ... )
2019-12-06 05:15:38 +01:00
2021-02-19 14:49:08 +01:00
library . reexportDeps ( library . baseCompiler . protoOrderOnlyDeps ... )
library . addExportedGeneratedHeaders ( library . baseCompiler . protoHeaders ... )
2016-10-21 01:11:43 +02:00
}
}
2020-11-23 06:43:02 +01:00
// If the library is sysprop_library, expose either public or internal header selectively.
2018-09-05 17:55:20 +02:00
if library . baseCompiler . hasSrcExt ( ".sysprop" ) {
2019-10-22 13:19:51 +02:00
dir := android . PathForModuleGen ( ctx , "sysprop" , "include" )
2019-02-08 13:00:45 +01:00
if library . Properties . Sysprop . Platform != nil {
isOwnerPlatform := Bool ( library . Properties . Sysprop . Platform )
2020-11-23 06:43:02 +01:00
// If the owner is different from the user, expose public header. That is,
// 1) if the user is product (as owner can only be platform / vendor)
2021-01-18 07:23:28 +01:00
// 2) if the owner is platform and the client is vendor
// We don't care Platform -> Vendor dependency as it's already forbidden.
if ctx . Device ( ) && ( ctx . ProductSpecific ( ) || ( isOwnerPlatform && ctx . inVendor ( ) ) ) {
2019-10-22 13:19:51 +02:00
dir = android . PathForModuleGen ( ctx , "sysprop/public" , "include" )
2019-02-08 13:00:45 +01:00
}
}
2021-02-19 18:05:39 +01:00
// Make sure to only export headers which are within the include directory.
_ , headers := android . FilterPathListPredicate ( library . baseCompiler . syspropHeaders , func ( path android . Path ) bool {
_ , isRel := android . MaybeRel ( ctx , dir . String ( ) , path . String ( ) )
return isRel
} )
2020-11-20 18:42:07 +01:00
// Add sysprop-related directories to the exported directories of this library.
2019-06-03 12:10:47 +02:00
library . reexportDirs ( dir )
2021-02-19 14:49:08 +01:00
library . reexportDeps ( library . baseCompiler . syspropOrderOnlyDeps ... )
2021-02-19 18:05:39 +01:00
library . addExportedGeneratedHeaders ( headers ... )
2018-09-05 17:55:20 +02:00
}
2020-11-20 18:42:07 +01:00
// Add stub-related flags if this library is a stub library.
2020-12-14 01:20:00 +01:00
library . exportVersioningMacroIfNeeded ( ctx )
2018-11-02 10:23:15 +01:00
2020-11-20 18:42:07 +01:00
// Propagate a Provider containing information about exported flags, deps, and include paths.
2020-09-18 23:15:30 +02:00
library . flagExporter . setProvider ( ctx )
2016-07-29 21:48:20 +02:00
return out
}
2020-12-14 01:20:00 +01:00
func ( library * libraryDecorator ) exportVersioningMacroIfNeeded ( ctx android . BaseModuleContext ) {
2020-12-17 01:46:01 +01:00
if library . buildStubs ( ) && library . stubsVersion ( ) != "" && ! library . skipAPIDefine {
2020-12-14 01:20:00 +01:00
name := versioningMacroName ( ctx . Module ( ) . ( * Module ) . ImplementationModuleName ( ctx ) )
2021-02-04 18:28:22 +01:00
apiLevel , err := android . ApiLevelFromUser ( ctx , library . stubsVersion ( ) )
if err != nil {
ctx . ModuleErrorf ( "Can't export version macro: %s" , err . Error ( ) )
}
library . reexportFlags ( "-D" + name + "=" + strconv . Itoa ( apiLevel . FinalOrPreviewInt ( ) ) )
2020-12-14 01:20:00 +01:00
}
}
2020-11-20 18:42:07 +01:00
// buildStatic returns true if this library should be built as a static library.
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) buildStatic ( ) bool {
2019-09-24 23:55:04 +02:00
return library . MutatedProperties . BuildStatic &&
BoolDefault ( library . StaticProperties . Static . Enabled , true )
2016-07-29 21:48:20 +02:00
}
2020-11-20 18:42:07 +01:00
// buildShared returns true if this library should be built as a shared library.
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) buildShared ( ) bool {
2019-09-24 23:55:04 +02:00
return library . MutatedProperties . BuildShared &&
BoolDefault ( library . SharedProperties . Shared . Enabled , true )
2016-07-29 21:48:20 +02:00
}
2016-09-27 02:33:01 +02:00
func ( library * libraryDecorator ) objs ( ) Objects {
return library . objects
2016-07-29 21:48:20 +02:00
}
2020-09-18 23:15:30 +02:00
func ( library * libraryDecorator ) reuseObjs ( ) Objects {
return library . reuseObjects
2016-07-29 21:48:20 +02:00
}
2016-10-01 02:10:16 +02:00
func ( library * libraryDecorator ) toc ( ) android . OptionalPath {
return library . tocFile
}
2019-02-25 03:05:47 +01:00
func ( library * libraryDecorator ) installSymlinkToRuntimeApex ( ctx ModuleContext , file android . Path ) {
dir := library . baseInstaller . installDir ( ctx )
dirOnDevice := android . InstallPathToOnDevicePath ( ctx , dir )
2023-03-24 01:48:07 +01:00
// libc_hwasan has relative_install_dir set, which would mess up the dir.Base() logic.
// hardcode here because it's the only target, if we have other targets that use this
// we can generalise this.
var target string
if ctx . baseModuleName ( ) == "libc_hwasan" {
target = "/" + filepath . Join ( "apex" , "com.android.runtime" , "lib64" , "bionic" , "hwasan" , file . Base ( ) )
} else {
base := dir . Base ( )
target = "/" + filepath . Join ( "apex" , "com.android.runtime" , base , "bionic" , file . Base ( ) )
}
2019-02-25 03:05:47 +01:00
ctx . InstallAbsoluteSymlink ( dir , file . Base ( ) , target )
2020-12-21 18:11:10 +01:00
library . postInstallCmds = append ( library . postInstallCmds , makeSymlinkCmd ( dirOnDevice , file . Base ( ) , target ) )
2019-02-25 03:05:47 +01:00
}
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) install ( ctx ModuleContext , file android . Path ) {
2017-04-15 00:42:53 +02:00
if library . shared ( ) {
2017-12-07 09:18:15 +01:00
if ctx . Device ( ) && ctx . useVndk ( ) {
2020-10-20 11:54:21 +02:00
// set subDir for VNDK extensions
2020-12-02 15:00:51 +01:00
if ctx . IsVndkExt ( ) {
2020-10-20 11:54:21 +02:00
if ctx . isVndkSp ( ) {
library . baseInstaller . subDir = "vndk-sp"
} else {
library . baseInstaller . subDir = "vndk"
}
}
2020-12-24 08:11:23 +01:00
// In some cases we want to use core variant for VNDK-Core libs.
// Skip product variant since VNDKs use only the vendor variant.
if ctx . isVndk ( ) && ! ctx . isVndkSp ( ) && ! ctx . IsVndkExt ( ) && ! ctx . inProduct ( ) {
2020-01-31 19:38:40 +01:00
mayUseCoreVariant := true
if ctx . mustUseVendorVariant ( ) {
mayUseCoreVariant = false
}
2021-06-24 19:15:17 +02:00
if ctx . Config ( ) . CFIEnabledForPath ( ctx . ModuleDir ( ) ) {
2020-01-31 19:38:40 +01:00
mayUseCoreVariant = false
}
if mayUseCoreVariant {
2020-01-08 23:32:28 +01:00
library . checkSameCoreVariant = true
if ctx . DeviceConfig ( ) . VndkUseCoreVariant ( ) {
library . useCoreVariant = true
}
2018-11-13 05:19:56 +01:00
}
2017-12-07 09:18:15 +01:00
}
Support VNDK extensions
This commit adds `extends: "name"` property and provides basic support
to VNDK extensions. This is the simplest example:
```
cc_library {
name: "libvndk",
vendor_available: true,
vndk {
enabled: true,
},
}
cc_library {
name: "libvndk_ext",
vendor: true,
vndk: {
enabled: true,
extends: "libvndk",
},
}
```
A vndk extension library must extend an existing vndk library which has
`vendor_available: true`. These two libraries must have the same
`support_system_process` property.
VNDK-ext libraries are installed to `/vendor/lib[64]/vndk` and
VNDK-SP-ext libraries are installed to `/vendor/lib[64]/vndk-sp` by
default.
If there is a matching abi-dumps in `prebuilts/abi-dumps`,
`header-abi-diff` will be invoked to check for ABI breakages.
Bug: 38340960
Test: lunch aosp_walleye-userdebug && make -j8 # runs unit tests
Test: lunch aosp_arm-userdebug && make -j8 # build a target w/o VNDK
Test: Create a lsdump for a vndk lib, add an exported API to vndk lib,
and build fails as expected.
Test: Create a lsdump for a vndk lib, create an vndk extension lib with
extra API, and build succeeds as expected.
Test: Create libutils_ext, add an extra function to libutils_ext, and
call it from a HIDL service.
Change-Id: Iba90e08848ee99814405457f047321e6b52b2df0
2017-10-31 11:04:35 +01:00
2020-10-20 11:54:21 +02:00
// do not install vndk libs
// vndk libs are packaged into VNDK APEX
2023-10-25 06:25:32 +02:00
if ctx . isVndk ( ) && ! ctx . IsVndkExt ( ) && ! ctx . Config ( ) . IsVndkDeprecated ( ) && ! ctx . inProduct ( ) {
2020-10-20 11:54:21 +02:00
return
2017-06-23 12:24:43 +02:00
}
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
} else if library . hasStubsVariants ( ) && ! ctx . Host ( ) && ctx . directlyInAnyApex ( ) {
2019-02-25 03:05:47 +01:00
// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
2019-09-17 23:45:31 +02:00
translatedArch := ctx . Target ( ) . NativeBridge == android . NativeBridgeEnabled
2020-09-16 03:30:11 +02:00
if InstallToBootstrap ( ctx . baseModuleName ( ) , ctx . Config ( ) ) && ! library . buildStubs ( ) &&
2020-10-22 00:17:56 +02:00
! translatedArch && ! ctx . inRamdisk ( ) && ! ctx . inVendorRamdisk ( ) && ! ctx . inRecovery ( ) {
2019-09-11 00:18:20 +02:00
if ctx . Device ( ) {
2019-03-15 17:10:08 +01:00
library . installSymlinkToRuntimeApex ( ctx , file )
}
2019-01-16 14:31:11 +01:00
library . baseInstaller . subDir = "bootstrap"
}
2020-12-17 01:46:01 +01:00
} else if ctx . directlyInAnyApex ( ) && ctx . IsLlndk ( ) && ! isBionic ( ctx . baseModuleName ( ) ) {
2019-07-12 15:06:23 +02:00
// Skip installing LLNDK (non-bionic) libraries moved to APEX.
2020-12-16 19:20:23 +01:00
ctx . Module ( ) . HideFromMake ( )
2017-06-23 12:24:43 +02:00
}
2019-07-12 15:06:23 +02:00
2016-07-29 21:48:20 +02:00
library . baseInstaller . install ( ctx , file )
}
2017-10-13 09:29:00 +02:00
2017-12-14 00:03:47 +01:00
if Bool ( library . Properties . Static_ndk_lib ) && library . static ( ) &&
2024-01-08 04:55:45 +01:00
! ctx . InVendorOrProduct ( ) && ! ctx . inRamdisk ( ) && ! ctx . inVendorRamdisk ( ) && ! ctx . inRecovery ( ) && ctx . Device ( ) &&
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
library . baseLinker . sanitize . isUnsanitizedVariant ( ) &&
2020-12-16 20:06:50 +01:00
ctx . isForPlatform ( ) && ! ctx . isPreventInstall ( ) {
2023-04-03 22:19:07 +02:00
installPath := getUnversionedLibraryInstallPath ( ctx ) . Join ( ctx , file . Base ( ) )
2017-10-13 09:29:00 +02:00
ctx . ModuleBuild ( pctx , android . ModuleBuildParams {
Rule : android . Cp ,
Description : "install " + installPath . Base ( ) ,
Output : installPath ,
Input : file ,
} )
2017-11-29 02:34:01 +01:00
library . ndkSysrootPath = installPath
2017-10-13 09:29:00 +02:00
}
2016-07-29 21:48:20 +02:00
}
2020-03-04 15:52:46 +01:00
func ( library * libraryDecorator ) everInstallable ( ) bool {
// Only shared and static libraries are installed. Header libraries (which are
// neither static or shared) are not installed.
return library . shared ( ) || library . static ( )
}
2020-11-20 18:42:07 +01:00
// static returns true if this library is for a "static' variant.
2016-07-30 02:28:03 +02:00
func ( library * libraryDecorator ) static ( ) bool {
2017-02-15 00:28:44 +01:00
return library . MutatedProperties . VariantIsStatic
}
2020-11-20 18:42:07 +01:00
// shared returns true if this library is for a "shared' variant.
2017-02-15 00:28:44 +01:00
func ( library * libraryDecorator ) shared ( ) bool {
return library . MutatedProperties . VariantIsShared
}
2020-11-20 18:42:07 +01:00
// header returns true if this library is for a header-only variant.
2017-02-15 00:28:44 +01:00
func ( library * libraryDecorator ) header ( ) bool {
2020-11-20 18:42:07 +01:00
// Neither "static" nor "shared" implies this library is header-only.
2017-02-15 00:28:44 +01:00
return ! library . static ( ) && ! library . shared ( )
}
2020-11-20 18:42:07 +01:00
// setStatic marks the library variant as "static".
2017-02-15 00:28:44 +01:00
func ( library * libraryDecorator ) setStatic ( ) {
library . MutatedProperties . VariantIsStatic = true
library . MutatedProperties . VariantIsShared = false
2016-07-29 21:48:20 +02:00
}
2020-11-20 18:42:07 +01:00
// setShared marks the library variant as "shared".
2017-02-15 00:28:44 +01:00
func ( library * libraryDecorator ) setShared ( ) {
library . MutatedProperties . VariantIsStatic = false
library . MutatedProperties . VariantIsShared = true
2016-07-30 02:28:03 +02:00
}
2016-07-29 21:48:20 +02:00
2020-11-20 18:42:07 +01:00
// BuildOnlyStatic disables building this library as a shared library.
2016-12-09 23:46:15 +01:00
func ( library * libraryDecorator ) BuildOnlyStatic ( ) {
2017-02-15 00:28:44 +01:00
library . MutatedProperties . BuildShared = false
2016-12-09 23:46:15 +01:00
}
2020-11-20 18:42:07 +01:00
// BuildOnlyShared disables building this library as a static library.
2016-12-09 23:46:15 +01:00
func ( library * libraryDecorator ) BuildOnlyShared ( ) {
2017-02-15 00:28:44 +01:00
library . MutatedProperties . BuildStatic = false
2016-12-09 23:46:15 +01:00
}
2020-11-20 18:42:07 +01:00
// HeaderOnly disables building this library as a shared or static library;
// the library only exists to propagate header file dependencies up the build graph.
2016-12-13 21:50:57 +01:00
func ( library * libraryDecorator ) HeaderOnly ( ) {
2017-02-15 00:28:44 +01:00
library . MutatedProperties . BuildShared = false
library . MutatedProperties . BuildStatic = false
2016-12-13 21:50:57 +01:00
}
2020-12-17 01:46:01 +01:00
// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
func ( library * libraryDecorator ) hasLLNDKStubs ( ) bool {
2021-04-27 02:19:41 +02:00
return String ( library . Properties . Llndk . Symbol_file ) != ""
2020-12-17 01:46:01 +01:00
}
2021-04-27 02:19:41 +02:00
// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs.
2021-04-27 03:37:44 +02:00
func ( library * libraryDecorator ) hasLLNDKHeaders ( ) bool {
return Bool ( library . Properties . Llndk . Llndk_headers )
}
2021-04-27 22:06:04 +02:00
// hasVendorPublicLibrary returns true if this cc_library module has a variant that will build
// vendor public library stubs.
func ( library * libraryDecorator ) hasVendorPublicLibrary ( ) bool {
return String ( library . Properties . Vendor_public_library . Symbol_file ) != ""
}
2020-10-14 03:43:54 +02:00
func ( library * libraryDecorator ) implementationModuleName ( name string ) string {
return name
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
func ( library * libraryDecorator ) buildStubs ( ) bool {
return library . MutatedProperties . BuildStubs
}
2019-08-27 07:02:19 +02:00
func ( library * libraryDecorator ) symbolFileForAbiCheck ( ctx ModuleContext ) * string {
2022-12-26 08:54:36 +01:00
if props := library . getHeaderAbiCheckerProperties ( ctx ) ; props . Symbol_file != nil {
return props . Symbol_file
2019-08-27 07:02:19 +02:00
}
2020-10-24 02:22:06 +02:00
if library . hasStubsVariants ( ) && library . Properties . Stubs . Symbol_file != nil {
2019-08-27 07:02:19 +02:00
return library . Properties . Stubs . Symbol_file
}
2024-03-11 13:02:34 +01:00
// TODO(b/309880485): Distinguish platform, NDK, LLNDK, and APEX version scripts.
if library . baseLinker . Properties . Version_script != nil {
return library . baseLinker . Properties . Version_script
}
2019-08-27 07:02:19 +02:00
return nil
}
2020-09-29 02:32:47 +02:00
func ( library * libraryDecorator ) hasStubsVariants ( ) bool {
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
// Just having stubs.symbol_file is enough to create a stub variant. In that case
// the stub for the future API level is created.
return library . Properties . Stubs . Symbol_file != nil ||
len ( library . Properties . Stubs . Versions ) > 0
2020-09-29 02:32:47 +02:00
}
2022-11-14 13:21:24 +01:00
func ( library * libraryDecorator ) isStubsImplementationRequired ( ) bool {
return BoolDefault ( library . Properties . Stubs . Implementation_installable , true )
}
2020-10-02 00:58:11 +02:00
func ( library * libraryDecorator ) stubsVersions ( ctx android . BaseMutatorContext ) [ ] string {
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
if ! library . hasStubsVariants ( ) {
return nil
}
2024-01-08 04:55:45 +01:00
if library . hasLLNDKStubs ( ) && ctx . Module ( ) . ( * Module ) . InVendorOrProduct ( ) {
2024-03-12 06:12:12 +01:00
// LLNDK libraries only need a single stubs variant (""), which is
// added automatically in createVersionVariations().
return nil
2021-05-06 22:42:48 +02:00
}
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
// Future API level is implicitly added if there isn't
2024-03-12 06:12:12 +01:00
versions := addCurrentVersionIfNotPresent ( library . Properties . Stubs . Versions )
normalizeVersions ( ctx , versions )
return versions
2023-04-20 15:13:25 +02:00
}
func addCurrentVersionIfNotPresent ( vers [ ] string ) [ ] string {
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
if inList ( android . FutureApiLevel . String ( ) , vers ) {
return vers
}
// In some cases, people use the raw value "10000" in the versions property.
// We shouldn't add the future API level in that case, otherwise there will
// be two identical versions.
if inList ( strconv . Itoa ( android . FutureApiLevel . FinalOrFutureInt ( ) ) , vers ) {
return vers
}
return append ( vers , android . FutureApiLevel . String ( ) )
2020-09-29 02:32:47 +02:00
}
func ( library * libraryDecorator ) setStubsVersion ( version string ) {
library . MutatedProperties . StubsVersion = version
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
func ( library * libraryDecorator ) stubsVersion ( ) string {
return library . MutatedProperties . StubsVersion
}
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
func ( library * libraryDecorator ) setBuildStubs ( isLatest bool ) {
2020-09-29 02:32:47 +02:00
library . MutatedProperties . BuildStubs = true
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
library . MutatedProperties . IsLatestVersion = isLatest
2020-09-29 02:32:47 +02:00
}
func ( library * libraryDecorator ) setAllStubsVersions ( versions [ ] string ) {
library . MutatedProperties . AllStubsVersions = versions
}
func ( library * libraryDecorator ) allStubsVersions ( ) [ ] string {
return library . MutatedProperties . AllStubsVersions
}
2020-02-27 09:56:44 +01:00
func ( library * libraryDecorator ) isLatestStubVersion ( ) bool {
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
return library . MutatedProperties . IsLatestVersion
2020-02-27 09:56:44 +01:00
}
2019-10-07 08:47:24 +02:00
func ( library * libraryDecorator ) availableFor ( what string ) bool {
var list [ ] string
if library . static ( ) {
list = library . StaticProperties . Static . Apex_available
} else if library . shared ( ) {
list = library . SharedProperties . Shared . Apex_available
}
if len ( list ) == 0 {
return false
}
return android . CheckAvailableForApex ( what , list )
}
2021-10-28 22:25:54 +02:00
func ( library * libraryDecorator ) installable ( ) * bool {
if library . static ( ) {
return library . StaticProperties . Static . Installable
} else if library . shared ( ) {
return library . SharedProperties . Shared . Installable
}
return nil
}
2023-03-20 12:05:16 +01:00
func ( library * libraryDecorator ) makeUninstallable ( mod * Module ) {
if library . static ( ) && library . buildStatic ( ) && ! library . buildStubs ( ) {
// If we're asked to make a static library uninstallable we don't do
// anything since AndroidMkEntries always sets LOCAL_UNINSTALLABLE_MODULE
// for these entries. This is done to still get the make targets for NOTICE
// files from notice_files.mk, which other libraries might depend on.
return
}
mod . ModuleBase . MakeUninstallable ( )
}
2022-09-02 00:47:07 +02:00
func ( library * libraryDecorator ) getPartition ( ) string {
return library . path . Partition ( )
}
2021-09-29 01:37:50 +02:00
func ( library * libraryDecorator ) getAPIListCoverageXMLPath ( ) android . ModuleOutPath {
return library . apiListCoverageXmlPath
}
2022-10-04 07:42:02 +02:00
func ( library * libraryDecorator ) overriddenModules ( ) [ ] string {
return library . Properties . Overrides
}
var _ overridable = ( * libraryDecorator ) ( nil )
2019-02-04 20:22:08 +01:00
var versioningMacroNamesListKey = android . NewOnceKey ( "versioningMacroNamesList" )
2020-11-20 18:42:07 +01:00
// versioningMacroNamesList returns a singleton map, where keys are "version macro names",
// and values are the module name responsible for registering the version macro name.
//
// Version macros are used when building against stubs, to provide version information about
// the stub. Only stub libraries should have an entry in this list.
//
// For example, when building against libFoo#ver, __LIBFOO_API__ macro is set to ver so
// that headers from libFoo can be conditionally compiled (this may hide APIs
// that are not available for the version).
//
// This map is used to ensure that there aren't conflicts between these version macro names.
2018-11-02 10:23:15 +01:00
func versioningMacroNamesList ( config android . Config ) * map [ string ] string {
2019-02-04 20:22:08 +01:00
return config . Once ( versioningMacroNamesListKey , func ( ) interface { } {
2018-11-02 10:23:15 +01:00
m := make ( map [ string ] string )
return & m
} ) . ( * map [ string ] string )
}
// alphanumeric and _ characters are preserved.
// other characters are all converted to _
var charsNotForMacro = regexp . MustCompile ( "[^a-zA-Z0-9_]+" )
2020-11-20 18:42:07 +01:00
// versioningMacroName returns the canonical version macro name for the given module.
2018-11-02 10:23:15 +01:00
func versioningMacroName ( moduleName string ) string {
macroName := charsNotForMacro . ReplaceAllString ( moduleName , "_" )
2020-03-13 10:57:35 +01:00
macroName = strings . ToUpper ( macroName )
2018-11-02 10:23:15 +01:00
return "__" + macroName + "_API__"
}
2020-11-20 18:42:07 +01:00
// NewLibrary builds and returns a new Module corresponding to a C++ library.
// Individual module implementations which comprise a C++ library (or something like
// a C++ library) should call this function, set some fields on the result, and
// then call the Init function.
2016-12-09 23:46:15 +01:00
func NewLibrary ( hod android . HostOrDeviceSupported ) ( * Module , * libraryDecorator ) {
2016-07-30 02:28:03 +02:00
module := newModule ( hod , android . MultilibBoth )
2016-07-29 21:48:20 +02:00
2016-07-30 02:28:03 +02:00
library := & libraryDecorator {
2017-02-15 00:28:44 +01:00
MutatedProperties : LibraryMutatedProperties {
2016-12-09 23:46:15 +01:00
BuildShared : true ,
BuildStatic : true ,
2016-07-29 21:48:20 +02:00
} ,
2016-07-30 02:28:03 +02:00
baseCompiler : NewBaseCompiler ( ) ,
2018-07-26 23:00:24 +02:00
baseLinker : NewBaseLinker ( module . sanitize ) ,
2016-07-30 02:28:03 +02:00
baseInstaller : NewBaseInstaller ( "lib" , "lib64" , InstallInSystem ) ,
2017-02-08 22:45:53 +01:00
sabi : module . sabi ,
2016-07-29 21:48:20 +02:00
}
2016-07-30 02:28:03 +02:00
module . compiler = library
module . linker = library
module . installer = library
2020-10-24 02:22:06 +02:00
module . library = library
2016-07-30 02:28:03 +02:00
return module , library
}
2017-05-03 20:01:58 +02:00
// connects a shared library to a static library in order to reuse its .o files to avoid
// compiling source files twice.
func reuseStaticLibrary ( mctx android . BottomUpMutatorContext , static , shared * Module ) {
if staticCompiler , ok := static . compiler . ( * libraryDecorator ) ; ok {
sharedCompiler := shared . compiler . ( * libraryDecorator )
2018-12-04 00:25:46 +01:00
// Check libraries in addition to cflags, since libraries may be exporting different
// include directories.
2019-09-24 23:55:04 +02:00
if len ( staticCompiler . StaticProperties . Static . Cflags ) == 0 &&
len ( sharedCompiler . SharedProperties . Shared . Cflags ) == 0 &&
len ( staticCompiler . StaticProperties . Static . Whole_static_libs ) == 0 &&
len ( sharedCompiler . SharedProperties . Shared . Whole_static_libs ) == 0 &&
len ( staticCompiler . StaticProperties . Static . Static_libs ) == 0 &&
len ( sharedCompiler . SharedProperties . Shared . Static_libs ) == 0 &&
len ( staticCompiler . StaticProperties . Static . Shared_libs ) == 0 &&
len ( sharedCompiler . SharedProperties . Shared . Shared_libs ) == 0 &&
2020-03-24 02:19:52 +01:00
// Compare System_shared_libs properties with nil because empty lists are
// semantically significant for them.
2019-09-24 23:55:04 +02:00
staticCompiler . StaticProperties . Static . System_shared_libs == nil &&
sharedCompiler . SharedProperties . Shared . System_shared_libs == nil {
2017-05-03 20:01:58 +02:00
mctx . AddInterVariantDependency ( reuseObjTag , shared , static )
sharedCompiler . baseCompiler . Properties . OriginalSrcs =
sharedCompiler . baseCompiler . Properties . Srcs
sharedCompiler . baseCompiler . Properties . Srcs = nil
sharedCompiler . baseCompiler . Properties . Generated_sources = nil
}
2020-09-18 23:15:30 +02:00
// This dep is just to reference static variant from shared variant
mctx . AddInterVariantDependency ( staticVariantTag , shared , static )
2017-05-03 20:01:58 +02:00
}
}
2020-11-20 18:42:07 +01:00
// LinkageMutator adds "static" or "shared" variants for modules depending
// on whether the module can be built as a static library or a shared library.
2018-10-03 07:25:58 +02:00
func LinkageMutator ( mctx android . BottomUpMutatorContext ) {
2020-12-21 18:11:10 +01:00
ccPrebuilt := false
2016-07-30 02:28:03 +02:00
if m , ok := mctx . Module ( ) . ( * Module ) ; ok && m . linker != nil {
2020-12-21 18:11:10 +01:00
_ , ccPrebuilt = m . linker . ( prebuiltLibraryInterface )
2019-10-18 23:49:46 +02:00
}
2020-12-21 18:11:10 +01:00
if ccPrebuilt {
2019-10-18 23:49:46 +02:00
library := mctx . Module ( ) . ( * Module ) . linker . ( prebuiltLibraryInterface )
2020-02-21 11:57:00 +01:00
// Differentiate between header only and building an actual static/shared library
2020-12-17 01:46:01 +01:00
buildStatic := library . buildStatic ( )
buildShared := library . buildShared ( )
if buildStatic || buildShared {
2020-02-21 11:57:00 +01:00
// Always create both the static and shared variants for prebuilt libraries, and then disable the one
// that is not being used. This allows them to share the name of a cc_library module, which requires that
// all the variants of the cc_library also exist on the prebuilt.
modules := mctx . CreateLocalVariations ( "static" , "shared" )
static := modules [ 0 ] . ( * Module )
shared := modules [ 1 ] . ( * Module )
static . linker . ( prebuiltLibraryInterface ) . setStatic ( )
shared . linker . ( prebuiltLibraryInterface ) . setShared ( )
2020-12-17 01:46:01 +01:00
if buildShared {
2020-08-07 02:46:48 +02:00
mctx . AliasVariation ( "shared" )
2020-12-17 01:46:01 +01:00
} else if buildStatic {
2020-08-07 02:46:48 +02:00
mctx . AliasVariation ( "static" )
}
2020-12-17 01:46:01 +01:00
if ! buildStatic {
2020-02-21 11:57:00 +01:00
static . linker . ( prebuiltLibraryInterface ) . disablePrebuilt ( )
}
2020-12-17 01:46:01 +01:00
if ! buildShared {
2020-02-21 11:57:00 +01:00
shared . linker . ( prebuiltLibraryInterface ) . disablePrebuilt ( )
}
} else {
// Header only
2019-10-18 23:49:46 +02:00
}
2020-02-21 11:57:00 +01:00
2024-05-14 03:03:34 +02:00
} else if library , ok := mctx . Module ( ) . ( LinkableInterface ) ; ok && ( library . CcLibraryInterface ( ) || library . RustLibraryInterface ( ) ) {
2019-11-21 21:30:50 +01:00
// Non-cc.Modules may need an empty variant for their mutators.
variations := [ ] string { }
if library . NonCcVariants ( ) {
variations = append ( variations , "" )
}
2020-12-17 01:46:01 +01:00
isLLNDK := false
if m , ok := mctx . Module ( ) . ( * Module ) ; ok {
2021-04-27 02:19:41 +02:00
isLLNDK = m . IsLlndk ( )
2020-12-17 01:46:01 +01:00
}
buildStatic := library . BuildStaticVariant ( ) && ! isLLNDK
buildShared := library . BuildSharedVariant ( )
if buildStatic && buildShared {
2019-11-21 21:30:50 +01:00
variations := append ( [ ] string { "static" , "shared" } , variations ... )
2016-07-30 02:28:03 +02:00
2019-10-18 23:49:46 +02:00
modules := mctx . CreateLocalVariations ( variations ... )
static := modules [ 0 ] . ( LinkableInterface )
shared := modules [ 1 ] . ( LinkableInterface )
2017-05-03 20:01:58 +02:00
2019-10-18 23:49:46 +02:00
static . SetStatic ( )
shared . SetShared ( )
if _ , ok := library . ( * Module ) ; ok {
reuseStaticLibrary ( mctx , static . ( * Module ) , shared . ( * Module ) )
2016-07-30 02:28:03 +02:00
}
2020-08-07 02:46:48 +02:00
mctx . AliasVariation ( "shared" )
2020-12-17 01:46:01 +01:00
} else if buildStatic {
2019-11-21 21:30:50 +01:00
variations := append ( [ ] string { "static" } , variations ... )
modules := mctx . CreateLocalVariations ( variations ... )
2019-10-18 23:49:46 +02:00
modules [ 0 ] . ( LinkableInterface ) . SetStatic ( )
2020-08-07 02:46:48 +02:00
mctx . AliasVariation ( "static" )
2020-12-17 01:46:01 +01:00
} else if buildShared {
2019-11-21 21:30:50 +01:00
variations := append ( [ ] string { "shared" } , variations ... )
modules := mctx . CreateLocalVariations ( variations ... )
2019-10-18 23:49:46 +02:00
modules [ 0 ] . ( LinkableInterface ) . SetShared ( )
2020-08-07 02:46:48 +02:00
mctx . AliasVariation ( "shared" )
2019-11-21 21:30:50 +01:00
} else if len ( variations ) > 0 {
mctx . CreateLocalVariations ( variations ... )
2020-08-07 02:46:48 +02:00
mctx . AliasVariation ( variations [ 0 ] )
2016-07-30 02:28:03 +02:00
}
}
2016-07-29 21:48:20 +02:00
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
2020-11-20 18:42:07 +01:00
// normalizeVersions modifies `versions` in place, so that each raw version
// string becomes its normalized canonical form.
// Validates that the versions in `versions` are specified in least to greatest order.
2023-12-07 22:10:56 +01:00
func normalizeVersions ( ctx android . BaseModuleContext , versions [ ] string ) {
2020-07-23 07:32:17 +02:00
var previous android . ApiLevel
2020-02-27 09:56:44 +01:00
for i , v := range versions {
2020-07-23 07:32:17 +02:00
ver , err := android . ApiLevelFromUser ( ctx , v )
2020-02-27 09:56:44 +01:00
if err != nil {
2020-04-01 18:41:41 +02:00
ctx . PropertyErrorf ( "versions" , "%s" , err . Error ( ) )
return
2020-02-27 09:56:44 +01:00
}
2020-07-23 07:32:17 +02:00
if i > 0 && ver . LessThanOrEqualTo ( previous ) {
ctx . PropertyErrorf ( "versions" , "not sorted: %v" , versions )
}
versions [ i ] = ver . String ( )
previous = ver
2020-04-01 18:41:41 +02:00
}
2020-02-27 09:56:44 +01:00
}
2020-03-21 15:21:46 +01:00
func createVersionVariations ( mctx android . BottomUpMutatorContext , versions [ ] string ) {
2020-12-17 01:46:01 +01:00
// "" is for the non-stubs (implementation) variant for system modules, or the LLNDK variant
// for LLNDK modules.
2020-09-18 23:15:30 +02:00
variants := append ( android . CopyOf ( versions ) , "" )
2020-03-21 15:21:46 +01:00
2020-12-17 01:46:01 +01:00
m := mctx . Module ( ) . ( * Module )
isLLNDK := m . IsLlndk ( )
2021-04-27 22:06:04 +02:00
isVendorPublicLibrary := m . IsVendorPublicLibrary ( )
2022-10-25 15:59:41 +02:00
isImportedApiLibrary := m . isImportedApiLibrary ( )
2020-12-17 01:46:01 +01:00
2020-08-19 03:35:15 +02:00
modules := mctx . CreateLocalVariations ( variants ... )
2020-03-21 15:21:46 +01:00
for i , m := range modules {
2020-12-17 01:46:01 +01:00
2022-10-25 15:59:41 +02:00
if variants [ i ] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
2020-12-17 01:46:01 +01:00
// A stubs or LLNDK stubs variant.
2020-10-24 02:22:06 +02:00
c := m . ( * Module )
c . sanitize = nil
c . stl = nil
c . Properties . PreventInstall = true
lib := moduleLibraryInterface ( m )
"current" is implicitly added to stubs.versions
So far, when a library `libfoo` has `stubs.versions: ["10", "11"]`, then
`shared_libs: ["libfoo"]` is linked to the version 11 of the stub.
This requires the author of `libfoo` to manually update the property
whenever a new version is introduced. Otherwise, clients are not able
to use the newly added APIs because the latest stub is for an old
version.
This change eliminates the need for manual updating. "current" version
is always implicitly added to `stubs.versions`. It is added even when
nothing is set on the property, if `stubs.symbol_file` is set. i.e.
```
cc_library {
name: "libfoo",
stubs: {
symbol_file: "libfoo.map.txt",
// no versions: [...] needed
},
}
cc_library {
name: "a_client",
shared_libs: ["libfoo"],
apex_available: ["myapex"],
min_sdk_version: "29",
}
apex {
name: "myapex",
native_shared_libraries: ["a_client"],
min_sdk_version: "29",
}
```
`a_client` links to the "current" stub of `libfoo` that has all symbols
shown in the map file.
Note that, above doesn't mean that the client has unlimited access to
APIs that are introduced even after the min_sdk_version of the client
(29 in this example). The use of such APIs still has to be guarded with
`__builtin_available` check.
Bug: N/A
Test: m
Change-Id: I70bb1600c18e74d36c6b24c3569d2149f02aaf96
2021-03-17 12:21:35 +01:00
isLatest := i == ( len ( versions ) - 1 )
lib . setBuildStubs ( isLatest )
2020-12-17 01:46:01 +01:00
if variants [ i ] != "" {
// A non-LLNDK stubs module is hidden from make and has a dependency from the
// implementation module to the stubs module.
c . Properties . HideFromMake = true
lib . setStubsVersion ( variants [ i ] )
mctx . AddInterVariantDependency ( stubImplDepTag , modules [ len ( modules ) - 1 ] , modules [ i ] )
}
2020-03-21 15:21:46 +01:00
}
}
2020-08-07 02:38:25 +02:00
mctx . AliasVariation ( "" )
2020-08-19 03:35:15 +02:00
latestVersion := ""
if len ( versions ) > 0 {
latestVersion = versions [ len ( versions ) - 1 ]
}
mctx . CreateAliasVariation ( "latest" , latestVersion )
2020-03-21 15:21:46 +01:00
}
2020-09-30 21:27:01 +02:00
func createPerApiVersionVariations ( mctx android . BottomUpMutatorContext , minSdkVersion string ) {
from , err := nativeApiLevelFromUser ( mctx , minSdkVersion )
if err != nil {
mctx . PropertyErrorf ( "min_sdk_version" , err . Error ( ) )
return
}
versionStrs := ndkLibraryVersions ( mctx , from )
modules := mctx . CreateLocalVariations ( versionStrs ... )
for i , module := range modules {
module . ( * Module ) . Properties . Sdk_version = StringPtr ( versionStrs [ i ] )
2021-03-19 14:18:04 +01:00
module . ( * Module ) . Properties . Min_sdk_version = StringPtr ( versionStrs [ i ] )
2020-09-30 21:27:01 +02:00
}
}
2022-04-08 21:41:00 +02:00
func canBeOrLinkAgainstVersionVariants ( module interface {
2020-04-10 05:57:24 +02:00
Host ( ) bool
InRamdisk ( ) bool
2020-10-22 00:17:56 +02:00
InVendorRamdisk ( ) bool
2020-04-10 05:57:24 +02:00
} ) bool {
2020-12-11 22:36:29 +01:00
return ! module . Host ( ) && ! module . InRamdisk ( ) && ! module . InVendorRamdisk ( )
2020-04-10 05:57:24 +02:00
}
2022-04-08 21:41:00 +02:00
func canBeVersionVariant ( module interface {
2020-10-01 00:34:40 +02:00
Host ( ) bool
InRamdisk ( ) bool
2020-10-22 00:17:56 +02:00
InVendorRamdisk ( ) bool
2020-10-01 00:34:40 +02:00
CcLibraryInterface ( ) bool
Shared ( ) bool
} ) bool {
2022-04-08 21:41:00 +02:00
return canBeOrLinkAgainstVersionVariants ( module ) &&
2020-10-23 23:53:06 +02:00
module . CcLibraryInterface ( ) && module . Shared ( )
2020-10-01 00:34:40 +02:00
}
2020-12-17 01:46:01 +01:00
func moduleLibraryInterface ( module blueprint . Module ) libraryInterface {
2020-10-24 02:22:06 +02:00
if m , ok := module . ( * Module ) ; ok {
return m . library
}
return nil
}
2022-04-08 21:41:00 +02:00
// setStubsVersions normalizes the versions in the Stubs.Versions property into MutatedProperties.AllStubsVersions.
func setStubsVersions ( mctx android . BottomUpMutatorContext , library libraryInterface , module * Module ) {
if ! library . buildShared ( ) || ! canBeVersionVariant ( module ) {
return
}
versions := library . stubsVersions ( mctx )
if mctx . Failed ( ) {
return
2020-08-19 03:35:15 +02:00
}
2022-04-08 21:41:00 +02:00
// Set the versions on the pre-mutated module so they can be read by any llndk modules that
// depend on the implementation library and haven't been mutated yet.
library . setAllStubsVersions ( versions )
2020-08-19 03:35:15 +02:00
}
2020-03-21 15:21:46 +01:00
2020-08-19 03:35:15 +02:00
// versionMutator splits a module into the mandatory non-stubs variant
// (which is unnamed) and zero or more stubs variants.
func versionMutator ( mctx android . BottomUpMutatorContext ) {
2022-04-08 21:41:00 +02:00
if mctx . Os ( ) != android . Android {
return
}
m , ok := mctx . Module ( ) . ( * Module )
if library := moduleLibraryInterface ( mctx . Module ( ) ) ; library != nil && canBeVersionVariant ( m ) {
setStubsVersions ( mctx , library , m )
2020-10-24 02:22:06 +02:00
createVersionVariations ( mctx , library . allStubsVersions ( ) )
2020-09-30 21:27:01 +02:00
return
}
2022-04-08 21:41:00 +02:00
if ok {
2020-09-30 21:27:01 +02:00
if m . SplitPerApiLevel ( ) && m . IsSdkVariant ( ) {
createPerApiVersionVariations ( mctx , m . MinSdkVersion ( ) )
}
Add support for versioned stubs.
A cc_library or cc_library_shared can be configured to have stubs
variants of the lib.
cc_library_shared {
name: "libfoo",
srcs: ["foo.cpp"],
stubs: {
symbol_file: "foo.map.txt",
versions: ["1", "2", "3"],
},
}
then, stubs variants of libfoo for version 1, 2, and 3 are created
from foo.map.txt. Each version has the symbols from the map file where
each symbol is annotated with the version that the symbol was introduced
via the 'introduced=<ver>' syntax. The versions don't need to be in sync
with the platform versions (e.g., P for 28). The versions are local to
the library.
For another library or executable to use the versioned stubs lib, use
the new 'name#ver' syntax to specify the version:
cc_binary {
name: "test",
....
shared_libs: ["libFoo#2"],
}
Internally, a new mutator 'version' is applied to all cc.Module objects.
By default, a variant named 'impl' is created for the non-stub version.
If the versions property is set, additional variations are created per a
version with the mutable property BuildStubs set as true, which lets the
compiler and the linker to build a stubs lib from the symbol file
instead from the source files.
This feature will be used to enforce stable interfaces among APEXs. When
a lib foo in an APEX is depending on a lib bar in another APEX, then bar
should have stable interface (in C lang) and foo should be depending on
one of the stubs libs of bar. Only libraries in the same APEX as foo can
link against non-stub version of it.
Bug: 112672359
Test: m (cc_test added)
Change-Id: I2488be0b9d7b7b8d7761234dc1c9c0e3add8601c
2018-10-15 15:25:07 +02:00
}
}
2019-09-05 23:26:33 +02:00
// maybeInjectBoringSSLHash adds a rule to run bssl_inject_hash on the output file if the module has the
// inject_bssl_hash or if any static library dependencies have inject_bssl_hash set. It returns the output path
// that the linked output file should be written to.
// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
func maybeInjectBoringSSLHash ( ctx android . ModuleContext , outputFile android . ModuleOutPath ,
inject * bool , fileName string ) android . ModuleOutPath {
// TODO(b/137267623): Remove this in favor of a cc_genrule when they support operating on shared libraries.
injectBoringSSLHash := Bool ( inject )
ctx . VisitDirectDeps ( func ( dep android . Module ) {
2020-07-28 06:26:48 +02:00
if tag , ok := ctx . OtherModuleDependencyTag ( dep ) . ( libraryDependencyTag ) ; ok && tag . static ( ) {
2019-09-05 23:26:33 +02:00
if cc , ok := dep . ( * Module ) ; ok {
if library , ok := cc . linker . ( * libraryDecorator ) ; ok {
if Bool ( library . Properties . Inject_bssl_hash ) {
injectBoringSSLHash = true
}
}
}
}
} )
if injectBoringSSLHash {
hashedOutputfile := outputFile
outputFile = android . PathForModuleOut ( ctx , "unhashed" , fileName )
2020-11-17 02:32:30 +01:00
rule := android . NewRuleBuilder ( pctx , ctx )
2019-09-05 23:26:33 +02:00
rule . Command ( ) .
2020-11-17 02:32:30 +01:00
BuiltTool ( "bssl_inject_hash" ) .
2019-09-05 23:26:33 +02:00
FlagWithInput ( "-in-object " , outputFile ) .
FlagWithOutput ( "-o " , hashedOutputfile )
2020-11-17 02:32:30 +01:00
rule . Build ( "injectCryptoHash" , "inject crypto hash" )
2019-09-05 23:26:33 +02:00
}
return outputFile
}