# How to pass arguments to the linker when building a cpp-application

**URL:** <https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855>\
**Category:** Help/Discuss\
**Tags:** native\
**Created:** [March 6, 2019, 8:21pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855 "2019-03-06T20:21:26Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![craigtmoore](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/craigtmoore/32/7553_2.png) [@craigtmoore](https://discuss.gradle.org/u/craigtmoore)\
**Post date:** [March 6, 2019, 8:21pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/1 "2019-03-06T20:21:26Z")

</div>

Hello,

I’m trying to compile some cpp code using gradle, but I don’t understand how to add linker arguments. With g++ it complies and links in one step, but the gradle compiler seems to do it in two steps. So I need a way to pass the linker arguments, so it knows which libraries to use when linking

My project is something like this:

```
root
├── extract_tiles
│ ├── build.gradle
│ └── src
│ └── main
│ ├── cpp
│ │ └── extract_tiles.cpp
│ └── headers
│ └── extract_tiles.h
├── parser
│ ├── build.gradle
│ └── src
│ └── main
│ ├── cpp
│ │ └── parser.cpp
│ └── public
│ └── parser.h
├── build.gradle
├── gradlew
├── gradlew.bat
└── settings.gradle

```

The extract\_tiles build.gradle file has:

```
plugins {
    id 'cpp-application'
}
application {
    targetMachines.add(machines.linux.x86_64)
    dependencies {
        implementation project(':parser')
    }
}
model {
    toolChains {
        gcc(Gcc) {
            eachPlatform {
                cppCompiler.withArguments { args ->
                    args << '-std=c++11'
                    args << '-DPIC64'
                    args << '-static'
                    args << '-pthread'
                    // This needs to be passed to the linker, not the compiler
                    args << '-ltiff'
                    args << '-llzma'
                    args << '-ljpeg'
                    args << '-ljbig'
                    args << '-lz'
                    args << '-lpiclx20'
                }
            }
        }
    }
    platforms {
        x64 {
            architecture "x86_64"
        }
    }
}

```

As noted in the build.gradle file, the linker arguments are not passed on the g++ when linking the executable. How can I get gradle to use them when linking?

when I do

```
./gradlew linkRelease

```

I see:

```
3:22:19 PM: Executing task 'linkRelease'...

> Task :parser:compileReleaseCpp
> Task :extract_tiles:compileReleaseCpp
> Task :parser:linkRelease
> Task :parser:stripSymbolsRelease

> Task :extract_tiles:linkRelease FAILED
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
/home/wsi/dev/workspace-pathology/lib/tiff_tools/parser/extract_tiles/build/obj/main/release/acyfrmxeqecjrfs2pp4llhfk3/extract_tiles.o: In function `wsim::tile_worker(void*)':
/home/wsi/dev/workspace-pathology/lib/tiff_tools/parser/extract_tiles/src/main/cpp/extract_tiles.cpp:50: undefined reference to `TIFFOpen'
/home/wsi/dev/workspace-pathology/lib/tiff_tools/parser/extract_tiles/src/main/cpp/extract_tiles.cpp:56: undefined reference to `TIFFSetDirectory'
/home/wsi/dev/workspace-pathology/lib/tiff_tools/parser/extract_tiles/src/main/cpp/extract_tiles.cpp:182: undefined reference to `_TIFFfree'
/home/wsi/dev/workspace-pathology/lib/tiff_tools/parser/extract_tiles/src/main/cpp/extract_tiles.cpp:110: undefined reference to `TIFFTileSize'
```

---

<div class="post-metadata">

**Author:** ![craigtmoore](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/craigtmoore/32/7553_2.png) [@craigtmoore](https://discuss.gradle.org/u/craigtmoore)\
**Post date:** [March 6, 2019, 8:38pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/2 "2019-03-06T20:38:56Z")

</div>

I think I’ve figured it out, maybe. I added this to the model section:

```
model {
    toolChains {
        gcc(Gcc) {
            eachPlatform {
                cppCompiler.withArguments { args ->
                    args << '-std=c++11'
                    args << '-DPIC64'
                    args << '-static'
                }
                linker.withArguments { args ->
                    args << '-pthread'
                    args << '-ltiff'
                    args << '-llzma'
                    args << '-ljpeg'
                    args << '-ljbig'
                    args << '-lz'
                    args << '-lpiclx20'
                }
            }
        }
    }
    platforms {
        x64 {
            architecture "x86_64"
        }
    }
}

```

Now I see this in the output:

```
3:33:20 PM: Executing task 'linkRelease'...

> Task :extract_tiles:compileReleaseCpp UP-TO-DATE
> Task :parser:compileReleaseCpp UP-TO-DATE
> Task :parser:linkRelease UP-TO-DATE
> Task :parser:stripSymbolsRelease UP-TO-DATE

> Task :extract_tiles:linkRelease FAILED
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

```

However, I do the flags in the options.txt file:

```
-o
/home/wsi/dev/workspace/lib/tiff_tools/parser/extract_tiles/build/exe/main/release/extract_tiles
/home/wsi/dev/workspace/lib/tiff_tools/parser/extract_tiles/build/obj/main/release/acyfrmxeqecjrfs2pp4llhfk3/extract_tiles.o
/home/wsi/dev/workspace/lib/tiff_tools/parser/parser/build/lib/main/release/stripped/libparser.so
-m64
-pthread
-ltiff
-llzma
-ljpeg
-ljbig
-lz
-lpiclx20

```

Now I just have to figure out the problem with that Scrt1.o file. Any ideas?

---

<div class="post-metadata">

**Author:** ![craigtmoore](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/craigtmoore/32/7553_2.png) [@craigtmoore](https://discuss.gradle.org/u/craigtmoore)\
**Post date:** [March 6, 2019, 8:58pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/3 "2019-03-06T20:58:57Z")

</div>

Good news, I am able to compile and link now. The problem was due to my ‘main()’ was inside my namespace declaration. Once I moved it out, everything worked well. Hope this helps future developers.

---

<div class="post-metadata">

**Author:** ![Daniel\_L](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/daniel_l/32/6420_2.png) [@Daniel\_L](https://discuss.gradle.org/u/Daniel_L)\
**Post date:** [March 29, 2019, 3:07pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/4 "2019-03-29T15:07:23Z")

</div>

Thanks @craigtmoore for sharing your progress. With the software model native plugin, it is recommended to configure the compiler/linker flags on the component instead of the tool chain. At the tool chain level, you only want to configure generic platform flags.

---

<div class="post-metadata">

**Author:** ![craigtmoore](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/craigtmoore/32/7553_2.png) [@craigtmoore](https://discuss.gradle.org/u/craigtmoore)\
**Post date:** [March 29, 2019, 4:22pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/5 "2019-03-29T16:22:23Z")

</div>

Hi Daniel,Can you give an example of how I can add compiler/linker flags on the component level. I read through the gradle documents, but couldn’t find a good example of how to do this.

---

<div class="post-metadata">

**Author:** ![Daniel\_L](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/daniel_l/32/6420_2.png) [@Daniel\_L](https://discuss.gradle.org/u/Daniel_L)\
**Post date:** [September 12, 2019, 12:54pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/6 "2019-09-12T12:54:29Z")

</div>

It should be something like this:

```gradle
application { // or library
    binaries.configureEach {
        compileTask.get().compilerArgs.add('--foo-flag')
        linkerTask.get().linkgerArgs.add('--bar-flag') // Only for executable and shared libraries
        createTask.get().staticLibArgs.add('--foobar--flag') // Only for static libraries
    }
}

```

---

<div class="post-metadata">

**Author:** ![pedrolamarao](https://avatars.discourse-cdn.com/v4/letter/p/958977/32.png) [@pedrolamarao](https://discuss.gradle.org/u/pedrolamarao)\
**Post date:** [November 28, 2019, 4:54pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/7 "2019-11-28T16:54:21Z")

</div>

How does using `binaries.configureEach` compare with using `tasks.withType(LinkExecutable).configureEach` etc.? Is `binaries.configureEach` the recommended approach?

---

<div class="post-metadata">

**Author:** ![Daniel\_L](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/daniel_l/32/6420_2.png) [@Daniel\_L](https://discuss.gradle.org/u/Daniel_L)\
**Post date:** [December 6, 2019, 10:34am UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/8 "2019-12-06T10:34:37Z")

</div>

Using `tasks.withType(LinkExecutable).configureEach` will configure all tasks in the project that are `LinkExecutable`. It becomes a problem when different variants of the same application exists. In this case, it will only be possible to know what variant you have by using the name of the task. We never recommend basing configuration on task names as it creates fragile code. Instead, it’s better to depend on the model. The `binaries.configureEach` route allows you do query the information about the variant itself as well as getting the associated `LinkExecutable` tasks. Both can be valid, we just try to add the configuration that is the most future-proof.

In the software model, the `tasks.withType(LinkExecutable)` was even more at a disadvantage as multiple independent component could be found inside the same project which easily broken the original intention of the author.

---

<div class="post-metadata">

**Author:** ![alannnna](https://avatars.discourse-cdn.com/v4/letter/a/ba9def/32.png) [@alannnna](https://discuss.gradle.org/u/alannnna)\
**Post date:** [January 24, 2020, 8:21pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/9 "2020-01-24T20:21:01Z")

</div>

I’m also trying to set linker args, but when I do what’s in your code snippet (using `library` instead of `application`), I get `Unresolved reference: linkerTask`. Gradle version is 6.1. Is there some updated way to do this? `compileTask` appears to be working.

```gradle
plugins {
    `cpp-library`
}

library {
    binaries.configureEach {
        linkerTask.get().linkerArgs.addAll(...) // Fails here
    }
}

```

---

<div class="post-metadata">

**Author:** ![Daniel\_L](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/daniel_l/32/6420_2.png) [@Daniel\_L](https://discuss.gradle.org/u/Daniel_L)\
**Post date:** [January 27, 2020, 4:48pm UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/10 "2020-01-27T16:48:50Z")

</div>

This is a common gotcha that would need to be handled in better ways, the binaries for a library contains both `CppStaticLibrary` and `CppSharedLibrary`. Only the `CppSharedLibrary` has the `linkerTask` as it links to an actual binary. The `CppStaticLibrary` has a `createTask` instead. You can find out what binaries will be created by looking at the configuration of `linkage` on the library. It’s always better to be precise in what you are trying to configure: `binaries.configureEach(CppSharedLibrary) { ... }`

---

<div class="post-metadata">

**Author:** ![azEf](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/azef/32/9088_2.png) [@azEf](https://discuss.gradle.org/u/azEf)\
**Post date:** [February 15, 2021, 11:32am UTC](https://discuss.gradle.org/t/how-to-pass-arguments-to-the-linker-when-building-a-cpp-application/30855/11 "2021-02-15T11:32:44Z")

</div>

For future readers, try `linkTask.get()` instead of `linkerTask.get()`

[Source](https://github.com/gradle/gradle/blob/124712713a77a6813e112ae1b68f248deca6a816/subprojects/language-native/src/main/java/org/gradle/language/cpp/internal/DefaultCppSharedLibrary.java#L90)
