[SOLVED] [Native build] Conditional sources sets

Hi guys,

I’m new to Gradle, but successfully used it in no time for Java/Groovy projects.

Now, I’m trying to write a Gradle native build script for a multiplatform C/C++ project which has common sources, and specific ones for each “platform”. I couldn’t find in the documentation how to configure this situation.

Is there a way to specify sources conditionally (for example, using something like toolChain in VisualCpp) or by other means?

If not, I guess I can use different components for each “platform”. In this scenario, is there a way to share sources between components?

Thanks in advance. I would appreciate any thoughts/directions on this.

You can add source sets conditionally:

model {
    components {
        main(NativeExecutableSpec) {
            binaries.all {
                if (targetPlatform.operatingSystem.windows) {
                    sources {
                        winSrc(CppSourceSet) {
                            // configure it
                        }
                    }
                }
            }
        }
    }
}

Hi Sterling,

Thanks for your response.

  1. The condition targetPlatform.operatingSystem.windows is never met. I guess the operating system is not defined by default or I’m missing something.

  2. If I remove the if (targetPlatform.operatingSystem.windows) I get the following error:

    Cannot create a CppSourceSet because this type is not known to this container. Known types are: NativeExecutableSpec, NativeLibrarySpec

Any thoughts?
Thanks again.

Can you post your build.gradle? Are you using 2.3 or a nightly?

It’s doing the same thing as this snippet:
http://gradle.org/docs/current/userguide/nativeBinaries.html#componentBinarySettings

Do you have your check for targetPlatform inside binaries.all {}?

By trial and error I found a solution.

I had to define the platforms in order to get the condition met (I’m trying to generate a VS project on OSX):

win32 {
    architecture "x86"
    operatingSystem "windows"
}

osx32 {
     architecture "x86"
     operatingSystem "osx"
}

… etc …

Also, I could specify another set using this syntax:

sources {
    if (targetPlatform.operatingSystem.windows) {
        cpp {
             source {
        	// Configure
            }
        }
    }
}

However I’m still having an issue. My project has the following structure:

code/src/ - Common sources
code/src/platform/windows - Windows sources
code/src/platform/osx - OSX sources
… etc …
code/include/ - Common headers
code/include/platform/windows - Windows headers
code/include/platform/osx - OSX headers
… etc …

In the global source set I have to exclude “platform”:

sources {
    cpp {
        source {
            srcDir "code/src"
            include "**/*.cpp", "**/*.c"
            exclude "platform"
        }
					
        exportedHeaders {
            srcDir "code/include"
            include "**/*.h"
            exclude "platform"
        }
    }
}

Then for each platform I add a source set. But the global exclude seems to prevent the specific sources from being included. Is there a way to avoid this? Or can I somehow define each different source set a with a different name?

@sterling Any thoughts? Thank you very much for your time.

You need to create new source sets for the OS-specific sets of sources. cpp is the source set that’s provided by the cpp plugin by default. You can create new ones like:

// in a binaries block
if (targetPlatform.operatingSystem.windows) {
   sources {
      mySourceSet(CppSourceSet) {
         // configure it
      }
   }
}

RIght now you’re configuring cpp to exclude and include the platform specific sources.

Yes. That’s the first thing I tried but I’m getting the following error:

Cannot create a CppSourceSet because this type is not known to this container. Known types are: NativeExecutableSpec, NativeLibrarySpec

This is a minimal grade.build throwing this error:

apply plugin: 'cpp'
apply plugin: 'visual-studio'

model {
    buildTypes {
        Debug
        Release
    }

    platforms {
        win32 {
            architecture "x86"
            operatingSystem "windows"
        }

        osx32 {
            architecture "x86"
            operatingSystem "osx"
        }
    }

    components {
        myLib(NativeLibrarySpec) {
            targetPlatform "win32"
            targetPlatform "osx32"

            sources {
                cpp {
                    source {
                        srcDir "code/src"
                        include "**/*.cpp"
                        exclude "platform"
                    }

                    exportedHeaders {
                        srcDir "code/include"
                        include "**/*.h"
                        exclude "platform"
                    }
                }
            }

            binaries.all {
                if (targetPlatform.operatingSystem.windows) {
                    sources {
                        win(CppSourceSet) {
                            srcDir "code/src"
                            include "platform/windows/**/*.cpp"
                        }
                    }
                }
            }
        }
    }
}

Can you post your model {} block?

Just updated my previous post with that info.

Ah, you’re missing a source {}

sources {
    win(CppSourceSet) {
        source {
           srcDir "code/src"
           include "platform/windows/**/*.cpp"
        }
    }
}

I think you could get away with just source.srcDir 'code/src/platform/windows' and source.include "**/*.cpp" too.

That’s it! I was missing the source {}. Thank you very much for your time.

I know it made a silly mistake and I missed it in the DSL documentation, but maybe IMHO the error message could be more informative. Is there a way I can “report” it?

Thank you again.

There’s a lot of active development in that area (the error message from the latest nightly is very different, still not very useful), but I’ll let the guys know.

@erdi this is probably the sort of thing that’ll happen frequently.

Ok, thanks.

Awesome work. Gradle is outstanding.

Thanks again.

@sterling, yeah this is all tinkered with as we speak. The error message should definitely be more helpful.