system compiler variables are not overwritten in merged project - install4j

I have a launcher in a sub-project whose name is dependend on the ${compiler:sys.version} variable.
The project is merged into a parent project, which is build with a gradle task on command line.
task serverSetup(type: com.install4j.gradle.Install4jTask, dependsOn: 'initialize') {
projectFile = file('server.install4j')
release = artifactVersion
}
Problem is, that the launcher of the sub-project is created with the value set in the sub-projects Application Info and not overridden with the version set by the gradle task.
Am I doing something wrong? The documentation says:
As a result of flat merging, there are no intermediary artifacts for merged projects. .... In particular, all elements in the final result share the same
namespace for compiler and installer variables.
Because of this I expect the sys.version variable to be overriden in the sub-project.

This is a bug, it will be fixed in 7.0.5. Please contact support#ej-technologies.com to get a build where this already fixed.

Related

Merge Project: Error while building merged project with error undefined compiler variable

I am using merge project feature of install4j.
I have created sub-project with one action in it. This action uses some compiler variables which are defined in same project(sub-project).
Now I have merged this project into main project, and created the link to an action from sub-project.
But when I try to build main project it gives error that variable used in action is not defined as shown below.
Build failed.
Cause: com.exe4j.b.z
When trying to process '${compiler:RegPath}': the variable 'RegPath' has not been defined. Stack trace:
com.exe4j.a.d: com.exe4j.b.z: When trying to process
'${compiler:RegPath}': the variable 'RegPath' has not been defined.
at com.install4j.b.i.b(ejt:175) at com.install4j.gui.b.run(ejt:100)
Caused by: com.exe4j.b.z: When trying to process
'${compiler:RegPath}': the variable 'RegPath' has not been defined.
at com.install4j.config.l.a(ejt:577) at
com.install4j.config.l.a(ejt:485) at
com.install4j.config.l.a(ejt:431) at com.install4j.b.c.f.a(ejt:84)
at com.install4j.b.c.f.a(ejt:87) at com.install4j.b.c.f.a(ejt:87)
at com.install4j.b.c.a.a(ejt:1079) at com.install4j.b.c.a.a(ejt:957)
at com.install4j.b.c.a.a(ejt:943) at com.install4j.b.c.a.a(ejt:925)
at com.install4j.b.c.a.a(ejt:762) at com.install4j.b.c.a.a(ejt:721)
at com.install4j.b.c.a.k(ejt:685) at com.install4j.b.c.a.b(ejt:227)
at com.install4j.b.c.a.a(ejt:133) at com.install4j.b.b.v.a(ejt:75)
at com.install4j.b.b.c(ejt:285) at com.install4j.b.b.a(ejt:141) at
com.install4j.b.i.a(ejt:413) at com.install4j.b.i.b(ejt:156) ... 1
more
Am I missing anything?
Project Files: Sub-Project Main Project
This is a bug that will be fixed in 7.0.9. Please contact support#ej-technologies.com to get a build where this is already fixed.

How to allow / workaround nested composite Gradle builds

I'm running into the same issue as reported here:
I have a Java project A which depends on project B (module), and
project B dependes on project C (another module). For project A I
would like to setup "includeBuild ../projectB" and for project B I
would like too setup "includeBuild ../projectC" so that I could
develop everything in Eclipse + Buildship 2.0 without the need to run
Gradle for every small change in each of the projecta A, B and C.
But if I setup this I get: "Included build '%s' cannot have included
builds.".
Expected Behavior
Recursive "includeBuild" would recursively include dependent projects.
Current Behavior
I get "Included build '%s' cannot have included builds.".
Your Environment
Gradle 3.5, Buildship 2.0, Eclipse 3.6
How can I resolve / work around this issue? In my instance, I have utility project that includes email functionality (using JavaMail). The email functionality is needed in the data project and a UI project. The UI project also depends on the data project.
Adding another answer for a different approach...
Each settings.gradle could add a check to before includeBuild to see if it's already inside a composite. If it's already inside a composite, it doesn't includeBuild.
See here for extra info on the composite check
Eg
project2/settings.gradle
boolean inComposite = gradle.parent != null
if (!inComposite) {
includeBuild '../project1'
}
project3/settings.gradle
boolean inComposite = gradle.parent != null
if (!inComposite) {
includeBuild '../project1'
includeBuild '../project2'
}
project4/settings.gradle
boolean inComposite = gradle.parent != null
if (!inComposite) {
includeBuild '../project1'
includeBuild '../project2'
includeBuild '../project3'
}
etc etc
Using this approach you could run gradle from wherever you like and it should behave as expected (ie substitute dependencies with local projects)
Have you considered
Ensuring that none of the individual builds are composite builds
Having an "uber" build which is a composite of everything
Note that the settings.gradle is itself a groovy script, so you could create a dynamic composite, eg all sub-folders with a build.gradle under a parent.
uber/settings.gradle
new File("c:/someFolder").listFiles().each { File f ->
if (f.directory && new File(f, 'build.gradle').exists()) {
includeBuild f
}
}
Eg
c:/someFolder/project1/build.gradle
c:/someFolder/project1/src/main/java/**/*.java
c:/someFolder/project2/build.gradle
c:/someFolder/project2/src/main/java/**/*.java
c:/uber/settings.gradle (as above)

SBT read STDIN for user input

I am creating a specialized build task in my project that would require user input in STDIN which will let users select which version of hadoop,spark etc libraries will be used to build the application.
so far I have created a that task looks like the below.
lazy val build = SettingKey[Unit]("build", "build the app with all dependencies") in all // all is a project key
build := {
println(s"input hadoop client version")
val hadoop = scala.io.Source.fromInputStream(System.in).bufferedReader().readLine
println(s"input hiveserver jdbc version")
val hiveserver = scala.io.Source.fromInputStream(System.in).bufferedReader().readLine
// bunch of code to customize the build
}
The problem with the above code is that the body of build task key is run whenever the project is initialized in sbt or whenever reload task is run. so whenever I open the project in sbt, it hangs waiting for me to enter the version inputs in the standard input. How the task be made such that its body is executed only when the task is run and not when the build is initialized
I would consider defining a new custom task [http://www.scala-sbt.org/0.12.2/docs/Getting-Started/Custom-Settings.html#implementing-a-task] rather than extending build with blocking commands such as user input. As you experienced build is executed quite often.
You could for example extend build to use predefined values, read from environment settings. And have a interactiveBuild task where you prompt the user, showing the defaults retrieved from the env vars.
For more info about defining custom tasks check these out:
https://github.com/earldouglas/sbt-custom-task/tree/master/project
SBT plugin - User defined configuration for Command via their build.sbt

TeamCity, version numbers from file in repo and assembly patcher

Context
In our repo, we have a file called version.txt that contains the major and minor version number: 0.7.
I added a TeamCity build step with a powershell script that sets this parameter into a config parameter, based on this answer:
$version = Get-Content version.txt
Write-Host "##teamcity[setParameter name='UserMajorDotMinor' value='$version']"
The UserMajorDotMinor parameter defaults to 0.6 on TeamCity.
I have a config parameter called %UserVersionNumber% that is used to set the actual version number, which is defined as
%UserMajorDotMinor%.0.%system.build.number%
The Problem
While prints 0.7 in the TeamCity build log, but it doesn't seem to properly set the UserVersionNumber, because the number that the assembly patcher writes into the dll is still 0.6.0.xxxxx.
What do I have to change so TeamCity will actually write the correct version number into the dlls?
The Assembly Info Patcher build feature will run before any build step, therefore, changes made to parameters within a step won´t affect the Assembly Info Patcher
If you really need to use the Major.Minor Info from the version.txt file then i would setup a seperate build configuration that reads the file and provides the content as build parameter %UserMajorDotMinor%. Basicly what you already did.
Then you can add the newly created config as dependency to the actual build and set the %Version% Parameter to %dep.[buildconfigname].UserMajorDotMinor%.0.%system.build.number%
As a Alternative, use a Script to patch your AssemblyInfo.cs files as seperate build step instead of the Assembly Info Pather Feature.

How to cherry pick ZIP contents with Gradle Distribution plugin?

My Gradle build currently produces the following directory structure under a build dir in my project root:
myapp/
src/
build.gradle
build/
docs/
groovydoc/* (all Groovydocs)
libs/
myapp-SNAPSHOT.jar
myapp-SNAPSHOT-sources.jar
reports/
codenarc/
main.html
test-results/* (JUnit test results)
I would like to add the distribution plugin (or anything that accomplishes my goals, really) to have Gradle produce a ZIP file with the following directory structure:
myapp-SNAPSHOT-buildreport.zip/
tests/
(JUnit tests from build/test-results above)
reports/
main.html (CodeNarc report from build/reports/codenarc above)
api/
(Groovydocs from build/docs above)
source/
myapp-SNAPSHOT-sources.jar (from build/libs above)
bin/
myapp-SNAPSHOT.jar (from build/libs above)
After reading the plugin's documentation, I can't tell how to configure it to suit these needs. Its obvious that I need to run gradle distZip, but as to how to actually configure it to produce the desired directory structure, it doesn't seem to provide any documentation/examples. Any ideas?
Note: The JAR's version is obviously SNAPSHOT, and is passed into the Gradle build with a -Pversion=SNAPSHOT command-line argument.
The Gradle Distribution plugin automatically has defaults (the problem is that the docs do not tell us the defaults, but the Gradle project default structure is what is assumed) so if your Gradle project is fairly straightforward and already using src/main/groovy or src/main/java, you typically just need to...
Use the CopySpec reversing pattern of giving your into{} (makes a dir) containing the contents of from{} , rather than the reverse, like so:
apply plugin: 'groovy'
apply plugin: 'eclipse'
apply plugin: 'application'
distributions {
main {
baseName= 'vz_sde_dm'
contents {
into('bin/config') {
from 'config'
}
into('lib/samples') {
from 'samples'
}
}
}
}
Notice I did not need to define a from{} for my contents{}, but only into{}s that's because I am already using the default Gradle Groovy project layout and only added 2 extra folders (config & samples) under my project in Eclipse but needed those 2 folders to land into a slightly different hierarchy for my Distribution compared to my regular build folder layout.
I would probably not use the distribution plugin and instead just create a new custom Zip task. It would look something like this:
task buildreportZip(type: Zip, dependsOn: build) {
classifier = 'buildreport'
from('build/test-results') {
into 'tests'
}
from('build/reports/codenarc') {
into 'reports'
}
from('build/docs') {
into 'api'
}
from(sourcesJar) { // or whatever you source jar task name is
into 'source'
}
from(jar) {
into 'bin'
}
}
I was trying to make a custom layout also, and had real trouble figuring out how to exclude the project output from build/libs from the yourProject.zip/yourProject/lib directory (and excluding things in general) and putting it instead into yourProject.zip/yourProject.
After quite a few hours across multiple days of searching and poking around in the API I finally found something that worked using actual configurations of the Distribution and underlying CopySpec (documented here and here, respectively for Gradle 5.6.1, you can just replace 5.6.1 with current in the URL to get the most recent API docs, 5.6.1 just happens to be the version I'm using):
distributions {
main {
baseName = appName
contents {
filesMatching("**/${appName}.jar", {
if (it.getPath().contains('/lib/')) {
it.setPath(it.getPath().replace('lib/', ''))
}
})
into('config') {
exclude(['server.crt', 'spotbugs-exclusion-filters.xml'])
from 'src/main/resources'
}
}
}
}
For exclusions the only thing that worked was matching on a glob pattern and specifying the correct action (to copy it to the root dist directory instead of root/lib) with a Closure through the filesMatching method of the main distribution's content CopySpec. You can see also how destination for configs is changed from the root to the root/config directory. Thanks so Thad's answer for helping to guide me to the correct build configuration, also.