-
-
Notifications
You must be signed in to change notification settings - Fork 645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modular design for build artifacts #100
Comments
This would go hand in hand with the gradle build script but you could try subprojects. That way it would also handle any dependencies that they have on other parts of the lib though it might need some refactoring of the codebase (I would work on it but i still don't really get how the generator works and don't have time to sit down and mess with it right now). |
After some discussing, here is what my current perspective of a modular build is with respect to deployment: Motivation
So, from the deployment perspective, I as a user want to choose from the list of possible libraries/modules the ones I would like to use. The result should be that I only have to download the chosen modules and their transitive dependencies, but nothing else. Project setups This now raises the question how to go about users with different project setups and build tools. Maven users will likely want to add the modules as Maven dependencies in their pom.xml. Together with the SharedLibraryLoader which extracts the native shared libraries from the classpath, this will work out of the box. This then necessitates that all modules are Maven artifacts being deployed in a public Maven repository. LWJGL Initializr Non-Maven/Gradle users will ideally be provided with a distribution zip file that can be downloaded from lwjgl.org, as is the case now with the fat distribution. For this, some kind of web application is desirable that lets the user choose which modules should be included in the distribution and then provide an assembled zip download for that, much like the Spring Initializr for Spring Boot. So, we have a scenario where dependency management is handled by the build tool (Maven/Gradle) and a scenario where we have to bundle all artifacts into the download zip. Building To satisfy the Maven/Gradle users, the existing deployment mechanism with Gradle and generated Maven pom.xml files can still be used. Every module will get a pom.xml that describes that module and its dependencies. For non-Maven users who download a customized zip file, we need a way to automatically provide a selection of available modules to the user. Preferably, the user will be shown a web UI which asks him which version of LWJGL to use and based on that, which modules with which versions are available. Maven project structure The basis is a parent Maven project. This project (probably named org.lwjgl:lwjgl) uses "pom" packaging and simply enumerates all modules as optional dependencies. In addition to the Java classes artifact, this artifact has profile-dependent dependencies to its native platform artifacts containing the respective shared libraries for the particular platform (windows/linux/osx). The pom.xml files for each module can probably be generated just like now via the Gradle build script. The only dependency so far is that every module will depend on the lwjgl-core module. Non-Maven Users Non-Maven users will be given a web UI to select and download a customized distribution zip file. To build the distribution with binaries and sources, either all of the selected modules' artifacts can be downloaded and packaged into a single distribution zip, or the modules' artifacts can be unpacked and repackaged into a single binary and source jar. The native shared libraries can also either be provided with their platform jar files or extracted and repackaged in a "natives" directory. Technically, the actual download can be triggered via a single GET URL containing as query parameters the selected modules, such as: Version management Currently, to ease version management, whenever a new version of LWJGL appears, all modules' versions will be updated accordingly to point to the same new version. Release management Just like now, every new release will build all module artifacts and deploy them to Maven Central. Like mentioned above, whenever a non-Maven user wants to obtain a new release distribution, he selects the modules he wants to use and will get a customized distribution. |
The latest nightly (3.0.1 build 6) is the first build with modular artifacts. Please give it a go and provide any feedback you may have here. This build is currently available as a monolithic Maven support is coming next, when we're happy with the new structure. The site will also be upgraded to support downloading individual modules and a tool will be added that:
|
why not put the native libraries in a single * .jar , to facilitate application portability for generator explained here you may have the option to generate only the *.jar needed for developers, example: I need only generate module GLFW or GL or GLFW+GL! |
What do you mean exactly? Having a single
That's coming, either via Maven/Gradle or the tool I mentioned above. |
When we eventually have the personalized/modularized build download available, in my opinion there won't be any need anymore for downloading separate platform native jars and even for separating the Java classes jars from the platform jars. |
i see the archives: lwjgl-glfw-natives-linux.jar, lwjgl-glfw-natives-macos.jar, lwjgl-glfw-natives-windows.jar, why no put all natives in only archive*.jar? (lwjgl-glfw-natives.jar) Some time ago work with JOGL, and I put libraries in a single *.jar as follows:
something other than the subject, have not thought lwjgl3 made compatible with Android |
The zip download currently provided on the lwjgl.org/download page is just one way of assembling a distribution, which currently chooses to separate the platforms' natives and the Java classes into separate jars for each module. |
A few reasons:
With that said, the tool on lwjgl.org/download will support merging the natives, so I think you'll be satisfied.
ARM support is scheduled for LWJGL 3.0.2. Android support will also be explored. |
Are you considering easy integration of LWJGL in SWT applications? I managed this with LWJGL 2, but have had a few issues with LWJGL 3. Know there's a project on Github to accomplish this. |
https://github.com/httpdigest/lwjgl3-swt link to project. |
Certainly. We could have an "external modules" section on the lwjgl.org/download site, where you can select lwjgl3-swt to be included in the download for all project types (Maven, Gradle, IDE). |
What do you mean? I can use a core context with SWT on Linux right now? Or you're saying it works as long as you use a compatibility profile? Because OSX isnt the only one that doesn't provides compatibility profiles, Intel's Linux drivers don't support them either. |
Modular maven artifacts are now available in the snapshot repository. I'm looking for feedback on the current structure. We now have the lwjgl artifact and one artifact for each binding (lwjgl-glfw, lwjgl-opengl, lwjgl-stb, etc). Each artifact contains the following:
The above structure has the benefit that a user may download exactly the artifacts they need and nothing else. On the other hand, since Maven has no concept of dependencies between classified artifacts, setting it up is quite verbose. For example a project that needs GLFW, stb, jemalloc and OpenGL, using the shortcut Gradle syntax: // lwjglVersion = '3.0.1-SNAPSHOT'
// lwjglArch = 'windows'
compile 'org.lwjgl:lwjgl:$lwjglVersion' // NOTE: this is optional, all binding artifacts have a dependency on lwjgl
compile 'org.lwjgl:lwjgl-glfw:$lwjglVersion'
compile 'org.lwjgl:lwjgl-stb:$lwjglVersion'
compile 'org.lwjgl:lwjgl-jemalloc:$lwjglVersion'
compile 'org.lwjgl:lwjgl-opengl:$lwjglVersion'
runtime 'org.lwjgl:lwjgl:$lwjglVersion:natives-$lwjglArch'
runtime 'org.lwjgl:lwjgl-glfw:$lwjglVersion:natives-$lwjglArch'
runtime 'org.lwjgl:lwjgl-stb:$lwjglVersion:natives-$lwjglArch'
runtime 'org.lwjgl:lwjgl-jemalloc:$lwjglVersion:natives-$lwjglArch' Our options: Option AKeep the above structure. We're soon going to have a tool on the LWJGL website that will let users choose the bindings they need and it will generate the corresponding Gradle/Maven declarations for them. Verbose, but auto-generated. Option BDon't use classifiers and make the natives separate artifacts with appropriate dependencies. The above example becomes: // lwjglVersion = '3.0.1-SNAPSHOT'
// lwjglArch = 'windows'
compile 'org.lwjgl:lwjgl-glfw-$lwjglArch:$lwjglVersion'
compile 'org.lwjgl:lwjgl-stb-$lwjglArch:$lwjglVersion'
compile 'org.lwjgl:lwjgl-jemalloc-$lwjglArch:$lwjglVersion'
compile 'org.lwjgl:lwjgl-opengl:$lwjglVersion' The above would automatically resolve the other dependencies declared in Option CWe could assume that most projects will use only a few of the available bindings and download speed is not a concern (Maven dependencies is a convenience for developers only, not end-users). The natives for all platforms could be merged into the unclassified artifact. The above example becomes: // lwjglVersion = '3.0.1-SNAPSHOT'
compile 'org.lwjgl:lwjgl-glfw:$lwjglVersion'
compile 'org.lwjgl:lwjgl-stb:$lwjglVersion'
compile 'org.lwjgl:lwjgl-jemalloc:$lwjglVersion'
compile 'org.lwjgl:lwjgl-opengl:$lwjglVersion' As simple as possible to configure, but at the price of downloading bigger artifacts. |
The ongoing modularisation ist very welcome! At the same time, for those who'd just like to hack away, it would be useful to have something like "lwjgl-all" which would give you an all-in-one package. |
The website tool is going to have a "I want everything" option, which will give you dependency declarations for all bindings. IMHO, that sufficiently covers users that simply want to try what LWJGL offers. Having said that, a particularly annoying aspect of having all bindings in a project is autocompletion of OpenGL APIs in the IDE; LWJGL supports both standard OpenGL and OpenGL ES and they share a lot of identically named functions, constants and extensions. It's very common to invoke autocompletion and get duplicate classes/method/constants in the list. It's annoying and you have to be careful with selecting the element you want from the correct package. |
Just updated nightly builds, something seems to have broken on my mac system (OSX 10.11) between "LWJGL 3.0.1 build 13" and "LWJGL 3.0.1 build 17" with OpenAL, the following calls now return just '0', whereas previously they returned proper values: int bytes = AL10.alGetBufferi(buffer, AL10.AL_SIZE);
int bits = AL10.alGetBufferi(buffer, AL10.AL_BITS);
int channels = AL10.alGetBufferi(buffer, AL10.AL_CHANNELS); Same code with build 17 works fine on linux. |
It should be possible to have the native library depend on the java one and, while technically not the correct use of dependencies, should allow you to do Option A but with only half of the declared dependencies. Also it seems that LWJGL is unable to find the natives itself currently when using the new system. |
I tracked this down to what seems like a bug in LLVM's optimizer. I had recently changed our CI build to use Xcode 8 (was on 6.1 before), which produced a buggy build. I've now reverted it to Xcode 7.2. You can download a fixed OpenAL build here, it will also be included in the next LWJGL nightly. |
Note that with Option A the native library is resolved using a classifier. The Java classes, sources, javadoc and native libraries (one for each platform) are all part of the same artifact. E.g. for GLFW the complete artifact is: // Java classes
groupId: 'org.lwjgl'
artifactId: 'lwjgl-glfw'
version: '3.0.1-SNAPSHOT'
// Java sources
groupId: 'org.lwjgl'
artifactId: 'lwjgl-glfw'
version: '3.0.1-SNAPSHOT'
classifier: 'sources'
// Javadoc
groupId: 'org.lwjgl'
artifactId: 'lwjgl-glfw'
version: '3.0.1-SNAPSHOT'
classifier: 'javadoc'
// Linux Natives
groupId: 'org.lwjgl'
artifactId: 'lwjgl-glfw'
version: '3.0.1-SNAPSHOT'
classifier: 'natives-linux'
// MacOS Natives
groupId: 'org.lwjgl'
artifactId: 'lwjgl-glfw'
version: '3.0.1-SNAPSHOT'
classifier: 'natives-macos'
// Windows Natives
groupId: 'org.lwjgl'
artifactId: 'lwjgl-glfw'
version: '3.0.1-SNAPSHOT'
classifier: 'natives-windows' Afaik, you cannot specify dependencies between secondary artifacts that belong to the same
Have you added the native JARs to the classpath? If yes, could you share more details on how you've set up your project? It would also be useful to see the output when running with |
Sorry it was me derping with the new system and forgetting to import the proper native file for it to actually make the link though. I didn't have it importing the base dependencies native file and that what was causing my problem. |
I like Option A, and I could even write a simple Gradle plugin to allow you to do code similar to Option C: // +natives signals to the plugin that there is natives
// Might be possible to allow something like +natives(osx,linux)
compile 'org.lwjgl:lwjgl-glfw:$lwjglVersion+natives'
compile 'org.lwjgl:lwjgl-stb:$lwjglVersion+natives'
compile 'org.lwjgl:lwjgl-jemalloc:$lwjglVersion+natives'
// opengl has no natives, no +natives
compile 'org.lwjgl:lwjgl-opengl:$lwjglVersion' Edit: The plugin might even be able to do natives detection, though I fear it might not always be 100% accurate. |
Just updated to LWJGL 3.0.1 build 18 and can confirm it works great on macOS now. |
We just deployed a first version of the new download page and it includes the Maven & Gradle script generators ( only for the nightly build at the moment ). It is still a work-in-progress but we would appreciate your feedback! Commit: |
@apostolos I think you should allow multiple natives too, as one might want a cross platform configuration. And the version is 3.0.1-SNAPSHOT but is generated as 3.0.0-SNAPSHOT I think, for the nightly. |
Looks great, would love to be able to download custom zip bundles. |
@sriharshachilakapati Just fixed the nightly version. Thanks I've discussed multiple natives with @Spasi but it makes no sense for Gradle & Maven. You can just generate a new script for your "other" computer. For the ZIP bundle it will be possible to select one or more platform and include them all in a single download. |
Looks excellent! |
I think multiple natives do actually make sense. Consider a scenario where me and another guy working on the same project using LWJGL, and we are on different OS. We do want to have the gradle script on the repository, and changing it on one system will cause the new script to go with commit (of course, we can ignore it, but..) making it a bit of a headache maintaining. Instead, making the radio buttons into check boxes will suit everyone. In case other platforms are unnecessary, the user can of course un-check them right? |
@kappaOne Started work on the bundles. To tell you the truth I'm kind of worried about server performance if we get simultaneous requests from multiple people. I might offload everything on Lambda since we are on Amazon and artifacts are stored on S3 already. Unfortunately we cannot really cache generated files on the CDN since potential bundle combinations are thousands. |
Would merging smaller jars/zips (possibly the maven ones) on the client side (using maybe a javascript zip libraries) be a viable option to create a custom zip? |
@sriharshachilakapati We now use Maven profiles and Gradle's org.gradle.internal.os to generate a single cross-platform configuration. We hid the Natives radio box for both Maven and Gradle since it is no longer necessary. We'll use it just for the ZIP bundle when the generator is ready. |
The ZIP bundle generator is now live! Initially only enabled for nightly builds but it's feature complete. It will be available for stable and release builds as soon as 3.1.0 is released. Surprisingly, it works on all modern browsers and on IE10+ What we ended up doing is uploading all files on S3 uncompressed. We then retrieve the folder structure in JSON format which is quite fast and pick all the file paths that were selected by the user. We then download each file and generate the ZIP file, both processes are done 100% client-side. @kappaOne There was no point in downloading ZIP files per binding since the JARs are already compressed. There is a performance penalty because we do many HTTP requests to download the files, but we've minimized it by doing up to 4 parallel downloads at a time ( actually we do a naive batch of 4 files at the time, will refactor it later to a real parallel download queue ). @Spasi I think you can close the issue! |
Does this mean that you cannot wget/curl a specific URL with just using query parameters in order to get a customized bundled zip file? |
Correct. Building a service for this would mean additional (bandwidth/computation) cost. The project has no income (donations/ads/etc) so keeping things simple is a priority. Currently the only costs are S3/CloudFront storage/bandwidth and an EC2 t2.small instance (already overwhelmed by TeamCity + build workers). Downloads should be faster too. Instead of everything going through our puny US-based server, build files are served from the nearest CloudFront edge. If more customization is required, it can be implemented without a dedicated service. The file structure generated by |
We've implemented a proper download queue. Downloads now complete at almost half the time in a good connection. @httpdigest I'll put up a page with the file catalog so people can manually curl whatever they need. |
@httpdigest There is now a file browser on the download page that you can use to either download the files directly or copy the paths and put them on a script. |
LWJGL currently has several bindings, with more coming in the future. Many users will only use a subset of those, but they all come in a single, monolithic archive. We should consider updating the build process to create separate archives for each binding, that can be downloaded and deployed independently. This should be in addition to the fat archive that will still be available, for convenience.
We may only do this for large APIs, especially those that come with their own shared libraries (currently jemalloc, GLFW, OpenAL and soon hwloc). The new design should ensure that loading the shared libraries is as easy/simple as before.
The text was updated successfully, but these errors were encountered: