Cpp custom sourceset - 2.5 syntax?

Hi ,

I have a build script which works in 1.12::

apply plugin: 'cpp'

sources {
    platformLinuxSrc {
        cpp {
            source {
                srcDir "../_linux"
                include "*.cpp"
            }
        }
    }

    platformWinSrc {
        cpp {
            source {
                srcDir "../_win32"
                include "*.cpp"
            }
        }
    }
}

["Server","Desktop"].each {
    String s = it
    libraries.create("platform" + s, {
        baseName "platform"

        cpp {
            lib library: 'platformAPI', linkage: 'api'
        }

        binaries.withType(StaticLibraryBinary){
            if (targetPlatform.operatingSystem.windows) {
                source sources.platformWinSrc**
            } else {
                source sources.platformLinuxSrc
            }
        }
    }
}

Unfortunately, with Gradle 2.5, this is not working anymore, giving me an error:

> Could not find method platformLinuxSrc() for arguments [build_5cad0k67czvd96t6bkkttfqrk$_run_closure2_closure15@fde0d5] on root project 'myproject'.

How can I declare a sourceset and use it by a reference (as seen above in “source sources.platformLinuxSrc”)?

According to new “model” syntax, I am able to do something like

components {
    ["Terminal","Desktop"].each {
        "platform${it}"(NativeLibrarySpec) {
            baseName = "platform"

            binaries.withType(StaticLibraryBinary) {
                if (targetPlatform.operatingSystem.windows) {
                    sources {
                        platformWinSrc(CppSourceSet) {
                            source {}
                            exportedHeaders {}
                            // lib: ...
                        }
                    }
                } else {
                    // sources myPreconfiguredLinuxSrc
                }
            }
        }
    }
}

but I am not able to externalize the sourceset :frowning:

Please, help me …

From my experience and the direction the development went between Gradle 1.12 and 2.5, the source set are now located inside the component definition as you shown in you new build script. In 2.5, there is no concept of externalizing the source set. The way I seen it now, instead of composing your component like in 1.12, you are simply configuring the component in 2.5. If multiple component share some code, there is 3 ways to configure them:

  1. Conditional configuration: Basically just like you did. Use condition base on the target platform, tool chain, etc. This is the less intrusive but requires more descriptive build script. Your example is pretty simple however in more complex example, you could try to find pattern and model them in your build script either at the project level or higher if you have multiple project. If you are allowed to move the code, sometime reorganizing the folder layout can help.
  2. #ifdef/#ifndef in your code: Change your code to add #ifndef of some define macro for each platform. This enable you to keep the source set definition as simple as possible. This one is a bit intrusive and can be problematic if you don’t own the code. You could still use a master C++ source file per platform that includes the required source file and only have that master file built. You just need to make sure your working directory and include path are setup accordingly. However Gradle will do a much better job them creating and maintaining those master files.
  3. Composing at link time: Create multiple library that target the different target platform and use condition to add dependencies to you final component through the lib dsl. The static library will be the only one that will compile correctly as it will not try to resolve the symbols. You still have to handle condition and it can become a dependency nightmare.

I hope this answer your question.