Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raylib doesn't build with windows.h #1217

Closed
ZelCloud opened this issue Apr 23, 2020 · 27 comments
Closed

Raylib doesn't build with windows.h #1217

ZelCloud opened this issue Apr 23, 2020 · 27 comments

Comments

@ZelCloud
Copy link

Raylib has a lot of same named functions to windows.h such as Rectangle, LoadImage, DrawText etc etc. Could we get some kind of workaround for this?

@scottmudge
Copy link

scottmudge commented Apr 23, 2020

Use CMake to generate a MSVS project file. I have just confirmed it compiles fine on Windows.

You'll tend to get those errors if you attempt to compile the raylib C files inside a separate C++ project.

The only other work around would be the use of namespaces, but that won't work with raylib given it's a C library, not a C++ library.

@ZelCloud
Copy link
Author

Hey @scottmudge , it compiles fine on windows by itself, the problem is when you're trying to compile it with the windows.h header for native window functions.

@raysan5
Copy link
Owner

raysan5 commented Apr 23, 2020

@ZelCloud you have three options to avoid conflicts:

  1. Definine the required symbols from windows.h instead of including the full header.

  2. Compile the windows.h with functions using it on an independent module/code-unit (a separate .c file to generate a separate .o) and link with it.

  3. Try to avoid conflics with windows.h defines:

#if defined(_WIN32)
// To avoid conflicting windows.h symbols with raylib, some flags are defined
// WARNING: Those flags avoid inclusion of some Win32 headers that could be required
// by user at some point and won't be included...
//-------------------------------------------------------------------------------------

// If defined, the following flags inhibit definition of the indicated items.
#define NOGDICAPMASKS     // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
#define NOVIRTUALKEYCODES // VK_*
#define NOWINMESSAGES     // WM_*, EM_*, LB_*, CB_*
#define NOWINSTYLES       // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
#define NOSYSMETRICS      // SM_*
#define NOMENUS           // MF_*
#define NOICONS           // IDI_*
#define NOKEYSTATES       // MK_*
#define NOSYSCOMMANDS     // SC_*
#define NORASTEROPS       // Binary and Tertiary raster ops
#define NOSHOWWINDOW      // SW_*
#define OEMRESOURCE       // OEM Resource values
#define NOATOM            // Atom Manager routines
#define NOCLIPBOARD       // Clipboard routines
#define NOCOLOR           // Screen colors
#define NOCTLMGR          // Control and Dialog routines
#define NODRAWTEXT        // DrawText() and DT_*
#define NOGDI             // All GDI defines and routines
#define NOKERNEL          // All KERNEL defines and routines
#define NOUSER            // All USER defines and routines
//#define NONLS             // All NLS defines and routines
#define NOMB              // MB_* and MessageBox()
#define NOMEMMGR          // GMEM_*, LMEM_*, GHND, LHND, associated routines
#define NOMETAFILE        // typedef METAFILEPICT
#define NOMINMAX          // Macros min(a,b) and max(a,b)
#define NOMSG             // typedef MSG and associated routines
#define NOOPENFILE        // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
#define NOSCROLL          // SB_* and scrolling routines
#define NOSERVICE         // All Service Controller routines, SERVICE_ equates, etc.
#define NOSOUND           // Sound driver routines
#define NOTEXTMETRIC      // typedef TEXTMETRIC and associated routines
#define NOWH              // SetWindowsHook and WH_*
#define NOWINOFFSETS      // GWL_*, GCL_*, associated routines
#define NOCOMM            // COMM driver routines
#define NOKANJI           // Kanji support stuff.
#define NOHELP            // Help engine interface.
#define NOPROFILER        // Profiler interface.
#define NODEFERWINDOWPOS  // DeferWindowPos routines
#define NOMCX             // Modem Configuration Extensions

// Type required before windows.h inclusion
typedef struct tagMSG *LPMSG;

#include <windows.h>

// Type required by some unused function...
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;
  LONG  biWidth;
  LONG  biHeight;
  WORD  biPlanes;
  WORD  biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG  biXPelsPerMeter;
  LONG  biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

#include <objbase.h>
#include <mmreg.h>
#include <mmsystem.h>

// Some required types defined for MSVC/TinyC compiler
#if defined(_MSC_VER) || defined(__TINYC__)
    #include "propidl.h"
#endif
#endif

@fctr
Copy link

fctr commented Aug 5, 2021

I've found a better solution:

#define WIN32_LEAN_AND_MEAN
#if defined(_WIN32)
#define WIN32
#endif
#if defined(_WIN64)
#define WIN64
#define _AMD64_
#undef _X86_
#else
#undef _AMD64_
#define _X86_
#endif

#include <minwindef.h>
#include <stdio.h>
#include <stdlib.h>

and change

int main()

to

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* pCmdLine, int nCmdShow)

@Availleight
Copy link

Hi,
I know this thread is dated but I think I might have a workaround using namespaces :
namespace raylib{ #include "raylib.h" }
Then include windows.h after this
Then use :
raylib::BeginDrawing();
raylib::ClearBackground(raylib::Color{255,255,255,255});
raylib::EndDrawing();
For exemple. Correct me if I made mistakes.

@orcmid
Copy link
Contributor

orcmid commented Jun 27, 2022

@Availleight See RobLoach/raylib-cpp#45

assuming you are using C++.

@KyrietS
Copy link

KyrietS commented Aug 18, 2022

For me this was enough to compile raylib with Windows.h (actually I needed raylib with spdlog library which includes Windows.h under the hood):

#if defined(_WIN32)           
	#define NOGDI             // All GDI defines and routines
	#define NOUSER            // All USER defines and routines
#endif

#include <Windows.h> // or any library that uses Windows.h

#if defined(_WIN32)           // raylib uses these names as function parameters
	#undef near
	#undef far
#endif

@fctr
Copy link

fctr commented Aug 18, 2022

For me this was enough to compile raylib with Windows.h (actually I needed raylib with spdlog library which includes Windows.h under the hood):

#if defined(_WIN32)           
	#define NOGDI             // All GDI defines and routines
	#define NOUSER            // All USER defines and routines
#endif

#include <Windows.h> // or any library that uses Windows.h

That is quite interesting, but is that for command line EXEs, or Windows GUIs?

@KyrietS
Copy link

KyrietS commented Aug 18, 2022

I can compile it with /SUBSYSTEM:CONSOLE and /SUBSYSTEM:WINDOWS (I'm using MSVC)

Also note: if you want to include raylib.h after including Windows.h then you also need to add:

#undef near
#undef far

Because raylib uses these two names as function parameters. (I've updated my answer above)

@fctr
Copy link

fctr commented Aug 18, 2022

I can compile it with /SUBSYSTEM:CONSOLE and /SUBSYSTEM:WINDOWS (I'm using MSVC)

Also note: if you want to include raylib.h after including Windows.h then you also need to add:

#undef near
#undef far

Because raylib uses these two names as function parameters. (I've updated my answer above)

So much for my superior knowledge. I guess after 45+ years as a programmer I've already peaked... 🤣

Thanks for keeping on top of this and keeping it SIMPLE.

@orcmid
Copy link
Contributor

orcmid commented Aug 18, 2022

Also note: if you want to include raylib.h after including Windows.h then you also need to add:

#undef near
#undef far

Because raylib uses these two names as function parameters. (I've updated my answer above)

So much for my superior knowledge. I guess after 45+ years as a programmer I've already peaked... 🤣

Thanks for keeping on top of this and keeping it SIMPLE.

Heading for my 65th anniversary as a programmer, I definitely have peaked :).

I am befuddled that windows.h got away with defining two lower-case preprocessor variables, near and far. I usually find this sort of cruft deep in the nest of stuff that windows.h pulls in. Adding new meaning to dependency hell.

@beetaa
Copy link

beetaa commented Nov 12, 2022

For me this was enough to compile raylib with Windows.h (actually I needed raylib with spdlog library which includes Windows.h under the hood):

#if defined(_WIN32)           
	#define NOGDI             // All GDI defines and routines
	#define NOUSER            // All USER defines and routines
#endif

#include <Windows.h> // or any library that uses Windows.h

#if defined(_WIN32)           // raylib uses these names as function parameters
	#undef near
	#undef far
#endif

thank you, it works and help me so much

@raysan5
Copy link
Owner

raysan5 commented Nov 27, 2022

@Staxcelrom thank you very much for your feedback! You are welcome! 👍🙂

@SiriusED
Copy link

SiriusED commented May 12, 2023

I had similar issue with my C++ project, and the best way I found was to just rename the functions. So for example I had issues with PlaySound() and CloseWuindow() functions.
So I just renamed them in this files, then rebuild raylib and build my application:
...YourProjectName\raylib-master\src\rcore.c
...YourProjectName\raylib-master\src\raylib.h
...YourProjectName\raylib-master\src\raudio.c

@KyrietS
Copy link

KyrietS commented May 12, 2023

Unfortunately I also ended up renaming the raylib functions and types in my own fork 😕
I spent days trying to compile Dear ImGui with Raylib and I finally gave up. There is no solution to this. Dear ImGui with Windows OpenGL backend includes <Windows.h> and it needs a ShowCursor function from Windows API. No matter what you do, linker will not let you build your program with both Windows' ShowCursor() and raylib's ShowCursor().

It is only one example. The complete list of renamings that I had to do in order to make raylib compile is as follows:

* near -> rl_near
* far -> rl_far
* Rectangle -> rl_Rectangle
* CloseWindow -> rl_CloseWindow
* ShowCursor -> rl_ShowCursor
* LoadImage -> rl_LoadImage
* DrawText -> rl_DrawText
* DrawTextEx -> rl_DrawTextEx
* PlaySound -> rl_PlaySound

@pineapplemachine
Copy link

pineapplemachine commented Sep 14, 2023

I also stumbled on this, so I wrote a Python script to automatically rename all public raylib declarations. It adds "Raylib" before function and type names, and "RAYLIB_" before define, macro, and enum member names. It is also able to update references in source files, in case you have existing dependencies using raylib.

So, for example, Rectangle becomes RaylibRectangle. FLAG_WINDOW_RESIZABLE becomes RAYLIB_FLAG_WINDOW_RESIZABLE.

The script is available here. So far it's tested with raylib 4.5.0 and building with PLATFORM=RAYLIB_PLATFORM_DESKTOP. (Note that PLATFORM_ETC defines are now named RAYLIB_PLATFORM_ETC.) Let me know with a @mention if you get any errors trying to use the script with other platforms or other versions of raylib and I'd be happy to take a look. Usage instructions are written at the beginning of the script.

https://github.com/pineapplemachine/unilevel/blob/master/scripts/raylib_rename.py

https://github.com/pineapplemachine/unilevel/blob/8bd7ff8899a967f6f6c11ff0748a95f4e23aeff4/scripts/raylib_rename.py

I'd really like to suggest that the next major version upgrade (4.x -> 5.x) should include adding an "rl" or "RL_" prefix to all public declarations, or something similar.

@orcmid
Copy link
Contributor

orcmid commented Sep 14, 2023

@pineapplemachine The problem is that such a 5.x would break all current raylib applications. I suspect that outweighs the occasional need for windows.h by a smaller number of users. And since raylib does not have bugfix releases (especially for previous versions), this is a rock-and-hard-place dilemma.

I also suppose this is not in the spirit of BGI, when there was no windows.h to compete with. Since raylib started out (at least) to be portable in the C Language sense, I am uncertain how this and the desire to be windows.h usable can be reconciled cleanly.

Not my problem to solve, fortunately. I wish Ramon the best in coping with these kinds of dependency conflicts.

@jamesl-github
Copy link

I wish Ramon would just prefix all functions and variables with rl_
or something similar
sdl does it, sfml does it, glfw does it I believe
they do it because C doesn't have namespaces like C++ does
I believe he has said he didn't do it because prefixing confused his students (and I find THAT confusing)
I know it would be breaking changes, but it really should be done

@raysan5
Copy link
Owner

raysan5 commented Sep 14, 2023

no plans for prefixes, sorry.

@Peter0x44
Copy link
Contributor

@orcmid it's simply impossible
windows.h is a badly behaved piece of shit that isn't worth including anyway
Just including it has a penalty of 0.7 seconds on compilation time, for me:

time printf "#include <windows.h>" | x86_64-w64-mingw32-gcc -x c - -c

real    0m0.722s

WIN32_LEAN_AND_MEAN does help, but not by very much:

time printf "#include <windows.h>" | x86_64-w64-mingw32-gcc -x c - -c -DWIN32_LEAN_AND_MEAN

real    0m0.468s

it's less than 0.3 seconds difference
Not to mention the huge symbol pollution, which is the cause of this issue in the first place
windows.h already has workarounds for existing collisions with... the C++ standard library!!!!
see NOMINMAX define. Perhaps someone should go bother microsoft and make them add:
NOCLOSEWINDOW
NORECTANGLE
NOLOADIMAGE
... and whatever else

coping with the "dependency conflicts" is trivial, and many strategies for doing it have been mentioned
my preference is to write the declarations from windows.h that I need manually on my own
it means I am not taking the compile time penalty for the rather underwhelming job windows.h does, very badly

https://nullprogram.com/blog/2023/05/31/
relevant resource on doing so

the separate translation including windows.h is the simplest option for people who don't want to bother with the slightly more tedious method described before
including both windows.h and raylib.h in the same TU seems to be very unreliable and absolutely not worth the trouble

@orcmid
Copy link
Contributor

orcmid commented Sep 15, 2023

@Peter0x44
LOL - The complete header has to be read and parsed either way. That's why precompiled headers were introduced, but I suspect that requires Visual Studio. I manage to avoid windows.h altogether. So far, I have not been punished for that sin.

Either way, trimming down to the sub-#includes that are of interest won't help with these Mexican Standoff name collisions at Link time.

@Peter0x44
Copy link
Contributor

Peter0x44 commented Sep 15, 2023

@orcmid

LOL - The complete header has to be read and parsed either way.

How can that be true if I don't include it?
About precompiled headers, gcc supports them too, but they are a compiler specific feature
They still don't fix the problem of it absolutely polluting the global namespace with junk like "near" "far" (apparently not relevant since 16 bit windows, which VS2022 can't even build), and the hundreds (maybe thousands) of irrelevant functions I will never call or think about
What link time collisions do you mean?

@orcmid
Copy link
Contributor

orcmid commented Sep 15, 2023

@Peter0x44

LOL - The complete header has to be read and parsed either way.

How can that be true if I don't include it?

I'm talking about the timing cases you tested.

What link time collisions do you mean?

The linker-time ShowCursor collisions that are a trigger for this issue.

@feivaoco
Copy link

feivaoco commented Nov 9, 2023

no plans for prefixes, sorry.
why

@huiseliming
Copy link

I cannot include the header files of cef and reylib in a cpp file because the header file of cef depends on the definition in winuser but Raylib must define NOUSER to remove him.

I don't understand why structures and functions are not prefixed with something like RL.

Macros can be used to enable/disable prefixed versions to maintain compatibility.

@joojn1122
Copy link

I found a simple solution:
You can just implement the function name with the types and it works like a charm!
No need to include windows.h.
extern "C" int __stdcall MessageBoxA(void* hWnd, const char* lpText, const char* lpCaption, unsigned int uType);

@Peter0x44
Copy link
Contributor

@joojn1122 I think to be fully correct, the declaration should also be __declspec(dllimport)
Though, with gcc you can get away without it. I would still recommend you put that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

17 participants