I have a project that depends on Jacob. The artifacts on Maven central are quite outdated, so I would like to download them directly from SF. But I don't know how to do that with gradle.
More specifically, what I try to achieve is:
Download the distribution .zip from SF.
Unpack the distribution and extract the .jar (with a rename so that the .jar file name contains the version) and the two .dlls.
Add the extracted .jar to the compile configuration.
The tests have a runtime dependency on the .dlls.
The final project .jar should include both the jacob.jar and the .dlls.
This is a quite open-ended question, and I think I know how to do some of the points on the list. Task 2 is probably just a copy task, and task 5 is just about telling gradle what goes into the jar. Task 1 seems like something that should be easy, but I don't think that the copy task accepts a URL as source.
What I really don't know how to do, is task 3. How can I add a derived resource to a configuration, and make it trigger a task if it is absent? It is like normal dependency resolution, but where the included dependency is derived from another, transformed, dependency.
I realize that the easy way out is to just include the Jacob dependencies in my project, but I really don't like to pollute my SCM repositories with binary artifacts :-)
For step 1, you'll have to write your own download task (should be easy with Groovy). Step 3 can already be done in the configuration phase, provided you know the path to the unzipped Jar beforehand. So you'll just add a regular file dependency. You are right about step 2 and 5. Step 4 will probably configure the test task (e.g. perhaps you'll have to set a system property for the native code location). What remains is to establish the necessary task dependencies.
Related
I am using gradle and its local repository is at \.gradle\caches\modules-2\files-2.1 which has all the downloaded jar but not my modules.Is there any specific place I should be searching it for ?
I need it as is in settings.gradle I am having a dependency path specified like :
include ':model'
project (':model').projectDir = new File(settingsDir, './model')
in a new project. Also I don't want to give path in that way because if I have a dependency from multiple projects on this project then mentioning path will be difficult and weird.
How can I make gradle search it from local maven or gradle repositories.
I'm still not sure what is being asked here, and I suspect there is some confusion over how multi-project builds work. So I'm going to attempt to provide a general-purpose answer.
The first question you need to answer is whether you're interested in dependencies between projects that are part of the same build — as in part of a multi-project build — or in separate builds.
Project dependencies (multi-project builds)
Project dependencies are covered in the user manual and only apply to multi-project builds. They use a logical path, using colons as 'path' separators, to specify the location of the target module, like so:
dependencies {
implementation project(":model")
}
At this point, Gradle needs to know where ":model" exists on the file system. There's no getting around that. You have a few options:
Follow the convention of directory structure matching the logical path structure, i.e. have a MyBigProject/model directory containing the ":model" child project
Specify the file path of ":model" in settings.gradle, e.g. with project(":model").projectDir = new File(rootDir, "unusual/path/to/model")
Automate the discovery of projects
The most common approach is the first one. The second is not unusual, particularly if you want to put child projects into a separate directory, like subprojects — something the build of Gradle itself does. I haven't seen the last option done, and I don't know whether it runs into problems.
For the sake of completeness, and at your own risk if you use something like it, here's an example of automatic discovery of projects in the settings.gradle file:
rootDir.eachDir { File dir ->
if ("build.gradle" in dir.listFiles()*.name) {
include dir.name
}
}
This fragment basically looks for directories within the root project folder that have a build.gradle file in them and adds them as child projects. The child projects' directory names become the projects' names.
It's not particularly clever, and you should really use different names for the build files, but it may give you some ideas to work with.
Non-project dependencies
As with project dependencies, Gradle needs to know where to get the corresponding JAR or other form of artifact for a specified module. You normally specify Maven Central or something similar for this, but there are other useful, but less common, options:
Copy a project's artifacts into the local Maven repository — both the Maven Plugin and Maven Publish Plugin support this
Publish to a Maven-compatible repository using a file:// URL rather than an HTTP/HTTPS one, which protects your projects from corruption of Maven Local
Worth noting is that Gradle supports composite builds that allow you to substitute a normal dependency with (effectively) a project dependency from another build. So if model were part of a separate build but you had the source code and build locally, you could make changes and immediately test them in another build's project without going through the whole "install" intermediate step that's common in the Maven world (and Gradle pre-composite-builds).
Hope all this makes sense.
My task is this:
Take a dependency, which is a zip
Unpack the dependency
Run some Java code, add some new files
Assemble the dependency back, including the new files
After assembly, build it as another artifact.
My queries:
The dependency coordinates need to be provided dynamically during build time. Am looking for something like SystemProperty, but not sure how to take them through my pom.
Unpacking is straightforward. unpack-dependencies is all I need.
Running Java code - Here's a hiccup again. This project doesn't produce a jar or a war, it's got to be a pom packaging. SO I cannot compile code in the project. I can use the compiler plugin with Java execution. Not sure it's a good practice.
Not a problem to assemble, if I can get uptill here.
Any suggestions for points 1 and 3?
Thanks for the help.
Alot of the problems with Maven arise from the decision about which build "tasks" translate into discrete Maven builds. The general idea is that each jar, zip, or whatever your building should get it's own mave build ( aka pom, aka module ). Looking at your bullets, I believe you have three maven builds, i.e. three poms.
1) The first pom will build your Java utility, i.e. jar. This jar then becomes a dependency of your other build that needs to execute it as part of the zip assembly process.
2) The second pom will do build the zip. ( I guess you will actually build several different ones; most likely these are then separate poms -- while you can have a single build produce more than one artifact, leveraging the concept of attached artifacts and classifiers, it's an unnecessary complication that should be avoided unless you know you need it. ) These zip assembly poms unzip the primary zip, massage the content via the java util( running the jar via maven-exec plugin), and reassembles the zip.
3) If you need to change the name of an artifact ( your zip ) when it's consumed in the production of another artifact ( your framework ), then you can use the dependency plugins' copy goal. It allows you to specify new names for the dependencies that you are pulling into your build -- but note you aren't actually changing the maven coords, which, I believe, is something to be avoided like the plague. :)
In my multi-module Maven project, suppose I have two modules, car and horse. They both depend on a JAR file, transport.jar, a file not available in any online Maven repositories. As such, I need to find a way to make these modules depend on a file found somewhere in the project folder structure.
From what I understand, the default Maven solution would be to manually register the JAR file in the local repository. While this would work on a development machine, it breaks on the build server, which clears its local repository before each build.
I've been searching online on how to do this on and off for a while and found some helpful things, but nothing that completely works.
For instance, a common answer is to add a dependency to the file using <scope>system</scope>. However, not only do others claim that it's extremely bad practice to do so, it also doesn't work on the build server. (On a side note, I would also like to point out that using absolute paths to the JAR is also out of the question due to, again, it being built on several different machines.)
A more useful method I found was to define a local repository in the POM file, pointing towards the path file:${project.basedir}/lib. (Such as in this article) Unfortunately, if I place the JAR and repository definition in the car POM, I cannot successfully add a dependency to the JAR in horse. I've tried both with and without an additional reference to car in horse, as well as defining a second repository in horse, pointing to file:${project.basedir}/../car/lib. This problem would also remain if I tried to make a third module, transport-lib, specifically for wrapping the JAR dependency.
I could most likely add the JAR file to both modules and define two separate module-local repositories, but I really don't want to unless I have to due to the need to keep the two (often updated) JARs in sync etc.
So, my question is as follows: Can someone give me a confirmed-to-work method to have two modules depend on the same JAR file inside the project, given the parameters and restrictions mentioned?
Best solution is to use a repository manager like Archiva, Artifactory or Nexus and install that artifact into the repository manager. Afterwards you can use this artifact directly in your pom files without any issue.
Don't use the scope system, cause it will cause other problem after a release for other etc.
I have a java application.
I can run the Maven Release task which will do some nice things for me:
Change Version number from 1.0.0-SNAPSHOT to 1.0.0
Increment the version number in my pom to 1.0.1-SNAPSHOT
Tag the release in source control
Upload the resulting package to my maven repository
I'd like to take things a step further. I have some post-build steps that I'm currently doing manually.
Update the launch4j configuration xml file with the appropriate version
Wrap the resulting jar in an executable using launch4j
Copy the resulting EXE into a package directory
Copy several supporting files into the package directory
Zip the package directory up
Email the package to my testers.
Eventually I'm going to have the additional task of building an installer leveraging the package directory.
I don't know that maven or ant are the right tools for automating my remaining 6 tasks, but it looks like either one or a combination of both could potentially accomplish what I need.
I could probably write a batch file or a simple perl script to do these things quicker than figuring out how to do them, but I would prefer to keep things as standard as possible so that I'm not taking on the additional responsibility of supporting a hack of a release process perpetually.
It seems to me that these are tasks that might not be standard part of build/release, but are commonly seen enough that there should be a best/most common practice for accomplishing them.
I would suggest to use the maven-assembly-plugin as well as the maven-launch4j-plugin during your build.
Update the launch4j configuration xml file with the appropriate version
put a placeholder into the configuration xml and let maven replace it during the
the build.
Wrap the resulting jar in an executable using launch4j
use the launch4j-maven-plugin to create the executable.
Copy the resulting EXE into a package directory
I would suggest to put the resulting artifact into a repository manager instead
of a separate folder, cause in Maven all artifacts are stored within
a repository. It might be necessary to setup your own repository manager
(Artifactory, Nexus, Archiva).
Copy several supporting files into the package directory
Using them as resources (src/main/resources) they will be copied
automatically.
Zip the package directory up
Use the maven-assembly-plugin to create a resulting zip file.
Email the package to my testers.
You can use a CI like Jenkins etc. to send the final mail or
you can take a look into maven-changes-plugin which might be solution.
This means all your mentioned steps can be handled by Maven during a usual build. This means in the end you can use the maven-release-plugin to produce a full release which contains all the above steps and produces all the wished artifacts.
If I were you, I would try a combination of the following:
Maven release plugin, unless it is not flexible enough for SCM related processes. If using SVN as SCM, I would use directly SVNKit(inside a custom Maven plugin), if flexibility is a concern.
Maven launch4j plugin.
Maven assembly plugin
Maven Ant Run plugin and/or one or more in-house Maven plugins for the remaining tasks.
I want to set the time stamp of the classes and resource in a maven module, just before it's built into the jar.
I guess I can use the maven-antrun-plugin, but I'd like to see if there are better ideas.
Does anyone have an idea?
Let me add more details for the reason I need this capability.
When we build a new version for the product, we also build a patch install which compares all artifacts of previous build to current, and packages only the ones which differ.
Jars (and any zip based archive) might have the same content, but time stamp of classes and resources are part of the metadata, and cause the diff to show jars differ (when in fact, the content is identical). I want to hack the jar packing and set all classes times tamp to be constant (like 1/1/2000 00:00).
I hope this explains my need.
Well, the best solution is to adapt your tool that compute the diff to go have a look deeper in the jar ;)
I am afraid there is no other way than using the a ant file with the touch task to reset the file date. There is no existing plugin that sets the file date.
You could also write your own maven plugin and contribute it to the community but it is probably a bit overkill...
HIH
M.
I just want to share what I decided to do.
I will not touch the maven build, and let it build the jars as before.
What I did is implement a script in my build to compare the jars. The logic of this script is simple:
Check arguments (jars exist)
Extract jars to a temp folder (with a unique name)
Run a diff on both folders
Cleanup
Exit with the relevant exit code (0 if same. 1 if differ)
I hope this is useful.