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

Support compiling Miniaudio under Cosmopolitan #495

Open
Keithcat1 opened this issue Jul 15, 2022 · 10 comments
Open

Support compiling Miniaudio under Cosmopolitan #495

Keithcat1 opened this issue Jul 15, 2022 · 10 comments

Comments

@Keithcat1
Copy link

Cosmopolitan is a C standard library that allows building statically linked binaries that run under Windows, Mac, Linux and a few other platforms all at the same time. Since it does not have an easy / good way to play audio (AKA Miniaudio) and Miniaudio is already cross-platform, it seems like it'd be a pretty good fit, however it might be a good bit of work. Since these binaries could run anywhere, it'd have to contain code for all supported backends, then at runtime we detect the platform and enable the right ones.
I believe Cosmopolitan wraps a lot of the Windows API and allows calling into it pretty easily but you'll get an error code at runtime if not on Windows. Don't know about anything else, but we link to those at runtime which might make things easier. Hopefully these links help:
Building actually portable executables on Windows
Cosmopolitan home page
Cosmopolitan on Github

@mackron
Copy link
Owner

mackron commented Jul 15, 2022

That is an interesting project. Have you tried compiling miniaudio with it as-is? If so, what errors did you encounter? miniaudio uses pre-processor macros for platform detection such as __linux__ and _WIN32. How does Cosmopolitan handle that situation?

@Keithcat1
Copy link
Author

Keithcat1 commented Jul 15, 2022

I did, and I only remember getting a lot of errors. I'll go set up my Cosmo environment and dump them all here if you want. I don't know about Cosmo platform macros. The Cosmo Github repository has a lot of examples. One of them displays a small GUI on Windows only and has the following code snippet:

int main(int argc, char *argv[]) {
  if (!IsWindows()) {
    fputs("Sorry! This GUI demo only runs on Windows\n", stderr);
    fputs("https://github.com/jart/cosmopolitan/issues/57\n", stderr);
    return 1;
  }
  Gui();
}

I imagine that macros like WIN32 would either be not defined or even if they were, they wouldn't be reliable since it can run on multiple platforms. Looks like platform detection is about as easy as it could be, assuming there are functions such as IsLinux and IsMacOs.

@mackron
Copy link
Owner

mackron commented Jul 15, 2022

I'd be curious to see the errors if possible. If there's a huge amount, maybe attach it as a text file.

This seems like an interesting project, but I'm a bit undecided at the moment. miniaudio depends very heavily on those platform detection macros for it's build system and I'm not sure the work involved to work around all that is worth it. I'll sit on this for a bit and think about it.

@Keithcat1
Copy link
Author

If you want a way to know when Miniaudio is compiling under Cosmopolitan, there's probably a 'cosmo' macro or something you can check at compile time. I'd be surprised if there wasn't one. I'm compiling the Cosmopolitan static library which is really large because it's full of Windows API stubs that are each in their own .O file so the linker, I believe, can remove dead code. A hello world binary is only about 40KB though, so it must be working. I'll get you the errors when it's done

@mackron
Copy link
Owner

mackron commented Mar 17, 2023

I've spent a few hours looking at this. I got it compiling at a very basic level, but there's a lot to consider here.

The first thing is the whole "cosmopolitan.h" thing. It looks to me that they want you to use that monolithic header for everything which does not work well for miniaudio because we need to use the standard include system for other compilers. To work around this, you'll need to use something like https://github.com/fabriziobertocci/cosmo-include and point the compiler to it with -I <path/to/cosmo-include>.

I pushed a fix for some general cross-platform compatibility issues, but this does not make it work cleanly across all platforms and all backends. For one, Cosmo does not support a lot of Win32 stuff from what I can tell, including common things like HANDLE and IID. This can certainly be worked around, but it'll be a lot of work. It would basically require us to eliminate the entire windows.h dependency, which considering there's 3 Windows backends, would be a ton of work and might introduce a fair bit of mess. It's the kind of thing that would need to be chipped away on over time.

As it stands in the dev branch right now, I believe only the PulseAudio, JACK and null backends work. The ALSA backend depends on eventfd() which is not supported by Cosmo at the moment by the looks of it. I believe that specifically could be replaced with a pipe, but considering a pipe is less efficient and ALSA will only be running on Linux in practice, I'm not sure I want to change that. It's something to consider going forward if I want to seriously support Cosmo.

The BSD platforms all depend on some platform-specific audio headers which I don't believe are supported by Cosmo so they would need some work to get working as well.

Android, iOS/macOS and Web will never be supported due to too many dependencies on platform-specific code.

@mackron
Copy link
Owner

mackron commented Mar 18, 2023

I've played around with this a bit more and unfortunately it looks like it's not going to work. I got it compiling with all three Windows backends (WASAPI, DirectSound and WinMM), but it doesn't run. miniaudio makes extensive use of dlopen(), etc. to dynamically link to shared objects at runtime. Unfortunately it appears the Cosmopolitan libc library does not implement dlopen() and family: https://github.com/jart/cosmopolitan/blob/master/libc/runtime/ldso.c. Without this it's unworkable with miniaudio.

I think the Cosmopolitan project needs time to mature before taking it too seriously in miniaudio. There's a lot missing from their Windows headers as a start. They also need to make it work better as a drop-in replacement for GCC before it'll be truly useful. If they add support for dlopen(), etc. and eventfd() I might take another look at this in the future, but for now I'm going to go ahead and close this issue.

The code as it stands at the time of writing will compile, but I won't be putting any active effort into maintaining it.

@mackron mackron closed this as completed Mar 18, 2023
mackron added a commit that referenced this issue Mar 18, 2023
@Keithcat1
Copy link
Author

Thanks for the work. Instead of using cosmopolitan.h, there are libc-like headers in https://github.com/jart/cosmopolitan/tree/master/libc/isystem.
I thought it at least exposes LoadLibrary on Window though.s

@mackron
Copy link
Owner

mackron commented Mar 20, 2023

Yes they've got LoadLibrary(), but there's two issues. The first being that when you compile it needs to detect both Win32 and POSIX and I've got it set up so that POSIX code is always prioritized over Win32 code when compiling with Cosmo which means dlopen() will be what's used. The second is that I need dlopen() for non-Windows builds anyway.

I wasn't aware of that isystem thing, but good to know. Thanks. I scratch my head as to why that's not the default option...

@jart
Copy link

jart commented Feb 21, 2024

Cosmopolitan author here. I'm looking into what needs to change on our end to get miniaudio working well with cosmocc (see https://justine.lol/cosmo3/) because https://github.com/Mozilla-Ocho/llamafile/ has need of this. One of the things I noticed for example is that you want #include <Windows.h> which got removed because it confused UNIX ./configure scripts. I can resurrect it as #include <windowsesque.h>.

@mackron
Copy link
Owner

mackron commented Feb 21, 2024

It's been a long while since I experimented with Cosmo so I can't remember the exact details, but miniaudio uses dynamic linking at runtime via dlopen() and LoadLibrary() which were not implemented at the time. If I remember correctly they were just stubs - have they since been implemented?

Also, I think from memory the windows headers were very incomplete, but I suspect that at the time the pre-packaged SDK might have been out of date and therefore I was using an old version. Not sure how that's changed since.

I'm happy to reopen this and revisit Cosmo when I get a chance.

@mackron mackron reopened this Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants