// Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package bionic import ( "fmt" "io" "strings" "github.com/google/blueprint/proptools" "android/soong/android" ) // bionic_mountpoint is a module type that is specialized to create // mount points for Bionic files (libc, libdl, libm, and linker). // // With following description, // // bionic_mountpoint { // name: "libc.mountpoint", // stem: "libc.so", // src: "dummy_mountpoint", // library: true, // symlinks: ["libc.so"], // } // // , the build system does following jobs: // // A mount point /bionic/lib[64]/libc.so is created. Its content // is from the file 'dummy_mountpoint'. // // Then a symlink is created at /system/lib[64]/libc.so which points to // the created mountpoint. // // At runtime, on the mount point, either bootstrap Bionic or default Bionic // (which is from the runtime APEX) is mounted by the init process. The // symlink exists to provide consistent legacy path for compatibility // reason. func init() { android.RegisterModuleType("bionic_mountpoint", bionicMountpointFactory) } type bionicMountpoint struct { android.ModuleBase properties bionicMountpointProperties outputFile android.Path pathInPartition string stem string } type bionicMountpointProperties struct { // The file that is installed as the mount point Src *string // True if the mount point is for a Bionic library such libc.so Library *bool // True if the mount point is for a Bionic binary such as linker Binary *bool // Base name of the mount point Stem *string `android:"arch_variant"` // Append to the name of the output Suffix *string `android:"arch_variant"` // Symlinks to the mountpoints from the system and recovery partitions // Symlinks names will have the same suffix as the mount point Symlinks []string } func (m *bionicMountpoint) DepsMutator(ctx android.BottomUpMutatorContext) { if Bool(m.properties.Library) == Bool(m.properties.Binary) { ctx.ModuleErrorf("either binary or library must be set to true") return } if m.properties.Stem == nil { ctx.PropertyErrorf("stem", "stem must be set") return } if m.properties.Src == nil { ctx.PropertyErrorf("src", "src must be set") } android.ExtractSourceDeps(ctx, m.properties.Src) } func (m *bionicMountpoint) GenerateAndroidBuildActions(ctx android.ModuleContext) { if Bool(m.properties.Library) { m.pathInPartition = "lib" if m.Arch().ArchType.Multilib == "lib64" { m.pathInPartition = "lib64" } } else if Bool(m.properties.Binary) { m.pathInPartition = "bin" } m.stem = String(m.properties.Stem) + String(m.properties.Suffix) m.outputFile = ctx.ExpandSource(String(m.properties.Src), "src") } func (m *bionicMountpoint) AndroidMk() android.AndroidMkData { return android.AndroidMkData { Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { if !m.Arch().Native { return } fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name) fmt.Fprintln(w, "LOCAL_USE_CLANG_LLD := false") fmt.Fprintln(w, "LOCAL_STRIP_MODULE := false") if Bool(m.properties.Library) { fmt.Fprintln(w, "LOCAL_MODULE_CLASS := SHARED_LIBRARIES") } else if Bool(m.properties.Binary) { fmt.Fprintln(w, "LOCAL_MODULE_CLASS := EXECUTABLES") } fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional") fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", m.outputFile.String()) fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", m.Arch().ArchType.String()) fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(TARGET_ROOT_OUT)/bionic/" + m.pathInPartition) fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem) if len(m.properties.Symlinks) > 0 { symlink_dir_in_system := "$(TARGET_OUT)/" + m.pathInPartition + "/" symlink_dir_in_recovery := "$(TARGET_RECOVERY_ROOT_OUT)/system/" + m.pathInPartition + "/" symlink_target := "/bionic/" + m.pathInPartition + "/" + m.stem cmds := []string{} cmds = append(cmds, "$(hide) mkdir -p " + symlink_dir_in_system) cmds = append(cmds, "mkdir -p " + symlink_dir_in_recovery) for _, s := range m.properties.Symlinks { symlink := s + String(m.properties.Suffix) cmds = append(cmds, "ln -sf " + symlink_target + " " + symlink_dir_in_system + symlink) cmds = append(cmds, "ln -sf " + symlink_target + " " + symlink_dir_in_recovery + symlink) } fmt.Fprintln(w, "LOCAL_POST_INSTALL_CMD := " + strings.Join(cmds, " && ")) } fmt.Fprintln(w, "include $(BUILD_PREBUILT)") }, } } func bionicMountpointFactory() android.Module { m := &bionicMountpoint{} m.AddProperties(&m.properties) android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth) return m } var Bool = proptools.Bool var String = proptools.String