Preprocessor macro __x86_64__ problem with CLHEP on Windows

ROOT Version: 6.26.04
Geant4 Version: 11.0.2 (with bundled CLHEP)
Platform: x86/64 Windows 10
Compiler: Visual Studio 2022 (MSVC 19.32.31329.0)
Compiler options: /permissive- /Zc:__cplusplus /Zc:inline

I’m trying to compile a code depends on ROOT, Geant4 and others on Windows with MSVC, which works fine on Linux with gcc and clang. I noticed that in ROOT/RConfig.h, at line 395 there is a #define introduces __x86_64__ which “by default” do not appear on Windows:

390 | #ifdef _WIN64
391 | #   define R__WIN64
392 | #   ifndef WIN64
393 | #      define WIN64
394 | #   endif
395 | #   define __x86_64__ 1
396 | #   define R__B64      /* enable when 64 bit machine */
397 | #endif

But I’m also working around with G4. In CLHEP/Random/MixMaxRng.h, there are:

166 | #if defined(__x86_64__)
167 |   myuint_t mod128(__uint128_t s);
168 |   myuint_t fmodmulM61(myuint_t cum, myuint_t a, myuint_t b);
169 | #else // on all other platforms, including 32-bit linux, PPC and PPC64, ARM and all Windows

These lines of code is protected by #if defined(__x86_64__). Obviously, this is to avoid involving
__uint128_t that does not exist on Windows. However, through the cooperation with ROOT/RConfig.h, this code is exposed and causes compilation error C2061: syntax error: identifier '__uint128_t' because __uint128_t is not defined.

I understand that it may be more convenient to introduce __x86_64__ on windows, but it does cause some problems. There is a way to solve the error I mentioned here, like globlally #define __uint128_t to some other things, but it just not perfect, and I am not sure whether this __x86_64__ will lead to more potential problems. Is there any better solutions? Or should this be considered a defect in ROOT or CLHEP? Could this lead to more potential problems?

Thanks for the help,

Try to “#include” everything you need from CLHEP (Geant4) before anything from ROOT.

Hi @ZhaoSH ,

welcome to the ROOT forum and thank you for the report.

So if I understand correctly:

  • ROOT defines __x86_64__ for Windows, as it’s not defined there
  • CLHEP assumes that if __x86_64__ is defined, then we are definitely not running on windows so we can use other stuff that’s not defined on Windows such as __uint128_t

On one hand ROOT defining such generic macros on Windows is tricky, on the other CLHEP could check for “are we on windows” more directly or could check for “is _uint128_t defined” as well.

@Axel @bellenot what do you think?


I’m convinced that we must not define __x86_64__; we need R__x86_64__ or similar and look at that instead inside ROOT.

Hello @eguiraud @Axel ,

Thanks for your reply! Yes, that’s exactly what I mean. I agree with @Axel that it seems unsafe to define __x86_64__ for windows inside ROOT, since __x86_64__ actually belongs to other platforms.

It is constructive to introduce some ROOT dialects, such as R__x86_64__ as proposed.


P.S. If we regard this as an issue of ROOT, do I need to report it elsewhere?

Hi @Wile_E_Coyote ,

Thanks for the reply! In fact, I am testing the cross-platform compatibility of a project, it’s interdependence inside is a little bit complex. Although the inclusion order of each file is correct (G4/CLHEP is included before any ROOT), not all files includes these two headers I mentioned at once, so there is no guarantee for the inclusion order of those two. However, the approach you proposed is certainly useful when there is only a single file, for example, ROOT macros.


I see 166 occurrences of __x86_64__ in 61 files in ROOT. I probably did define that on Windows 64 to avoid having yet another #define. Anyway, I’ll fix that

FYI, this should be fixed now in master by commit #250785e56ae and in v6-26-00-patches by commit #cbe71e917c5

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.