MSVC project missing "__popcountdi2" when linking against GCC-built static library - c

I have a windows executable project that links against a static library (.lib) built with GCC 6 (MinGW). The following error occurs during compilation:
LNK2019 unresolved external symbol __popcountdi2 referenced in function ...
The symbol is linked in as a result of using a GCC built-in function __builtin_popcount(), which resides in libgcc. However, despite adding -static-libgcc as an argument to gcc, the problem still persists.
Is there a way for my library (.lib) to contain parts of libgcc rather than requiring libgcc to be on the system for an executable to link against? Is some way around having to ship the library with libgcc?
__builtin_popcount() is not the only built-in function that I'm currently using. The library makes use of __builtin_bswap32(), which doesn't seem to run into this issue.
I'm using GCC 6.1.0. Updated to 6.2.0; same issue.

The issue was that on windows, MinGW (GCC) was not detecting the current CPU architecture properly when -march=native was passed in. It was falling back to an architecture that did not support POPCNT as a native instruction (probably i686). As a test, -mpopcnt was added to the build and everything worked fine.
The fix is to manually specify the architecture using -march=.
Furthermore: is this a bug with MingGW since the native architecture is not polled for properly?

Related

Why does (host) GCC need to be built against the target's standard library?

I've been looking into building cross-toolchains and have a general question about the compilation and workings of gcc.
The question is about this excerpt from the official gcc documentation:
In order to build GCC, the C standard library and headers must be present for all target variants for which target libraries will be built (and not only the variant of the host C++ compiler).
Why is the target's standard library required to build the (cross) compiler itself? Shouldn't the (cross) compiler running on the host only require the host's standard library to be built and then be able to compile the target's standard library?
I also found this on crosstool-NG's how a toolchain is constructed:
the final compiler needs the C library, to know how to use it, but: building the C library requires a compiler
This is consistent with what's stated above but I don't get why the final compiler needs to be built against a prebuilt target C library just to know how to use it later on. What is there to know for the host compiler about the target C library? Isn't it the linker's job to link target programs against the target's standard library at compile time?
Because that's the only way to ensure a working compiler for the target platform is created. There's no point in creating a non-working compiler, distributing it to the target platform, and finding out then that it's useless.
In general, a non-shared-object executable file is only successfully created if there are no unresolved symbols.
Per the GCC 11.2 "Overall Options" documentation
Compilation can involve up to four stages: preprocessing, compilation proper, assembly and linking, always in that order. GCC is capable of preprocessing and compiling several files either into several assembler input files, or into one assembler input file; then each assembler input file produces an object file, and linking combines all the object files (those newly compiled, and those specified as input) into an executable file.
So the final step is linking. The GNU linker 'ld' man page states:
Normally the linker will generate an error message for each
reported unresolved symbol but the option
--warn-unresolved-symbols can change this to a warning.
and
--error-unresolved-symbols
This restores the linker's default behaviour of generating
errors when it is reporting unresolved symbols.
So, by default linking fails when there are unresolved symbols.
Why?
Because if there are unresolved symbols, the resulting executable file won't work when it's run.
And the only way to ensure there are no unresolved symbols is to have all the necessary libraries from the target platform available when cross-compiling so all symbols can be resolved when the new compiler executables are being linked.

Static build of GMP for MSVC (Windows)

Is it possible to build GMP for MSVC on Windows?
I need fully static solution (static library), without any DLL dependencies. So that my final EXE doesn't depend on any external (non-system) DLLs.
I'm alright if building GMP will need Cygwin or MSYS, as far as it can be used later in MSVC without any problems. But as far as I know at least Cygwin builds always depend on extra DLLs like cygwin1.dll which is not affordable for me, fully static-library solution is needed.
I'm aware there exists MPIR library that is more Windows friendly. But right now I need specifically GMP solution if possible.
Of course would be great if all optimizations and assembly is used when building for Windows. But if assembly is not possible then at least non-assembly (generic) variant of GMP is needed.
Of course I need 64-bit version.
If someone can post all steps needed to produce such static library for MSVC usage? Or maybe link some web-site that has such instructions?
I successfully managed to compile a working fully statically linked program with GMP using MSVC under Windows.
For that I used installation of MSYS, which is located in c:/bin/msys/ on my machine.
Then inside MSYS shell installed GMP packages mingw-w64-clang-x86_64-gmp and gmp-devel (pacman -S gmp-devel to install and pacman -Ss gmp to search).
In MSVC compiler I added include directory c:/bin/msys/clang64/include/.
Wrote an example of GMP usage program in C++, that implements Trial Division / Pollard's Rho / Pollard's P-1 factoring algorithms using long arithmetics. This program uses both mpz_...() C routines and mpz_class C++ wrapper class. For example this program is located in main.cpp.
To linker command line I added following libraries:
c:/bin/msys/clang64/lib/libgmp.a
c:/bin/msys/clang64/lib/libgmpxx.a
c:/bin/msys/mingw64/lib/gcc/x86_64-w64-mingw32/10.3.0/libgcc.a
c:/bin/msys/clang64/x86_64-w64-mingw32/lib/libmingwex.a
Also I had to add /FORCE flag (read about it here) to linker command, because libmingwex.a has some symbols overlapping with default MSVC's libraries, precisely without /FORCE I had following errors:
libucrt.lib(strnlen.obj) : error LNK2005: wcsnlen already defined in libmingwex.a(lib64_libmingwex_a-wcsnlen.o)
libucrt.lib(strnlen.obj) : error LNK2005: strnlen already defined in libmingwex.a(lib64_libmingwex_a-strnlen.o)
bin\win-msvc-m-64-release\drafts\gmp_int_msvc.exe : fatal error LNK1169: one or more multiply defined symbols found
All steps produced working (tested) final statically-linked program without any external DLL dependencies (of course except for default system DLLs of Windows).
It means MSYS's libraries .a are fully compatible with MSVC and link successfully in MSVC compilation.
Not to have /FORCE linker flag I also did extra following steps. Made a copy of c:/bin/msys/clang64/x86_64-w64-mingw32/lib/libmingwex.a library. Used c:/bin/msys/clang64/bin/objcopy.exe util, which probably was installed together with Clang. With objcopy renamed overlapping symbols:
objcopy --redefine-sym wcsnlen=msys_wcsnlen libmingwex.a
objcopy --redefine-sym strnlen=msys_strnlen libmingwex.a
which allowed me to successfully use this modified libmingwex.a library to link in MSVC without using /FORCE.

Are static c libraries created with one compiler compatible with another?

In my case I have a library built with code sourcery gcc targeting arm cortex-m4. I am trying to then link that library into a project being compiled with IAR compiler.
Is it possible to do this or does the library have to be rebuilt with the new tools? What factors affect this?
Static library is bundle of several object files which are always compiler specific. So if you try to link a gcc based lib with IAR compiler, you will get error at compile time due to mismatch between object file formats to be linked.
You need to rebuild your library using IAR.
The IAR compiler for ARM supports the AEABI format, which allows you to compile files with one compiler and link with another.
If you have built your library using GCC and have enabled AEABE, it should be possible to use the static library in a project build using the IAR tools.

linking library built with g 2.95.2 to object files built with gcc 4.6

I'm trying to reuse an old static library built with Linux GCC 2.95.2. I'm using a recent compiler (GCC 4.6) from a 32bit Ubuntu distro. The library is written in C++. I have problems linking against the functions which are encapsulated in classes.
I guess that the naming of the symbols has changed.
http://www.qnx.com/developers/docs/6.3.2/momentics/compatibility/about.html#C++_code:
GCC 2.95.3 (from 6.2.1 or 6.3) and GCC 3.3.5 use different C++ ABIs and have different name mangling. As a result, you can't link C++ binaries (objects, executables, libraries) built with GCC 2.95.3 with binaries built with GCC 3.3.5.
The error output of ld is:
undefined reference to `foo1::Bar()'
(class foo1; Member Bar)
With the tool mn the symbols could be read out. The matching symbol is named in a different way:
Bar__4Foo1
Question: Is there a way the rename the symbols in the library file? Or can I force ld to accept the old naming format?
I guess that the naming of the symbols has changed.
Correct.
What you are missing is that the naming has changed for a reason, namely code produced by g++ 2.95 and g++ 3.3 is ABI incompatible. If you were allowed to link two objects compiled with these compilers together, all you'd get is unexplainable crashes.
By changing the name mangling, GCC developers have saved you the trouble of debugging such crashes.
Is there a way the rename the symbols in the library file?
There is, but if you succeed with that, you'll end up with said crashes, so don't shoot your foot off.

linker error on the llvm gcc compiler for the simulator only

We are in the process of moving our project from LLVM GCC to Apple LLVM. One of the libraries we have is built only for arm and not i386. This is causing issues where we get the warning on the simulator build after which we not end up linking anymore. This worked fine in GCC as I was able to compile the app just fine. This warning is harmless for us on the simulator. Is there any way to ignore the warning as it was on LLVM GCC.
I looked at the project build settings as well to figure out if there was a flag that I could use to switch off this warning.
I have looked enough stack overflow questions similar to this one. Most of them suggest to get both the flavors (arm and i386) of the binary and combine them. I still wonder how this worked in LLVM GCC and why there was no compilation error.
Any ideas ?
the warning that I get,
ld: warning: ignoring file library.a, file was built for archive which is not the architecture being linked (i386)
thanks

Resources