Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add func KATI_visibility_prefix #275

Merged
merged 1 commit into from
Apr 30, 2024
Merged

Conversation

mrziwang
Copy link
Contributor

syntax: $(KATI_visibility_prefix var, prefix)

  1. Add a func KATI_visibility_prefix that takes a variable name and a list of strings, set this variable's visibility to these strings. Each string represents the relative path from the root, and is considered as prefix.

e.g. $(KATI_visibility_prefix VAR, vendor/ device/b baz.mk) --> VAR is visible to "vendor/foo.mk", "device/bar.mk", "device/baz.mk", "baz.mk", but not visible to "bar.mk", "vendor.mk" or "vendor/baz.mk".

If variable visibility is set more than once, and with a different list of strings, an error will occur.

  1. When a variable is being referenced, if this variable has visibility prefix set, check if the current referencing file matches the visibility prefix. Throw an error if not.

  2. In $(KATI_visibility_prefix FOO, prefix):
    If FOO is not defined, create a variable FOO with empty value.
    The prefix can also be reference to variable. If so, this function will expand the reference and set the visibility_prefix.

@mrziwang mrziwang requested a review from a team as a code owner April 17, 2024 23:29
Copy link
Contributor

@lamontj lamontj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One minor nit.

src/var.cc Outdated
std::string referencingFile(loc.filename);
bool valid = false;
for (const std::string& prefix : prefixes) {
if (referencingFile.find(prefix) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would seem that the preferred syntax here is: if HasPrefix(referencingFile, prefix) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, and if you use HasPrefix you can use loc.filename directly instead of creating a copy of it in referencingFile.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also from our discussion, this should only check path prefixes instead of string prefixes (i.e. ven is not a prefix of vendor/)

This is how visibility works in soong/bazel, see https://cs.android.com/android/platform/superproject/main/+/main:build/soong/android/visibility.go;l=174;drc=9a24d909369ae20566c85dfbfe8b14054ed6dd5d

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: prefix matching -- sounds good to me.

src/var.h Outdated
@@ -73,6 +73,10 @@ class Var : public Evaluable {
bool SelfReferential() const { return self_referential_; }
void SetSelfReferential() { self_referential_ = true; }

std::vector<std::string> VisibilityPrefix() const { return visibility_prefix_; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return const std::vector<std::string>& to avoid copies. Also change the signature to match where you call this function.

src/var.cc Outdated
std::string referencingFile(loc.filename);
bool valid = false;
for (const std::string& prefix : prefixes) {
if (referencingFile.find(prefix) == 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, and if you use HasPrefix you can use loc.filename directly instead of creating a copy of it in referencingFile.

std::stringstream ss(args[1]->Eval(ev));
std::string prefix;
while (ss >> prefix) {
prefixes.push_back(prefix);
Copy link
Collaborator

@Colecf Colecf Apr 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be some checks here:

  • The path doesn't start with a / or ../ (isn't absolute)
  • The path is equal to NormalizePath(path)
  • One path isn't a prefix of another

VAR2 := $$(BAZ)
VAR3 = $$(BAZ)
VAR4 = $($(BAZ))
VAR5 := $($(BAZ))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VAR3, VAR4, and VAR5 are not being tested because the makefile errored out at VAR2. You should move them into separate tests.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From our discussion, VAR2/VAR3 aren't referenced due to the double dollar sign, and VAR4 isn't because the recursive expansion means it's not expanded.

That VAR4 case is a bug in my eyes, we should also check for usages via recursive expansion. This may require expanding recursive assignments immediately but then throwing away the results.

src/var.cc Outdated
}
}
if (!valid) {
ERROR("%s is not a valid file to reference variable %s. Line #%d", loc.filename, name, loc.lineno);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please print out the valid locations the variable can be in as part of the error message.

endif

test:
@:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test that involves multiple makefiles, and a test like:

$(KATI_visibility_prefix BAZ, baz)
FOO := BAZ
X := $($(FOO)) # should be an error

@mrziwang mrziwang force-pushed the kati-visibility branch 2 times, most recently from 4ddffa7 to 958bd22 Compare April 18, 2024 23:58
src/func.cc Outdated Show resolved Hide resolved
@mrziwang mrziwang force-pushed the kati-visibility branch 2 times, most recently from 935f0cd to 7a22bea Compare April 19, 2024 17:49
if (HasPrefix(prefix, "/")) {
ERROR_LOC(ev->loc(), "Visibility prefix should not start with /");
}
if (HasPrefix(prefix, "../")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows "./../", which has the same effect. The best solution is probably to just not print normalizedPrefix in line 681, rather than trying to detect all of the places where the passed argument would escape the workspace.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, ./../ would fail the normalization check.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of having this check here? If it was removed completely the normalization check would still fail.

This check is either:

  • redundant because of the normalization check, or
  • insufficient in its effort to avoid leaking the parent directory name in the normalization check. If leaking the parent directory is considered bad, then just drop that from the error message below.

In any case, this check provides no added value.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NormalizePath can still produce paths starting with ../. For example, ../foo is a normalized path. But a ../ anywhere else in the path would be removed by the normalization process, e.g. foo/../../bar normalizes to ../bar, so we'd catch it.

I don't think this check is either redundant or insufficient.

It's not really about leaking the parent directory name, it's that you'd never want to make a variable visible to a location outside of the android source tree, so we should deny that nonsense argument.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was misunderstanding NormalizePath, and expecting "../foo" to turn into an absolute path.

Agreed.

syntax: $(KATI_visibility_prefix var, prefix)

1, Add a func KATI_visibility_prefix that takes a variable
name and a list of strings, set this variable's visibility
to these strings. Each string represents the relative path
from the root, and is considered as prefix.

e.g. $(KATI_visibility_prefix VAR, vendor/ device/b baz.mk)
--> VAR is visible to "vendor/foo.mk", "device/bar.mk",
"device/baz.mk", "baz.mk", but not visible to "bar.mk",
"vendor.mk" or "vendor/baz.mk".

If variable visibility is set more than once, and with a
different list of strings, an error will occur.

2. When a variable is being referenced, if this variable has
visibility prefix set, check if the current referencing file
matches the visibility prefix. Throw an error if not.

3. In $(KATI_visibility_prefix FOO, prefix)
If FOO is not defined, create a variable FOO with empty value.
The prefix can also be reference to variable.
If so, this function will expand the reference and set the
visibility_prefix.
@Colecf Colecf merged commit 8b60db2 into google:master Apr 30, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants