nokeedev / gradle-native

The home of anything about Gradle support for natively compiled languages

Home Page:https://nokee.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add example to configure linker args

bric3 opened this issue · comments

For example in Kotlin DSL

import dev.nokee.platform.nativebase.ExecutableBinary

/*
 * sandbox
 *
 * Copyright (c) 2021,today - Brice Dutheil <brice.dutheil@gmail.com>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */
plugins {
    id("dev.nokee.c-application")
}

application {
    binaries.configureEach(ExecutableBinary::class.java) {
        baseName.set("test-dlopen")
        linkTask {
            linkerArgs.add("-ldl")
        }
    }
}

Also I wonder if the API could be make more kotlin friendly, so one could write

binaries.configureEach<ExecutableBinary> {
  ...
}

Oh actually there's one with the objective c plugin. But stil it would be nice to have in the C plugins.

You are right; we should expand the samples. As for making the DSL more friendly to Kotlin, we aren't Kotlin experts. If you could help us by pointing out the Kotlin concept for these types of Kotlin-friendly methods, we can look into adding them.

Mhh about kotlin friendly API, this might require writing kotlin code. For example the method withType on the task container have this Java API,

DomainObjectCollection {
  // ...
  <S extends T> DomainObjectCollection<S> withType(Class<S> type, Action<? super S> configureAction);
}

and usable in Groovy DSL or Kotlin DSL

tasks.withType(JavaExec) {
    
}
tasks.withType(JavaExec::class.java) {
    
}

However to improve the friendliness of the kotlin DSL API

tasks.withType<JavaExec>() {
    
}

There are extension function

inline fun <reified S : Any> DomainObjectCollection<in S>.withType(noinline configuration: S.() -> Unit) =
    withType(S::class.java, configuration)

This function declaration might be daunting at first as there are 6 different concepts there

  1. inline, in Kotlin an inline function tells the compiler to put the bytecode instructions where the method is referenced. This function is like a C/C++ macro.

    https://kotlinlang.org/docs/inline-functions.html

  2. <reified S : Any> this is a generic declaration, equivalent to <S extends Object> (Any in kotlin is an alias to Object) ; the reified keyword means the generic information is not erased as in Java, however this require the function to be inline.

    DomainObjectCollection<in S> is the reference to the generic variable, and is somewhat equivalent to DomainObjectCollection<? super S> in Java

    https://kotlinlang.org/docs/generics.html

  3. noinline configuration: S.() -> Unit, the no inline simply indicates the compiler to not inline the body of the lambda. The lambda has the type S.() -> Unit. There's no type between the parenthesis (), so there's no args and Unit is like void in Java, so this is equivalent to a Java Runnable ; the interesting bit here is S.(), it means S is the receiver type meaning that this within the lambda is of type S. The receiver type are really powerful to write convenient DSLs.

    https://kotlinlang.org/docs/lambdas.html
    https://kotlinlang.org/docs/lambdas.html#function-literals-with-receiver

  4. ... fun ... .withType(...) = withType(S::class.java, configuration) means this function has a single statement, and as such kotlin offer a short hand = instead of writing { return withType(S::class.java, configuration) } ; also note the return type can be omitted in this declaration just like var s = "Hello" can be omitted in Java.

    https://kotlinlang.org/docs/functions.html#single-expression-functions

  5. S::class.java Like in groovy kotlin has it's own class reference and in order here to link to the right java API, it is necessary to access the Java Class. In this function this notation works because S is reified.

    https://kotlinlang.org/docs/reflection.html#class-references

  6. Additionally there's a 6th concept on the "callsite", in kotlin if the last parameter is a lambda it can be written outside the method ; this should be similar to Groovy. Both notation ate the same

    tasks.withType<JavaExec>({ })
    tasks.withType<JavaExec>() {
        
    }

Thanks a lot for the information. I will see what I can do about that.