-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Migrate ObjcProvider compile info to CcCompilationContext #10674
Description
Overview
This issue describes the plans to migrate compile info from ObjcProvider to CcCompilationContext. It will focus on the main migration step, which moves the compilation info in ObjcProvider into an embedded CcCompilationContext. Note this step is Starlark API compatible (except for one secondary feature). The issue will also describe any expected changes in behavior and the followup cleanup work.
Scope
What is being migrated:
- Headers, defines, all four flavors of include paths (regular, quote, system, framework).
What is not being migrated:
- Module maps, objc_proto strict dependency include.
- Any non-compile info.
Initial rollout is Starlark API compatible, except for the strict dependency propagation feature. Later cleanups may break compatibility.
Changes to ObjcProvider
The migration will make the following changes to ObjcProvider:
- The migrated fields will be stored in an embedded
CcCompilationContext, instead of directly asitemsinObjcProvider. The items for those fields inObjcProviderwill become empty. - Strict dependency and non-propagated items will no longer be supported generically. Instead, the only intended remaining use of strict dependency is for
objc_proto_libraryincludes (which is only used within Google), and that will be moved to a special field inObjcProvider. - Strict dependency includes will no longer be propagated to a dependent
ObjcProvider. Instead, to get the strict dependency behavior, a rule should fetch that information directly from its dependencies. For an example of how to do this, seeswift_librarywhich is already set up this way. - The
ObjcProviderStarlark API will have a new accessor field (compilation_context) to access itsCcCompilationContext. This field is a temporary measure to ease migration, and will be deleted once all the cleanup tasks are completed. - Otherwise, the Starlark API will remain the same.
Changes to native rules
The migration will make the following changes the native rules:
-
Previously,
objc_libraryexports aCcInfowith an incompleteCcCompilationContextthat only has header information. Now it will export the completeCcCompilationContext, identical to the one embedded in itsObjcProvider.Note this change can expose bugs/issues in rules that depend on
objc_libraryand consume itsCcInfo. -
Rules that produce final library or executable artifacts (e.g.
apple_binary,apple_static_libary) generateObjcProvidersfor linking. TheseObjcProviderswill no longer carry compilation information.
Other changes in behavior that may impact users
- Private headers (those in
srcsattribute) ofobjc_libraryare now propagated to dependencies. This behavior makesobjc_librarymore consistent with that forcc_library. - The quote include paths now contain ".", the root of the source directory. Previously this path was added implicitly to every compile, but never put into the provider.
- The ordering of defines and include paths will likely change, in ways that don't affect correctness. Furthermore, the Starlark APIs for accessing these fields only provide stable order, so with the change in underlying representation that is even more likely to change. Tulsi unit tests, which assumes a specific ordering, would need to be remastered.
Internal changes
This section describes the changes made to the blaze internals for the migration. It is mainly of interest to code reviewers, or those who are interested in the inner workings of Objective C/C++ rules. It may be skipped by most users.
Migrating internal uses of ObjcProvider
ObjcProvider is used not only for information exchange between rules, it is used internally as well. The migration covers these uses. There are three issues in migrating them:
-
objc_library's compile action depends on its own provider.Currently, a compilation rule such as
objc_librarygenerates itsObjcProvider, then uses it to generate its compile action. This flow is problematic for the migration, because the compile action generates aCcCompilationContextthat we want to use to create theObjcProvider-- so the migration would cause a circular dependency in this flow.The migration requires breaking this circular dependency. A compilation rule is modified so that it collects all the compilation info into a new object called
ObjcCompilationContext, which serves as a substitute for the wayObjcProviderwas used before in its own compilation. WhereasObjcCommonused to create anObjcProviderup front, it now creates anObjcCompilationContextand anObjcProvider.Builder, the latter of which only contains non-compile information. The creation of the finalObjcProvideris postponed untilCompilationSupport.compile()is called. -
Distinguish between two kinds of uses of
ObjcCommon.Because of the the aforementioned change, it is useful to distinguish between two use cases of
ObjcCommon: those that are used to create compilation actions and those that are not.ObjcCommonused to create compilation actions needs to export anObjcProvider.Builder, and rely onCompilationSupport.compile()to create the finalObjcProviderthat has theCcCompilationContextfrom the compile action.ObjcCommonthat do not create compilation actions can export anObjcProviderdirectly, as before.
We define a enum
ObjcCommon.Purpose, set during the creation ofObjcCommon, to distinguish the two use cases. -
Implementation of strict dependency propagation
Changing
objc_libraryso that it doesn't depend on its own provider also affects how strict dependency propagation is implemented. Because we fetch strict dependency items directly from the dependent providers, rather than indirectly through a new provider, we no longer need to propagate those items. This simplifies implementation and allows us to get rid of the wonky propagation mechanism altogether.The only remaining use of strict dependency propagation is for objc proto library include paths, so we just store that in a normal field in
ObjcProviderthat is not propagated.
Clean up Objc to Cc hooks
The migration to CcCompilationContext allows us to get rid of a bunch of existing hacky hooks used to get Objective-C compilation to work properly with underlying C++ infrastructure. The following hooks are used to work around include scanning issues, which are obsoleted by the migration and can be deleted:
- The concepts of additional prunable includes and alternate include scanning data input (see
ObjcCppSemanticsandCppCompilationAction). - The hack in
CompilationSupport.ccCompileAndLink().
Followup plan
The followup work can be divided into three phases:
- Migrate all native and Starlark rules to generate
CcInfo/CcCompilationContextfor compile info. This info will be identical to information stored in theCcCompilationContextembedded inObjcProvider. - Migrate all native and Starlark rules to use
CcInfofor compile info. - Migrate all rules to stop generating compile info in
ObjcProvider. Remove theObjcProvidercompile-info related Starlark APIs.
I will migrate the native rules, apple rules, swift rules, and tulsi as described above. Users also need to migrate any Starlark rules they own that use ObjcProvider for compile information. We will provide two incompatible flags to aid the migration:
--incompatible_objc_compile_info_migration: This flag controls whether native rules will use compile info from ObjcProvider or CcInfo. If the flag is false, bazel will get its compile info from ObjcProvider (pre-migration behavior). If the flag is true, bazel will get its compile info from CcInfo (post-migration behavior).
Tentative time-frame: available and default false in 3.0, default true the next release (i.e. 3.1), removed the following release (i.e. 3.2).
--incompatible_objc_provider_remove_compile_info: This flag deletes the Starlark APIs to put compile info in an ObjcProvider.
Tentative time-frame: available and default false in 3.2, default true next release (i.e. 4.0), removed in the following release (i.e. 4.1).
We recommend that rules be migrated as follows:
-
Migrate Starlark rules that define
ObjcProviderwith compile info.These are rules that insert any of the following fields into
ObjcProvider:define,framework_search_paths,header,include,include_system,iquote. For each such rule, generate aCcInfocontaining aCcCompilationContextwith the same information, and add it to list of providers emitted by that rule.There is a 1:1 correspondence between these fields and where they should land in
CcCompilationContext:define->definesframework_search_paths->framework_includesheader->headersinclude->includesinclude_system->system_includesiquote->quote_includes
-
Make sure all bazel Starlark rules you are using have been migrated up to this step (you may have to update your rules_apple, etc.). Flip
--incompatible_objc_compile_info_migrationto true, which will help test whether you have migrated all your rules in step (1) properly. -
Migrate Starlark rules that use compile info in
ObjcProvider. These rules should be migrated to use compile info fromCcinfoinstead. This migration may include migrating rules that propagate compile info from its deps, which can be done usingcc_common.merge_cc_infos. -
Migrate Starlark rules so that they stop adding compile info to
ObjcProvider. -
Make sure all bazel Starlark rules you are using have been migrated up to this step (you may have to update your rules_apple, etc.) Flip
--incompatible_objc_provider_remove_compile_infoto true. This will help test whether you have completed the migration.
I will attach examples of the migrations as they become available, in rules_apple/rules_swift/tulsi.