blob: c9056e1b46e6b0c4ee80ce7f0ac1758ec78ccfd4 [file] [log] [blame]
Ivan Lozanoffee3342019-08-27 12:03:00 -07001// Copyright 2019 The Android Open Source Project
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
15package rust
16
17import (
18 "fmt"
19 "io"
20 "path/filepath"
21 "regexp"
22 "strings"
23
24 "android/soong/android"
25)
26
27type AndroidMkContext interface {
28 Name() string
29 Target() android.Target
30 subAndroidMk(*android.AndroidMkData, interface{})
31}
32
33type subAndroidMkProvider interface {
34 AndroidMk(AndroidMkContext, *android.AndroidMkData)
35}
36
37func (mod *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) {
38 if mod.subAndroidMkOnce == nil {
39 mod.subAndroidMkOnce = make(map[subAndroidMkProvider]bool)
40 }
41 if androidmk, ok := obj.(subAndroidMkProvider); ok {
42 if !mod.subAndroidMkOnce[androidmk] {
43 mod.subAndroidMkOnce[androidmk] = true
44 androidmk.AndroidMk(mod, data)
45 }
46 }
47}
48
49func (mod *Module) AndroidMk() android.AndroidMkData {
50 ret := android.AndroidMkData{
51 OutputFile: mod.outputFile,
52 Include: "$(BUILD_SYSTEM)/soong_rust_prebuilt.mk",
53 Extra: []android.AndroidMkExtraFunc{
54 func(w io.Writer, outputFile android.Path) {
55 if len(mod.Properties.AndroidMkRlibs) > 0 {
56 fmt.Fprintln(w, "LOCAL_RLIB_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkRlibs, " "))
57 }
58 if len(mod.Properties.AndroidMkDylibs) > 0 {
59 fmt.Fprintln(w, "LOCAL_DYLIB_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkDylibs, " "))
60 }
61 if len(mod.Properties.AndroidMkProcMacroLibs) > 0 {
62 fmt.Fprintln(w, "LOCAL_PROC_MACRO_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkProcMacroLibs, " "))
63 }
64 if len(mod.Properties.AndroidMkSharedLibs) > 0 {
65 fmt.Fprintln(w, "LOCAL_SHARED_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkSharedLibs, " "))
66 }
67 if len(mod.Properties.AndroidMkStaticLibs) > 0 {
68 fmt.Fprintln(w, "LOCAL_STATIC_LIBRARIES := "+strings.Join(mod.Properties.AndroidMkStaticLibs, " "))
69 }
70 },
71 },
72 }
73
74 mod.subAndroidMk(&ret, mod.compiler)
75
76 return ret
77}
78
79func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
80 ctx.subAndroidMk(ret, binary.baseCompiler)
81
82 ret.Class = "EXECUTABLES"
83 ret.DistFile = binary.distFile
84 ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
85 fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String())
86 })
87}
88
89func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
90 ctx.subAndroidMk(ret, library.baseCompiler)
91
92 if library.rlib() {
93 ret.Class = "RLIB_LIBRARIES"
94 } else if library.dylib() {
95 ret.Class = "DYLIB_LIBRARIES"
96 }
97 ret.DistFile = library.distFile
98 ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
99 if !library.rlib() {
100 fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", library.unstrippedOutputFile.String())
101 }
102 })
103}
104
105func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
106 ctx.subAndroidMk(ret, procMacro.baseCompiler)
107
108 ret.Class = "PROC_MACRO_LIBRARIES"
109 ret.DistFile = procMacro.distFile
110
111}
112
113func (compiler *baseCompiler) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
114 // Soong installation is only supported for host modules. Have Make
115 // installation trigger Soong installation.
116 if ctx.Target().Os.Class == android.Host {
117 ret.OutputFile = android.OptionalPathForPath(compiler.path)
118 }
119 ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
120 path := compiler.path.RelPathString()
121 dir, file := filepath.Split(path)
122 stem, suffix, _ := splitFileExt(file)
123 fmt.Fprintln(w, "LOCAL_MODULE_SUFFIX := "+suffix)
124 fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(OUT_DIR)/"+filepath.Clean(dir))
125 fmt.Fprintln(w, "LOCAL_MODULE_STEM := "+stem)
126 })
127}
128
129//TODO: splitFileExt copied from cc/util.go; move this to android/util.go and refactor usages.
130
131// splitFileExt splits a file name into root, suffix and ext. root stands for the file name without
132// the file extension and the version number (e.g. "libexample"). suffix stands for the
133// concatenation of the file extension and the version number (e.g. ".so.1.0"). ext stands for the
134// file extension after the version numbers are trimmed (e.g. ".so").
135var shlibVersionPattern = regexp.MustCompile("(?:\\.\\d+(?:svn)?)+")
136
137func splitFileExt(name string) (string, string, string) {
138 // Extract and trim the shared lib version number if the file name ends with dot digits.
139 suffix := ""
140 matches := shlibVersionPattern.FindAllStringIndex(name, -1)
141 if len(matches) > 0 {
142 lastMatch := matches[len(matches)-1]
143 if lastMatch[1] == len(name) {
144 suffix = name[lastMatch[0]:lastMatch[1]]
145 name = name[0:lastMatch[0]]
146 }
147 }
148
149 // Extract the file name root and the file extension.
150 ext := filepath.Ext(name)
151 root := strings.TrimSuffix(name, ext)
152 suffix = ext + suffix
153
154 return root, suffix, ext
155}