Sample:native:cpp: how to link the static part of a NativeLibrarySpec statically?

Hello

I am running the sample ...\gradle\subprojects\docs\src\samples\native-binaries\cpp\build.gradle. Since the model defines hello as a NativeLibrarySpec,

{
    components {
        hello(NativeLibrarySpec)
    }
}

I am expecting to get 2 main executables (one, with the shared hello lib, the other with the static hello lib) but there is only one

> Task :components

------------------------------------------------------------
Root project
------------------------------------------------------------

Native library 'hello'
----------------------

Source sets
    C++ source 'hello:cpp'
        srcDir: src\hello\cpp

Binaries
    Shared library 'hello:sharedLibrary'
        build using task: :helloSharedLibrary
        build type: build type 'debug'
        flavor: flavor 'default'
        target platform: platform 'windows_x86'
        tool chain: Tool chain 'visualCpp' (Visual Studio)
        shared library file: build\libs\hello\shared\hello.dll
    Static library 'hello:staticLibrary'
        build using task: :helloStaticLibrary
        build type: build type 'debug'
        flavor: flavor 'default'
        target platform: platform 'windows_x86'
        tool chain: Tool chain 'visualCpp' (Visual Studio)
        static library file: build\libs\hello\static\hello.lib

Native executable 'main'
------------------------

Source sets
    C++ source 'main:cpp'
        srcDir: src\main\cpp

Binaries
    Executable 'main:executable'
        build using task: :mainExecutable
        install using task: :installMainExecutable
        build type: build type 'debug'
        flavor: flavor 'default'
        target platform: platform 'windows_x86'
        tool chain: Tool chain 'visualCpp' (Visual Studio)
        executable file: build\exe\main\main.exe

So, the questions are

  1. Why Gradle generates only one executable (the one that links with the shared hello)
    2 What needs to be changed in the script to get the fully static main executable linked with the static hello lib?

Executables can exist in one form only from a NativeExecutableSpec. The library they will link with is determined by the linkage parameter in the spec. If not specified the default linkage is ‘shared’.

Adding a statically linked executable would require a second specification with a new name and different linkage.

Like this:

model {
    components {
        mainShared(NativeExecutableSpec) {
            sources {
                cpp {
                    source.srcDir "src/main"
                    lib library: "hello", linkage: 'shared'
                }
            }
            binaries {
                all {
                    executable.file = new File(executable.file.parentFile, 'main')
                }
            }
        }
        mainStatic(NativeExecutableSpec) {
            sources {
                cpp {
                    source.srcDir "src/main"
                    lib library: "hello", linkage: 'static'
                }
            }
            binaries {
                all {
                    executable.file = new File(executable.file.parentFile, 'main')
                }
            }
        }
    }
}

The name of the component becomes the name of the executable with a platform specific extension on Windows and other OS that need it. So, you can compensate for that with the binaries.all closure that renames the final executable to still have the name ‘main’.

Note also the specification of source.srcDir which uses the same source base directory for the two executables. The default convention for srcDir is “src/” but you only want one set of sources for both kinds of linked executable. If for some reason you needed different code for each flavor of executable you could have that in separate directories as the defaults would have it.

1 Like