Visual Studio plugin generates non-buildable binary's project files

Hi,

I am using the Visual Studio plugin, and I noticed that using the ‘api’ linkage infers the need to generate a NativeLibrarySpec's shared library VS project files even if the shared library binary is not buildable. Below is an example project where all shared libraries are not buildable, but lib2’s Dll project files are still generated because lib1 uses lib2 with ‘api’ linkage.

Is this the expected behavior?

I suppose I would expect this if all binaries are buildable and the linkage is still ‘api’. However, if a binary is specifically made non-buildable, I would think the Visual Studio plugin would not generate the project files for the binary.

I have no intention of linking one library into another, so I thought this was the correct usage of the ‘api’ linkage. Is my thinking correct?

Any clarity into these matters would help greatly my own understanding of how Gradle works with native projects and its software model. Thanks!

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

model {
    visualStudio {
        solutions.all {
            solutionFile.location = "vs/${name}.sln"
        }
        projects.all {
            projectFile.location = "vs/projects/${name}.vcxproj"
            filtersFile.location = "vs/projects/${name}.vcxproj.filters"
        }
    }
    components {
        exe(NativeExecutableSpec) {
            sources {
                cpp {
                    // change linkage to 'shared' and only respective lib1/lib2 project files are generated
                    lib library: 'lib1', linkage: 'static'
                    lib library: 'lib2', linkage: 'static'
                }
            }
        }
        lib1(NativeLibrarySpec) {
            sources {
                cpp {
                    // change linkage to 'static' or 'shared' and only respective lib2 project files are generated
                    lib library: 'lib2', linkage: 'api'
                }
            }
        }
        lib2(NativeLibrarySpec)
    }
    binaries {
        withType(SharedLibraryBinarySpec) {
            buildable = false // no shared libraries desired
        }
    }
}
tasks {
    task deleteVisualStudioDirectory(type: Delete) {
        delete file('vs/')
    }
    clean {
        dependsOn deleteVisualStudioDirectory
    }
}

Here are the VS project files that are created:

$ tree vs
vs
├── exeExe.sln
└── projects
    ├── exeExe.vcxproj
    ├── exeExe.vcxproj.filters
    ├── lib1Lib.vcxproj
    ├── lib1Lib.vcxproj.filters
    ├── lib2Dll.vcxproj
    ├── lib2Dll.vcxproj.filters
    ├── lib2Lib.vcxproj
    └── lib2Lib.vcxproj.filters

Hi @Kevin2, sorry for the late reply.

Adding an API linkage will still create a project so the code can be edited inside Visual Studio. This plugin needs a bit more polishing, but it’s functional for development. It’s important to keep in mind that building from within Visual Studio simply delegates the compilation to Gradle.

I hope this helps with your understanding,

Daniel

Thanks for the response, @Daniel_L! Just curious, if a library depends on another library, and I have no intention of linking the two together, ‘api’ linkage is the right option, correct? Also, I didn’t think using a ‘static’ linkage on a library dependency for a library component would do any linking anyways, or am I wrong on that?

The creation of the DLL projects isn’t any real problem since both the lib2Lib and lib2Dll projects reference the same source files. I just wasn’t sure how the plugin respected a binary’s buildable property.

Glad I could help you @Kevin2. api linkage will only add the headers to the include root during preprocessing. The static linkage will add the headers to the include root as well as add the static library binary to the list of libraries to link together. In both cases, if your code isn’t referencing the code in question, no action will be taken by the compiler (binary size won’t suffer from additional unused headers and libraries). However, you risk symbols collision the more unused libraries you add to as well as will have some performance hit. It’s best to know the desired code architecture you want to follow. Gradle won’t be any help on that level. We are working on modeling more information in Gradle so you can take educated decisions as well as analyze your application structure.