platform_build_soong/python/builder.go
Cole Faust eb3a900c5c Add flag to not add directory of entrypoint to sys.path
The python interpreter will by default add the directory of
the entrypoint script to the beginning of sys.path. This
can be disabled in python 3.11+ (which is not released yet)
using the PYTHON_SAFE_PATH environment variable or the -P flag.
As a workaround to have this behavior in older python versions,
we can make an __soong_entrypoint_redirector__.py file at the
root of the zip file that is the entrypoint, and then that
file will redirect to the real entrypoint.

This brings non-embedded-launcher python modules closer to
the embedded launcher version. The embedded launcher binaries
already act like this because they start at an __main__.py file
at the root of the zip file.

Bug: 245583294
Test: m py_dont_import_folder_of_entrypoint_test && out/host/linux-x86/nativetest64/py_dont_import_folder_of_entrypoint_test/py_dont_import_folder_of_entrypoint_test
Change-Id: I39aaf04fb19c3ba7f5c9d98220872d6d08abf736
2022-09-26 11:22:38 -07:00

166 lines
6.2 KiB
Go

// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package python
// This file contains Ninja build actions for building Python program.
import (
"strings"
"android/soong/android"
"github.com/google/blueprint"
_ "github.com/google/blueprint/bootstrap"
)
var (
pctx = android.NewPackageContext("android/soong/python")
zip = pctx.AndroidStaticRule("zip",
blueprint.RuleParams{
Command: `$parCmd -o $out $args`,
CommandDeps: []string{"$parCmd"},
},
"args")
combineZip = pctx.AndroidStaticRule("combineZip",
blueprint.RuleParams{
Command: `$mergeParCmd $out $in`,
CommandDeps: []string{"$mergeParCmd"},
},
)
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
`echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
`$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips && ` +
`chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix)`,
CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/stub_template_host.txt"},
},
"interp", "main", "srcsZips", "addTopDirectoriesToPath")
hostParWithoutAddingEntrypointFolderToPath = pctx.AndroidStaticRule("hostParWithoutAddingEntrypointFolderToPath",
blueprint.RuleParams{
Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
"sed -e 's/ENTRY_POINT/$main/g' build/soong/python/scripts/main_non_embedded.py >`dirname $out`/__soong_entrypoint_redirector__.py && " +
"$parCmd -o $out.entrypoint_zip -C `dirname $out` -f `dirname $out`/__soong_entrypoint_redirector__.py && " +
`echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
`$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips $out.entrypoint_zip && ` +
"chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix; rm -f $out.entrypoint_zip; rm -f `dirname $out`/__soong_entrypoint_redirector__.py)",
CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/stub_template_host.txt", "build/soong/python/scripts/main_non_embedded.py"},
},
"interp", "main", "srcsZips", "addTopDirectoriesToPath")
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
blueprint.RuleParams{
Command: `rm -f $out.main && ` +
`sed 's/ENTRY_POINT/$main/' build/soong/python/scripts/main.py >$out.main &&` +
`$mergeParCmd -p -pm $out.main --prefix $launcher $out $srcsZips && ` +
`chmod +x $out && rm -rf $out.main`,
CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/main.py"},
},
"main", "srcsZips", "launcher")
embeddedParNoMain = pctx.AndroidStaticRule("embeddedParNoMain",
blueprint.RuleParams{
Command: `$mergeParCmd -p --prefix $launcher $out $srcsZips && ` +
`chmod +x $out`,
CommandDeps: []string{"$mergeParCmd"},
},
"srcsZips", "launcher")
)
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
pctx.Import("android/soong/android")
pctx.HostBinToolVariable("parCmd", "soong_zip")
pctx.HostBinToolVariable("mergeParCmd", "merge_zips")
}
func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
launcherPath android.OptionalPath, interpreter, main, binName string,
srcsZips android.Paths, addTopDirectoriesToPath bool, dontAddEntrypointFolderToPath bool) android.Path {
// .intermediate output path for bin executable.
binFile := android.PathForModuleOut(ctx, binName)
// implicit dependency for parFile build action.
implicits := srcsZips
if !embeddedLauncher {
addDirsString := "False"
if addTopDirectoriesToPath {
addDirsString = "True"
}
if dontAddEntrypointFolderToPath {
ctx.Build(pctx, android.BuildParams{
Rule: hostParWithoutAddingEntrypointFolderToPath,
Description: "host python archive",
Output: binFile,
Implicits: implicits,
Args: map[string]string{
"interp": strings.Replace(interpreter, "/", `\/`, -1),
"main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
"srcsZips": strings.Join(srcsZips.Strings(), " "),
"addTopDirectoriesToPath": addDirsString,
},
})
} else {
ctx.Build(pctx, android.BuildParams{
Rule: hostPar,
Description: "host python archive",
Output: binFile,
Implicits: implicits,
Args: map[string]string{
"interp": strings.Replace(interpreter, "/", `\/`, -1),
"main": strings.Replace(main, "/", `\/`, -1),
"srcsZips": strings.Join(srcsZips.Strings(), " "),
"addTopDirectoriesToPath": addDirsString,
},
})
}
} else if launcherPath.Valid() {
// added launcherPath to the implicits Ninja dependencies.
implicits = append(implicits, launcherPath.Path())
if main == "" {
ctx.Build(pctx, android.BuildParams{
Rule: embeddedParNoMain,
Description: "embedded python archive",
Output: binFile,
Implicits: implicits,
Args: map[string]string{
"srcsZips": strings.Join(srcsZips.Strings(), " "),
"launcher": launcherPath.String(),
},
})
} else {
ctx.Build(pctx, android.BuildParams{
Rule: embeddedPar,
Description: "embedded python archive",
Output: binFile,
Implicits: implicits,
Args: map[string]string{
"main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
"srcsZips": strings.Join(srcsZips.Strings(), " "),
"launcher": launcherPath.String(),
},
})
}
}
return binFile
}