Implement cc_cmake_snapshot
Bug: 302718225 Test: cd build/soong/cc && go test Test: https://r.android.com/2803466 Change-Id: Ie7df635233ed68c40d917ea1f83f9fd4b5bfe729
This commit is contained in:
parent
5b007eaa91
commit
1c8ea5b6e1
12 changed files with 746 additions and 11 deletions
|
@ -51,6 +51,7 @@ bootstrap_go_package {
|
|||
"vndk.go",
|
||||
"vndk_prebuilt.go",
|
||||
|
||||
"cmake_snapshot.go",
|
||||
"cmakelists.go",
|
||||
"compdb.go",
|
||||
"compiler.go",
|
||||
|
@ -92,6 +93,7 @@ bootstrap_go_package {
|
|||
"binary_test.go",
|
||||
"cc_test.go",
|
||||
"cc_test_only_property_test.go",
|
||||
"cmake_snapshot_test.go",
|
||||
"compiler_test.go",
|
||||
"gen_test.go",
|
||||
"genrule_test.go",
|
||||
|
@ -109,5 +111,12 @@ bootstrap_go_package {
|
|||
"tidy_test.go",
|
||||
"vendor_public_library_test.go",
|
||||
],
|
||||
embedSrcs: [
|
||||
"cmake_ext_add_aidl_library.txt",
|
||||
"cmake_ext_append_flags.txt",
|
||||
"cmake_main.txt",
|
||||
"cmake_module_aidl.txt",
|
||||
"cmake_module_cc.txt",
|
||||
],
|
||||
pluginFor: ["soong_build"],
|
||||
}
|
||||
|
|
10
cc/cc.go
10
cc/cc.go
|
@ -352,6 +352,10 @@ type BaseProperties struct {
|
|||
// for building binaries that are started before APEXes are activated.
|
||||
Bootstrap *bool
|
||||
|
||||
// Allows this module to be included in CMake release snapshots to be built outside of Android
|
||||
// build system and source tree.
|
||||
Cmake_snapshot_supported *bool
|
||||
|
||||
// Even if DeviceConfig().VndkUseCoreVariant() is set, this module must use vendor variant.
|
||||
// see soong/cc/config/vndk.go
|
||||
MustUseVendorVariant bool `blueprint:"mutated"`
|
||||
|
@ -587,6 +591,7 @@ type compiler interface {
|
|||
compilerDeps(ctx DepsContext, deps Deps) Deps
|
||||
compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags
|
||||
compilerProps() []interface{}
|
||||
baseCompilerProps() BaseCompilerProperties
|
||||
|
||||
appendCflags([]string)
|
||||
appendAsflags([]string)
|
||||
|
@ -601,6 +606,7 @@ type linker interface {
|
|||
linkerDeps(ctx DepsContext, deps Deps) Deps
|
||||
linkerFlags(ctx ModuleContext, flags Flags) Flags
|
||||
linkerProps() []interface{}
|
||||
baseLinkerProps() BaseLinkerProperties
|
||||
useClangLld(actx ModuleContext) bool
|
||||
|
||||
link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
|
||||
|
@ -2155,6 +2161,10 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||
|
||||
android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()})
|
||||
|
||||
if Bool(c.Properties.Cmake_snapshot_supported) {
|
||||
android.SetProvider(ctx, cmakeSnapshotSourcesProvider, android.GlobFiles(ctx, ctx.ModuleDir()+"/**/*", nil))
|
||||
}
|
||||
|
||||
android.CollectDependencyAconfigFiles(ctx, &c.mergedAconfigFiles)
|
||||
|
||||
c.maybeInstall(ctx, apexInfo)
|
||||
|
|
47
cc/cmake_ext_add_aidl_library.txt
Normal file
47
cc/cmake_ext_add_aidl_library.txt
Normal file
|
@ -0,0 +1,47 @@
|
|||
function(add_aidl_library NAME LANG SOURCES AIDLFLAGS)
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.20")
|
||||
cmake_policy(SET CMP0116 NEW)
|
||||
endif()
|
||||
|
||||
set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/.intermediates/${NAME}-source")
|
||||
set(GEN_SOURCES)
|
||||
foreach(SOURCE ${SOURCES})
|
||||
get_filename_component(SOURCE_WE ${SOURCE} NAME_WE)
|
||||
get_filename_component(SOURCE_ABSOLUTE ${SOURCE} ABSOLUTE)
|
||||
get_filename_component(SOURCE_DIR ${SOURCE_ABSOLUTE} DIRECTORY)
|
||||
set(GEN_SOURCE "${GEN_DIR}/${SOURCE_WE}.cpp")
|
||||
set(DEPFILE_ARG)
|
||||
if (NOT ${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
|
||||
set(DEPFILE_ARG DEPFILE "${GEN_SOURCE}.d")
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT "${GEN_SOURCE}"
|
||||
MAIN_DEPENDENCY "${SOURCE_ABSOLUTE}"
|
||||
${DEPFILE_ARG}
|
||||
COMMAND "${AIDL_BIN}"
|
||||
ARGS
|
||||
--lang=${LANG}
|
||||
--include="${SOURCE_DIR}"
|
||||
--dep="${GEN_SOURCE}.d"
|
||||
--out="${GEN_DIR}"
|
||||
--header_out="${GEN_DIR}/include"
|
||||
--ninja
|
||||
--structured
|
||||
--min_sdk_version=current
|
||||
${AIDLFLAGS}
|
||||
"${SOURCE_ABSOLUTE}"
|
||||
)
|
||||
list(APPEND GEN_SOURCES "${GEN_SOURCE}")
|
||||
endforeach()
|
||||
|
||||
add_library(${NAME} ${GEN_SOURCES})
|
||||
|
||||
target_include_directories(${NAME}
|
||||
PUBLIC
|
||||
"${GEN_DIR}/include"
|
||||
"${ANDROID_BUILD_TOP}/frameworks/native/libs/binder/ndk/include_${LANG}"
|
||||
)
|
||||
target_link_libraries(${NAME}
|
||||
libbinder_sdk
|
||||
)
|
||||
endfunction()
|
10
cc/cmake_ext_append_flags.txt
Normal file
10
cc/cmake_ext_append_flags.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
include(CheckCXXCompilerFlag)
|
||||
|
||||
macro(append_cxx_flags_if_supported VAR)
|
||||
foreach(FLAG ${ARGN})
|
||||
check_cxx_compiler_flag(${FLAG} HAS_FLAG${FLAG})
|
||||
if(${HAS_FLAG${FLAG}})
|
||||
list(APPEND ${VAR} ${FLAG})
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
29
cc/cmake_main.txt
Normal file
29
cc/cmake_main.txt
Normal file
|
@ -0,0 +1,29 @@
|
|||
cmake_minimum_required(VERSION 3.18)
|
||||
project(<<.M.Name>> CXX)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(AddAidlLibrary)
|
||||
include(AppendCxxFlagsIfSupported)
|
||||
|
||||
if (NOT ANDROID_BUILD_TOP)
|
||||
set(ANDROID_BUILD_TOP "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
set(PREBUILTS_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/prebuilts/host/linux-x86/bin")
|
||||
if (NOT AIDL_BIN)
|
||||
find_program(AIDL_BIN aidl REQUIRED HINTS "${PREBUILTS_BIN_DIR}")
|
||||
endif()
|
||||
|
||||
<<cflagsList .M.Name "_CFLAGS" .M.Properties.Cflags .M.Properties.Unportable_flags .M.Properties.Cflags_ignored>>
|
||||
|
||||
<<range .Pprop.SystemPackages ->>
|
||||
find_package(<<.>> REQUIRED)
|
||||
<<end >>
|
||||
<<range .Pprop.PregeneratedPackages ->>
|
||||
add_subdirectory("${ANDROID_BUILD_TOP}/<<.>>" "<<.>>/build" EXCLUDE_FROM_ALL)
|
||||
<<end>>
|
||||
add_compile_options(${<<.M.Name>>_CFLAGS})
|
||||
<<range $moduleDir, $value := .ModuleDirs ->>
|
||||
add_subdirectory(<<$moduleDir>>)
|
||||
<<end>>
|
8
cc/cmake_module_aidl.txt
Normal file
8
cc/cmake_module_aidl.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# <<.M.Name>>
|
||||
|
||||
<<setList .M.Name "_SRCS" "${ANDROID_BUILD_TOP}/" (getCompilerProperties .M).AidlInterface.Sources>>
|
||||
|
||||
<<setList .M.Name "_AIDLFLAGS" "" (getCompilerProperties .M).AidlInterface.Flags>>
|
||||
|
||||
add_aidl_library(<<.M.Name>> <<(getCompilerProperties .M).AidlInterface.Lang>> "${<<.M.Name>>_SRCS}" "${<<.M.Name>>_AIDLFLAGS}")
|
||||
add_library(android::<<.M.Name>> ALIAS <<.M.Name>>)
|
35
cc/cmake_module_cc.txt
Normal file
35
cc/cmake_module_cc.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
<<$srcs := getSources .M>>
|
||||
<<$includeDirs := getIncludeDirs .Ctx .M>>
|
||||
<<$cflags := (getCompilerProperties .M).Cflags>>
|
||||
<<$deps := mapLibraries (concat5
|
||||
(getLinkerProperties .M).Whole_static_libs
|
||||
(getLinkerProperties .M).Static_libs
|
||||
(getLinkerProperties .M).Shared_libs
|
||||
(getLinkerProperties .M).Header_libs
|
||||
(getExtraLibs .M)
|
||||
) .Pprop.LibraryMapping>>
|
||||
|
||||
# <<.M.Name>>
|
||||
<<if $srcs>>
|
||||
<<setList .M.Name "_SRCS" "${ANDROID_BUILD_TOP}/" (toStrings $srcs)>>
|
||||
add_<<getModuleType .M>>(<<.M.Name>> ${<<.M.Name>>_SRCS})
|
||||
<<- else>>
|
||||
add_<<getModuleType .M>>(<<.M.Name>> INTERFACE)
|
||||
<<- end>>
|
||||
add_<<getModuleType .M>>(android::<<.M.Name>> ALIAS <<.M.Name>>)
|
||||
<<print "">>
|
||||
|
||||
<<- if $includeDirs>>
|
||||
<<setList .M.Name "_INCLUDES" "${ANDROID_BUILD_TOP}/" $includeDirs>>
|
||||
target_include_directories(<<.M.Name>> <<if $srcs>>PUBLIC<<else>>INTERFACE<<end>> ${<<.M.Name>>_INCLUDES})
|
||||
<<end>>
|
||||
|
||||
<<- if and $srcs $cflags>>
|
||||
<<cflagsList .M.Name "_CFLAGS" $cflags .Snapshot.Properties.Unportable_flags .Snapshot.Properties.Cflags_ignored>>
|
||||
target_compile_options(<<.M.Name>> PRIVATE ${<<.M.Name>>_CFLAGS})
|
||||
<<end>>
|
||||
|
||||
<<- if $deps>>
|
||||
<<setList .M.Name "_DEPENDENCIES" "" $deps>>
|
||||
target_link_libraries(<<.M.Name>> <<if not $srcs>>INTERFACE <<end ->> ${<<.M.Name>>_DEPENDENCIES})
|
||||
<<end>>
|
509
cc/cmake_snapshot.go
Normal file
509
cc/cmake_snapshot.go
Normal file
|
@ -0,0 +1,509 @@
|
|||
// Copyright 2024 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 (
|
||||
"android/soong/android"
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
)
|
||||
|
||||
const veryVerbose bool = false
|
||||
|
||||
//go:embed cmake_main.txt
|
||||
var templateCmakeMainRaw string
|
||||
var templateCmakeMain *template.Template = parseTemplate(templateCmakeMainRaw)
|
||||
|
||||
//go:embed cmake_module_cc.txt
|
||||
var templateCmakeModuleCcRaw string
|
||||
var templateCmakeModuleCc *template.Template = parseTemplate(templateCmakeModuleCcRaw)
|
||||
|
||||
//go:embed cmake_module_aidl.txt
|
||||
var templateCmakeModuleAidlRaw string
|
||||
var templateCmakeModuleAidl *template.Template = parseTemplate(templateCmakeModuleAidlRaw)
|
||||
|
||||
//go:embed cmake_ext_add_aidl_library.txt
|
||||
var cmakeExtAddAidlLibrary string
|
||||
|
||||
//go:embed cmake_ext_append_flags.txt
|
||||
var cmakeExtAppendFlags string
|
||||
|
||||
var defaultUnportableFlags []string = []string{
|
||||
"-Wno-class-memaccess",
|
||||
"-Wno-exit-time-destructors",
|
||||
"-Wno-inconsistent-missing-override",
|
||||
"-Wreorder-init-list",
|
||||
"-Wno-reorder-init-list",
|
||||
"-Wno-restrict",
|
||||
"-Wno-stringop-overread",
|
||||
"-Wno-subobject-linkage",
|
||||
}
|
||||
|
||||
var ignoredSystemLibs []string = []string{
|
||||
"libc++",
|
||||
"libc++_static",
|
||||
"prebuilt_libclang_rt.builtins",
|
||||
"prebuilt_libclang_rt.ubsan_minimal",
|
||||
}
|
||||
|
||||
// Mapping entry between Android's library name and the one used when building outside Android tree.
|
||||
type LibraryMappingProperty struct {
|
||||
// Android library name.
|
||||
Android_name string
|
||||
|
||||
// Library name used when building outside Android.
|
||||
Mapped_name string
|
||||
|
||||
// If the make file is already present in Android source tree, specify its location.
|
||||
Package_pregenerated string
|
||||
|
||||
// If the package is expected to be installed on the build host OS, specify its name.
|
||||
Package_system string
|
||||
}
|
||||
|
||||
type CmakeSnapshotProperties struct {
|
||||
// Modules to add to the snapshot package. Their dependencies are pulled in automatically.
|
||||
Modules []string
|
||||
|
||||
// Host prebuilts to bundle with the snapshot. These are tools needed to build outside Android.
|
||||
Prebuilts []string
|
||||
|
||||
// Global cflags to add when building outside Android.
|
||||
Cflags []string
|
||||
|
||||
// Flags to skip when building outside Android.
|
||||
Cflags_ignored []string
|
||||
|
||||
// Mapping between library names used in Android tree and externally.
|
||||
Library_mapping []LibraryMappingProperty
|
||||
|
||||
// List of cflags that are not portable between compilers that could potentially be used to
|
||||
// build a generated package. If left empty, it's initialized with a default list.
|
||||
Unportable_flags []string
|
||||
|
||||
// Whether to include source code as part of the snapshot package.
|
||||
Include_sources bool
|
||||
}
|
||||
|
||||
var cmakeSnapshotSourcesProvider = blueprint.NewProvider[android.Paths]()
|
||||
|
||||
type CmakeSnapshot struct {
|
||||
android.ModuleBase
|
||||
|
||||
Properties CmakeSnapshotProperties
|
||||
|
||||
zipPath android.WritablePath
|
||||
}
|
||||
|
||||
type cmakeProcessedProperties struct {
|
||||
LibraryMapping map[string]LibraryMappingProperty
|
||||
PregeneratedPackages []string
|
||||
SystemPackages []string
|
||||
}
|
||||
|
||||
type cmakeSnapshotDependencyTag struct {
|
||||
blueprint.BaseDependencyTag
|
||||
name string
|
||||
}
|
||||
|
||||
var (
|
||||
cmakeSnapshotModuleTag = cmakeSnapshotDependencyTag{name: "cmake-snapshot-module"}
|
||||
cmakeSnapshotPrebuiltTag = cmakeSnapshotDependencyTag{name: "cmake-snapshot-prebuilt"}
|
||||
)
|
||||
|
||||
func parseTemplate(templateContents string) *template.Template {
|
||||
funcMap := template.FuncMap{
|
||||
"setList": func(name string, nameSuffix string, itemPrefix string, items []string) string {
|
||||
var list strings.Builder
|
||||
list.WriteString("set(" + name + nameSuffix)
|
||||
templateListBuilder(&list, itemPrefix, items)
|
||||
return list.String()
|
||||
},
|
||||
"toStrings": func(files android.Paths) []string {
|
||||
strings := make([]string, len(files))
|
||||
for idx, file := range files {
|
||||
strings[idx] = file.String()
|
||||
}
|
||||
return strings
|
||||
},
|
||||
"concat5": func(list1 []string, list2 []string, list3 []string, list4 []string, list5 []string) []string {
|
||||
return append(append(append(append(list1, list2...), list3...), list4...), list5...)
|
||||
},
|
||||
"cflagsList": func(name string, nameSuffix string, flags []string,
|
||||
unportableFlags []string, ignoredFlags []string) string {
|
||||
if len(unportableFlags) == 0 {
|
||||
unportableFlags = defaultUnportableFlags
|
||||
}
|
||||
|
||||
var filteredPortable []string
|
||||
var filteredUnportable []string
|
||||
for _, flag := range flags {
|
||||
if slices.Contains(ignoredFlags, flag) {
|
||||
continue
|
||||
} else if slices.Contains(unportableFlags, flag) {
|
||||
filteredUnportable = append(filteredUnportable, flag)
|
||||
} else {
|
||||
filteredPortable = append(filteredPortable, flag)
|
||||
}
|
||||
}
|
||||
|
||||
var list strings.Builder
|
||||
|
||||
list.WriteString("set(" + name + nameSuffix)
|
||||
templateListBuilder(&list, "", filteredPortable)
|
||||
|
||||
if len(filteredUnportable) > 0 {
|
||||
list.WriteString("\nappend_cxx_flags_if_supported(" + name + nameSuffix)
|
||||
templateListBuilder(&list, "", filteredUnportable)
|
||||
}
|
||||
|
||||
return list.String()
|
||||
},
|
||||
"getSources": func(m *Module) android.Paths {
|
||||
return m.compiler.(CompiledInterface).Srcs()
|
||||
},
|
||||
"getModuleType": getModuleType,
|
||||
"getCompilerProperties": func(m *Module) BaseCompilerProperties {
|
||||
return m.compiler.baseCompilerProps()
|
||||
},
|
||||
"getLinkerProperties": func(m *Module) BaseLinkerProperties {
|
||||
return m.linker.baseLinkerProps()
|
||||
},
|
||||
"getExtraLibs": getExtraLibs,
|
||||
"getIncludeDirs": getIncludeDirs,
|
||||
"mapLibraries": func(libs []string, mapping map[string]LibraryMappingProperty) []string {
|
||||
var mappedLibs []string
|
||||
for _, lib := range libs {
|
||||
mappedLib, exists := mapping[lib]
|
||||
if exists {
|
||||
lib = mappedLib.Mapped_name
|
||||
} else {
|
||||
lib = "android::" + lib
|
||||
}
|
||||
if lib == "" {
|
||||
continue
|
||||
}
|
||||
mappedLibs = append(mappedLibs, lib)
|
||||
}
|
||||
sort.Strings(mappedLibs)
|
||||
mappedLibs = slices.Compact(mappedLibs)
|
||||
return mappedLibs
|
||||
},
|
||||
}
|
||||
|
||||
return template.Must(template.New("").Delims("<<", ">>").Funcs(funcMap).Parse(templateContents))
|
||||
}
|
||||
|
||||
func sliceWithPrefix(prefix string, slice []string) []string {
|
||||
output := make([]string, len(slice))
|
||||
for i, elem := range slice {
|
||||
output[i] = prefix + elem
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func templateListBuilder(builder *strings.Builder, itemPrefix string, items []string) {
|
||||
if len(items) > 0 {
|
||||
builder.WriteString("\n")
|
||||
for _, item := range items {
|
||||
builder.WriteString(" " + itemPrefix + item + "\n")
|
||||
}
|
||||
}
|
||||
builder.WriteString(")")
|
||||
}
|
||||
|
||||
func executeTemplate(templ *template.Template, buffer *bytes.Buffer, data any) string {
|
||||
buffer.Reset()
|
||||
if err := templ.Execute(buffer, data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
output := strings.TrimSpace(buffer.String())
|
||||
buffer.Reset()
|
||||
return output
|
||||
}
|
||||
|
||||
func (m *CmakeSnapshot) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
variations := []blueprint.Variation{
|
||||
{"os", "linux_glibc"},
|
||||
{"arch", "x86_64"},
|
||||
}
|
||||
ctx.AddVariationDependencies(variations, cmakeSnapshotModuleTag, m.Properties.Modules...)
|
||||
ctx.AddVariationDependencies(variations, cmakeSnapshotPrebuiltTag, m.Properties.Prebuilts...)
|
||||
}
|
||||
|
||||
func (m *CmakeSnapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
var templateBuffer bytes.Buffer
|
||||
var pprop cmakeProcessedProperties
|
||||
m.zipPath = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
|
||||
|
||||
// Process Library_mapping for more efficient lookups
|
||||
pprop.LibraryMapping = map[string]LibraryMappingProperty{}
|
||||
for _, elem := range m.Properties.Library_mapping {
|
||||
pprop.LibraryMapping[elem.Android_name] = elem
|
||||
|
||||
if elem.Package_pregenerated != "" {
|
||||
pprop.PregeneratedPackages = append(pprop.PregeneratedPackages, elem.Package_pregenerated)
|
||||
}
|
||||
sort.Strings(pprop.PregeneratedPackages)
|
||||
pprop.PregeneratedPackages = slices.Compact(pprop.PregeneratedPackages)
|
||||
|
||||
if elem.Package_system != "" {
|
||||
pprop.SystemPackages = append(pprop.SystemPackages, elem.Package_system)
|
||||
}
|
||||
sort.Strings(pprop.SystemPackages)
|
||||
pprop.SystemPackages = slices.Compact(pprop.SystemPackages)
|
||||
}
|
||||
|
||||
// Generating CMakeLists.txt rules for all modules in dependency tree
|
||||
moduleDirs := map[string][]string{}
|
||||
sourceFiles := map[string]android.Path{}
|
||||
visitedModules := map[string]bool{}
|
||||
var pregeneratedModules []*Module
|
||||
ctx.WalkDeps(func(dep_a android.Module, parent android.Module) bool {
|
||||
moduleName := ctx.OtherModuleName(dep_a)
|
||||
dep, ok := dep_a.(*Module)
|
||||
if !ok {
|
||||
return false // not a cc module
|
||||
}
|
||||
if visited := visitedModules[moduleName]; visited {
|
||||
return false // visit only once
|
||||
}
|
||||
visitedModules[moduleName] = true
|
||||
if mapping, ok := pprop.LibraryMapping[moduleName]; ok {
|
||||
if mapping.Package_pregenerated != "" {
|
||||
pregeneratedModules = append(pregeneratedModules, dep)
|
||||
}
|
||||
return false // mapped to system or pregenerated (we'll handle these later)
|
||||
}
|
||||
if ctx.OtherModuleDependencyTag(dep) == cmakeSnapshotPrebuiltTag {
|
||||
return false // we'll handle cmakeSnapshotPrebuiltTag later
|
||||
}
|
||||
if slices.Contains(ignoredSystemLibs, moduleName) {
|
||||
return false // system libs built in-tree for Android
|
||||
}
|
||||
if dep.compiler == nil {
|
||||
return false // unsupported module type (e.g. prebuilt)
|
||||
}
|
||||
isAidlModule := dep.compiler.baseCompilerProps().AidlInterface.Lang != ""
|
||||
|
||||
if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) {
|
||||
ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported",
|
||||
"CMake snapshots not supported, despite being a dependency for %s",
|
||||
ctx.OtherModuleName(parent))
|
||||
return false
|
||||
}
|
||||
|
||||
if veryVerbose {
|
||||
fmt.Println("WalkDeps: " + ctx.OtherModuleName(parent) + " -> " + moduleName)
|
||||
}
|
||||
|
||||
// Generate CMakeLists.txt fragment for this module
|
||||
templateToUse := templateCmakeModuleCc
|
||||
if isAidlModule {
|
||||
templateToUse = templateCmakeModuleAidl
|
||||
}
|
||||
moduleFragment := executeTemplate(templateToUse, &templateBuffer, struct {
|
||||
Ctx *android.ModuleContext
|
||||
M *Module
|
||||
Snapshot *CmakeSnapshot
|
||||
Pprop *cmakeProcessedProperties
|
||||
}{
|
||||
&ctx,
|
||||
dep,
|
||||
m,
|
||||
&pprop,
|
||||
})
|
||||
moduleDir := ctx.OtherModuleDir(dep)
|
||||
moduleDirs[moduleDir] = append(moduleDirs[moduleDir], moduleFragment)
|
||||
|
||||
if m.Properties.Include_sources {
|
||||
files, _ := android.OtherModuleProvider(ctx, dep, cmakeSnapshotSourcesProvider)
|
||||
for _, file := range files {
|
||||
sourceFiles[file.String()] = file
|
||||
}
|
||||
}
|
||||
|
||||
// if it's AIDL module, no need to dive into their dependencies
|
||||
return !isAidlModule
|
||||
})
|
||||
|
||||
// Enumerate sources for pregenerated modules
|
||||
if m.Properties.Include_sources {
|
||||
for _, dep := range pregeneratedModules {
|
||||
if !proptools.Bool(dep.Properties.Cmake_snapshot_supported) {
|
||||
ctx.OtherModulePropertyErrorf(dep, "cmake_snapshot_supported",
|
||||
"Pregenerated CMake snapshots not supported, despite being requested for %s",
|
||||
ctx.ModuleName())
|
||||
continue
|
||||
}
|
||||
|
||||
files, _ := android.OtherModuleProvider(ctx, dep, cmakeSnapshotSourcesProvider)
|
||||
for _, file := range files {
|
||||
sourceFiles[file.String()] = file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merging CMakeLists.txt contents for every module directory
|
||||
var makefilesList android.Paths
|
||||
for moduleDir, fragments := range moduleDirs {
|
||||
moduleCmakePath := android.PathForModuleGen(ctx, moduleDir, "CMakeLists.txt")
|
||||
makefilesList = append(makefilesList, moduleCmakePath)
|
||||
sort.Strings(fragments)
|
||||
android.WriteFileRule(ctx, moduleCmakePath, strings.Join(fragments, "\n\n\n"))
|
||||
}
|
||||
|
||||
// Generating top-level CMakeLists.txt
|
||||
mainCmakePath := android.PathForModuleGen(ctx, "CMakeLists.txt")
|
||||
makefilesList = append(makefilesList, mainCmakePath)
|
||||
mainContents := executeTemplate(templateCmakeMain, &templateBuffer, struct {
|
||||
Ctx *android.ModuleContext
|
||||
M *CmakeSnapshot
|
||||
ModuleDirs map[string][]string
|
||||
Pprop *cmakeProcessedProperties
|
||||
}{
|
||||
&ctx,
|
||||
m,
|
||||
moduleDirs,
|
||||
&pprop,
|
||||
})
|
||||
android.WriteFileRule(ctx, mainCmakePath, mainContents)
|
||||
|
||||
// Generating CMake extensions
|
||||
extPath := android.PathForModuleGen(ctx, "cmake", "AppendCxxFlagsIfSupported.cmake")
|
||||
makefilesList = append(makefilesList, extPath)
|
||||
android.WriteFileRuleVerbatim(ctx, extPath, cmakeExtAppendFlags)
|
||||
extPath = android.PathForModuleGen(ctx, "cmake", "AddAidlLibrary.cmake")
|
||||
makefilesList = append(makefilesList, extPath)
|
||||
android.WriteFileRuleVerbatim(ctx, extPath, cmakeExtAddAidlLibrary)
|
||||
|
||||
// Generating the final zip file
|
||||
zipRule := android.NewRuleBuilder(pctx, ctx)
|
||||
zipCmd := zipRule.Command().
|
||||
BuiltTool("soong_zip").
|
||||
FlagWithOutput("-o ", m.zipPath)
|
||||
|
||||
// Packaging all sources into the zip file
|
||||
if m.Properties.Include_sources {
|
||||
var sourcesList android.Paths
|
||||
for _, file := range sourceFiles {
|
||||
sourcesList = append(sourcesList, file)
|
||||
}
|
||||
|
||||
sourcesRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_sources.rsp")
|
||||
zipCmd.FlagWithRspFileInputList("-r ", sourcesRspFile, sourcesList)
|
||||
}
|
||||
|
||||
// Packaging all make files into the zip file
|
||||
makefilesRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_makefiles.rsp")
|
||||
zipCmd.
|
||||
FlagWithArg("-C ", android.PathForModuleGen(ctx).OutputPath.String()).
|
||||
FlagWithRspFileInputList("-r ", makefilesRspFile, makefilesList)
|
||||
|
||||
// Packaging all prebuilts into the zip file
|
||||
if len(m.Properties.Prebuilts) > 0 {
|
||||
var prebuiltsList android.Paths
|
||||
|
||||
ctx.VisitDirectDepsWithTag(cmakeSnapshotPrebuiltTag, func(dep android.Module) {
|
||||
for _, file := range dep.FilesToInstall() {
|
||||
prebuiltsList = append(prebuiltsList, file)
|
||||
}
|
||||
})
|
||||
|
||||
prebuiltsRspFile := android.PathForModuleObj(ctx, ctx.ModuleName()+"_prebuilts.rsp")
|
||||
zipCmd.
|
||||
FlagWithArg("-C ", android.PathForArbitraryOutput(ctx).String()).
|
||||
FlagWithArg("-P ", "prebuilts").
|
||||
FlagWithRspFileInputList("-r ", prebuiltsRspFile, prebuiltsList)
|
||||
}
|
||||
|
||||
// Finish generating the final zip file
|
||||
zipRule.Build(m.zipPath.String(), "archiving "+ctx.ModuleName())
|
||||
}
|
||||
|
||||
func (m *CmakeSnapshot) OutputFiles(tag string) (android.Paths, error) {
|
||||
switch tag {
|
||||
case "":
|
||||
return android.Paths{m.zipPath}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *CmakeSnapshot) AndroidMkEntries() []android.AndroidMkEntries {
|
||||
return []android.AndroidMkEntries{{
|
||||
Class: "DATA",
|
||||
OutputFile: android.OptionalPathForPath(m.zipPath),
|
||||
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
|
||||
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
||||
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
|
||||
},
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
func getModuleType(m *Module) string {
|
||||
switch m.linker.(type) {
|
||||
case *binaryDecorator:
|
||||
return "executable"
|
||||
case *libraryDecorator:
|
||||
return "library"
|
||||
case *testBinary:
|
||||
return "executable"
|
||||
}
|
||||
panic(fmt.Sprintf("Unexpected module type: %T", m.compiler))
|
||||
}
|
||||
|
||||
func getExtraLibs(m *Module) []string {
|
||||
switch decorator := m.linker.(type) {
|
||||
case *testBinary:
|
||||
if decorator.testDecorator.gtest() {
|
||||
return []string{"libgtest"}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIncludeDirs(ctx android.ModuleContext, m *Module) []string {
|
||||
moduleDir := ctx.OtherModuleDir(m) + string(filepath.Separator)
|
||||
switch decorator := m.compiler.(type) {
|
||||
case *libraryDecorator:
|
||||
return sliceWithPrefix(moduleDir, decorator.flagExporter.Properties.Export_include_dirs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// cmake_snapshot allows defining source packages for release outside of Android build tree.
|
||||
// As a result of cmake_snapshot module build, a zip file is generated with CMake build definitions
|
||||
// for selected source modules, their dependencies and optionally also the source code itself.
|
||||
func CmakeSnapshotFactory() android.Module {
|
||||
module := &CmakeSnapshot{}
|
||||
module.AddProperties(&module.Properties)
|
||||
android.InitAndroidModule(module)
|
||||
return module
|
||||
}
|
||||
|
||||
func init() {
|
||||
android.InitRegistrationContext.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
|
||||
}
|
69
cc/cmake_snapshot_test.go
Normal file
69
cc/cmake_snapshot_test.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Copyright 2024 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 (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
)
|
||||
|
||||
func wasGenerated(t *testing.T, m *android.TestingModule, fileName string, ruleType string) {
|
||||
t.Helper()
|
||||
ruleName := m.Output(fileName).Rule.String()
|
||||
if !strings.HasSuffix(ruleName, ruleType) {
|
||||
t.Errorf("Main Cmake file wasn't generated, expected rule %v, found %v", ruleType, ruleName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyCmakeSnapshot(t *testing.T) {
|
||||
t.Parallel()
|
||||
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
|
||||
cc_cmake_snapshot {
|
||||
name: "foo",
|
||||
modules: [],
|
||||
prebuilts: ["libc++"],
|
||||
include_sources: true,
|
||||
}`)
|
||||
|
||||
snapshotModule := result.ModuleForTests("foo", "")
|
||||
|
||||
wasGenerated(t, &snapshotModule, "CMakeLists.txt", "rawFileCopy")
|
||||
wasGenerated(t, &snapshotModule, "foo.zip", "")
|
||||
}
|
||||
|
||||
func TestCmakeSnapshotWithBinary(t *testing.T) {
|
||||
t.Parallel()
|
||||
xtra := android.FixtureAddTextFile("some/module/Android.bp", `
|
||||
cc_binary {
|
||||
name: "foo_binary",
|
||||
host_supported: true,
|
||||
cmake_snapshot_supported: true,
|
||||
}
|
||||
`)
|
||||
result := android.GroupFixturePreparers(PrepareForIntegrationTestWithCc, xtra).RunTestWithBp(t, `
|
||||
cc_cmake_snapshot {
|
||||
name: "foo",
|
||||
modules: [
|
||||
"foo_binary",
|
||||
],
|
||||
include_sources: true,
|
||||
}`)
|
||||
|
||||
snapshotModule := result.ModuleForTests("foo", "")
|
||||
|
||||
wasGenerated(t, &snapshotModule, "some/module/CMakeLists.txt", "rawFileCopy")
|
||||
}
|
|
@ -278,6 +278,10 @@ func (compiler *baseCompiler) compilerProps() []interface{} {
|
|||
return []interface{}{&compiler.Properties, &compiler.Proto}
|
||||
}
|
||||
|
||||
func (compiler *baseCompiler) baseCompilerProps() BaseCompilerProperties {
|
||||
return compiler.Properties
|
||||
}
|
||||
|
||||
func includeBuildDirectory(prop *bool) bool {
|
||||
return proptools.BoolDefault(prop, true)
|
||||
}
|
||||
|
|
|
@ -287,6 +287,10 @@ func (linker *baseLinker) linkerProps() []interface{} {
|
|||
return []interface{}{&linker.Properties, &linker.dynamicProperties}
|
||||
}
|
||||
|
||||
func (linker *baseLinker) baseLinkerProps() BaseLinkerProperties {
|
||||
return linker.Properties
|
||||
}
|
||||
|
||||
func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
|
||||
deps.WholeStaticLibs = append(deps.WholeStaticLibs, linker.Properties.Whole_static_libs...)
|
||||
deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Header_libs...)
|
||||
|
|
|
@ -35,6 +35,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
|
|||
|
||||
ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
|
||||
ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
|
||||
ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
|
||||
ctx.RegisterModuleType("cc_object", ObjectFactory)
|
||||
ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
|
||||
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
|
||||
|
@ -570,17 +571,17 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
|
|||
|
||||
// Additional files needed in tests that disallow non-existent source.
|
||||
android.MockFS{
|
||||
"defaults/cc/common/libc.map.txt": nil,
|
||||
"defaults/cc/common/libdl.map.txt": nil,
|
||||
"defaults/cc/common/libft2.map.txt": nil,
|
||||
"defaults/cc/common/libm.map.txt": nil,
|
||||
"defaults/cc/common/ndk_libc++_shared": nil,
|
||||
"defaults/cc/common/crtbegin_so.c": nil,
|
||||
"defaults/cc/common/crtbegin.c": nil,
|
||||
"defaults/cc/common/crtend_so.c": nil,
|
||||
"defaults/cc/common/crtend.c": nil,
|
||||
"defaults/cc/common/crtbrand.c": nil,
|
||||
"external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
|
||||
"defaults/cc/common/libc.map.txt": nil,
|
||||
"defaults/cc/common/libdl.map.txt": nil,
|
||||
"defaults/cc/common/libft2.map.txt": nil,
|
||||
"defaults/cc/common/libm.map.txt": nil,
|
||||
"defaults/cc/common/ndk_libc++_shared": nil,
|
||||
"defaults/cc/common/crtbegin_so.c": nil,
|
||||
"defaults/cc/common/crtbegin.c": nil,
|
||||
"defaults/cc/common/crtend_so.c": nil,
|
||||
"defaults/cc/common/crtend.c": nil,
|
||||
"defaults/cc/common/crtbrand.c": nil,
|
||||
"external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
|
||||
|
||||
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
|
||||
"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a": nil,
|
||||
|
|
Loading…
Reference in a new issue