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

Printing to stdout/stderr fails with SDL import on Windows #86

Open
nxths opened this issue Sep 16, 2015 · 22 comments
Open

Printing to stdout/stderr fails with SDL import on Windows #86

nxths opened this issue Sep 16, 2015 · 22 comments
Labels

Comments

@nxths
Copy link
Contributor

nxths commented Sep 16, 2015

When importing SDL the following program will no longer print anything:

module Main
    where

import qualified SDL

main :: IO ()
main = print "5"

Removing the SDL import will print as expected. My linux box's 256MB of ram is insufficient to compile the bindings so I'm assuming this issue is Windows only otherwise someone would have already noticed. I installed the bindings on Windows with these steps.

Most likely the stdout/stderr (and probably stdin) handles are getting clobbered somewhere, causing the apparent no-op? Replacing the print in the above program w/ trace similarly yields no output. Not that familiar w/ the FFI, but do the handles need to be explicitly preserved when interfacing w/ C code (e.g. SDL2)? Creating new file handles and reading/writing to them do not have any issues w/ the SDL import, fwiw

@akhra
Copy link
Collaborator

akhra commented Sep 16, 2015

Can't reproduce:

D:\>type main.hs
module Main
    where

import qualified SDL

main :: IO ()
main = print "5"
D:\>ghc main
[1 of 1] Compiling Main             ( main.hs, main.o )
Linking main.exe ...

D:\>main
"5"

I used an MSYS2 package install for SDL rather than those steps, but I don't think that's relevant -- it's the same library (right down to needing that replacement SDL_platform.h) and if anything were broken you'd be getting an error rather than nothing.

On the other hand, I'm using all 64-bit, and if you followed those instructions 100% you're using 32-bit. It's definitely plausible for there to be a bug in one but not the other. If that's not it, a broader inspection of the differences in our configurations might be helpful, though I'm honestly not sure what to look for.

@nxths
Copy link
Contributor Author

nxths commented Sep 16, 2015

Hmm I tried reinstalling sdl2 w/ 64-bit GHC + libraries w/ the instructions above but running the above program yields the same result, not printing anything. Are you using the v2.0.0 bindings @tejon?

@polarina
Copy link
Member

At a quick glance, this looks a lot more like an issue with your tooling/compiler than something in sdl2. The sdl2 library doesn't execute any code at all when simply imported.

@akhra
Copy link
Collaborator

akhra commented Sep 17, 2015

Everything I have was installed fresh yesterday, from github. Bleeding-edge current. :)

What happens if you import some other module? Try split for one with no dependencies at all, and if that's fine maybe postgresql-simple for something with a binary dependency that's easy to install on Windows.

@nxths
Copy link
Contributor Author

nxths commented Sep 17, 2015

@tejon changing the import to Data.List.Split, or Linear or Control.Lens all builds and runs printing the output as expected, it's only the SDL import that's no-oping. Note that I am building with ghc --make Main.hs which should be pulling in all the dependencies automatically.

Oddly in ghci I can import SDL and then running print does output as expected.

@polarina I checked the source and you're right I don't see any code running. This is very confusing

@redxaxder
Copy link

I have the same issue on windows 7 building with GHC 7.10.2.

The problem occurs with both 32 bit and 64 bit SDL. The files I used to build are here: https://www.sendspace.com/file/xxg33j
It also includesthe SDL files I used. (http://libsdl.org/release/SDL2-devel-2.0.3-mingw.tar.gz with SDL_platform.h replaced by https://hg.libsdl.org/SDL/raw-file/e217ed463f25/include/SDL_platform.h).

The wacky_***_.bat files build/run the examples and all four of them reproduce the problem on my machine.

@ocharles
Copy link
Member

Thanks. I have a window machine now so may be able to work on this.

On Mon, 9 Nov 2015 11:38 pm redxaxder notifications@github.com wrote:

I have the same issue on windows 7 building with GHC 7.10.2.

The problem occurs with both 32 bit and 64 bit SDL. The files I used to
build are here: https://www.sendspace.com/file/xxg33j
It also includesthe SDL files I used. (
http://libsdl.org/release/SDL2-devel-2.0.3-mingw.tar.gz with
SDL_platform.h replaced by
https://hg.libsdl.org/SDL/raw-file/e217ed463f25/include/SDL_platform.h).

The wacky____*.bat files build/run the examples and all four of them
reproduce the problem on my machine.


Reply to this email directly or view it on GitHub
#86 (comment).

@redxaxder
Copy link

It seems this is an intentional SDL feature: http://sdl.beuc.net/sdl.wiki/FAQ_Console

A workaround is for windows users to recompile SDL with the right incantation.

However, the import shouldn't be triggering this behavior for sure. I'd guess there's a call to SDL_Init() hiding in the top level of the Haskell bindings.

@polarina
Copy link
Member

@redxaxder just importing a package shouldn't evaluate any top-level declarations, even with unsafePerformIO and other shenanigans. I find this issue to be strange.

@ivanperez-keera
Copy link

Hi

Could SDL2 be redefining a symbol? (for example, SDL2 defines main)

Does the same thing happen if you use dynamic vs static linking? (the
linker might prefer SDL2's function, but if you load it dynamically, it
might not.)

Ivan

On 16/09/15 21:41, nxths wrote:

When importing SDL the following program will no longer print anything:

module Main
where

import qualified SDL

main :: IO ()
main =print "5"

Removing the SDL import will print as expected. My linux box's 256MB
of ram is insufficient to compile the bindings so I'm assuming this
issue is Windows only otherwise someone would have already noticed. I
installed the bindings on Windows with these steps
https://www.reddit.com/r/haskellgamedev/comments/3kvm7z/building_and_installing_sdl2_200_sdl2image/.

Most likely the stdout/stderr (and probably stdin) handles are getting
clobbered somewhere, causing the apparent no-op? Replacing the print
in the above program w/ trace similarly yields no output. Not that
familiar w/ the FFI, but do the handles need to be explicitly
preserved when interfacing w/ C code (e.g. SDL2)? Creating new file
handles and reading/writing to them do not have any issues w/ the SDL
import, fwiw


Reply to this email directly or view it on GitHub
#86.

@alandao
Copy link

alandao commented Dec 8, 2015

I have this problem too. I'm on Windows 10 64-bit with 64-bit GHC and SDL2 2.03.

EDIT:
Also when I add "sdl2" to my build-depends in cabal it stops console output as well.

@nxths
Copy link
Contributor Author

nxths commented Jun 3, 2016

I don't have this issue anymore when installing SDL2 2.0.4 w/ stack, following https://www.reddit.com/r/haskellgamedev/comments/4jpthu/windows_sdl2_is_now_almost_painless_via_stack/

@akhra
Copy link
Collaborator

akhra commented Sep 6, 2016

Closing since this is reported fixed.

@akhra akhra closed this as completed Sep 6, 2016
@Invisible-Rabbit-Hunter
Copy link

I am experiencing the same problem on windows 10, even when I installed via stack as explained in the post linked to by @nxths.

@LukaHorvat
Copy link

Same issue here with the latest sdl2, Windows 10 64bit.

@ocharles ocharles reopened this Sep 1, 2018
@cronokirby
Copy link

Same issue on win7 64 bit

@ghost
Copy link

ghost commented Feb 10, 2019

This issue stems from the user's system configuration of SDL2.

For my case, I installed SDL2 via msys2 (mingw64) and have the mingw64 tools in my path such that they come before Haskell Platform's mingw64 binaries.

My guess was that cabal would use pkg-config to set up external libraries, so I found the SDL pkg-config file for mingw64: /mingw64/lib/pkgconfig/sdl2.pc (somewhere in your msys install directory like C:\msys64\mingw64\lib\pkgconfig\sdl2.pc).

For whatever reason, the mingw64 package is set with the option -mwindows, which will treat the final build as a Windows application (no console opened):

Libs: -L${libdir}  -lmingw32 -lSDL2main -lSDL2  -mwindows

So you can supersede this option by appending -mconsole like so:

Libs: -L${libdir}  -lmingw32 -lSDL2main -lSDL2  -mwindows -mconsole

Then in my cabal store, I deleted sdl2 to force it to reinstall with this changed configuration:

C:\Users\cro\AppData\Roaming\cabal\store\ghc-8.4.3\sdl2-2.4.1.0-669a3c6f96fa5560671e7a96610a5f0b374d164f

Rerunning the build. Note the final line is some putStrLn from my program:

C:\Users\cro\Dropbox\Projects\distfun-hs>cabal new-run
Build profile: -w ghc-8.4.3 -O1
In order, the following will be built (use -v for more details):
 - sdl2-2.4.1.0 (lib) (requires build)
 - distfun-0.1.0.0 (exe:distfun) (dependency rebuilt)
Configuring sdl2-2.4.1.0 (lib)...
Building sdl2-2.4.1.0 (lib)...
ignoring (possibly broken) abi-depends field for packages
Preprocessing executable 'distfun' for distfun-0.1.0.0..
Building executable 'distfun' for distfun-0.1.0.0..
Linking C:\Users\cro\Dropbox\Projects\distfun-hs\dist-newstyle\build\x86_64-windows\ghc-8.4.3\distfun-0.1.0.0\x\distfun\build\distfun\distfun.exe ...
PROGRAM OK

I do not know how to set up my own cabal files such that dependent libraries are passed cc-options but I figure a more flexible option would start there. Or perhaps a configuration setting in this library that passes -mconsole on to the C compiler.

@ghost
Copy link

ghost commented Feb 10, 2019

With a little extra research, I found that linking is done with ghc, so the flag can be passed with ghc-options (see haskell/cabal#1865).

In my project's cabal file I added:

ghc-options: -optl-mconsole

Or from the command line:

cabal new-run --ghc-options="-optl-mconsole"

Of course if you did any of the above that I suggested in the previous comment, undo that and delete sdl2 from the cabal store again.

@ghost
Copy link

ghost commented Feb 10, 2019

Another caveat, cabal new* seems to have some issues and this option could get stuck on. Use this to get the Windows behavior back:

cabal new-run --ghc-options="-optl-mwindows"

@costructuralist
Copy link

I'm using stack, and adding -optl-mconsole and -optl-mwindows to ghc-options for the executable in the package.yaml file worked, but only after deleting the .stack-work directory in the project's root.

My project is using sdl2-2.5.0.0.

Thanks @cromachina!

@expipiplus1
Copy link
Contributor

Is there any way to make this the default behaviour for programs using this package? The behaviour is very surprising, and the plerthora of ghc/windows/utf8/crummy-cmd.exe bugs provide plenty of red herrings when trying to troubleshoot the exceptions thrown and messages not printed.

Perhaps a visible notice in the readme could help if there's no technical solution.

@chansey97
Copy link

chansey97 commented Feb 17, 2024

I'm using stack, and adding -optl-mconsole and -optl-mwindows to ghc-options for the executable in the package.yaml file

Just turn on -optl-mconsole for the executable is OK.

Don't add -optl-mwindows. It will cause "ERROR: stdout: commitBuffer: invalid argument (Bad file descriptor)". https://stackoverflow.com/questions/59831702/create-a-windows-executable-that-does-not-create-a-console-window

For cabal, we must delete your-project\dist-newstyle\build\x86_64-windows\ghc-xxx\your-project\x\some-executable before build.

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

No branches or pull requests