Closed nakul02 closed 7 years ago
I am also interested in this, and am willing to help with linux build/testing if help is needed. I think @jcuda mentioned that maven upload is on his TODO list, so I hope his schedule will align with this issue soon :)
Yes, bringing JCuda into Maven Central is one important goal. One of the main reasons for the restructurings between 0.7.5 and 0.8.0 was exactly done for this: Distributing the natives separately means that the end-user would have to fiddle with the LD_LIBRARY_PATH
or java.library.path
, which is a nuisance. Now, in version 0.8.0, the natives are contained in the JARs and can be loaded at runtime, and thus, this should be a huge step towards proper Maven deployment - as you also pointed out in the comment of your PR.
In the longterm, we want to have jcuda available through maven. My plan was to upload the jcuda jars and the jcuda-native jars (v0.8.0) to maven central. Does the license allow this and is this ok by you?
Technically and regarding the license, this would be OK. But conceptually, I would strongly prefer to upload them "officially". I already prepared this locally (e.g. Sonatype account etc). But I'd really appreciate help regarding the remaining open issues that I see right now:
There are no natives for MacOS. I think that they should be available when doing an "official" release on Maven. Otherwise, it will work on Linux+Win, but Mac users will encounter missing dependencies (or in the worst case, receive an unpleasant UnsatisfiedLinkError
at runtime)
The upload to Maven Central may be fiddly. Until now, I only did this with mvn release
. It will automatically tag everything, assemble the package with the SHAs, and upload it to the staging area. This is convenient. But I think that this will not (directly) work for JCuda. Instead, I will probably have to manually assemble some package, and manually upload it to Sonatype staging area (i.e. not as part of the mvn release
). Is this correct? Has anybody done this before? How complicated is this? (I'll read more about this, but any pointers would be appreciated)
Maybe @MysterionRise can give some helpful hints here as well...?
Sorry, I overlooked that you mentioned "apple" as well.
So right now, I think that one approach could be:
The last step would be quite a lot. I'd create a BATch script for that, unless there is a way to bundle and deploy multiple artifacts that are contained in one big JAR file - does anybody have experience with this?
@jcuda - anyway i can help to speed this up?
Yes, sorry, I had some other appointments this week (glTF webinar, job interviews), but allocated next week for tackling this. I'll start on sunday/monday. If you (or anybody) could tell me whether the approach sketched above could work, or whether there are other/better approaches, that would be great. I'm a bit skeptical about this "jar bundling" step - Maven is veeery picky when something is not absolutely right (that's a good thing, but it can be tricky to get it right). In any case, I'll give it a try, and see how far I get (possibly posting questions or intermediate states here...)
I actually don't have any experience uploading to sonatype. Even so, here are my 2 cents: It seems that this method is lesser work than the bundling method, but you'd need access to all the platforms for this method. (Not to mention ease with future releases). But seeing as how that's not possible, maybe sticking to the bundling method is the best.
Thanks for this link, I've already looked at some resources, but in the end, I guess I'll just have to try them out, and see which one works best (also in view of a then hopefully smooth upload for CUDA 9).
From a first, short (!) look at the link, I'm not sure what you mean by
you'd need access to all the platforms for this method
Does this really refer to the deployment itself? As mentioned above: I cannot build the natives for all libraries anyhow, so would have to resort to the natives that @MysterionRise collected (hoping that the "re-signing" is possible...)
I assumed that if you were to follow the directions given here (linked in the original article under point 3), you'd be doing a mvn clean deploy
. For doing this, you'd need to be on the platform from which artifacts are being uploaded (think *-natives-0.8.0-linux-x86_64.jar
or *-natives-0.8.0-linux-ppc_64.jar
, etc). From the previous discussion on this thread, I assumed that you don't have access to a mac or to a power8 and said that just sticking to the bundling method (for all 4 platforms) is a good idea.
Some questions that I'm currently juggling with:
Maven Central needs -sources
and -javadoc
JARs. For the native library JARs, I'd just create empty ones here (maybe containing a README pointing at the GitHub repo...). Better ideas?
The POMs must contain certain information. I knew that, basically, but tried the process of using a bundle.jar
(with invalid POMs) nevertheless, and it said
Project name missing, Project description missing, Project URL missing, License information missing, SCM URL missing, Developer information missing
Now I'm not sure how to bring this information into the respective POMs. It's not sufficient to put them into the parent POM, because this will only be referenced with a relative path. Can one force maven to "inline" the parent POM? (Actually, only parts of the parent POM would have to be added - namely, the ones that the validation complained about)
In any case, I'd like to avoid having specific SCM tags for each artifact (that would be a hassle). Does anybody know whether a generic SCM like this will be valid and sufficient?
<scm>
<connection>scm:git:git@github.com:jcuda</connection>
<developerConnection>scm:git:git@github.com:jcuda</developerConnection>
<url>git@github.com:jcuda</url>
</scm>
In doubt, I would have to create one POM for each artifact (and there are 16 artifacts right now...), each containing the same information, so that these POMs could all be added to the local repo, with
mvn deploy:deploy-file -DpomFile=pomsForDeployment/jcuda/pom.xml -Dfile=pomsForDeployment/jcuda//pom.xml -Durl=file://.
...
(The same for jcuda-natives, jcublas, jcublas-natives ....)
But that looks a bit odd...
So it looks like a combination of dedicated POMs (that are only used for deployment) and several empty JARs might work. It seems that additional empty JARs (so called "main JARs") will be required for the *-natives
artifacts.
Missing: no main jar artifact found in folder '/org/jcuda/jcublas/0/8/0/org/jcuda/jcurand-natives/0.8.0' ....
I'll try this tomorrow.
Also, as seen in the folder: There's still something wrong with the path... /0/8/0
... I think that all files have to be in the root folder of the resulting bundle.jar
....
Sorry, i really missed most of the fun :) What's the current state now? Anything I could help with? For parent pom, you could specify some props and then reuse them in the child pom. Makes sense?
Now I have created 16 POMs that are only used for preparing the deployment, and that therefore contain the information that is required for Maven Central (developer, name, scm, license). They only differ in the artifact name - there must be a better solution for this...
Beyond that ... tomorrow I'll try adding the remaining (missing, empty) JARs for the *-natives
artifacts, throw all this into a flat bundle.jar
(i.e. without an internal directory structure), and see whether Sonatype can dissect this properly. If you have any ideas for improvements or simplifications, that would be welcome.
Another intermediate step: It seems to basically work, but only when uploading each artifact bundle individually (so there are 16 bundles to be created and uploaded...).
But regardless of that, there has to be a different solution for the POMs.
As mentioned above: There now are 16 dedicated POMs for deployment. These contain the developer
...scm
information, as required by Maven central. They do not (yet) contain dependency information. This has to be added - otherwise, the most important part of maven would not work. But this would make the duplication even more ridiculous: The original POMs and the deployment POMs would then basically be the same, with these differences:
I would suggest to make your parent (../jcuda-common/JCudaParentPOM/pom.xml) a real separate project (git repo) which only consist of the pom file and a README.md (maybe some other files) and put the information you need there: license, project name, url, developer list etc. plus plugin definition (pluginManagement etc. cause you are defining versions in sub projects) into it. Make a release of it . Using the usual mvn release:prepare release:perform
way...afterwards you can use this parent in each of your projects and define a single version of this parent which inherits things like description, dev list etc. into your sub projects without the need to define a relativePath in parent definition In each of your sub projects of course you need to define the scm area cause it's using a different git repo so it should have different scm entry for it plus the special things for each project...
I already considered such a "parent POM project" (and thought I had mentioned it here, but obviously did not), but hoped that this would not be necessary. It would be the third pseudoproject besides jcuda-common
and jcuda-main
.
In fact, I think it would conceptually make sense to declare jcuda-common
as the "Parent POM project", but I'm not sure whether I'm not mixing unrelated things here just for convenience. (I think that it could later make even more sense, when the native code is added, and the jcuda-common-X.Y.Z-sources.jar
could contain the source code of jcuda-common
- which would otherwise appear nowhere...)
Or, maybe I'm misinterpreting this, because the intended workflow is not yet clear, e.g. for the update to 0.9.0:
?!
In any case, the release hardly can be done with mvn release
. The natives have to be built separately on different platforms. Sure, it's technically possible to collect all native libraries and then create all the natives
-JARs in one run during the release. But I do this for other projects, and it can really be a pain in the back. Maven is messing around with tags in the SCM, does not properly support passwords, and when something goes wrong, it always happens at the end, and the state has to be cleaned up with git reset --hard XXX
+git push -f origin master
... I will not do this for 8 different repos. (In hindsight, it might have been easier to just mess everything into one, large repo, but I'm not so sure about that...)
This is also related to the last point:
In each of your sub projects of course you need to define the scm area
Is this really necessary? Right now, I intended to give every project the same SCM info:
<scm>
<connection>scm:git:git@github.com:jcuda</connection>
<developerConnection>scm:git:git@github.com:jcuda</developerConnection>
<url>git@github.com:jcuda</url>
</scm>
without the actual project name. Of course, this will not work with mvn release
, but ... it is not supposed to work with that (in fact, it's only there to make Maven happy...)
So unless being told otherwise, I assume that the following would be OK:
jcuda-common
as a deployable artifact, defining the parent POM. The parent POM would be the one that is currently in https://github.com/jcuda/jcuda-common/tree/master/JCudaParentPOM , but I assume that it would have to be moved one level up, into the root directory, to make maven happy (and to be able to define this directory as the pseudo-src
directory, so that the jcuda-common-X-sources.jar
could eventually contain all the CMake- and common JNI files)developer
, name
and license
in the parent POMscm
in each project POM. I'm still not sure about this. For example, https://github.com/jcuda/jcuda currently contains two artifacts: The jcuda
project and the jcuda-natives
. I think that this would lead to problems if I ever decided to use the mvn release
plugin: It would try to create the same tag twice ... (It should not be a problem now, but something to keep in mind)I hope that I can make some progress here tomorrow and on friday. Any hints and comments would be welcome.
The next step:
jcuda-common
project now contains the parent POM in its root directory. -natives
project each contain four executions of the maven-jar-plugin
, for creating the (empty) main JAR, the (empty) javadoc
jar, the sources
JAR containing the native sources, and the -windows-x86_64
JAR containing the actual native library.I still have to figure out how to proceed from there. Particularly, I'm looking for a way to create the bundle.jar
files conveniently. Doing mvn deploy:deploy-file
calls for all the 49 JARs seems odd (even odder than the current infrastructure that copies all these artifacts into the jcuda-main/target
directory). I naively tried
mvn -Dmaven.repo.local=C:/JCudaMavenRepo clean install -U
but of course, Maven once more showed me a finger. Sometimes, it feels like it is intended to be complicated.
The natives
POM executions:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<!-- Create the JAR containing the native libraries -->
<execution>
<id>create-native-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>nativeLibraries\${jcuda.os}\${jcuda.arch}</classesDirectory>
<classifier>${jcuda.os}-${jcuda.arch}</classifier>
<includes>
<include>lib/*JCublas*</include>
<include>lib/*JCublas2*</include>
</includes>
</configuration>
</execution>
<!-- Create the placeholder main JAR that contains the README.txt -->
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${basedir}/../jcuda-main/resources/readme</classesDirectory>
</configuration>
</execution>
<!-- Create the JAR containing the native sources -->
<execution>
<id>create-native-sources-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${basedir}</classesDirectory>
<classifier>sources</classifier>
<includes>
<include>JCublasJNI/**</include>
<include>JCublas2JNI/**</include>
</includes>
</configuration>
</execution>
<!-- Create the placeholder JAR for the javadoc that contains the README.txt -->
<execution>
<id>create-native-javadoc-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>javadoc</classifier>
<classesDirectory>${basedir}/../jcuda-main/resources/readme</classesDirectory>
</configuration>
</execution>
</executions>
</plugin>
It seems like the jcuda-parent
project (containing only the parent POM) is in fact necessary. Otherwise, the jcuda-common
project could not have a proper POM file that does what it should do. (I thought it should be possible, using pluginManagement
, but no avail).
So now there is the jcuda-parent
project that all other projects refer to. As already mentioned in https://github.com/jcuda/jcuda-main/issues/14#issuecomment-281485064 , it seems like it is then necessary to first do a
cd jcuda-parent
mvn clean install
before the
cd jcuda-main
mvn clean install
can be executed. The latter will then place all the JARs and POMs into the jcuda-main/output
folder. (These are 100 files...). Locally, I created a .BAT file that then signs all these files with GPG, generating the corresponding .asc
files, and finally packs the files together into bundle.jar
files.
Eventually, it should be possible to upload these 9 bundle.jar
files to Sonatype - I'll try this next week.
Until then, any feedback would be welcome.
No feedback. OK.
The release has just been created. Iff everything worked well, then the following artifacts should be available in Maven Central soon:
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcuda</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcublas</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcufft</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcusparse</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcusolver</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcurand</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jnvgraph</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.jcuda</groupId>
<artifactId>jcudnn</artifactId>
<version>0.8.0</version>
</dependency>
(Now, preparing version 0.8.0b, to fix the parts that are not working as expected...)
I just tested it locally, on Win64, by deleting m2/org/jcuda
and the native DLLs in the temp
folder, and it seems to work. The dependencies are resolved, the natives are unpacked, and (hoping that it also works for all other platforms), it seems like JCuda finally made its way into Maven Central.
Thanks to all supporters for your comments and hints, and particularly to @MysterionRise for setting the stage with mavenized-jcuda
.
If there are any problems, comments, or suggestions for improvements, they can either be added here or in dedicated issues.
(I'll leave this issue open for a while, at least until the website and README are updated)
Thanks @jcuda!
Hi,
I work on the systemml project, where we use the JCuda project. For now we don't have a straightforward deployment for JCuda (0.75b) through maven and expect the user to have the jcuda jar files in the classpath (and the .so files in the LD_LIBRARY_PATH).
I contributed jcuda8 jars for linux, apple & ppcle64 to the mavenized jcuda project. I did this to try out a simple deployment method in this PR.
In the longterm, we want to have jcuda available through maven. My plan was to upload the jcuda jars and the jcuda-native jars (v0.8.0) to maven central. Does the license allow this and is this ok by you?
For now, people from the nd4j project seem to have jcuda jars for v0.6.0. If you, @jcuda, did this, that would be ideal.