diff options
| -rw-r--r-- | android/arch_list.go | 3 | ||||
| -rw-r--r-- | android/config.go | 5 | ||||
| -rw-r--r-- | android/module.go | 2 | ||||
| -rw-r--r-- | cc/config/arm64_device.go | 7 | ||||
| -rw-r--r-- | cc/library.go | 47 | ||||
| -rw-r--r-- | cc/llndk_library.go | 4 | ||||
| -rw-r--r-- | cc/ndk_headers.go | 133 | ||||
| -rw-r--r-- | cc/ndk_sysroot.go | 12 | ||||
| -rw-r--r-- | sdk/sdk_test.go | 39 | ||||
| -rw-r--r-- | sdk/update.go | 30 | ||||
| -rw-r--r-- | ui/build/config.go | 46 | ||||
| -rw-r--r-- | ui/build/path.go | 18 | ||||
| -rw-r--r-- | ui/build/sandbox_linux.go | 52 |
13 files changed, 122 insertions, 276 deletions
diff --git a/android/arch_list.go b/android/arch_list.go index f1289a3b6..2937092af 100644 --- a/android/arch_list.go +++ b/android/arch_list.go @@ -159,6 +159,9 @@ var androidArchFeatureMap = map[ArchType]map[string][]string{ "armv9-a": { "dotprod", }, + "armv9-2a": { + "dotprod", + }, }, X86: { "amberlake": { diff --git a/android/config.go b/android/config.go index bbb08dde7..cf3499f2c 100644 --- a/android/config.go +++ b/android/config.go @@ -1490,11 +1490,6 @@ func (c *deviceConfig) NativeCoverageEnabledForPath(path string) bool { } } if coverage && len(c.config.productVariables.NativeCoverageExcludePaths) > 0 { - // Workaround coverage boot failure. - // http://b/269981180 - if strings.HasPrefix(path, "external/protobuf") { - coverage = false - } if HasAnyPrefix(path, c.config.productVariables.NativeCoverageExcludePaths) { coverage = false } diff --git a/android/module.go b/android/module.go index c50d1a302..009b0dfb6 100644 --- a/android/module.go +++ b/android/module.go @@ -1997,7 +1997,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) TargetDependencies: targetRequired, HostDependencies: hostRequired, Data: data, - Required: m.RequiredModuleNames(ctx), + Required: append(m.RequiredModuleNames(ctx), m.VintfFragmentModuleNames(ctx)...), } SetProvider(ctx, ModuleInfoJSONProvider, ctx.moduleInfoJSON) } diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go index beb68e19d..761afcf18 100644 --- a/cc/config/arm64_device.go +++ b/cc/config/arm64_device.go @@ -41,11 +41,18 @@ var ( "armv8-2a-dotprod": []string{ "-march=armv8.2-a+dotprod", }, + // On ARMv9 and later, Pointer Authentication Codes (PAC) are mandatory, + // so -fstack-protector is unnecessary. "armv9-a": []string{ "-march=armv8.2-a+dotprod", "-mbranch-protection=standard", "-fno-stack-protector", }, + "armv9-2a": []string{ + "-march=armv9.2-a", + "-mbranch-protection=standard", + "-fno-stack-protector", + }, } arm64Ldflags = []string{ diff --git a/cc/library.go b/cc/library.go index 65a923a5e..03f7174c6 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1264,14 +1264,6 @@ func (library *libraryDecorator) exportedIncludeDirsForAbiCheck(ctx ModuleContex func (library *libraryDecorator) llndkIncludeDirsForAbiCheck(ctx ModuleContext, deps PathDeps) []string { var includeDirs, systemIncludeDirs []string - // The ABI checker does not need the preprocess which adds macro guards to function declarations. - preprocessedDirs := android.PathsForModuleSrc(ctx, library.Properties.Llndk.Export_preprocessed_headers).Strings() - if Bool(library.Properties.Llndk.Export_headers_as_system) { - systemIncludeDirs = append(systemIncludeDirs, preprocessedDirs...) - } else { - includeDirs = append(includeDirs, preprocessedDirs...) - } - if library.Properties.Llndk.Override_export_include_dirs != nil { includeDirs = append(includeDirs, android.PathsForModuleSrc( ctx, library.Properties.Llndk.Override_export_include_dirs).Strings()...) @@ -1579,25 +1571,6 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathD } } -func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) (timestamp android.Path, installPaths android.WritablePaths) { - srcDir := android.PathForModuleSrc(ctx, srcHeaderDir) - srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil) - - for _, header := range srcFiles { - headerDir := filepath.Dir(header.String()) - relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir) - if err != nil { - ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s", - srcDir.String(), headerDir, err) - continue - } - - installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base())) - } - - return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths), installPaths -} - // link registers actions to link this library, and sets various fields // on this library to reflect information that should be exported up the build // tree (for example, exported flags and include paths). @@ -1605,26 +1578,6 @@ func (library *libraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { if ctx.IsLlndk() { - if len(library.Properties.Llndk.Export_preprocessed_headers) > 0 { - // This is the vendor variant of an LLNDK library with preprocessed headers. - genHeaderOutDir := android.PathForModuleGen(ctx, "include") - - var timestampFiles android.Paths - for _, dir := range library.Properties.Llndk.Export_preprocessed_headers { - timestampFile, installPaths := processLLNDKHeaders(ctx, dir, genHeaderOutDir) - timestampFiles = append(timestampFiles, timestampFile) - library.addExportedGeneratedHeaders(installPaths.Paths()...) - } - - if Bool(library.Properties.Llndk.Export_headers_as_system) { - library.reexportSystemDirs(genHeaderOutDir) - } else { - library.reexportDirs(genHeaderOutDir) - } - - library.reexportDeps(timestampFiles...) - } - // override the module's export_include_dirs with llndk.override_export_include_dirs // if it is set. if override := library.Properties.Llndk.Override_export_include_dirs; override != nil { diff --git a/cc/llndk_library.go b/cc/llndk_library.go index 5ece78a83..c7950f9ff 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -36,10 +36,6 @@ type llndkLibraryProperties struct { // bionic/libc. Export_headers_as_system *bool - // Which headers to process with versioner. This really only handles - // bionic/libc/include right now. - Export_preprocessed_headers []string - // Whether the system library uses symbol versions. Unversioned *bool diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index e00293143..74819540b 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -23,15 +23,6 @@ import ( ) var ( - versionBionicHeaders = pctx.AndroidStaticRule("versionBionicHeaders", - blueprint.RuleParams{ - // The `&& touch $out` isn't really necessary, but Blueprint won't - // let us have only implicit outputs. - Command: "$versionerCmd -o $outDir $srcDir $depsPath && touch $out", - CommandDeps: []string{"$versionerCmd"}, - }, - "depsPath", "srcDir", "outDir") - preprocessNdkHeader = pctx.AndroidStaticRule("preprocessNdkHeader", blueprint.RuleParams{ Command: "$preprocessor -o $out $in", @@ -40,10 +31,6 @@ var ( "preprocessor") ) -func init() { - pctx.SourcePathVariable("versionerCmd", "prebuilts/clang-tools/${config.HostPrebuiltTag}/bin/versioner") -} - // Returns the NDK base include path for use with sdk_version current. Usable with -I. func getCurrentIncludePath(ctx android.PathContext) android.OutputPath { return getNdkSysrootBase(ctx).Join(ctx, "usr/include") @@ -167,126 +154,6 @@ func NdkHeadersFactory() android.Module { return module } -type versionedHeaderProperties struct { - // Base directory of the headers being installed. As an example: - // - // versioned_ndk_headers { - // name: "foo", - // from: "include", - // to: "", - // } - // - // Will install $SYSROOT/usr/include/foo/bar/baz.h. If `from` were instead - // "include/foo", it would have installed $SYSROOT/usr/include/bar/baz.h. - From *string - - // Install path within the sysroot. This is relative to usr/include. - To *string - - // Path to the NOTICE file associated with the headers. - License *string -} - -// Like ndk_headers, but preprocesses the headers with the bionic versioner: -// https://android.googlesource.com/platform/bionic/+/main/tools/versioner/README.md. -// -// Unlike ndk_headers, we don't operate on a list of sources but rather a whole directory, the -// module does not have the srcs property, and operates on a full directory (the `from` property). -// -// Note that this is really only built to handle bionic/libc/include. -type versionedHeaderModule struct { - android.ModuleBase - - properties versionedHeaderProperties - - srcPaths android.Paths - installPaths android.Paths - licensePath android.Path -} - -// Return the glob pattern to find all .h files beneath `dir` -func headerGlobPattern(dir string) string { - return filepath.Join(dir, "**", "*.h") -} - -func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - if String(m.properties.License) == "" { - ctx.PropertyErrorf("license", "field is required") - } - - m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License)) - - fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From)) - toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To)) - m.srcPaths = ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil) - var installPaths []android.WritablePath - for _, header := range m.srcPaths { - installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To)) - installPath := installDir.Join(ctx, header.Base()) - installPaths = append(installPaths, installPath) - m.installPaths = append(m.installPaths, installPath) - } - - if len(m.installPaths) == 0 { - ctx.ModuleErrorf("glob %q matched zero files", String(m.properties.From)) - } - - processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, m.srcPaths, installPaths) -} - -func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path, - srcPaths android.Paths, installPaths []android.WritablePath) android.Path { - // The versioner depends on a dependencies directory to simplify determining include paths - // when parsing headers. This directory contains architecture specific directories as well - // as a common directory, each of which contains symlinks to the actually directories to - // be included. - // - // ctx.Glob doesn't follow symlinks, so we need to do this ourselves so we correctly - // depend on these headers. - // TODO(http://b/35673191): Update the versioner to use a --sysroot. - depsPath := android.PathForSource(ctx, "bionic/libc/versioner-dependencies") - depsGlob := ctx.Glob(filepath.Join(depsPath.String(), "**/*"), nil) - for i, path := range depsGlob { - if ctx.IsSymlink(path) { - dest := ctx.Readlink(path) - // Additional .. to account for the symlink itself. - depsGlob[i] = android.PathForSource( - ctx, filepath.Clean(filepath.Join(path.String(), "..", dest))) - } - } - - timestampFile := android.PathForModuleOut(ctx, "versioner.timestamp") - ctx.Build(pctx, android.BuildParams{ - Rule: versionBionicHeaders, - Description: "versioner preprocess " + srcDir.Rel(), - Output: timestampFile, - Implicits: append(srcPaths, depsGlob...), - ImplicitOutputs: installPaths, - Args: map[string]string{ - "depsPath": depsPath.String(), - "srcDir": srcDir.String(), - "outDir": outDir.String(), - }, - }) - - return timestampFile -} - -// versioned_ndk_headers preprocesses the headers with the bionic versioner: -// https://android.googlesource.com/platform/bionic/+/main/tools/versioner/README.md. -// Unlike the ndk_headers soong module, versioned_ndk_headers operates on a -// directory level specified in `from` property. This is only used to process -// the bionic/libc/include directory. -func VersionedNdkHeadersFactory() android.Module { - module := &versionedHeaderModule{} - - module.AddProperties(&module.properties) - - android.InitAndroidModule(module) - - return module -} - // preprocessed_ndk_header { // // name: "foo", diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index f571523a0..92da17241 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -79,7 +79,6 @@ func init() { func RegisterNdkModuleTypes(ctx android.RegistrationContext) { ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory) ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) - ctx.RegisterModuleType("versioned_ndk_headers", VersionedNdkHeadersFactory) ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) ctx.RegisterParallelSingletonType("ndk", NdkSingleton) } @@ -230,17 +229,6 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { licensePaths = append(licensePaths, m.licensePath) } - if m, ok := module.(*versionedHeaderModule); ok { - headerSrcPaths = append(headerSrcPaths, m.srcPaths...) - headerInstallPaths = append(headerInstallPaths, m.installPaths...) - // Verification intentionally not done for headers that go through - // versioner. It'd be nice to have, but the only user is bionic, and - // that one module would also need to use skip_verification, so it - // wouldn't help at all. - installPaths = append(installPaths, m.installPaths...) - licensePaths = append(licensePaths, m.licensePath) - } - if m, ok := module.(*preprocessedHeadersModule); ok { headerSrcPaths = append(headerSrcPaths, m.srcPaths...) headerInstallPaths = append(headerInstallPaths, m.installPaths...) diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 057b370d3..416dce62c 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -131,11 +131,7 @@ apex_contributions_defaults { java_import { name: "myjavalib", prefer: false, - visibility: [ - "//other/foo", - "//package", - "//prebuilts/mysdk", - ], + visibility: ["//visibility:public"], apex_available: ["//apex_available:platform"], jars: ["java/myjavalib.jar"], } @@ -151,11 +147,7 @@ java_import { java_import { name: "mydefaultedjavalib", prefer: false, - visibility: [ - "//other/bar", - "//package", - "//prebuilts/mysdk", - ], + visibility: ["//visibility:public"], apex_available: ["//apex_available:platform"], jars: ["java/mydefaultedjavalib.jar"], } @@ -163,10 +155,7 @@ java_import { java_import { name: "myprivatejavalib", prefer: false, - visibility: [ - "//package", - "//prebuilts/mysdk", - ], + visibility: ["//visibility:public"], apex_available: ["//apex_available:platform"], jars: ["java/myprivatejavalib.jar"], } @@ -185,28 +174,6 @@ func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) { `) } -func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) { - testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, ` - sdk { - name: "mysdk", - prebuilt_visibility: [ - "//visibility:private", - ], - java_header_libs: [ - "myjavalib", - ], - } - - java_library { - name: "myjavalib", - // Uses package default visibility - srcs: ["Test.java"], - system_modules: "none", - sdk_version: "none", - } -`) -} - func TestSdkInstall(t *testing.T) { sdk := ` sdk { diff --git a/sdk/update.go b/sdk/update.go index e1b363a89..9379f36cb 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -1109,20 +1109,22 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType // same package so can be marked as private. m.AddProperty("visibility", []string{"//visibility:private"}) } else { - // Extract visibility information from a member variant. All variants have the same - // visibility so it doesn't matter which one is used. - visibilityRules := android.EffectiveVisibilityRules(s.ctx, variant) - - // Add any additional visibility rules needed for the prebuilts to reference each other. - err := visibilityRules.Widen(s.sdk.properties.Prebuilt_visibility) - if err != nil { - s.ctx.PropertyErrorf("prebuilt_visibility", "%s", err) - } - - visibility := visibilityRules.Strings() - if len(visibility) != 0 { - m.AddProperty("visibility", visibility) - } + // Change the visibility of the module SDK prebuilts to public. + // This includes + // 1. Stub libraries of `sdk` modules + // 2. Binaries and libraries of `module_exports` modules + // + // This is a workaround to improve maintainlibility of the module SDK. + // Since module sdks are generated from release branches and dropped to development + // branches, there might be a visibility skew between the sources and prebuilts + // of a specific module. + // To reconcile this potential skew, change the visibility to public + // + // This is safe for (1) since these are stub libraries. + // This is ok for (2) since these are host and test exports and are intended for + // ART development. + // TODO (b/361303067): This can be removed if ART uses full manifests. + m.AddProperty("visibility", []string{"//visibility:public"}) } // Where available copy apex_available properties from the member. diff --git a/ui/build/config.go b/ui/build/config.go index 64323487d..08e195783 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -41,6 +41,7 @@ import ( const ( envConfigDir = "vendor/google/tools/soong_config" jsonSuffix = "json" + abfsSrcDir = "/src" ) var ( @@ -214,6 +215,10 @@ func NewConfig(ctx Context, args ...string) Config { sandboxConfig: &SandboxConfig{}, ninjaWeightListSource: DEFAULT, } + wd, err := os.Getwd() + if err != nil { + ctx.Fatalln("Failed to get working directory:", err) + } // Skip soong tests by default on Linux if runtime.GOOS == "linux" { @@ -245,17 +250,13 @@ func NewConfig(ctx Context, args ...string) Config { // Make sure OUT_DIR is set appropriately if outDir, ok := ret.environ.Get("OUT_DIR"); ok { - ret.environ.Set("OUT_DIR", filepath.Clean(outDir)) + ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, filepath.Clean(outDir))) } else { outDir := "out" if baseDir, ok := ret.environ.Get("OUT_DIR_COMMON_BASE"); ok { - if wd, err := os.Getwd(); err != nil { - ctx.Fatalln("Failed to get working directory:", err) - } else { - outDir = filepath.Join(baseDir, filepath.Base(wd)) - } + outDir = filepath.Join(baseDir, filepath.Base(wd)) } - ret.environ.Set("OUT_DIR", outDir) + ret.environ.Set("OUT_DIR", ret.sandboxPath(wd, outDir)) } // loadEnvConfig needs to know what the OUT_DIR is, so it should @@ -361,12 +362,12 @@ func NewConfig(ctx Context, args ...string) Config { ret.environ.Set("PYTHONDONTWRITEBYTECODE", "1") tmpDir := absPath(ctx, ret.TempDir()) - ret.environ.Set("TMPDIR", tmpDir) + ret.environ.Set("TMPDIR", ret.sandboxPath(wd, tmpDir)) // Always set ASAN_SYMBOLIZER_PATH so that ASAN-based tools can symbolize any crashes symbolizerPath := filepath.Join("prebuilts/clang/host", ret.HostPrebuiltTag(), "llvm-binutils-stable/llvm-symbolizer") - ret.environ.Set("ASAN_SYMBOLIZER_PATH", absPath(ctx, symbolizerPath)) + ret.environ.Set("ASAN_SYMBOLIZER_PATH", ret.sandboxPath(wd, absPath(ctx, symbolizerPath))) // Precondition: the current directory is the top of the source tree checkTopDir(ctx) @@ -426,9 +427,9 @@ func NewConfig(ctx Context, args ...string) Config { } ret.environ.Unset("OVERRIDE_ANDROID_JAVA_HOME") - ret.environ.Set("JAVA_HOME", absJavaHome) - ret.environ.Set("ANDROID_JAVA_HOME", javaHome) - ret.environ.Set("ANDROID_JAVA8_HOME", java8Home) + ret.environ.Set("JAVA_HOME", ret.sandboxPath(wd, absJavaHome)) + ret.environ.Set("ANDROID_JAVA_HOME", ret.sandboxPath(wd, javaHome)) + ret.environ.Set("ANDROID_JAVA8_HOME", ret.sandboxPath(wd, java8Home)) ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator))) // b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches @@ -444,7 +445,7 @@ func NewConfig(ctx Context, args ...string) Config { ret.buildDateTime = strconv.FormatInt(time.Now().Unix(), 10) } - ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile) + ret.environ.Set("BUILD_DATETIME_FILE", ret.sandboxPath(wd, buildDateTimeFile)) if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok { username := "unknown" @@ -455,6 +456,7 @@ func NewConfig(ctx Context, args ...string) Config { } ret.environ.Set("BUILD_USERNAME", username) } + ret.environ.Set("PWD", ret.sandboxPath(wd, wd)) if ret.UseRBE() { for k, v := range getRBEVars(ctx, Config{ret}) { @@ -1296,6 +1298,19 @@ func (c *configImpl) UseABFS() bool { return err == nil } +func (c *configImpl) sandboxPath(base, in string) string { + if !c.UseABFS() { + return in + } + + rel, err := filepath.Rel(base, in) + if err != nil { + return in + } + + return filepath.Join(abfsSrcDir, rel) +} + func (c *configImpl) UseRBE() bool { // These alternate modes of running Soong do not use RBE / reclient. if c.Queryview() || c.JsonModuleGraph() { @@ -1722,6 +1737,11 @@ func (c *configImpl) EmptyNinjaFile() bool { } func (c *configImpl) SkipMetricsUpload() bool { + // b/362625275 - Metrics upload sometimes prevents abfs unmount + if c.UseABFS() { + return true + } + return c.skipMetricsUpload } diff --git a/ui/build/path.go b/ui/build/path.go index 51ebff117..075bf2eb7 100644 --- a/ui/build/path.go +++ b/ui/build/path.go @@ -57,6 +57,22 @@ func parsePathDir(dir string) []string { return ret } +func updatePathForSandbox(config Config) { + wd, err := os.Getwd() + if err != nil { + return + } + + var newPath []string + if path, ok := config.Environment().Get("PATH"); ok && path != "" { + entries := strings.Split(path, string(filepath.ListSeparator)) + for _, ent := range entries { + newPath = append(newPath, config.sandboxPath(wd, ent)) + } + } + config.Environment().Set("PATH", strings.Join(newPath, string(filepath.ListSeparator))) +} + // SetupLitePath is the "lite" version of SetupPath used for dumpvars, or other // places that does not need the full logging capabilities of path_interposer, // wants the minimal performance overhead, and still get the benefits of $PATH @@ -121,6 +137,7 @@ func SetupLitePath(ctx Context, config Config, tmpDir string) { // Set $PATH to be the directories containing the host tool symlinks, and // the prebuilts directory for the current host OS. config.Environment().Set("PATH", myPath) + updatePathForSandbox(config) config.pathReplaced = true } @@ -265,5 +282,6 @@ func SetupPath(ctx Context, config Config) { // Replace the $PATH variable with the path_interposer symlinks, and // checked-in prebuilts. config.Environment().Set("PATH", myPath) + updatePathForSandbox(config) config.pathReplaced = true } diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go index d9ca85417..95b71a794 100644 --- a/ui/build/sandbox_linux.go +++ b/ui/build/sandbox_linux.go @@ -50,7 +50,6 @@ var ( const ( nsjailPath = "prebuilts/build-tools/linux-x86/bin/nsjail" - abfsSrcDir = "/src" ) var sandboxConfig struct { @@ -148,20 +147,42 @@ func (c *Cmd) sandboxSupported() bool { return sandboxConfig.working } -func (c *Cmd) srcDirArg() string { - if !c.config.UseABFS() { - return sandboxConfig.srcDir +// Assumes input path is absolute, clean, and if applicable, an evaluated +// symlink. If path is not a subdirectory of src dir or relative path +// cannot be determined, return the input untouched. +func (c *Cmd) relFromSrcDir(path string) string { + if !strings.HasPrefix(path, sandboxConfig.srcDir) { + return path + } + + rel, err := filepath.Rel(sandboxConfig.srcDir, path) + if err != nil { + return path } - return sandboxConfig.srcDir + ":" + abfsSrcDir + return rel } -func (c *Cmd) outDirArg() string { +func (c *Cmd) dirArg(path string) string { if !c.config.UseABFS() { - return sandboxConfig.outDir + return path } - return sandboxConfig.outDir + ":" + filepath.Join(abfsSrcDir, sandboxConfig.outDir) + rel := c.relFromSrcDir(path) + + return path + ":" + filepath.Join(abfsSrcDir, rel) +} + +func (c *Cmd) srcDirArg() string { + return c.dirArg(sandboxConfig.srcDir) +} + +func (c *Cmd) outDirArg() string { + return c.dirArg(sandboxConfig.outDir) +} + +func (c *Cmd) distDirArg() string { + return c.dirArg(sandboxConfig.distDir) } // When configured to use ABFS, we need to allow the creation of the /src @@ -187,8 +208,17 @@ func (c *Cmd) readMountArgs() []string { return args } +func (c *Cmd) workDir() string { + if !c.config.UseABFS() { + wd, _ := os.Getwd() + return wd + } + + return abfsSrcDir +} + func (c *Cmd) wrapSandbox() { - wd, _ := os.Getwd() + wd := c.workDir() var sandboxArgs []string sandboxArgs = append(sandboxArgs, @@ -226,7 +256,7 @@ func (c *Cmd) wrapSandbox() { ) sandboxArgs = append(sandboxArgs, - c.readMountArgs()... + c.readMountArgs()..., ) sandboxArgs = append(sandboxArgs, @@ -264,7 +294,7 @@ func (c *Cmd) wrapSandbox() { if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) { //Mount dist dir as read-write if it already exists - sandboxArgs = append(sandboxArgs, "-B", sandboxConfig.distDir) + sandboxArgs = append(sandboxArgs, "-B", c.distDirArg()) } if c.Sandbox.AllowBuildBrokenUsesNetwork && c.config.BuildBrokenUsesNetwork() { |