Hello,
TL;DR: In multi-project builds, if app has a lot subproject dependencies in this way: compile(project(':project:path'))
some build/test tasks are failing on windows OS with command is too long error…
From requirements, we must build self-contained fat-jar app, but to provide any functionality depends on our customers needs we have to combine customer-specific functionality and reuse a lot of common functionality together to achieve best value. To do so, I have created next multi-project build structure:
# deliverable apps:
apps/customer1
apps/customer2
apps/customer3
....
# reusable non-application modules and libraries:
modules/module1/
modules/module2/submodule1/
modules/module2/submodule2/
modules/module3/
modules/module4/submodules/submodule1/
modules/module4/submodules/submodule2/
modules/module4/submodules/submodule3/
...
settings.gradle
rootProject.name = 'bla-bla'
[
':modules:module1',
':modules:module2:submodule1',
':modules:module2:submodule2',
':modules:module3',
':modules:module4:submodule1',
':modules:module4:submodule2',
':modules:module4:submodule3',
//...
':apps:customer1',
':apps:customer2',
':apps:customer3',
//...
].each { include it }
so by composing common functionality and customizing specific to particular customers functionality, as result i can finally build and deliver apps: customer1
, customer2
, customer3
to my different customers…
Short app description:
- gradle 4.7 (using wrapper), jdk 1.8+
-
customer1
,customer2
andcustomer3
reusing some submodules frommodules/**
- some submodules from
modules/**
also using other submodules / sub-submodules frommodules/
- for testing I’m using JUnit5 (
junitPlatformTest
task) together with vintage JUnit4 - as base framework in my application architecture, I’m using spring-boot 2.x
all submodules from modules/**
has configuration like so:
modules/build.gradle:
allprojects {
apply from: "$rootDir/gradle/subprojects.gradle" // common spring-boot configuration
plugins.withType(SpringBootPlugin) {
bootJar {
enabled = false
}
jar {
enabled = true
}
}
}
it allows me apply spring-boot auto-configurations approach and depends on any submodules from modules/**
in my other modules/
or apps/**
projects with no issues in my spring-boot projects, like so:
apps and non-apps modules could potentially depends on any other modules: modules/module3/build.gradle
and apps/customer1/build.gradle
both might contains:
dependencies {
[
':modules:module1',
':modules:module4:submodules:submodule1',
':modules:module4:submodules:submodule3',
].each {
compile(project(it))
/*
yeah, I know, ugly, but during some investigation, I found that this configuration is working
for any of my projects depending. using here configurations together, because in some
submodules I have annotation processors libraries like lombok and
spring-boot-configuration-processor. please, let me know if it could be and root cause of
my main problem in this case. thanks.
*/
compileOnly(project(it))
annotationProcessor(project(it))
}
// ...
}
finally if for example customer2 module depends on many other project submodules, it rises that annoying windows gradle issue.
please help me reconfigure my modularity to avoid this windows gradle limitation.
as far as I understand unix also potentially could have same limitation, question here is only in amount of dependent modules. So using unix to fix that issue is not an option…
if it can help me make final gradlew command line shorter, I’m thinking if it’s possible to build any non apps modules as collection of jars per customerX project, then in my apps modules depends not on modules projects, but on for example apps/customer2/libs/*.jar
files which modules/**
project build task will produce
don’t know how to do that, please help
PS: also I would like to know if that error might be produced not because of classpath length, but systemProperties I’m passing into test/junitPlatrofmTest tasks? Theoretically, when gradle wrapper is running junitPlatformTask, it’s may spread all system props as like so:
./gradlew -Dorg.gradle.systemProp.key1=value1 -D...key2=value2 -D... :apps:customer2:junitPlatformTest
if I’m using build configuration like this:
def e2eTestProps = [ ....some key=pairs is comms form here + whole System.properites ... ]
test {
systemProperties = e2eTestProps
}
junitPlatformTest {
systemProperties = e2eTestProps
}
I have prepared little example, to show you, what do I mean by this (don’t know if it does matter, but better is show you output of junitPlatformTest task on my mac, see java.class.path
system property on page 2):
junitPlatformTask command output (page 1):
junitPlatformTask command output (page 2):
junitPlatformTask command output (page 3):
PS2: I have also found IDEA has interesting feature could shorten command line:
seems like it what It’s exact something I need… can I do similar in my gradle build configuration?
thank you in any advice!
Regards,
Maksim