0

I am using Debian 9 (stable) and I recently decided to install mingw-w64 so that I could do cross platform C/++ development since I don't have consistent access to a Windows machine. When I had first installed it a couple days ago to test out doing 32 and 64-bit builds, it seemed to work but now the 64-bit command (x86_64-w64-mingw32-gcc) seems to only put out 32-bit executables despite the fact that it should only put out 64-bit by default. I even explicitly declared the options -m64 and -march=x86_64 in an attempt to force it, but it seems like no matter what I try now it will only do a 32-bit build.

For reference, all the code consists of is three files: hello.c, hellofunc.c, and hellofunc.h. The file hello.c simply calls a function defined in hellofunc.c called printHelloWorld:

void printHelloWorld(void){
    long z;

    printf("Hello World!\n");

    switch(sizeof(z)){
        case 4:
            printf("This program is 32-bit\n");
            break;
        case 8:
            printf("This program is 64-bit\n");
            break;
        default:
            printf("This program is of unknown bit size\n");
    }


    printf("Long int size is %i bytes long!\n", sizeof(z));
}

With the expected output being "This program is 32-bit" or 64-bit, with an explicit statement showing the byte length of a long variable. The problem I am having is that despite the fact that the 64-bit mingw-w64 gcc command is being used, when I do test it on Windows it will display the 32-bit message and a byte length of 4 instead of the expected 8.

Again, when I initially tested it right after download it worked as expected and I have no idea what could have changed the default functionality of it over the last couple of days- I didn't install anything new, and all I was doing was trying to work with makefiles (this directory does not contain one though). Also, for the record, the default gcc native to my Debian system works perfectly well with the -m32 and -m64 commands so it's not like my system isn't capable of it and... in fact, if anything, I would expect the behavior to be backwards as Linux seems to require special set-up to do 32-bit builds or run 32-bit programs on a 64-bit machine.

For the last attempt to understand the problem myself I ran the command x86_64-w64-mingw32-gcc -v -o hello.exe hello.c hellofunc.c -I . so that I could get the full command sequence of the compiler, and I also ran gcc on it as well. Here is the full output I put on pastebin just for reference. I don't 100% understand the output, but it seriously looks like all the configuration and options should be outputting 64-bit?? I don't know, I'm still pretty new to Linux and still don't entirely understand how to dissect when something goes wrong- especially when something runs counter to the explicitly defined functionality lol.

If somebody could recommend possible fixes for this or alternatives I probably didn't think of, I would really appreciate. I tried Googling for answers before hand, but x86_64-w64-ming32-gcc seems to only ever come up in conversation to tell newbies that it's the obvious default way to compile for 64-bit architecture.

Thanks for reading and any help you can give, cheers~

AniMerrill
  • 63
  • 1
  • 6
  • 3
    In the Windows x86-64 compiler world (including MinGW cross compilers) the size of a long is 32-bits, long long is 64-bits. This differs from x86-64 targets like Linux/MacOS etc with different type sizes. For a list of sizes in Windows based compilers see this MS document: https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=vs-2019 – Michael Petch Jun 13 '19 at 19:44
  • @MichaelPetch Hm, that's weird but interesting. So in Windows development, it seems like most variable types are fixed to a specific byte length then? Is there any way to test the architecture as a sanity measure, similar to how this example works on *nix systems? – AniMerrill Jun 13 '19 at 19:50
  • 1
    Agner Fog has a [table with the type sizes](https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=vs-2019) for different environments and compilers. Since x86-64 MinGW cross compilers conform to the sizes of a Microsoft compiler for compatibility you can review the column 64-bit Microsoft to confirm this. – Michael Petch Jun 13 '19 at 19:53
  • 2
    `sizeof(void*)` would work in more cases, but even that would be wrong on ILP32 ABIs (like AArch64's ILP32 ABI, and [x86-64 Linux's x32 ABI](https://en.wikipedia.org/wiki/X32_ABI)) – Peter Cordes Jun 13 '19 at 19:58
  • 1
    @PeterCordes : There are 2 parts to t his question. I'd add https://stackoverflow.com/questions/1505582/determining-32-vs-64-bit-in-c as a duplicate as well. I don't have the ability to add the dupe myself. – Michael Petch Jun 13 '19 at 20:05
  • @MichaelPetch: Does SO let you edit the dup list, or does that require a gold badge? I think dup-list editing appeared after I had gold badges in many of the questions I see, so I was never sure if that new feature was open for anyone once a question was closed as a duplicate. – Peter Cordes Jun 13 '19 at 20:07
  • @PeterCordes Thanks for that info, it seemed to work on my current arrangement but I'll keep in mind that it's not really a sophisticated solution likely to work everywhere. I'll probably look into the solution Michael put up here since that seems potentially promising too. Sorry everyone for being dumb lol. – AniMerrill Jun 13 '19 at 20:09
  • 1
    `sizeof(void*)` is still useful if false-negatives are only a perf problem, not correctness. (e.g. to select a version that's more optimal if native 64-bit integers are available). Combined with some CPP macros for specific ILP32-on-64 ABIs, that covers the real-world cases. (Like `#ifdef __x86_64__`) – Peter Cordes Jun 13 '19 at 20:13
  • 1
    @AniMerrill : In particular I'd review this answer: https://stackoverflow.com/a/12338526/3857942 – Michael Petch Jun 13 '19 at 20:13
  • 1
    Also note that in C, the bit-size of a type is `sizeof(T) * CHAR_BIT`. You can just print that. `sizeof(char)` is guaranteed to be 1, but `CHAR_BIT` is not guaranteed to be 8. e.g. a DSP with word-addressable memory might have 32-bit char/short/int so they all have sizeof() = 1. – Peter Cordes Jun 13 '19 at 20:15
  • @MichaelPetch yeah that one looks pretty promising and I'll probably toss together a new version of my hello world project just to tinker around with that option so I have an example lying around. Thank you~ – AniMerrill Jun 13 '19 at 20:18
  • besides printing sizeof result with `%i` is UB. You must use [`%zu`](https://stackoverflow.com/q/940087/995714) – phuclv Jun 14 '19 at 01:55

0 Answers0