Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows clang Hello World lnk4217

Tags:

c++

clang

I have installed clang version 6.0 as well as Visual Studio 2017. I am compiling a simple 'hello world' application:

#include <iostream>

int main()
{
  std::cout << "Hello, World!" << std::endl;
  return 0;
}

using

clang hello.cpp

This gives me warnings:

hello-d1b2c6.o : warning LNK4217: locally defined symbol __std_terminate 
imported in function "int `public: static unsigned __int64 __cdecl
std::char_traits<char>::length(char const * const)'::`1'::dtor$2"
(?dtor$2@?0??length@?$char_traits@D@std@@SA_KQEBD@Z@4HA)

hello-d1b2c6.o : warning LNK4217: locally defined symbol _CxxThrowException 
imported in function "public: void __cdecl std::ios_base::clear(int,bool)"
(?clear@ios_base@std@@QEAAXH_N@Z)

I am aware that I can mitigate these warnings by using clang-cl (as suggested in this SO question and here), however, I do not want to do that without fully understanding the implications.

So here are my actual questions:

  1. What do these warnings mean or what is causing them?
  2. What does using clang-cl change and what do I have to keep in mind when using it? (I guess there is a reason to not use it all the time)
  3. Are there other ways to not receive these warnings (except for turning off warnings)?
like image 884
Jerome Reinländer Avatar asked May 10 '18 13:05

Jerome Reinländer


1 Answers

I ran into this issue myself and did some investigation.

What do these warnings mean?

There is a detailed answer here (that I do not fully understand), but the high level idea, as I understand it, is there is a mismatch between the object file (.o file) that clang compiled and the library file (.lib file) that is being linked with.

Therefore, although the program seems to work, it's probably a bad idea to just ignore the warnings.

What is causing them?

The warning is being issued by the Microsoft linker, link.exe, which clang invokes. Clang does not include its own linker. By default, on Windows, it looks for the Microsoft Visual Studio C compiler headers, libraries, and linker. You can see exactly what it is doing by adding the -v (verbose) switch to the clang command line.

I'm not sure how Clang finds these tools. I'd forgotten I even had them installed, and they certainly are not on the PATH. I think Clang must have dug them out of the registry somehow.

What does using clang-cl change?

It changes the switches passed to the Clang compiler (also called clang or clang++ or clang-cl, but with the -cc1 switch passed) and the linker (MSVC link.exe). At a high level, clang-cl tries to emulate the MSVC cl.exe compiler, while clang ... does something else. I'm not sure what. It's not emulating MinGW; see below.

The detailed differences can be seen in the respective -v outputs. Using clang++ and clang-cl from LLVM 8.0.1, I see these compiler switch differences:

clang-cl has but clang++ lacks:
  -relaxed-aliasing
  -mllvm
  -x86-asm-syntax=intel
  -D_MT
  -flto-visibility-public-std
  --dependent-lib=libcmt
  --dependent-lib=oldnames
  -stack-protector 2
  -fms-volatile
  -fdiagnostics-format msvc

clang++ has but clang-cl lacks:
  -fcxx-exceptions
  -fexceptions

And during linking, clang++ passes -defaultlib:libcmt, while clang-cl does not.

The big difference I see is clang-cl passes -D_MT, enabling the thread-aware C and C++ standard libraries. I think it's a bad idea to mix modules compiled with and without _MT. The mismatch regarding -fcxx-exceptions is also concerning, suggesting that C++ exceptions might not work.

clang-cl also passes -flto-visibility-public-std, the flag recommended by this answer to a related question. I don't know whether this flag is merely suppressing a warning or significantly changing the way the code is compiled.

What do I have to keep in mind when using it?

As I understand it, you want to use clang-cl if and only if you want Clang to do its best to emulate the Microsoft cl.exe compiler, including using its header files and invoking the Microsoft linker with its libraries.

Furthermore, I'm unaware of a reason to use clang++ on Windows without also specifying -target (next section). Without -target, clang++ still uses the MSVC headers, libraries, and linker, but does not pass the switches needed to emulate the cl.exe compiler. I suspect this will always result in an executable with mismatched object code.

Are there other ways to not receive these warnings?

In my case, I want Clang to emulate the MinGW gcc compiler and invoke its linker instead. To do that, per this answer, add -target x86_64-pc-windows-gnu to the clang++ command line:

  $ clang++.exe -target x86_64-pc-windows-gnu -o cpphello.exe cpphello.cpp

That command produces no warnings, and a working executable.

By adding -v to that command line, you can see the details, including invocation of the MinGW ld.exe linker.

Note: You need a MinGW gcc on your PATH!

What about clang versus clang++?

Like gcc, clang will compile C++ code if the file uses an extension it recognizes, such as .cc or .cpp. However, it does not pass the C++ standard library to the linker, even when you compile and link in a single command. Therefore, it's generally best to use clang++ exclusively when working with C++ code.

Likewise, clang -x c++ can be used to compile C++, but again does not pass the C++ standard library to the linker.

like image 89
Scott McPeak Avatar answered Oct 27 '22 01:10

Scott McPeak