How to include headers for C compilation in Gradle? - gradle

I am a newbie to Gradle. I am trying to compile a set of source files which contain headers which are distributed across the project directory. My source directory structure does not comply with the Gradle convention. How do I add the header locations needed for compilation in my build.gradle? Attached here is my build.gradle file.
// build.gradle
apply plugin: 'c'
model {
components {
my_project (NativeExecutableSpec){
sources {
c {
source {
srcDir "my_proj_src/a/a1.1"
include "**/*.c"
}
exportedHeaders {
srcDir "my_proj_src/a/a1.1", "fsw/b/b1.2"
}
}
}
}
}
}
This does not work. And additionally, is there a possibility to do partial linking using Gradle?
EDIT: Additionally, I would like to also know how to make Gradle search recursively for headers within the source hierarchy.

exportedHeaders` are for exporting headers from the component itself, not for adding headers. So this would not work.
You would need to create a library and add it as the api linkage so that those headers will be added to headers your component is compiled against:
model {
repositories {
libs(PrebuiltLibraries) {
ffmpegHeaders {
headers.srcDirs "$ffmpegDir/include"
}
}
}
components {
libUsingHeaders(NativeLibrarySpec) {
sources {
c {
lib library: 'ffmpegHeaders', linkage: 'api'
}
}
}
}
}

Related

Using Gradle `from project` in `settings.gradle` for a module in the same level of folder cannot be found

In https://docs.gradle.org/current/userguide/platforms.html#sec:importing-published-catalog, when we want to include a versionCatalog from another library, in our settings.gradle, we can use
dependencyResolutionManagement {
versionCatalogs {
libs {
from("com.mycompany:catalog:1.0")
}
}
}
If the catalog is in the same project, I tried to do as below
dependencyResolutionManagement {
versionCatalogs {
libs {
from project(":catalog")
}
}
}
It keeps complaining that Project with path ':catalog' could not be found. even though the catalog project is there in the same level as settings.gradle.
How can I solve the problem?

How to add another sourceSet with a mod in Minecraft Forge (Forge Gradle 3)?

I have a library made in Forge dev environment, one is in the main source set, containing library code; another is in the testmod (or any other name) source set, containing testing code that needs to be loaded as a Forge mod.
Simply adding
sourceSets {
testmod {
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
java {
srcDir "src/testmod/java"
}
resources {
srcDir "src/testmod/resources"
}
}
}
into my build.gradle, Forge doesn't scan the source set and therefore doesn't load my mod. How can I make Forge load my mod?
Note that my mod is in Forge 1.14.4, and this should apply to all versions with Forge Gradle 3.
Forge loads mod through the mods declared in the minecraft/run section. You will need to add the following lines to make Forge scan the testmod source set for mods.
minecraft {
// ...
runs {
client {
// ...
mods {
mainmodid {
source sourceSets.main
}
testmodid {
source sourceSets.testmod
}
}
}
server {
// ...
mods {
mainmodid {
source sourceSets.main
}
testmodid {
source sourceSets.testmod
}
}
}
}
}
Replace mainmodid and testmodid with your own modid's. The mainmodid should be included in MDK as examplemod.
Although this does make Forge load your classes, it won't be able to find your mods.toml properly though (depends on ForgeGradle version). If you run into loading errors saying test mod isn't found in mods.toml, add the following snippet too
processResources {
from(sourceSets.testmod.resources.srcDirs) {
include "META_INF/mods.toml"
}
}
Also simply adding the source set testmod won't add Forge and Minecraft as a dependency for it automatically. You will also to have add
configurations {
testmodCompile.extendsFrom(compile)
testmodCompileOnly.extendsFrom(compileOnly)
testmodRuntimeOnly.extendsFrom(runtimeOnly)
}
to make Gradle add Forge and Minecraft (the testmod in testmodCompile is the source set name, see Gradle documentation).

How can I add generated kotlin sources to source path in gradle?

For generated java sources I use:
sourceSets["main"].java {
srcDir("$buildDir/generated/java")
}
tasks.withType(JavaCompile::class) {
dependsOn("myGenerator")
}
But now I have generated kotlin sources and function sourceSets["main"].kotlin is not defined.
Solution:
sourceSets["main"].withConvention(conventionType = KotlinSourceSet::class) {
kotlin.srcDir("$buildDir/generated/kotlin")
}
More: https://kotlinlang.org/docs/reference/using-gradle.html

How to use CUnit to test a native application with multiple components

I have a gradle project for a native c application in gradle (version 2.10) made from multiple components:
components {
component_1(NativeLibrarySpec)
component_2(NativeLibrarySpec)
...
component_n(NativeLibrarySpec)
main_component(NativeExecutableSpec){
sources {
c.lib library: "component_1", linkage: "static"
c.lib library: "component_2", linkage: "static"
...
c.lib library: "component_n", linkage: "static"
}
}
}
The main idea of having the application in this form was to made easier to test individual components. However, I'm having two big problems:
The main_component is an application, therefore has a main function and this generates this error: multiple definition of 'main' ... gradle_cunit_main.c:(.text+0x0): first defined here. This is something to expect and is mentioned in the documentation, but I'm wondering if there's way to avoid this issue, as for instance, prevent the main component to be included in the tests. This is related to the next question
The CUnit plugin (as of version 2.10 of gradle) complains when I try to define the components to be tested as follows:
testSuites {
component_1Test(CUnitTestSuiteSpec){
testing $.components.component_1
}
}
}
gradle complains:
Cannot create 'testSuites.component_1Test' using creation rule
'component_1Test(org.gradle.nativeplatform.test.cunit.CUnitTestSuiteSpec)
{ ... } # build.gradle line 68, column 9' as the rule
'CUnitPlugin.Rules#createCUnitTestSuitePerComponent >
create(component_1Test)' is already registered to create this model
element
In summary, I would like to instruct the cunit plugin to test only some components and prevent the main component (with the main function) to be compiled for tests. Again, please notice I'm using gradle 2.10 and cannot upgrade to a more recent version as that would brake our CI tool chain.
Thanks in advance for your comments.
Here is how to structure the project to allow unit testing of the components, but prevent unit testing of the main program: split the components in a sub-project and apply the cunit plugin to the subproject, as shown below:
project(':libs'){
apply plugin: 'c'
apply plugin: 'cunit'
model{
repositories {
libs(PrebuiltLibraries) {
cunit {
headers.srcDir "/usr/include/"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("/usr/lib/x86_64-linux-gnu/libcunit.a")
}
}
}
}
components {
component_1(NativeLibrarySpec)
component_2(NativeLibrarySpec)
...
component_n(NativeLibrarySpec)
}
binaries {
withType(CUnitTestSuiteBinarySpec) {
lib library: "cunit", linkage: "static"
}
}
}
}
apply plugin: 'c'
model {
components{
myprogram(NativeExecutableSpec) {
sources.c {
lib project: ':libs', library: 'component_1', linkage: 'static'
lib project: ':libs', library: 'component_2', linkage: 'static'
lib project: ':libs', library: "component_n", linkage: 'static'
source {
srcDir "src/myprogram/c"
include "**/*.c"
}
}
}
}
}

Copy Task after Linking

I am trying to perform a copy of the build artifacts after performing the linking for Native Executables. Attached is an excerpt from my build.gradle
components {
all {
binaries.withType(SharedLibraryBinarySpec) {
buildable = false
}
binaries.withType(NativeExecutableBinarySpec) {
tasks.withType(LinkExecutable) {
doFirst {
outputFile = file("$buildDir/exe/${baseName}/${baseName}.o")
}
doLast {
copy {
from (file("$buildDir/exe/${baseName}/"))
into "./objs_exe/exe/"
include "*.o"
}
}
}
}
}
}
I would like to rename my linked executable and then copy it to another location. However, I get the error as
Attempt to modify a closed view of model element 'components' of type 'ComponentSpecContainer' given to rule model.components
This is a multi-project build and the above code is part of the root project's build.gradle. The doFirst closure works without any issues. Also, I have applied the c plugin

Resources