| Cole Faust | dff9c14 | 2023-09-01 16:11:47 -0700 | [diff] [blame] | 1 | // Copyright 2023 Google Inc. All rights reserved. | 
|  | 2 | // | 
|  | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 | // you may not use this file except in compliance with the License. | 
|  | 5 | // You may obtain a copy of the License at | 
|  | 6 | // | 
|  | 7 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 | // | 
|  | 9 | // Unless required by applicable law or agreed to in writing, software | 
|  | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 | // See the License for the specific language governing permissions and | 
|  | 13 | // limitations under the License. | 
|  | 14 |  | 
|  | 15 | package etc | 
|  | 16 |  | 
|  | 17 | import ( | 
|  | 18 | "android/soong/android" | 
|  | 19 | "path/filepath" | 
|  | 20 | "strings" | 
|  | 21 | ) | 
|  | 22 |  | 
|  | 23 | func init() { | 
|  | 24 | RegisterInstallSymlinkBuildComponents(android.InitRegistrationContext) | 
|  | 25 | } | 
|  | 26 |  | 
|  | 27 | func RegisterInstallSymlinkBuildComponents(ctx android.RegistrationContext) { | 
|  | 28 | ctx.RegisterModuleType("install_symlink", InstallSymlinkFactory) | 
|  | 29 | } | 
|  | 30 |  | 
|  | 31 | // install_symlink can be used to install an symlink with an arbitrary target to an arbitrary path | 
|  | 32 | // on the device. | 
|  | 33 | func InstallSymlinkFactory() android.Module { | 
|  | 34 | module := &InstallSymlink{} | 
|  | 35 | module.AddProperties(&module.properties) | 
|  | 36 | android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) | 
|  | 37 | return module | 
|  | 38 | } | 
|  | 39 |  | 
|  | 40 | type InstallSymlinkProperties struct { | 
|  | 41 | // Where to install this symlink, relative to the partition it's installed on. | 
|  | 42 | // Which partition it's installed on can be controlled by the vendor, system_ext, ramdisk, etc. | 
|  | 43 | // properties. | 
|  | 44 | Installed_location string | 
|  | 45 | // The target of the symlink, aka where the symlink points. | 
|  | 46 | Symlink_target string | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | type InstallSymlink struct { | 
|  | 50 | android.ModuleBase | 
|  | 51 | properties InstallSymlinkProperties | 
|  | 52 |  | 
|  | 53 | output        android.Path | 
|  | 54 | installedPath android.InstallPath | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | func (m *InstallSymlink) GenerateAndroidBuildActions(ctx android.ModuleContext) { | 
|  | 58 | if filepath.Clean(m.properties.Symlink_target) != m.properties.Symlink_target { | 
|  | 59 | ctx.PropertyErrorf("symlink_target", "Should be a clean filepath") | 
|  | 60 | return | 
|  | 61 | } | 
|  | 62 | if filepath.Clean(m.properties.Installed_location) != m.properties.Installed_location { | 
|  | 63 | ctx.PropertyErrorf("installed_location", "Should be a clean filepath") | 
|  | 64 | return | 
|  | 65 | } | 
|  | 66 | if strings.HasPrefix(m.properties.Installed_location, "../") || strings.HasPrefix(m.properties.Installed_location, "/") { | 
|  | 67 | ctx.PropertyErrorf("installed_location", "Should not start with / or ../") | 
|  | 68 | return | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | out := android.PathForModuleOut(ctx, "out.txt") | 
|  | 72 | android.WriteFileRuleVerbatim(ctx, out, "") | 
|  | 73 | m.output = out | 
|  | 74 |  | 
|  | 75 | name := filepath.Base(m.properties.Installed_location) | 
|  | 76 | installDir := android.PathForModuleInstall(ctx, filepath.Dir(m.properties.Installed_location)) | 
|  | 77 | m.installedPath = ctx.InstallAbsoluteSymlink(installDir, name, m.properties.Symlink_target) | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | func (m *InstallSymlink) AndroidMkEntries() []android.AndroidMkEntries { | 
|  | 81 | return []android.AndroidMkEntries{{ | 
|  | 82 | Class: "FAKE", | 
|  | 83 | // Need at least one output file in order for this to take effect. | 
|  | 84 | OutputFile: android.OptionalPathForPath(m.output), | 
|  | 85 | Include:    "$(BUILD_PHONY_PACKAGE)", | 
|  | 86 | ExtraEntries: []android.AndroidMkExtraEntriesFunc{ | 
|  | 87 | func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { | 
|  | 88 | entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", m.installedPath.String()) | 
|  | 89 | }, | 
|  | 90 | }, | 
|  | 91 | }} | 
|  | 92 | } |