1// Copyright (C) 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 cc
16
17import (
18	"path/filepath"
19	"testing"
20
21	"android/soong/android"
22	"android/soong/genrule"
23	"android/soong/multitree"
24)
25
26func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
27	RegisterPrebuiltBuildComponents(ctx)
28	RegisterCCBuildComponents(ctx)
29	RegisterBinaryBuildComponents(ctx)
30	RegisterLibraryBuildComponents(ctx)
31	RegisterLibraryHeadersBuildComponents(ctx)
32	RegisterLibraryStubBuildComponents(ctx)
33
34	multitree.RegisterApiImportsModule(ctx)
35
36	ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
37	ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
38	ctx.RegisterModuleType("cc_cmake_snapshot", CmakeSnapshotFactory)
39	ctx.RegisterModuleType("cc_object", ObjectFactory)
40	ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
41	ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
42	ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
43	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
44	ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
45}
46
47func GatherRequiredDepsForTest(oses ...android.OsType) string {
48	ret := commonDefaultModules()
49
50	supportLinuxBionic := false
51	for _, os := range oses {
52		if os == android.Windows {
53			ret += withWindowsModules()
54		}
55		if os == android.LinuxBionic {
56			supportLinuxBionic = true
57			ret += withLinuxBionic()
58		}
59	}
60
61	if !supportLinuxBionic {
62		ret += withoutLinuxBionic()
63	}
64
65	return ret
66}
67
68func commonDefaultModules() string {
69	return `
70		cc_defaults {
71			name: "toolchain_libs_defaults",
72			host_supported: true,
73			vendor_available: true,
74			product_available: true,
75			recovery_available: true,
76			no_libcrt: true,
77			sdk_version: "minimum",
78			nocrt: true,
79			no_crt_pad_segment: true,
80			system_shared_libs: [],
81			stl: "none",
82			check_elf_files: false,
83			sanitize: {
84				never: true,
85			},
86			apex_available: [
87				"//apex_available:anyapex",
88				"//apex_available:platform",
89			],
90		}
91
92		cc_prebuilt_library_static {
93			name: "libcompiler_rt-extras",
94			defaults: ["toolchain_libs_defaults"],
95			vendor_ramdisk_available: true,
96			srcs: [""],
97		}
98
99		cc_prebuilt_library_static {
100			name: "libclang_rt.builtins",
101			defaults: ["toolchain_libs_defaults"],
102			host_supported: true,
103	        vendor_available: true,
104			vendor_ramdisk_available: true,
105			native_bridge_supported: true,
106			srcs: [""],
107		}
108
109		cc_prebuilt_library_shared {
110			name: "libclang_rt.hwasan",
111			defaults: ["toolchain_libs_defaults"],
112			srcs: [""],
113		}
114
115		cc_prebuilt_library_static {
116			name: "libunwind",
117			defaults: [
118				"linux_bionic_supported",
119				"toolchain_libs_defaults",
120			],
121			vendor_ramdisk_available: true,
122			native_bridge_supported: true,
123			srcs: [""],
124		}
125
126		cc_prebuilt_library_static {
127			name: "libclang_rt.fuzzer",
128			defaults: [
129				"linux_bionic_supported",
130				"toolchain_libs_defaults",
131			],
132			srcs: [""],
133		}
134
135		// Needed for sanitizer
136		cc_prebuilt_library_shared {
137			name: "libclang_rt.ubsan_standalone",
138			defaults: ["toolchain_libs_defaults"],
139			srcs: [""],
140		}
141
142		cc_prebuilt_library_static {
143			name: "libclang_rt.ubsan_standalone.static",
144			defaults: ["toolchain_libs_defaults"],
145			srcs: [""],
146		}
147
148		cc_prebuilt_library_static {
149			name: "libclang_rt.ubsan_minimal",
150			defaults: ["toolchain_libs_defaults"],
151			host_supported: true,
152			target: {
153				android_arm64: {
154					srcs: ["libclang_rt.ubsan_minimal.android_arm64.a"],
155				},
156				android_arm: {
157					srcs: ["libclang_rt.ubsan_minimal.android_arm.a"],
158				},
159				linux_glibc_x86_64: {
160					srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
161				},
162				linux_glibc_x86: {
163					srcs: ["libclang_rt.ubsan_minimal.x86.a"],
164				},
165				linux_musl_x86_64: {
166					srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
167				},
168				linux_musl_x86: {
169					srcs: ["libclang_rt.ubsan_minimal.x86.a"],
170				},
171			},
172		}
173
174		cc_library {
175			name: "libc",
176			defaults: ["linux_bionic_supported"],
177			no_libcrt: true,
178			nocrt: true,
179			stl: "none",
180			system_shared_libs: [],
181			recovery_available: true,
182			stubs: {
183				versions: ["27", "28", "29"],
184			},
185			llndk: {
186				symbol_file: "libc.map.txt",
187			},
188		}
189		cc_library {
190			name: "libm",
191			defaults: ["linux_bionic_supported"],
192			no_libcrt: true,
193			nocrt: true,
194			stl: "none",
195			system_shared_libs: [],
196			recovery_available: true,
197			stubs: {
198				versions: ["27", "28", "29"],
199			},
200			apex_available: [
201				"//apex_available:platform",
202				"myapex"
203			],
204			llndk: {
205				symbol_file: "libm.map.txt",
206			},
207		}
208
209		// Coverage libraries
210		cc_library {
211			name: "libprofile-extras",
212			vendor_available: true,
213			vendor_ramdisk_available: true,
214			product_available: true,
215			recovery_available: true,
216			native_coverage: false,
217			system_shared_libs: [],
218			stl: "none",
219		}
220		cc_library {
221			name: "libprofile-clang-extras",
222			vendor_available: true,
223			vendor_ramdisk_available: true,
224			product_available: true,
225			recovery_available: true,
226			native_coverage: false,
227			system_shared_libs: [],
228			stl: "none",
229		}
230		cc_library {
231			name: "libprofile-extras_ndk",
232			vendor_available: true,
233			product_available: true,
234			native_coverage: false,
235			system_shared_libs: [],
236			stl: "none",
237			sdk_version: "current",
238		}
239		cc_library {
240			name: "libprofile-clang-extras_ndk",
241			vendor_available: true,
242			product_available: true,
243			native_coverage: false,
244			system_shared_libs: [],
245			stl: "none",
246			sdk_version: "current",
247		}
248
249		cc_library {
250			name: "libdl",
251			defaults: ["linux_bionic_supported"],
252			no_libcrt: true,
253			nocrt: true,
254			stl: "none",
255			system_shared_libs: [],
256			recovery_available: true,
257			stubs: {
258				versions: ["27", "28", "29"],
259			},
260			apex_available: [
261				"//apex_available:platform",
262				"myapex"
263			],
264			llndk: {
265				symbol_file: "libdl.map.txt",
266			},
267		}
268		cc_library {
269			name: "libft2",
270			no_libcrt: true,
271			nocrt: true,
272			system_shared_libs: [],
273			recovery_available: true,
274			llndk: {
275				symbol_file: "libft2.map.txt",
276				private: true,
277			}
278		}
279		cc_library {
280			name: "libc++_static",
281			no_libcrt: true,
282			nocrt: true,
283			system_shared_libs: [],
284			stl: "none",
285			vendor_available: true,
286			vendor_ramdisk_available: true,
287			product_available: true,
288			recovery_available: true,
289			host_supported: true,
290			min_sdk_version: "29",
291			apex_available: [
292				"//apex_available:platform",
293				"//apex_available:anyapex",
294			],
295		}
296		cc_library {
297			name: "libc++",
298			no_libcrt: true,
299			nocrt: true,
300			system_shared_libs: [],
301			stl: "none",
302			vendor_available: true,
303			vendor_ramdisk_available: true,
304			product_available: true,
305			recovery_available: true,
306			host_supported: true,
307			min_sdk_version: "29",
308			double_loadable: true,
309			apex_available: [
310				"//apex_available:platform",
311				"//apex_available:anyapex",
312			],
313		}
314		cc_library {
315			name: "libc++demangle",
316			no_libcrt: true,
317			nocrt: true,
318			system_shared_libs: [],
319			stl: "none",
320			host_supported: false,
321			vendor_available: true,
322			vendor_ramdisk_available: true,
323			product_available: true,
324			recovery_available: true,
325			min_sdk_version: "29",
326			apex_available: [
327				"//apex_available:platform",
328				"//apex_available:anyapex",
329			],
330		}
331
332		cc_defaults {
333			name: "crt_defaults",
334			defaults: ["linux_bionic_supported"],
335			recovery_available: true,
336			vendor_available: true,
337			vendor_ramdisk_available: true,
338			product_available: true,
339			native_bridge_supported: true,
340			stl: "none",
341			min_sdk_version: "16",
342			crt: true,
343			system_shared_libs: [],
344			apex_available: [
345				"//apex_available:platform",
346				"//apex_available:anyapex",
347			],
348		}
349
350		cc_object {
351			name: "crtbegin_so",
352			defaults: ["crt_defaults"],
353			srcs: ["crtbegin_so.c"],
354			objs: ["crtbrand"],
355		}
356
357		cc_object {
358			name: "crtbegin_dynamic",
359			defaults: ["crt_defaults"],
360			srcs: ["crtbegin.c"],
361			objs: ["crtbrand"],
362		}
363
364		cc_object {
365			name: "crtbegin_static",
366			defaults: ["crt_defaults"],
367			srcs: ["crtbegin.c"],
368			objs: ["crtbrand"],
369		}
370
371		cc_object {
372			name: "crtend_so",
373			defaults: ["crt_defaults"],
374			srcs: ["crtend_so.c"],
375			objs: ["crtbrand"],
376		}
377
378		cc_object {
379			name: "crtend_android",
380			defaults: ["crt_defaults"],
381			srcs: ["crtend.c"],
382			objs: ["crtbrand"],
383		}
384
385		cc_object {
386			name: "crt_pad_segment",
387			defaults: ["crt_defaults"],
388		}
389
390		cc_object {
391			name: "crtbrand",
392			defaults: ["crt_defaults"],
393			srcs: ["crtbrand.c"],
394		}
395
396		cc_library {
397			name: "libprotobuf-cpp-lite",
398		}
399
400		cc_library {
401			name: "ndk_libunwind",
402			sdk_version: "minimum",
403			stl: "none",
404			system_shared_libs: [],
405		}
406
407		ndk_library {
408			name: "libc",
409			first_version: "minimum",
410			symbol_file: "libc.map.txt",
411		}
412
413		ndk_library {
414			name: "libm",
415			first_version: "minimum",
416			symbol_file: "libm.map.txt",
417		}
418
419		ndk_library {
420			name: "libdl",
421			first_version: "minimum",
422			symbol_file: "libdl.map.txt",
423		}
424
425		ndk_prebuilt_shared_stl {
426			name: "ndk_libc++_shared",
427			export_include_dirs: ["ndk_libc++_shared"],
428		}
429
430		cc_library_static {
431			name: "libgoogle-benchmark",
432			sdk_version: "current",
433			stl: "none",
434			system_shared_libs: [],
435		}
436
437		cc_library_static {
438			name: "note_memtag_heap_async",
439		}
440
441		cc_library_static {
442			name: "note_memtag_heap_sync",
443		}
444
445		cc_library {
446			name: "libc_musl",
447			host_supported: true,
448			no_libcrt: true,
449			nocrt: true,
450			system_shared_libs: [],
451			stl: "none",
452		}
453	`
454}
455
456func withWindowsModules() string {
457	return `
458		cc_prebuilt_library_static {
459			name: "libwinpthread",
460			host_supported: true,
461			enabled: false,
462			target: {
463				windows: {
464					enabled: true,
465				},
466			},
467			stl: "none",
468			srcs:[""],
469		}
470		`
471}
472
473func withLinuxBionic() string {
474	return `
475				cc_binary {
476					name: "linker",
477					defaults: ["linux_bionic_supported"],
478					recovery_available: true,
479					stl: "none",
480					nocrt: true,
481					static_executable: true,
482					native_coverage: false,
483					system_shared_libs: [],
484				}
485
486				cc_genrule {
487					name: "host_bionic_linker_script",
488					host_supported: true,
489					device_supported: false,
490					target: {
491						host: {
492							enabled: false,
493						},
494						linux_bionic: {
495							enabled: true,
496						},
497					},
498					out: ["linker.script"],
499				}
500
501				cc_defaults {
502					name: "linux_bionic_supported",
503					host_supported: true,
504					target: {
505						host: {
506							enabled: false,
507						},
508						linux_bionic: {
509							enabled: true,
510						},
511					},
512				}
513			`
514}
515
516func withoutLinuxBionic() string {
517	return `
518			cc_defaults {
519				name: "linux_bionic_supported",
520			}
521		`
522}
523
524func GatherRequiredFilesForTest(fs map[string][]byte) {
525}
526
527// The directory in which cc linux bionic default modules will be defined.
528//
529// Placing them here ensures that their location does not conflict with default test modules
530// defined by other packages.
531const linuxBionicDefaultsPath = "defaults/cc/linux-bionic/Android.bp"
532
533// The directory in which the default cc common test modules will be defined.
534//
535// Placing them here ensures that their location does not conflict with default test modules
536// defined by other packages.
537const DefaultCcCommonTestModulesDir = "defaults/cc/common/"
538
539// Test fixture preparer that will register most cc build components.
540//
541// Singletons and mutators should only be added here if they are needed for a majority of cc
542// module types, otherwise they should be added under a separate preparer to allow them to be
543// selected only when needed to reduce test execution time.
544//
545// Module types do not have much of an overhead unless they are used so this should include as many
546// module types as possible. The exceptions are those module types that require mutators and/or
547// singletons in order to function in which case they should be kept together in a separate
548// preparer.
549var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers(
550	android.PrepareForTestWithAndroidBuildComponents,
551	android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
552	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
553		ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
554		ctx.RegisterModuleType("cc_test", TestFactory)
555		ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
556		ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
557
558		RegisterLlndkLibraryTxtType(ctx)
559	}),
560
561	// Additional files needed in tests that disallow non-existent source files.
562	// This includes files that are needed by all, or at least most, instances of a cc module type.
563	android.MockFS{
564		// Needed for ndk_prebuilt_(shared|static)_stl.
565		"defaults/cc/common/current/sources/cxx-stl/llvm-libc++/libs": nil,
566	}.AddToFixture(),
567)
568
569// Preparer that will define default cc modules, e.g. standard prebuilt modules.
570var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
571	PrepareForTestWithCcBuildComponents,
572
573	// Additional files needed in tests that disallow non-existent source.
574	android.MockFS{
575		"defaults/cc/common/libc.map.txt":                nil,
576		"defaults/cc/common/libdl.map.txt":               nil,
577		"defaults/cc/common/libft2.map.txt":              nil,
578		"defaults/cc/common/libm.map.txt":                nil,
579		"defaults/cc/common/ndk_libc++_shared":           nil,
580		"defaults/cc/common/crtbegin_so.c":               nil,
581		"defaults/cc/common/crtbegin.c":                  nil,
582		"defaults/cc/common/crtend_so.c":                 nil,
583		"defaults/cc/common/crtend.c":                    nil,
584		"defaults/cc/common/crtbrand.c":                  nil,
585		"external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil,
586
587		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil,
588		"defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a":   nil,
589		"defaults/cc/common/libclang_rt.ubsan_minimal.x86_64.a":        nil,
590		"defaults/cc/common/libclang_rt.ubsan_minimal.x86.a":           nil,
591	}.AddToFixture(),
592
593	// Place the default cc test modules that are common to all platforms in a location that will not
594	// conflict with default test modules defined by other packages.
595	android.FixtureAddTextFile(DefaultCcCommonTestModulesDir+"Android.bp", commonDefaultModules()),
596	// Disable linux bionic by default.
597	android.FixtureAddTextFile(linuxBionicDefaultsPath, withoutLinuxBionic()),
598)
599
600// Prepare a fixture to use all cc module types, mutators and singletons fully.
601//
602// This should only be used by tests that want to run with as much of the build enabled as possible.
603var PrepareForIntegrationTestWithCc = android.GroupFixturePreparers(
604	android.PrepareForIntegrationTestWithAndroid,
605	genrule.PrepareForIntegrationTestWithGenrule,
606	PrepareForTestWithCcDefaultModules,
607)
608
609// The preparer to include if running a cc related test for windows.
610var PrepareForTestOnWindows = android.GroupFixturePreparers(
611	// Place the default cc test modules for windows platforms in a location that will not conflict
612	// with default test modules defined by other packages.
613	android.FixtureAddTextFile("defaults/cc/windows/Android.bp", withWindowsModules()),
614)
615
616// The preparer to include if running a cc related test for linux bionic.
617var PrepareForTestOnLinuxBionic = android.GroupFixturePreparers(
618	// Enable linux bionic
619	//
620	// Can be used after PrepareForTestWithCcDefaultModules to override its default behavior of
621	// disabling linux bionic, hence why this uses FixtureOverrideTextFile.
622	android.FixtureOverrideTextFile(linuxBionicDefaultsPath, withLinuxBionic()),
623)
624
625// PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc.  It also disables the test
626// on mac, which doesn't support musl libc, and adds musl modules.
627var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
628	android.FixtureModifyConfig(android.ModifyTestConfigForMusl),
629	android.PrepareForSkipTestOnMac,
630	android.FixtureAddTextFile("external/musl/Android.bp", `
631		cc_defaults {
632			name: "libc_musl_crt_defaults",
633			host_supported: true,
634			device_supported: false,
635		}
636
637		cc_object {
638			name: "libc_musl_crtbegin_so",
639			defaults: ["libc_musl_crt_defaults"],
640		}
641
642		cc_object {
643			name: "libc_musl_crtend_so",
644			defaults: ["libc_musl_crt_defaults"],
645		}
646
647		cc_object {
648			name: "libc_musl_crtbegin_dynamic",
649			defaults: ["libc_musl_crt_defaults"],
650		}
651
652		cc_object {
653			name: "libc_musl_crtbegin_static",
654			defaults: ["libc_musl_crt_defaults"],
655		}
656
657		cc_object {
658			name: "libc_musl_crtend",
659			defaults: ["libc_musl_crt_defaults"],
660		}
661	`),
662)
663
664// PrepareForTestWithFdoProfile registers module types to test with fdo_profile
665var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
666	ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
667	ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
668})
669
670// TestConfig is the legacy way of creating a test Config for testing cc modules.
671//
672// See testCc for an explanation as to how to stop using this deprecated method.
673//
674// deprecated
675func TestConfig(buildDir string, os android.OsType, env map[string]string,
676	bp string, fs map[string][]byte) android.Config {
677
678	// add some modules that are required by the compiler and/or linker
679	bp = bp + GatherRequiredDepsForTest(os)
680
681	mockFS := map[string][]byte{}
682
683	GatherRequiredFilesForTest(mockFS)
684
685	for k, v := range fs {
686		mockFS[k] = v
687	}
688
689	return android.TestArchConfig(buildDir, env, bp, mockFS)
690}
691
692// CreateTestContext is the legacy way of creating a TestContext for testing cc modules.
693//
694// See testCc for an explanation as to how to stop using this deprecated method.
695//
696// deprecated
697func CreateTestContext(config android.Config) *android.TestContext {
698	ctx := android.NewTestArchContext(config)
699	genrule.RegisterGenruleBuildComponents(ctx)
700	ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
701	ctx.RegisterModuleType("cc_test", TestFactory)
702	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
703	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
704	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
705
706	RegisterLlndkLibraryTxtType(ctx)
707
708	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
709	android.RegisterPrebuiltMutators(ctx)
710	RegisterRequiredBuildComponentsForTest(ctx)
711
712	return ctx
713}
714
715func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
716	t.Helper()
717	mod := ctx.ModuleForTests(moduleName, variant)
718	outputFiles := mod.OutputFiles(t, "")
719	if len(outputFiles) != 1 {
720		t.Errorf("%q must have single output\n", moduleName)
721		return
722	}
723	snapshotPath := filepath.Join(subDir, snapshotFilename)
724
725	if include {
726		out := singleton.Output(snapshotPath)
727		if fake {
728			if out.Rule == nil {
729				t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0])
730			}
731		} else {
732			if out.Input.String() != outputFiles[0].String() {
733				t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
734			}
735		}
736	} else {
737		out := singleton.MaybeOutput(snapshotPath)
738		if out.Rule != nil {
739			t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
740		}
741	}
742}
743
744func CheckSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
745	t.Helper()
746	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
747}
748
749func CheckSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
750	t.Helper()
751	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
752}
753
754func CheckSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
755	t.Helper()
756	checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
757}
758
759func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
760	for _, moduleName := range moduleNames {
761		module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
762		output := module.outputFile.Path().RelativeToTop()
763		paths = append(paths, output)
764	}
765	return paths
766}
767