Using msvcrt with Mingw-w64 - c

I'm trying to use the Mingw-w64 toolchain provided by LH_Mouse, version 10.2.1.
When compiling this small program:
#include <windows.h>
#include <stdio.h>
int wmain()
{
wprintf(L"Hello world!\n");
ExitProcess(0);
}
with the following command:
gcc.exe test.c -o test64.exe -municode -s -Os -Wall -nostdlib -lmsvcrt -lkernel32 -e wmain
I get an error: undefined reference to `__mingw_vfwprintf'
Z:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.2.1/../../../../x86_64-w64-mingw32/bin/ld.exe: R:\Temp\ccDSsj2M.o:test.c:(.text+0x3d): undefined reference to `__mingw_vfwprintf'
collect2.exe: error: ld returned 1 exit status
I previously used Mingw-w64 7.3.0 provided on SourceForge and everything worked fine.
Of course I can use the stdlib (and in this case there is no error) but this increases the size of the executable.
I have read that some changes have been done recently to support UCRT. Is it related?
Is there a way to use msvcrt like before?
Edit: using -lmingwex does not really help. If located after -lmsvcrt, it produces a huge amount of varied "undefined reference" errors. If located before, we got several "undefined reference" to ___chkstk_ms, and one to _pei386_runtime_relocator.
The first ones can be removed by adding -lgcc after -lmingwex. For the last "undefined reference", I have found nothing. Adding -lmingw32 does not help, no matter its location.
So for now, the only possibilities I see are to either modify stdio.h, or create my own declarations.
Well, I use mingw since many years and its not the biggest issue I encountered. But I am a bit disappointed that it affects such basic functions.

You are trying to compile your application with -nostdlib option which means that standard C functions (like printf, scanf, wprintf, ...) are not available for your application. Therefore you should not include standard C header files (like stdio.h, stdlib.h, ...) and also you should not use wprintf in your application.
If you really want to standard C function with -nostdlib option then you have to write your own C header files and also your own implementation of standard C functions (like wprintf).
What you did was to include MinGW's stdio.h header file which calls lot of standard C functions and also internal MinGW functions and then told gcc (via -nostdlib to not link these standard functions and neither internal MinGW functions. Which obviously resulted in lot of linker errors.
Then you have tried to manually link msvcrt.dll library but it failed too as this Windows library does not contain internal MinGW functions used in MinGW's stdio.h header file.
If you really want not use standard C functions from gcc/MinGW (via -nostdlib option) but rather directly via Windows msvcrt.dll library then you have to use also Windows stdio.h header file and not MinGW one. But beware that Windows header file stdio.h is not supported for gcc compiler and it also does not have to work.
So you should first answer questions, why you are trying to use standard C functions (like wprintf) without standard C library with gcc compiler? This sounds really strange and such thing is common only in freestanding environment or for bare-metal applications (like firmware, bootloader, kernel, ...). Are you workarounding some other bug which you have not mentioned?
And to answer your question, why in previous version it (probably) worked fine. Older version of gcc compiled C code according to C89 standard (with GCC extensions). New version of gcc started to compile C code according to C11 standard. Windows library msvcrt.dll provides only subset of standard C functions and only for C89 standard. For this reason MinGW provides its own implementation (or fixes) for some standard C functions to be compliant with C99 and C11 standards. As older gcc compiled your application as C89 code and manually linked msvcrt.dll library provided somehow compatible implementation for printf and wprintf, it resulted in final exe file without errors. Now with new gcc you are compiling your application as C11 code and you are trying to call C11 wprintf function but this function in msvcrt.dll is not compatible with C11 and therefore you get lot of errors.
Windows provides C11 standard functions in UCRT libraries. msvcrt.dll provides only subset of C89.
So you really should not compile your application with -nostdlib if your intention is to produce executable application and use standard C functions.
You can instruct new gcc to compile your C application as C89 with option -std=c89. This should instruct new gcc to behave like old gcc.

Related

linking pgi compiled library with gcc linker

I would like to know how to link a pgc++ compiled code (blabla.a) with a main code compiled with c++ or g++ GNU compiler.
For the moment linking with default gnu c++ linker gives errors like:
undefined reference to `__pgio_initu'
As the previous person already pointed out, PGI supports G++ name mangling when using the pgc++ command. Judging from this output, I'm guessing that you're linking with g++ rather than pgc++. I've had the most success when using pgc++ as the linker so that it finds the PGI libraries. If that's not an option, you can link an executable with pgc++ -dryrun to get the full link line and past the -L and -l options from there to get the same libraries.
Different C++ compilers use different name-mangling conventions
to generate the names that they expose to the linker, so the member function
name int A::foo(int) will be emitted to to the linker by compiler A as one string
of goobledegook, and by compiler B as quite a different string of goobledegook,
and the linker has no way of knowing they refer to the same function. Hence
you can't link object files produced by different C++ compilers unless they
employ the same name-mangling convention (and quite possibly not even then: name-mangling
is just one aspect of ABI compatibility.)
That being said, according to this document,
PGC++ supported name-mangling compatibility with g++ 3-and-half years ago, provided that PGI C++ compiler was invoked with precisely the command pgc++ or pgcpp --gnu. It may be that the library you are dealing with was not built in that specific way, or perhaps was built with an older PGI C++ compiler.
Anyhow, if g++ compiles the headers of your blabla.a and emits different
symbols from the ones in blabla.a, you can't link g++ code with blabla.a.
You'd need to rebuild blabla.a with g++, which perhaps is not an option.

GNU Triplet, GCC and Linux kernel compiling

My native gcc says, that its triplet is the following.
> gcc -dumpmachine
x86_64-suse-linux
Where cpu-vendor-os are correspondingly x86_64, suse, linux. The latter means that glibs is in use(?). When I am doing cross-compiling busybux-based system the compiler triplet is something like avr32-linux-uclibc, where os is 'linux-uclibc', meaning that uclibc is used.
The difference between 'linux-glibc' and 'linux-uclibc' is (AFAIU) in collect2 behavior and libgcc.a content. Either glibc or uclibs are silently linked to the target binary.
The questions is that how is the linux kernel been compiled by the same compilers? As soon as the kernel runs on bare-metal it must not been linked with any kind of user-space libc, and should use appropriate libgcc.a
gcc has all kind of options to control how it works.
Here's a few relevant ones:
-nostdlib to omit linking to the standard libraries and startup code
-nostdinc to omit searching for header files in the standard locations.
-ffreestanding to compile for a freestanding environment (such as a kernel)
You also do not need to use gcc for linking. You can invoke the linker directly, supply it with your own linker map, startup object code, and anything else you need.
The linux kernel build seems, for arbitrary reasons not to use -ffreestanding , it does control the linking stage though, and ensures the kernel gets linked without pulling in any userspace code.

How to change compiler from C to C++ in Eclipse IDE?

My project is in C and shared library in C++ (I using Eclipse IDE on Linux platform). Default setting of project taking C compiler (GCC). Can anybody suggest me how to change compiler from C to C++ for my project.
GCC can compile both C and C++ source files. It uses filename extensions to determine if it should compile as C or C++.
C++ source files conventionally use one of the suffixes ‘.C’, ‘.cc’, ‘.cpp’, ‘.CPP’, ‘.c++’, ‘.cp’, or ‘.cxx’; C++ header files often use ‘.hh’, ‘.hpp’, ‘.H’, or (for shared template code) ‘.tcc’; and preprocessed C++ files use the suffix ‘.ii’. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs (usually with the name gcc).
GCC: GNU Compiler Collection
gcc: GNU C Compiler g++: GNU C++ Compiler
The main differences:
gcc will compile: .c/.cpp files as C and C++ respectively.
g++ will compile: .c/.cpp files but they will all be treated as C++ files.
Also if you use g++ to link the object files it automatically links in the std C++ libraries (gcc does not do this).

Standard functions defined in header files or automatically linked?

When writing a basic c program.
#include <stdio.h>
main(){
printf("program");
}
Is the definition of printf in "stdio.h" or is the printf function automatically linked?
Usually, in stdio.h there's only the prototype; the definition should be inside a library that your object module is automatically linked against (the various msvcrt for VC++ on Windows, libcsomething for gcc on Linux).
By the way, it's <stdio.h>, not "stdio.h".
Usually they are automatically linked, but the compiler is allowed to implement them as it pleases (even by compiler magic).
The #include is still necessary, because it brings the standard functions into scope.
Stricto sensu, the compiler and the linker are different things (and I am not sure that the C standard speaks of compilation & linking, it more abstractly speaks of translation and implementation issues).
For instance, on Linux, you often use gcc to translate your hello.c source file, and gcc is a "driving program" which runs the compiler cc1, the assembler as, the linker ld etc.
On Linux, the <stdio.h> header is an ordinary file. Run gcc -v -Wall -H hello.c -o hello to understand what is happening. The -v option asks gcc to show you the actual programs (cc1 and others) that are used. The -Wall flag asks for all warnings (don't ignore them!). The -H flag asks the compiler to show you the header files which are included.
The header file /usr/include/stdio.h is #include-ing itself other headers. At some point, the declaration of printf is seen, and the compiler parses it and adjust its state accordingly.
Later, the gcc command would run the linker ld and ask it to link the standard C library (on my system /usr/lib/x86_64-linux-gnu/libc.so). This library contains the [object] code of printf
I am not sure to understand your question. Reading wikipedia's page about compilers, linkers, linux kernel, system calls should be useful.
You should not want gcc to link automagically your own additional libraries. That would be confusing. (but if you really wanted to do that with GCC, read about GCC specs file)

floor of double(time_t)

I cannot understand why this throws undefined reference to `floor'":
double curr_time = (double)time(NULL);
return floor(curr_time);
Hasn't it been casted to double, which is what floor receives?
You possibly have run in to the infamous -lm problem: Compile as:
gcc yourfile.c -o out -lm
This is C FAQ 14.3 item as well.
Maybe because you don't link with the math library? The error has nothing to do with casts and data types, btw.
You probably have to link explicitly to the library. On an UNIX-like system this would typically be "/usr/lib/libm.a". The C standard library should be linked by default, but the math library is, depending on your system, not linked and you may have to link explicitly. (e.g. on Mac OS X it is also linked by default on my ubuntu system it is not).
Note that this has nothing to do with your include path. If you are on something UNIX-like you will probably find the header with the prototype declaration under "/usr/include/math.h", where your compiler will always look for headers.
If you are using gcc, you can either link directly with:
gcc yourfile.c /usr/lib/libm.a -o out
or with "-lnameroflibrary" like this:
gcc yourfile.c -lm -o out
this will look for a library in the same directory as the C standard library with the name "libnameoflibrary.a"

Resources