LWJGL natives os + JPMS + GRADLE - java

ERROR: UnsatisfiedLinkError
[LWJGL] Failed to load a library. Possible solutions:
a) Add the directory that contains the shared library to -Djava.library.path or -Dorg.lwjgl.librarypath.
b) Add the JAR that contains the shared library to the classpath.
[LWJGL] Enable debug mode with -Dorg.lwjgl.util.Debug=true for better diagnostics.
[LWJGL] Enable the SharedLibraryLoader debug mode with -Dorg.lwjgl.util.DebugLoader=true for better diagnostics.
Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to locate library: lwjgl.dll
at org.lwjgl/org.lwjgl.system.Library.loadSystem(Library.java:162)
at org.lwjgl/org.lwjgl.system.Library.loadSystem(Library.java:62)
at org.lwjgl/org.lwjgl.system.Library.<clinit>(Library.java:50)
at org.lwjgl.glfw/org.lwjgl.glfw.GLFW.<clinit>(GLFW.java:674)
FAILURE: Build failed with an exception.
I tried to had/implement the java platform module system to one of my
projects and this linking error had me. The following lines are build script and the module-info src code.
lib module: buld.gradle.kts
import org.gradle.kotlin.dsl.support.unzipTo
plugins {
`java-library`
}
group = "com.moc"
version = "0.0"
java {
modularity.inferModulePath.set(true)
}
repositories {
mavenCentral()
}
val nativesClasses: Configuration by configurations.creating {
isTransitive = false
extendsFrom(configurations.runtimeOnly.get())
}
tasks.register("unzips") {
nativesClasses.asFileTree.forEach {
unzipTo(File("${buildDir}/libs/natives"), it)
}
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
implementation(fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl.jar") )
implementation(fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl-glfw.jar") )
implementation(fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl-assimp.jar") )
implementation(fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl-opengl.jar") )
runtimeOnly( fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl-natives-windows.jar" ) )
runtimeOnly( fileTree("hard-typed/path/for/the/lwjgl-3.2.3/wjgl-glfw-natives-windows.jar" ) )
runtimeOnly( fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl-assimp-natives-windows.jar" ) )
runtimeOnly( fileTree("hard-typed/path/for/the/lwjgl-3.2.3/lwjgl-opengl-natives-windows.jar" ) )
}
tasks.test {
useJUnitPlatform()
}
app module: build.gradle.kts
plugins {
application
}
group = "com.moc"
version = "0.0"
java {
modularity.inferModulePath.set(true)
}
application {
mainModule.set("moc.app")
mainClass.set("com.moc.main.App")
}
tasks.withType<JavaExec> {
System.setProperty("org.lwjgl.librarypath",
"hard-typed/path/of/natives-os/lwjgl;" +
"hard-typed/path/of/natives-os/opengl;" +
"hard-typed/path/of/natives-os/glfw;" +
"hard-typed/path/of/natives-os/assimp" )
}
repositories {
mavenCentral()
}
dependencies {
implementation(project(":lib"))
}
lib & app module: module-info.java
module moc.lib {
requires org.lwjgl.glfw;
requires org.lwjgl.opengl;
requires org.lwjgl.assimp;
exports com.moc;
}
module moc.app {
requires moc.lib;
}
> How do we link this natives os to our project by using a gradle build script and without any external plugins?

I tried this one and it's working but somehow I feel this is not the right way?
tasks.withType<JavaExec> {
val lwjgl = System.setProperty("org.lwjgl.librarypath", "../libs/natives"
systemProperty("org.lwjgl.librarypath", System.getProperty("org.lwjgl.librarypath") )
}
repositories {
mavenCentral()
}

And try this one for the application extension
val lwjgNativesProp : String? = System.setProperty("org.lwjgl.librarypathz", "../libs/natives")
application {
applicationDefaultJvmArgs = arrayListOf("-Dorg.lwjgl.librarypath=${System.getProperty("org.lwjgl.librarypathz")}")
}
tasks.withType<JavaExec> {
lwjglNativesProp?.let { systemProperty("org.lwjgl.librarypath", it) }
}

Related

Publish java library with custom primary artifact

I m trying to create a java library with custom primary artifact..
I followed this documentation, but the problem is when i run the "publish" task, i get this error.
Could not determine the dependencies of task ':publishMavenPublicationToMyRepoRepository'.
> Task with path 'rpm' not found in root project 'commons'.
This is my gradle file :
import com.netflix.gradle.plugins.rpm.Rpm
plugins {
`java-library`
`maven-publish`
id("nebula.ospackage") version "7.4.1"
kotlin("jvm") version "1.3.50"
}
group = "com.test"
version = "1.0.0"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencies {
implementation("javax.xml.bind:jaxb-api:2.3.1")
implementation("io.jsonwebtoken:jjwt:0.9.1")
implementation("com.googlecode.libphonenumber:libphonenumber:8.10.14")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9")
}
tasks.withType<Rpm> {
version = "1.0.0"
release = "1"
packageName = "com.test.commons"
into("$buildDir/rpms/com.test.commons.rpm")
}
val rpmFile = file("$buildDir/rpms/com.test.commons.rpm")
val rpmArtifact = artifacts.add("archives", rpmFile) {
type = "rpm"
builtBy("rpm")
}
publishing {
publications {
create<MavenPublication>("maven") {
artifact(rpmArtifact)
}
}
repositories {
maven {
name = "myRepo"
url = uri("file://${buildDir}/repo")
}
}
}
I think the problem is in the rpm task, how can i solve that?
The rpm task type is available with the nebula.rpm plugin as explained in the wiki here
plugins {
id("nebula.ospackage") version "7.4.1"
id("nebula.rpm") version "7.4.1"
}
Not familiar with this plugin, but it doesn't look like applying nebula.ospackage is enough.
The nebula.ospackage plugin will create a task named buildRpm of type com.netflix.gradle.plugins.rpm.Rpm.
In your script you reference a task by the name rpm, which does not exists : this explains the error you got (> Task with path 'rpm' not found in root project 'commons'.)
Just update your script to use correct task name :
val rpmArtifact = artifacts.add("archives", rpmFile) {
type = "rpm"
builtBy("buildRpm") // <=== instead of "rpm"
}
Note : you don't have to apply plugin nebula.rpm, nebula.ospackage is enough.

Gradle build: Exclude resources files from Spring Boot Jar file

I would like to exclude all config files from the jar file since they will be provided at the provisioning and having a different version in the build path may create some runtime issues. I am using the following Gradle build script, but for some reason, I can still see whatever exist in the resources directory to be copied into the built Jar. Which means for some reason the provided Gradle build is not working as expected.
apply plugin: 'distribution'
distributions {
main {
baseName = "${project.name}"
contents {
into('/conf'){
from('src/main/resources')
exclude("application.yml")
}
into('/lib'){
from('build/libs')
}
into('/bin'){
from('../bin')
}
}
}
}
processResources {
# Not sure how I need to point to the resources, so I included both. However, none is working.
exclude('resources/*')
exclude('src/main/resources/*')
}
bootJar{
# Not sure how I need to point to the resources, so I included both. However, none is working.
exclude('resources/*')
exclude('src/main/resources/*')
}
distTar {
dependsOn bootJar
}
tasks.withType(Tar) {
compression = Compression.GZIP
extension = "tar.gz"
}
configurations {
customArch
}
artifacts {
customArch file(distTar.archivePath)
}
I was able to exclude resources from appearing in the Jar file by using processResources.enabled = false, so the build file is as follows.
apply plugin: 'distribution'
distributions {
main {
baseName = "${project.name}"
contents {
into('/conf'){
from('src/main/resources')
exclude("application.yml")
}
into('/lib'){
from('build/libs')
}
into('/bin'){
from('../bin')
}
}
}
}
processResources.enabled = false
distTar {
dependsOn bootJar
}
tasks.withType(Tar) {
compression = Compression.GZIP
extension = "tar.gz"
}
configurations {
customArch
}
artifacts {
customArch file(distTar.archivePath)
}
I found that this solution works for me:
processResources {
exclude('logback-spring.xml')
}
...where logback-spring.xml is located in src/main/resources

Changing QueryDSL Generated Files Directory

I have integrated QueryDSL into my Spring boot project.
build.gradle:
//dependencies
compile("com.mysema.querydsl:querydsl-jpa:3.7.4")
compile("com.mysema.querydsl:querydsl-apt:3.7.4:jpa")
idea {
module {
sourceDirs += file('src/main/generated/')
generatedSourceDirs += file('src/main/generated/')
}
}
The generated .class and .java (Q classes) files are currently deployed into build/classes/main/my/package/model where the entity class files are created.
How can I configure the JPAAnnotationProcessor to put generated sources(e.g. QMyEntity.java) into src/main/generated?
You could try something like that (hard way):
def queryDslOutput = file("src/main/generated")
sourceSets {
main {
java {
srcDir queryDslOutput
}
}
}
task generateQueryDSL(type: JavaCompile, group: 'build') {
source = sourceSets.main.java
classpath = configurations.compile
destinationDir = queryDslOutput
options.compilerArgs = [
"-proc:only",
"-processor", 'com.querydsl.apt.jpa.JPAAnnotationProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor'
]
}
compileJava.dependsOn(generateQueryDSL)
clean {
delete queryDslOutput
}
The compiler options are required if you are using lombok.
Or if you are using the querydsl-plugin you could configure the output directory (easy way):
def generatedClassesPath= "build/generated/source/querydsl/main"
querydsl {
jpa = true
querydslSourcesDir = generatedClassesPath
}
You could always add generated sources to classpath to catch the files by Intellij Idea:
def queryDslOutput = file(generatedClassesPath)
sourceSets {
main {
java {
srcDir queryDslOutput
}
}
}
From plugin documentation:
querydslSourcesDir
The project relative path to where the querydsl
meta model sources are created in. It does not matter which annotation
processors are used, all meta model classes will be created within
this directory.
Defaults to src/querydsl/java.

How to add static files to jar using Gradle build in Spring Boot + Angular 2 project

I have a Spring Boot + Angular 2 project. I want to deploy it to Heroku.
I'm able to run the npm build then copy the generated files over to the public folder (src/resources/public) manually, then run the backend build.
What I want to do is to set up a gradle build that will do all of that at once.
What I have so far is a gradle build that will build the front end, build the backend, however it does not copy the static files before generating the jar. Since the jar does not contain said static files, it won't work on Heroku.
Here's the project folder structure:
root
backend
src/main/java
src/main/resources
frontend
--> angular files go here
build/libs -> where the JAR file goes
The gradle build file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// spring
classpath('org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE')
classpath('org.springframework:springloaded:1.2.6.RELEASE')
}
}
plugins {
id "com.moowork.node" version "1.2.0"
}
// gradle wrapper
task wrapper(type: Wrapper) {
gradleVersion = '3.4'
}
// configure gradle-node-plugin
node {
version = '8.1.4'
npmVersion = '5.0.3'
download = true
workDir = file("${project.projectDir}/node")
nodeModulesDir = file("${project.projectDir}/")
}
// clean node/node_modules/dist
task npmClean(type: Delete) {
final def webDir = "${rootDir}/frontend"
delete "${webDir}/node"
delete "${webDir}/node_modules"
delete "${webDir}/dist"
delete "${webDir}/coverage"
delete "${rootDir}/backend/src/main/resources/public"
}
// clean task for npm
task copyFiles {
doLast {
copy {
from "${rootDir}/frontend/dist"
into "${rootDir}/backend/src/main/resources/public"
}
}
}
// build task for npm
task frontendBuild {}
frontendBuild.dependsOn(npm_install)
frontendBuild.dependsOn(npm_run_build)
npm_install {
args = ['--prefix', './frontend']
}
npm_run_build {
args = ['--prefix', './frontend']
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
sourceSets {
main {
java {
srcDirs = ['backend/src/main/java']
}
resources {
srcDirs = ['backend/src/main/resources']
}
}
}
copyFiles.dependsOn(frontendBuild);
compileJava.dependsOn(frontendBuild);
task backendBuild {}
backendBuild.dependsOn(compileJava)
backendBuild.dependsOn(jar)
jar.dependsOn(copyFiles)
repositories {
mavenCentral()
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8')
}
}
idea {
module {
inheritOutputDirs = false
outputDir = file("${buildDir}/classes/main/")
}
}
jar {
baseName = 'expense-splitter'
version = '0.0.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
configurations {
dev
}
dependencies {
// spring
compile('org.springframework.boot:spring-boot-starter-web:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE')
compile('org.springframework.boot:spring-boot-starter-security:1.5.2.RELEASE')
compile('org.apache.commons:commons-lang3:3.3.2')
// to make hibernate handle java 8 date and time types correctly
// it's marked as deprecated but we need to keep it until
// spring boot jpa starts using hibernate 5.2
compile('org.hibernate:hibernate-java8:5.1.0.Final')
// json web tokens
compile ('io.jsonwebtoken:jjwt:0.7.0')
compile 'mysql:mysql-connector-java'
// google gson
compile('com.google.code.gson:gson:2.8.0')
// jackson - parsing of java 8 date and time types
compile('com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.7')
// spring dev tools
dev('org.springframework.boot:spring-boot-devtools:1.5.2.RELEASE')
// testing
testCompile('org.springframework.boot:spring-boot-starter-test:1.5.2.RELEASE')
}
// run spring boot app
bootRun {
//addResources = true
classpath = sourceSets.main.runtimeClasspath + configurations.dev
jvmArgs = ["-Xdebug -agentlib:jdwp=transport=dt_socket,address=8080,server=y,suspend=n"]
}
// run all task
task runAll {}
runAll.dependsOn(bootRun)
Thanks in advance,
Try a different approach. Instead of manually copying the resources, tell Gradle that when it processes resources for the JAR, also take into consideration what is in frontend/dist/:
processResources {
from ('frontend/dist/') {
into 'public'
}
}
This should result in a JAR containing a public/ directory, with the contents of frontend/dist/ inside of it.
Gradle configuration for Spring Boot 1.5\2.x + Angular 2-6
Angular in sub-folder frontend
Frontend module
Crate build.gradle:
plugins {
id "com.moowork.node" version "1.2.0"
}
node {
version = '8.11.3'
npmVersion = '5.6.0'
download = true
workDir = file("${project.buildDir}/node")
nodeModulesDir = file("${project.projectDir}")
}
task build(type: NpmTask) {
args = ['run', 'build']
}
build.dependsOn(npm_install)
Note for Angular 6
Update outputPath value in angular.json to 'dist'
Backend module
Edit build.gradle for backend module:
Spring Boot 2.X:
bootJar {
archiveName = "yourapp.jar"
mainClassName = 'com.company.app.Application'
from('frontend/dist') {
into 'static'
}
}
Spring Boot 1.5.X:
jar {
archiveName = "yourapp.jar"
manifest {
attributes 'Main-Class': 'com.company.app.Application'
}
from('frontend/dist') {
into 'static'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Finally execute bootRepackage or bootJar task and check results in builds/libs
Assume that front end is located at the following folder: src/main/webapp/fe-ui/, the following solution for the Spring Boot version 2.1.1.RELEASE could be considered:
bootJar {
baseName = 'jar-name'
version = '0.1.0'
from('src/main/webapp/fe-ui/build') {
into 'public'
}
}
task installFeDependencies(type: NpmTask) {
args = ['install']
}
task buildFe(type: NpmTask) {
args = ['run', 'build']
dependsOn installFeDependencies
}
compileJava {
dependsOn buildFe
}
Running gradlew build will install, build front end as well as will invoke bootJar. The latter will package built front end bundle.

Use Roboeletric with Gradle

I'm trying to setup Gradle to run Android test using Roboelectric mocking framework.
I have an Eclipse workspace with this structure:
MyApp
src
gen
test
....
MyAppTest
libs
test (source folder linked to MyApp.test)
....
Tests runs fine in Eclipse manually configuring build path.
How can I configure Gradle build scripts in MyAppTest to run tests in MyApp project using Roboelectric?
I was able to get this working based on this solution
In summary, try adding the following to your build.gradle:
sourceSets {
testLocal {
java.srcDir file('src/test/java')
resources.srcDir file('src/test/resources')
}
}
dependencies {
// Dependencies for your production code here.
compile 'some.library'
// localTest dependencies, including dependencies required by production code.
testLocalCompile 'some.library'
testLocalCompile 'junit:junit:4.11'
testLocalCompile 'com.google.android:android:4.1.1.4'
testLocalCompile 'org.robolectric:robolectric:2.2'
}
task localTest(type: Test, dependsOn: assemble) {
testClassesDir = sourceSets.testLocal.output.classesDir
android.sourceSets.main.java.srcDirs.each { dir ->
def buildDir = dir.getAbsolutePath().split('/')
buildDir = (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/')
sourceSets.testLocal.compileClasspath += files(buildDir)
sourceSets.testLocal.runtimeClasspath += files(buildDir)
}
classpath = sourceSets.testLocal.runtimeClasspath
}
check.dependsOn localTest
Don't forget to alter your *Test.java to #RunWith(RobolectricGradleTestRunner.class):
public class RobolectricGradleTestRunner extends RobolectricTestRunner {
public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
}
#Override
protected AndroidManifest getAppManifest(Config config) {
String pwd = YourApplication.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String root = pwd + "../../../src/main/";
return new AndroidManifest(
Fs.fileFromPath(root + "AndroidManifest.xml"),
Fs.fileFromPath(root + "res"),
Fs.fileFromPath(root + "assets"));
}
}
You will then be able to run your test via gradle compileDebugJava localTest. If I remember correctly, this will require a newer version of gradle (perhaps 1.8 or 1.9)

Categories