Sorry for the delay in getting back to you. I shouldn't have put `-subsystem=console` because it'd lead to confusion in my example. The point is that, when you compile with `-subsystem=windows` (which all GUI applications do), you _have_ to allocate a console; GUI apps have a graphical window but no command-line interface upon starting. It is a very common and sensible usage case to want to have a console alongside your main window.
In a console-based program, allocation and freopen is done automatically; in a GUI app, you also need to freopen() or freopen_s() the stdin/stderr/stdout streams, otherwise your printf outputs will not show up on the newly allocated console. In <stdio.h>, stdin/stderr/stdout are dependent on the definition of either `_iob` or `_imp___iob`. As mentioned in my earlier threads, both _iob and _imp___iob are mis-configured in TCC's version of <stdio.h>; even the compiler itself complains that they must've been declared with __declspec or __atribute__ ((dllimport). Also, that is the exact same way it's done in new MinGW's headers, using the _CRTIMP macro. I guess using TCC (at least for building full-fledged windows apps) is rather niche in comparison to "mainstream" compilers (and its `-m32` compiler even more so), explaining why no one has encountered/reported this basic bug before. the _MSVCRT_ macro is really not all that important here; it's just telling <stdio.h> to use the latest MSVCRT.dll as opposed to "old" versions of it. Newer MSVCRT.dll only comes with _iob, because _imp___iob has been deprecated. I didn't compile my program with MinGW GCC, but this code is pretty much the "hello world" equivalent of Win32 consoles and should work anywhere; it's just a matter of header misconfiguration in TCC's headers. To be concise, both _iob and _imp___iob are external symbols that ought to be provided at runtime via msvcrt.dll (or, in case of _imp___iob, older versions thereof); the MinGW headers that you linked correctly label them as __declspec((dllimport)), whereas TCC's headers don't. The reason this bug only shows up in the `-m32` version and not `-m64` is because of line 94 in <stdio.h> #ifdef _WIN64 _CRTIMP FILE *__cdecl __iob_func(void); #else It "skips" those _iob and _imp__iob stuff on Win64. On Sun, Nov 24, 2024 at 8:05 PM avih <avih...@yahoo.com> wrote: > > Can we maybe start from the begining again? > > If you compile with subsusyem=console, why do you need to allocate a console > in the first place and then reopen stdout? console apps already do that > automatically, like so: > > // test.c > #include <stdio.h> > int main() { > printf("press enter to exit\n"); > fgetc(stdin); > return 0; > } > > And you compile it simply as: > tcc test.c > > Or as in your example (omitting -m32 because I use a native tcc 32, to reduce > the number of variables): > tcc -std=c11 -Wall -Werror -Wl,-subsystem=console test.c > > Then if you run it in a console then it prints the message and waits for > "enter", and if you double click it in explorer then it opens a console and > prints the message in that console and waits for "enter". > > Isn't this what you're trying to achieve? > > Why is _MSVCRT_ defined in your example? Why is windows.h included in your > example? > > Maybe you have some other problem, and the example program which you attached > is your attempted solution, which didn't work, and now you try to make it > work? > > If that's the case, maybe you can go back and describe your original problem, > and the standard minimal program which you wrote to solve it (without > defining _MSVCRT_), and which compiles in mingw gcc or msvc. > > Please describe exactly how you compile it with mingw gcc, and then how you > tried to compile it with tcc, and what went wrong. > > - avih > > > > > On Sunday, November 24, 2024 at 07:43:30 PM GMT+2, Fereydoun Memarzanjany via > Tinycc-devel <tinycc-devel@nongnu.org> wrote: > > > > > > If you use TinyCC in its 32-bit mode (`-m32`) to compile a sample > program that uses any CRT function/symbol from `msvcrt.dll` (such as > the snippet provided later in this message), you'll be met with > compilation failures: > > `tcc.exe -std=c11 -Wall -Werror -Wl,-subsystem=console -m32 .\main.c` > "tcc: error: undefined symbol '_iob', missing __declspec(dllimport)?" > > (This only happens under `-m32`, whereas `-m64` works perfectly fine.) > > `_iob` is not the only "unresolved" symbol, either; `printf`, > `freopen`, `freopen_s`, and basically everything from the CRT will > fail to link. > > Regardless of whether or not you use `-lmsvcrt`, `#pragma comment(lib, > "msvcrt")`, `_declspec(dllimport)`, `attribute ((dllimport))`, > `-static` or `-shared`, or even `-impdef` on > "C:\Windows\SysWow64\msvcrt.dll" (or earlier versions thereof: > "msvcrt40.dll"), TCC still complains. > > I've verified with `DUMPBIN.exe` that both 32- and 64-bit "msvcrt.dll" > do, in fact, define `_iob` and other symbols. > > By some arcane logic, the following works perfectly fine: `tcc.exe > -std=c11 -Wall -Werror -Wl,-subsystem=console -m64 .\main.c` > > `main.c` > ```c > //#pragma comment(lib, "msvcrt") > //__attribute__((dllimport)) extern __declspec(dllimport) FILE _iob[]; > > #include <windows.h> > > // _MSVCRT_ being defined will cause MinGW's stdio.h to use _iob as > // opposed to _imp___iob; only the former is defined in msvcrt.dll. > // However, even though _iob is exported by both the 32- and 64-bit > // versions of said dll, TinyCC still fails to find _iob in the former. > #define _MSVCRT_ > #include <stdio.h> > > void main() { > // AllocConsole() and basically everything from kernel32.dll or > // user32.dll work perfectly fine, both in -m32 and -m64; it's > // only msvcrt.dll that causes issues with TinyCC. > AllocConsole(); > > // Any CRT function (e.g., freopen, freopen_s, printf, etc.) > // fail to get linked properly ONLY in -m32; -m64 is fine. > // Even if I change the -I and -L paths to C:/Windows/SysWow64 > // and/or use tcc.exe -impdef to create .def files from them, > // TCC still fails in finding _iob and other symbols. > // Also, using #pragma comment(lib, "msvcrt") or -lmsvcrt > // doesn't help at all. Even if you do get TCC to somehow > // stop complaining about missing symbols, it'd just include > // a blank IAT.printf or IAT.freopen, causing segfaults. > freopen("CONOUT$", "w", stdout); > printf("This only compiles (and prints) under TCC in 64-bit mode."); > } > ``` > > As mentioned earlier, this error in `-m32` happens regardless of other > switches like `-std`, `-shared`, `-static`, `-lmsvcrt`, `-subsyetem`, > etc. So, at this point, I'm starting to think this might really be a > bug with TinyCC 0.9.27 (Win32 & Win64 builds) itself. > > _______________________________________________ > Tinycc-devel mailing list > Tinycc-devel@nongnu.org > https://lists.nongnu.org/mailman/listinfo/tinycc-devel _______________________________________________ Tinycc-devel mailing list Tinycc-devel@nongnu.org https://lists.nongnu.org/mailman/listinfo/tinycc-devel