Fork me on GitHub
#polylith
<
2024-02-28
>
jasonjckn05:02:45

Any good examples how to build a library jar for publishing to a maven repository. I managed to whip up a project that could do it, but generating the pom.xml file was tricky, I ended up just copying all the transitive lib dependencies (from bases, components), into the deps.edn file of the project, or it wouldn't appear in pom.xml. The library can be produced from a component, base, or project, it doesn't matter to me.

jasonjckn06:02:24

i don't see the transitive true flag in tools.build though. (?).

furkan3ayraktar06:02:00

You can look at how the poly tool deploys itself in its https://github.com/polyfy/polylith/blob/master/build.clj.

🙌 1
jasonjckn06:02:28

nice, "lifted basis" looks like what i need.

đź‘Ť 1
Joel17:02:43

So a base doesn’t have to follow any particular namespace structure (I could have my-ns.my-random-package.* ? In contrast with a component that requires an interface named top-ns.my-component.interface*?

Joel17:02:06

I’m shipping an API (library), and was planning to have an example “usage” of that API. It sounds like I want a base api for the API itself, and also a base example that is example code for using the api? Should a base depend on another base? Or in my situation should I put example logic code in a project, where I understand src is discouraged?

seancorfield18:02:07

Pretty sure bases have to have the <top-ns>.<base>. prefix but otherwise are unrestricted. Easy enough to test with poly check...

✔️ 1
seancorfield18:02:04

I've toyed with the idea of merging HoneySQL and next.jdbc into a single Polylith monorepo but there are problems with shipping libraries from Polylith: • shared nses will run into version conflicts if users end up depending, even transitively, on multiple libraries -- since you'll end up with the same (`component`) nses on both paths • you can't put the library API in projects if anything else in your code depends on it • you shouldn't have bases depending on each other Polylith is designed for applications.

seancorfield18:02:45

I don't know if there will ever be a solution. There's been some talk of adding machinery to rewrite nses to support libraries (so a shared component would get rewritten to have a different <top-ns>.<component>. prefix, presumably, based on the library project) but that's fragile, IMO, and means you'd end up with nses in your library that didn't match your actual source code which messes with documentation generation (e.g., http://cljdoc.org) and potentially other tooling too.

imre19:02:53

'base' isnt required in my exp as a ns segment

✔️ 1
Joel19:02:16

So instead of shipping one library jar, it sounds like I could potentially ship multiple… base.jar, component.jar and component-fake.jar. It just means the users would have to set up their dev so when running locally, they use one jar instead of the other. That sounds like it might jive with polylith model and might be acceptable as this is all internal facing code.

Joel20:02:21

I do like the polylith “opinion”, feels a bit like Bazel and Hivemind (apache).

seancorfield20:02:01

If component.jar and component-fake.jar contain the same nses, that can still cause those same conflicts if a user ends up with versions of both on their classpath due to some transitive dependency on your libraries...

Joel20:02:11

True. They could use build exclusions. The bigger danger would be not detecting it.

hiredman22:02:21

Build exclusions don't let you exclude the contents inside jars

hiredman23:02:01

When you build a jar with polylith it is effectively an uberjar(components are collapsed into it), and as a library you have all the issues that uberjar as libraries produce, and exclusions at the jar level don't fix those

Joel23:02:28

I couldn’t have multiple projects each building their own jar based on deps?

hiredman23:02:42

if have two components CA and CB that implement the same interface, then both of their jars at a minimum will overlap in both defining the "same" interface namespace, where if you depend on different versions of CA and CB the interface namespace might have the same name between them but be different

hiredman23:02:42

that is before you even start looking at transitive dependencies between components and how those are packaged

Joel02:02:24

CA/CB needing to be the same version number doesn’t seem too bad to me, although it would be nice if deps.edn allowed for a constant to be defined. The transitive dependencies. Not sure on that. I would want to build a jar that is devoid of any “overloaded” component interfaces, and a jar for each “overloaded” implementation. Being a newbie to polylist, I don’t know how difficult that would be to figure out.

Joel02:02:57

Although, in general polylith isn’t looking like a “fit” for my purposes, which is disappointing. Sean’s https://corfield.org/blog/2021/02/23/deps-edn-monorepo/ might be more amenable.

seancorfield02:02:51

> I would want to build a jar that is devoid of any “overloaded” component interfaces, and a jar for each “overloaded” implementation. Right, but as soon as someone else's library decided to depend on yours, they're going to have deps for each of those pieces at a specific version, and you're off into transitive dependency conflict land at that point. There really is no current safe way to build/deploy libraries from Polylith (short of some tool to rewrite namespaces -- sometimes called "shading" -- MrAnderson is an example).

hiredman05:02:09

More than a decade ago steve yegge proposed some feature to add to clojure, and I don't even remember what it was, and when he didn't get a hearty "hell yeah!" about it he soured on clojure pretty quickly and decided the clojure community was a bunch for crypto-MLers (like a crypto-catholic, but for the ml family of languages). I forget if he ever actually used that term, but it is what was associated with his critique in my mind. And I think polylith is in some ways doomed to disappoint because it plays to ML sensibilities (components are structures and interfaces are signatures) without being able to deliver on what people want from that (functors, parameterized module sort of things). Shading is a way to hack together generative functors on top of clojures existing namespace system.