gradle / gradle-native

The home of Gradle's support for natively compiled languages
https://blog.gradle.org/introducing-the-new-cpp-plugins
Apache License 2.0
92 stars 8 forks source link

Debug Libraries generated using gradle are incompatble with default MSVS application project #972

Open amz-shahji opened 5 years ago

amz-shahji commented 5 years ago

Debug libraries generated using default gradle options are incompatible with a default MSVS application project.

Expected Behavior

Generated libraries should be compatible.

Current Behavior

Libraries are incompatible with default options and need tweaking to make them work.

Context

We publish a number of libraries that user can consume in their project. However, the libraries generated using default gradle options are not compatble. When attempted, the linker throws two errors - one related to mismatch _ITERATOR_DEBUG_LEVEL (library is 0 and application is 2) and other related to mismatch of runtime library (library is MT_StaticRelease and app is MTd_StaticDebug).

Steps to Reproduce (for bugs)

  1. Using the static-library project from native-samples project
  2. Build the list (shared) and utilities (static) project
  3. Create a default MSVS C++ Console project with the main.cpp file from app project
  4. Setup the project to link the appropriate libraries for debug & release generated by gradle for project list and utilities above
  5. Debug configuration should fail with two errors, however, release link successfully

P.S. It shouldn't matter but just in case - I am using MSVS 2017 Version 15.6.6 and Gradle v5.0

Workaround

Add _DEBUG macro to the list and utilities project to generate compatible debug libraries.

k-mack commented 5 years ago

I can confirm this behavior. It would make sense for Gradle to automatically apply /MTd to MSVC's arguments when compiling the static debug binary. The workaround I used was to set this flag manually. This worked while building a cpp-application:

binaries.whenElementFinalized { binary ->
    binary.compileTask.get().configure {
        if (binary.targetMachine.operatingSystemFamily.windows) {
            if (binary.optimized) {
                compilerArgs.add("/MT")  // static, release linkage
            } else {
                compilerArgs.add("/MTd") // static, debug linkage
            }
        }
    }
}

Not sure what the preferred workaround is.

zosrothko commented 5 years ago

@k-mack From my perspective, the test binary.targetMachine.operatingSystemFamily.windowsshould be toolChain instanceof VisualCppsince one can now have clang, and may be gcc under Windows

k-mack commented 5 years ago

Great point, @zosrothko.

lacasseio commented 5 years ago

Thanks for the feedback @k-mack. We will see what we can do around default options. Some issues we need to consider when adding defaults is the allowing developers to opt-out of those defaults. Luckily the Provider API keeps evolving and now allow "convention" to be set which can be overwritten. It's a great idea, but still, lack some demonstration and possibly some use case where someone just wants to opt-out one default but not the other one.