xref: /aosp_15_r20/build/soong/cc/ndk_headers.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2016 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage cc
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
19*333d2b36SAndroid Build Coastguard Worker
20*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
21*333d2b36SAndroid Build Coastguard Worker
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
23*333d2b36SAndroid Build Coastguard Worker)
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Workervar (
26*333d2b36SAndroid Build Coastguard Worker	preprocessNdkHeader = pctx.AndroidStaticRule("preprocessNdkHeader",
27*333d2b36SAndroid Build Coastguard Worker		blueprint.RuleParams{
28*333d2b36SAndroid Build Coastguard Worker			Command:     "$preprocessor -o $out $in",
29*333d2b36SAndroid Build Coastguard Worker			CommandDeps: []string{"$preprocessor"},
30*333d2b36SAndroid Build Coastguard Worker		},
31*333d2b36SAndroid Build Coastguard Worker		"preprocessor")
32*333d2b36SAndroid Build Coastguard Worker)
33*333d2b36SAndroid Build Coastguard Worker
34*333d2b36SAndroid Build Coastguard Worker// Returns the NDK base include path for use with sdk_version current. Usable with -I.
35*333d2b36SAndroid Build Coastguard Workerfunc getCurrentIncludePath(ctx android.PathContext) android.OutputPath {
36*333d2b36SAndroid Build Coastguard Worker	return getNdkSysrootBase(ctx).Join(ctx, "usr/include")
37*333d2b36SAndroid Build Coastguard Worker}
38*333d2b36SAndroid Build Coastguard Worker
39*333d2b36SAndroid Build Coastguard Workertype headerProperties struct {
40*333d2b36SAndroid Build Coastguard Worker	// Base directory of the headers being installed. As an example:
41*333d2b36SAndroid Build Coastguard Worker	//
42*333d2b36SAndroid Build Coastguard Worker	// ndk_headers {
43*333d2b36SAndroid Build Coastguard Worker	//     name: "foo",
44*333d2b36SAndroid Build Coastguard Worker	//     from: "include",
45*333d2b36SAndroid Build Coastguard Worker	//     to: "",
46*333d2b36SAndroid Build Coastguard Worker	//     srcs: ["include/foo/bar/baz.h"],
47*333d2b36SAndroid Build Coastguard Worker	// }
48*333d2b36SAndroid Build Coastguard Worker	//
49*333d2b36SAndroid Build Coastguard Worker	// Will install $SYSROOT/usr/include/foo/bar/baz.h. If `from` were instead
50*333d2b36SAndroid Build Coastguard Worker	// "include/foo", it would have installed $SYSROOT/usr/include/bar/baz.h.
51*333d2b36SAndroid Build Coastguard Worker	From *string
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker	// Install path within the sysroot. This is relative to usr/include.
54*333d2b36SAndroid Build Coastguard Worker	To *string
55*333d2b36SAndroid Build Coastguard Worker
56*333d2b36SAndroid Build Coastguard Worker	// List of headers to install. Glob compatible. Common case is "include/**/*.h".
57*333d2b36SAndroid Build Coastguard Worker	Srcs []string `android:"path"`
58*333d2b36SAndroid Build Coastguard Worker
59*333d2b36SAndroid Build Coastguard Worker	// Source paths that should be excluded from the srcs glob.
60*333d2b36SAndroid Build Coastguard Worker	Exclude_srcs []string `android:"path"`
61*333d2b36SAndroid Build Coastguard Worker
62*333d2b36SAndroid Build Coastguard Worker	// Path to the NOTICE file associated with the headers.
63*333d2b36SAndroid Build Coastguard Worker	License *string `android:"path"`
64*333d2b36SAndroid Build Coastguard Worker
65*333d2b36SAndroid Build Coastguard Worker	// Set to true if the headers installed by this module should skip
66*333d2b36SAndroid Build Coastguard Worker	// verification. This step ensures that each header is self-contained (can
67*333d2b36SAndroid Build Coastguard Worker	// be #included alone) and is valid C. This should not be disabled except in
68*333d2b36SAndroid Build Coastguard Worker	// rare cases. Outside bionic and external, if you're using this option
69*333d2b36SAndroid Build Coastguard Worker	// you've probably made a mistake.
70*333d2b36SAndroid Build Coastguard Worker	Skip_verification *bool
71*333d2b36SAndroid Build Coastguard Worker}
72*333d2b36SAndroid Build Coastguard Worker
73*333d2b36SAndroid Build Coastguard Workertype headerModule struct {
74*333d2b36SAndroid Build Coastguard Worker	android.ModuleBase
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Worker	properties headerProperties
77*333d2b36SAndroid Build Coastguard Worker
78*333d2b36SAndroid Build Coastguard Worker	srcPaths     android.Paths
79*333d2b36SAndroid Build Coastguard Worker	installPaths android.Paths
80*333d2b36SAndroid Build Coastguard Worker	licensePath  android.Path
81*333d2b36SAndroid Build Coastguard Worker}
82*333d2b36SAndroid Build Coastguard Worker
83*333d2b36SAndroid Build Coastguard Workerfunc getHeaderInstallDir(ctx android.ModuleContext, header android.Path, from string,
84*333d2b36SAndroid Build Coastguard Worker	to string) android.OutputPath {
85*333d2b36SAndroid Build Coastguard Worker	// Output path is the sysroot base + "usr/include" + to directory + directory component
86*333d2b36SAndroid Build Coastguard Worker	// of the file without the leading from directory stripped.
87*333d2b36SAndroid Build Coastguard Worker	//
88*333d2b36SAndroid Build Coastguard Worker	// Given:
89*333d2b36SAndroid Build Coastguard Worker	// sysroot base = "ndk/sysroot"
90*333d2b36SAndroid Build Coastguard Worker	// from = "include/foo"
91*333d2b36SAndroid Build Coastguard Worker	// to = "bar"
92*333d2b36SAndroid Build Coastguard Worker	// header = "include/foo/woodly/doodly.h"
93*333d2b36SAndroid Build Coastguard Worker	// output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
94*333d2b36SAndroid Build Coastguard Worker
95*333d2b36SAndroid Build Coastguard Worker	// full/platform/path/to/include/foo
96*333d2b36SAndroid Build Coastguard Worker	fullFromPath := android.PathForModuleSrc(ctx, from)
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Worker	// full/platform/path/to/include/foo/woodly
99*333d2b36SAndroid Build Coastguard Worker	headerDir := filepath.Dir(header.String())
100*333d2b36SAndroid Build Coastguard Worker
101*333d2b36SAndroid Build Coastguard Worker	// woodly
102*333d2b36SAndroid Build Coastguard Worker	strippedHeaderDir, err := filepath.Rel(fullFromPath.String(), headerDir)
103*333d2b36SAndroid Build Coastguard Worker	if err != nil {
104*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s", headerDir,
105*333d2b36SAndroid Build Coastguard Worker			fullFromPath.String(), err)
106*333d2b36SAndroid Build Coastguard Worker	}
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Worker	// full/platform/path/to/sysroot/usr/include/bar/woodly
109*333d2b36SAndroid Build Coastguard Worker	installDir := getCurrentIncludePath(ctx).Join(ctx, to, strippedHeaderDir)
110*333d2b36SAndroid Build Coastguard Worker
111*333d2b36SAndroid Build Coastguard Worker	// full/platform/path/to/sysroot/usr/include/bar/woodly/doodly.h
112*333d2b36SAndroid Build Coastguard Worker	return installDir
113*333d2b36SAndroid Build Coastguard Worker}
114*333d2b36SAndroid Build Coastguard Worker
115*333d2b36SAndroid Build Coastguard Workerfunc (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
116*333d2b36SAndroid Build Coastguard Worker	if String(m.properties.License) == "" {
117*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("license", "field is required")
118*333d2b36SAndroid Build Coastguard Worker	}
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Worker	m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
121*333d2b36SAndroid Build Coastguard Worker
122*333d2b36SAndroid Build Coastguard Worker	m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
123*333d2b36SAndroid Build Coastguard Worker	for _, header := range m.srcPaths {
124*333d2b36SAndroid Build Coastguard Worker		installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
125*333d2b36SAndroid Build Coastguard Worker			String(m.properties.To))
126*333d2b36SAndroid Build Coastguard Worker		installPath := installDir.Join(ctx, header.Base())
127*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
128*333d2b36SAndroid Build Coastguard Worker			Rule:   android.Cp,
129*333d2b36SAndroid Build Coastguard Worker			Input:  header,
130*333d2b36SAndroid Build Coastguard Worker			Output: installPath,
131*333d2b36SAndroid Build Coastguard Worker		})
132*333d2b36SAndroid Build Coastguard Worker		m.installPaths = append(m.installPaths, installPath)
133*333d2b36SAndroid Build Coastguard Worker	}
134*333d2b36SAndroid Build Coastguard Worker
135*333d2b36SAndroid Build Coastguard Worker	if len(m.installPaths) == 0 {
136*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs)
137*333d2b36SAndroid Build Coastguard Worker	}
138*333d2b36SAndroid Build Coastguard Worker}
139*333d2b36SAndroid Build Coastguard Worker
140*333d2b36SAndroid Build Coastguard Worker// ndk_headers installs the sets of ndk headers defined in the srcs property
141*333d2b36SAndroid Build Coastguard Worker// to the sysroot base + "usr/include" + to directory + directory component.
142*333d2b36SAndroid Build Coastguard Worker// ndk_headers requires the license file to be specified. Example:
143*333d2b36SAndroid Build Coastguard Worker//
144*333d2b36SAndroid Build Coastguard Worker//	Given:
145*333d2b36SAndroid Build Coastguard Worker//	sysroot base = "ndk/sysroot"
146*333d2b36SAndroid Build Coastguard Worker//	from = "include/foo"
147*333d2b36SAndroid Build Coastguard Worker//	to = "bar"
148*333d2b36SAndroid Build Coastguard Worker//	header = "include/foo/woodly/doodly.h"
149*333d2b36SAndroid Build Coastguard Worker//	output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
150*333d2b36SAndroid Build Coastguard Workerfunc NdkHeadersFactory() android.Module {
151*333d2b36SAndroid Build Coastguard Worker	module := &headerModule{}
152*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&module.properties)
153*333d2b36SAndroid Build Coastguard Worker	android.InitAndroidModule(module)
154*333d2b36SAndroid Build Coastguard Worker	return module
155*333d2b36SAndroid Build Coastguard Worker}
156*333d2b36SAndroid Build Coastguard Worker
157*333d2b36SAndroid Build Coastguard Worker// preprocessed_ndk_header {
158*333d2b36SAndroid Build Coastguard Worker//
159*333d2b36SAndroid Build Coastguard Worker//	name: "foo",
160*333d2b36SAndroid Build Coastguard Worker//	preprocessor: "foo.sh",
161*333d2b36SAndroid Build Coastguard Worker//	srcs: [...],
162*333d2b36SAndroid Build Coastguard Worker//	to: "android",
163*333d2b36SAndroid Build Coastguard Worker//
164*333d2b36SAndroid Build Coastguard Worker// }
165*333d2b36SAndroid Build Coastguard Worker//
166*333d2b36SAndroid Build Coastguard Worker// Will invoke the preprocessor as:
167*333d2b36SAndroid Build Coastguard Worker//
168*333d2b36SAndroid Build Coastguard Worker//	$preprocessor -o $SYSROOT/usr/include/android/needs_preproc.h $src
169*333d2b36SAndroid Build Coastguard Worker//
170*333d2b36SAndroid Build Coastguard Worker// For each src in srcs.
171*333d2b36SAndroid Build Coastguard Workertype preprocessedHeadersProperties struct {
172*333d2b36SAndroid Build Coastguard Worker	// The preprocessor to run. Must be a program inside the source directory
173*333d2b36SAndroid Build Coastguard Worker	// with no dependencies.
174*333d2b36SAndroid Build Coastguard Worker	Preprocessor *string
175*333d2b36SAndroid Build Coastguard Worker
176*333d2b36SAndroid Build Coastguard Worker	// Source path to the files to be preprocessed.
177*333d2b36SAndroid Build Coastguard Worker	Srcs []string
178*333d2b36SAndroid Build Coastguard Worker
179*333d2b36SAndroid Build Coastguard Worker	// Source paths that should be excluded from the srcs glob.
180*333d2b36SAndroid Build Coastguard Worker	Exclude_srcs []string
181*333d2b36SAndroid Build Coastguard Worker
182*333d2b36SAndroid Build Coastguard Worker	// Install path within the sysroot. This is relative to usr/include.
183*333d2b36SAndroid Build Coastguard Worker	To *string
184*333d2b36SAndroid Build Coastguard Worker
185*333d2b36SAndroid Build Coastguard Worker	// Path to the NOTICE file associated with the headers.
186*333d2b36SAndroid Build Coastguard Worker	License *string
187*333d2b36SAndroid Build Coastguard Worker
188*333d2b36SAndroid Build Coastguard Worker	// Set to true if the headers installed by this module should skip
189*333d2b36SAndroid Build Coastguard Worker	// verification. This step ensures that each header is self-contained (can
190*333d2b36SAndroid Build Coastguard Worker	// be #included alone) and is valid C. This should not be disabled except in
191*333d2b36SAndroid Build Coastguard Worker	// rare cases. Outside bionic and external, if you're using this option
192*333d2b36SAndroid Build Coastguard Worker	// you've probably made a mistake.
193*333d2b36SAndroid Build Coastguard Worker	Skip_verification *bool
194*333d2b36SAndroid Build Coastguard Worker}
195*333d2b36SAndroid Build Coastguard Worker
196*333d2b36SAndroid Build Coastguard Workertype preprocessedHeadersModule struct {
197*333d2b36SAndroid Build Coastguard Worker	android.ModuleBase
198*333d2b36SAndroid Build Coastguard Worker
199*333d2b36SAndroid Build Coastguard Worker	properties preprocessedHeadersProperties
200*333d2b36SAndroid Build Coastguard Worker
201*333d2b36SAndroid Build Coastguard Worker	srcPaths     android.Paths
202*333d2b36SAndroid Build Coastguard Worker	installPaths android.Paths
203*333d2b36SAndroid Build Coastguard Worker	licensePath  android.Path
204*333d2b36SAndroid Build Coastguard Worker}
205*333d2b36SAndroid Build Coastguard Worker
206*333d2b36SAndroid Build Coastguard Workerfunc (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
207*333d2b36SAndroid Build Coastguard Worker	if String(m.properties.License) == "" {
208*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("license", "field is required")
209*333d2b36SAndroid Build Coastguard Worker	}
210*333d2b36SAndroid Build Coastguard Worker
211*333d2b36SAndroid Build Coastguard Worker	preprocessor := android.PathForModuleSrc(ctx, String(m.properties.Preprocessor))
212*333d2b36SAndroid Build Coastguard Worker	m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
213*333d2b36SAndroid Build Coastguard Worker
214*333d2b36SAndroid Build Coastguard Worker	m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
215*333d2b36SAndroid Build Coastguard Worker	installDir := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
216*333d2b36SAndroid Build Coastguard Worker	for _, src := range m.srcPaths {
217*333d2b36SAndroid Build Coastguard Worker		installPath := installDir.Join(ctx, src.Base())
218*333d2b36SAndroid Build Coastguard Worker		m.installPaths = append(m.installPaths, installPath)
219*333d2b36SAndroid Build Coastguard Worker
220*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
221*333d2b36SAndroid Build Coastguard Worker			Rule:        preprocessNdkHeader,
222*333d2b36SAndroid Build Coastguard Worker			Description: "preprocess " + src.Rel(),
223*333d2b36SAndroid Build Coastguard Worker			Input:       src,
224*333d2b36SAndroid Build Coastguard Worker			Output:      installPath,
225*333d2b36SAndroid Build Coastguard Worker			Args: map[string]string{
226*333d2b36SAndroid Build Coastguard Worker				"preprocessor": preprocessor.String(),
227*333d2b36SAndroid Build Coastguard Worker			},
228*333d2b36SAndroid Build Coastguard Worker		})
229*333d2b36SAndroid Build Coastguard Worker	}
230*333d2b36SAndroid Build Coastguard Worker
231*333d2b36SAndroid Build Coastguard Worker	if len(m.installPaths) == 0 {
232*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("srcs %q matched zero files", m.properties.Srcs)
233*333d2b36SAndroid Build Coastguard Worker	}
234*333d2b36SAndroid Build Coastguard Worker}
235*333d2b36SAndroid Build Coastguard Worker
236*333d2b36SAndroid Build Coastguard Worker// preprocessed_ndk_headers preprocesses all the ndk headers listed in the srcs
237*333d2b36SAndroid Build Coastguard Worker// property by executing the command defined in the preprocessor property.
238*333d2b36SAndroid Build Coastguard Workerfunc preprocessedNdkHeadersFactory() android.Module {
239*333d2b36SAndroid Build Coastguard Worker	module := &preprocessedHeadersModule{}
240*333d2b36SAndroid Build Coastguard Worker
241*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&module.properties)
242*333d2b36SAndroid Build Coastguard Worker
243*333d2b36SAndroid Build Coastguard Worker	android.InitAndroidModule(module)
244*333d2b36SAndroid Build Coastguard Worker
245*333d2b36SAndroid Build Coastguard Worker	return module
246*333d2b36SAndroid Build Coastguard Worker}
247