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

Conflict between haskell_libraries with the same name in different directories #219

Closed
judah opened this issue Apr 26, 2018 · 8 comments · Fixed by #222
Closed

Conflict between haskell_libraries with the same name in different directories #219

judah opened this issue Apr 26, 2018 · 8 comments · Fixed by #222

Comments

@judah
Copy link
Collaborator

judah commented Apr 26, 2018

Example:
9039058

A binary depends on two haskell_library rules with the same name: tests/library-deps/sublib:sublib and tests/library-deps:sublib. This fails:

bazel build tests/library-deps:bin

It conflicts with tests/library-deps/sublib:sublib; in fact,
renaming one of the sublib rules to, e.g., ...:sublibA lets the build succeed.

The relevant code is here:

return "{0}-{1}".format(ctx.attr.name, ctx.attr.version)

We should be able to change that function to make a package name that includes the ctx.label's package and workspace_root. (I'm not sure at the moment whether we'd need to escape slashes like we do here:

qualifier = '/'.join(components).replace('_', '_U').replace('/', '_S')
)

@mrkkrp
Copy link
Member

mrkkrp commented Apr 27, 2018

Here is a potential fix: f26cca4.

@judah @mboes I discovered that GHC does not allow underscores or two dashes in a row in package names, so using -U- as delimiter between Bazel package and component name looks like a good-enough option. What do you think?

(The CI failures is because we need to adjust the names of generated files in all the tests, so before starting with this boilerplate I decided to settle with what to use as the delimiter.)

@judah
Copy link
Collaborator Author

judah commented Apr 30, 2018

@mrkkrp, we should also take into account the workspace_root of the label, not just the package:
https://docs.bazel.build/versions/master/skylark/lib/Label.html#workspace_root

I also think the ctx.label.package.replace('/','-') is not disambiguating enough; for example, the following two labels would map to the same package name: //foo-test:bar and //foo/test:bar. See: https://docs.bazel.build/versions/master/build-ref.html#package-names-package-name

@mboes
Copy link
Member

mboes commented Apr 30, 2018

I also think the ctx.label.package.replace('/','-') is not disambiguating enough

@mrkkrp This form of encoding should always be injective, otherwise you'll get ambiguities. As it happens we already have an injective encoding snippet in the codebase: https://github.com/tweag/rules_haskell/blob/master/haskell/actions.bzl#L89-L91. This scheme is taken from the Bazel source code itself, so I suggest reusing it everywhere, just like GHC uses "z-encoding" everywhere.

See here for the original source.

@mrkkrp
Copy link
Member

mrkkrp commented Apr 30, 2018

The problem here is that this thing, package id, should be a valid package id that GHC accepts. GHC however does not accept underscores or any tricky things like two dashes in a row. In other words, there is no way to achieve injectivity here because the set of names GHC accepts is smaller than the set of possible package names. Which means, we will lose some information when we obtain GHC package id from bazel package name, which means there will always be potential for ambiguity.

That said, this is a good catch by @judah, I'm already experimenting with this. So far I think we indeed could use something similar to that existing mangling function:

  • _ -> -uU-
  • / -> -sU-
  • and we need something better than - to separate package name and target name so things like //foo-bar:baz and //foo:bar-baz don't clash.

Note that still, particularly perverted package names will have the potential for clashing, e.g. I can have two packages: foo/bar and foo-sU-bar.

@mrkkrp
Copy link
Member

mrkkrp commented Apr 30, 2018

I'll go with this, probably as good as you can get here:

  return "{0}-zZ-{1}".format(
    ctx.label.package.replace("_", "-zU-").replace("/", "-zS-"),
    ctx.attr.name,
  )

@mboes
Copy link
Member

mboes commented Apr 30, 2018

In other words, there is no way to achieve injectivity here because the set of names GHC accepts is smaller than the set of possible package names.

Of course we can! GHC's z-encoding is an example of that: linkers only want [A-Z] characters in sames so anything else (underscores, hyphens etc) is encoded injectively to that character set. Bazel's encoding is another.

@Fuuzetsu
Copy link
Collaborator

Or we could just require unique package names. It's not really any different from existing systems.

@mboes mboes closed this as completed in #222 May 1, 2018
@mboes
Copy link
Member

mboes commented May 2, 2018

@Fuuzetsu I think what @judah is going for is very fine-grained targets, in which case reusing generic target names in packages could be very convenient.

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 a pull request may close this issue.

4 participants