```$ cat settings.gradle.kts val properties = java...
# community-support
b
Copy code
$ cat settings.gradle.kts
val properties = java.util.Properties().let {
  it.load(java.io.FileReader(settings.rootDir + "/gradle.properties"))
  it
}

settings.rootProject.name = properties.getProperty("artifact")
Gradle:
Copy code
1: unable to resolve class val
   @ line 1, column 5.
     val properties = java.util.Properties().let {
         ^

  1 error
The
.kts
file isn't really a Kotlin source file..?
v
Yes it is, this error seems strange and an MCVE would be necessary to see what the problem might be. But anyway, you should just do
Copy code
val artifact: String by settings
settings.rootProject.name = artifact
instead of custom Gradle properties parsing
p
This is quite similar to what I've got before what I did to fix was I moved
java.util.Properties
to import instead of using full path here
Copy code
import java.util.Properties
...
val properties = Properties()
b
val artifact: String by settings
woow, that's much nicer, thanks!
Anyway, from what I'm seeing, these weird errors pop up as soon as I'm starting to use symlinks for
settings.gradle.kts
, because they're all copy/paste and I was trying to avoid it. That is:
Copy code
project/
  a/
  b/
  settings.gradle.kts-template
And then
a/settings.gradle.kts
is symlinked to
../settings.gradle.kts-template
. Back to copy/paste... or is there a way for all subprojects to get their name from their
gradle.properties
without copying the file?
t
Subprojects‽ or included builds? 'cause there's only one settings script and one gradle.properties file per build
b
And here I thought I understood Gradle's project model, heh. Um.. I'm not sure? Just want each monorepo's subproject to have its artifact name and artifact version configured in their own property files. The version is being set in each of their corresponding
build.gradle.kts
, but name cannot be set from there, only from
settings.gradle.kts
?
So right now the top
settings.gradle.kts
uses
include("...")
for all subprojects.
and each subproject has its own
settings.gradle.kts
just so that it can set its own artifact name
v
That's an extremely extremely bad idea and will also not work as you intend
You should never ever ever ever ever ever include one project in multiple builds or you earn a big load of problems for it
One settings script defines one build with potentially multiple projects
If you need to use one project also in another build, then import the whole build into that other build using
includeBuild
to construct a composite build.
If it is just about the project names but you actually want only one big build with all those projects, just define the names for the projects in that one top-level settings script
Regarding the symlinks and strange error, I have no idea, would need to test it, but maybe Gradle sees the name of the link target which does not end in
.kts
and thus treats it as Groovy DSL file. Because if I create a Groovy DSL settings script and put in there just
val foo = ""
, I get exactly the error you described:
Copy code
Settings file '...\showcase\settings.gradle' line: 1

Could not compile settings file '...\showcase\settings.gradle'.
> startup failed:
  settings file '...\showcase\settings.gradle': 1: unable to resolve class val 
   @ line 1, column 5.
     val foo = ""
         ^
So if you would need such a symlinking, you probably need to make sure the link target is called
...gradle.kts
.
But usually this sounds anyway like a bad idea either way and instead you should write a settings convention plugin and apply that to the settings scripts if you want to centralize some settings script logic
b
but maybe Gradle sees the name of the link target which does not end in
.kts
and thus treats it as Groovy DSL file.
that must be it
If it is just about the project names but you actually want only one big build with all those projects, just define the names for the projects in that one top-level settings script
Not sure I understand. Are you saying subprojects (subdirectories with their own build script) are not able to control their own artifact names, and they have to be set at the parent settings script?
Oof, this is hard, I'm sorry for any confusion. I'm trying to recreate Maven's project structure, where at the top you've got an aggregate project, and subdirectories have their own build scripts / pom configs. Then, at the top, you can invoke "build all", and it delegates to the subprojects.
Is that a single build or multiple builds?
v
Not sure I understand. Are you saying subprojects (subdirectories with their own build script) are not able to control their own artifact names, and they have to be set at the parent settings script?
You can control the artifact names in the normal build script, no need for settings script. But you should not do that, as it causes various other quirks. You should usually just make sure that the project name is equal to the artifact name. And that you can control in the settings script that includes the project by including the project with the name you want and then configuring the project dir to be something different if you really want different directory names than artifact names.
Is that a single build or multiple builds?
could be both
b
settings script that includes the project by including the project with the name you want and then configuring the project dir to be something different if you really want different directory names than artifact names
So for example, if my monorepo has two directories for the same artifact name:
Copy code
project/
  superlib1/
  superlib2/
One produces
superlib-1.0.jar
, the other
superlib-2.0.jar
. As you can see, their artifact names should be
superlib
, not the directory name. You're saying that
project/settings.gradle.kts
should include both directories and set new project names for them? But, then if you go into
superlib1/
and do a
gradle jar
just for that subproject, what will its jar filename be?
v
Actually it is a very bad idea to have two libraries with the same coordinates in the same build, or iirc even in the same composite build.
I'm not sure whether there is a setup that properly supports that in Gradle, I actually doubt it.
b
I mean, internally Gradle could treat them as
superlib1
and
superlib2
, it's just that the artifacts they produce are the same group+artifact, but different versions. It can be done by specifying the jar name in publications config, but you said it's a bad idea?
v
It is.
If you really need such a non-standard and non-idiomatic setup, you can probably do it somehow. But then still this would not be done in any settings script, but you would just configure the artifact name in the publication.
And that is what is discouraged, as it will make some problems in certain situations that work much better when the project group, name, and version match the publication group, name, and version.
b
Probably because certain plugins don't respect all of the customization and assume things?
Just seems like if Gradle allows customization of published artifact names, it should be ok.
But yeah, good to be forewarned, thank you
t
For instance, if one project is depended on by another, the dependency in the POM will use the project name, irrespective of the customized published artifact name. So if you customize the publishing coordinates, it must be for a project that is a "leaf" (not depended on by any other project), or possibly depended on by projects that themselves aren't published
b
makes sense
v
Just seems like if Gradle allows customization of published artifact names, it should be ok.
... no Gradle is extremely flexible in what you can do if you really need to. But that doesn't mean it is a good idea to do so. 🙂
With great flexibility and great power comes great responsibility, you know? 🙂
(Spiderman reference: ✔️)