Building without _CRT_NONSTDC_NO_WARNINGS
results in warnings with MSVC:
1>C:\Users\manx\projects\openmpt\wc\trunk-2\include\mpg123\src\libmpg123\lfs_wrap.c(140,3): warning C4996: 'close': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _close. See online help for details.
1>C:\Users\manx\projects\openmpt\wc\trunk-2\include\mpg123\src\libmpg123\lfs_wrap.c(764,9): warning C4996: 'lseek': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _lseek. See online help for details.
1>C:\Users\manx\projects\openmpt\wc\trunk-2\include\mpg123\src\libmpg123\lfs_wrap.c(871,9): warning C4996: 'read': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _read. See online help for details.
1>C:\Users\manx\projects\openmpt\wc\trunk-2\include\mpg123\src\libmpg123\lfs_wrap.c(905,46): warning C4996: 'lseek': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _lseek. See online help for details.
1>C:\Users\manx\projects\openmpt\wc\trunk-2\include\mpg123\src\compat\compat.c(141,9): warning C4996: 'fdopen': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name: _fdopen. See online help for details.
These are completely harmless and I generally just compile everything with _CRT_NONSTDC_NO_WARNINGS
defined. Microsoft recommends (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/lseek?view=msvc-170) using _
-prefixed names though, i.e. _lseek
instead of lseek
.
Normally, I would not care, however when building for ARM64EC (which is different ABI for ARM64 with the same alignment requirements as AMD64 to allow mixing ARM64EC and AMD64 code inside the same process, https://learn.microsoft.com/en-us/windows/arm/arm64ec), I additionally see the following warning:
1>LINK : warning LNK4286: symbol 'lseek' defined in 'ucrt.lib(api-ms-win-crt-stdio-l1-1-0.dll)' is imported by 'lfs_wrap.obj'
See https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/linker-tools-warning-lnk4286?view=msvc-170, which is not exactly really useful.
The warning goes away when using _lseek
instead. I tend to suspect this is actually a bug in Microsofts C library (UCRT) for ARM64EC, however I really do not know if it causes any real harm.
Would you consider using the Microsoft-recommended names, at least when building against UCRT (_UCRT
defined after including any standard C library header)? These names also work and avoid warnings for the C libraries included with MSVC versions before VS2015. I do not remember if they already existed even with VS6 MSVCRT. Detecting these earlier C libraries reliably is more difficult though.
This issue is nothing new. What's new here is me trying to build for ARM64EC.
What about building with --enable-portable? You only need decoding, not file I/O?
Im kinda sick of this political game of Microsoft, suggesting the POSIX names are in
conflict with ISO C.
--
sent from mobile device, trustworthy or not
These are not the warnings I am concerned about. I only mentioned that for context and explanation of the work-around/solution. The linker warning is independent of Microsoft's opinions regarding POSIX, and may at the root well be a bug in their ARM64EC UCRT. I would still prefer if libmpg123 would not require patching to be compilable without warnings for ARM64EC.
Sure, that would work-around the problem for me. However, if you start recommending that for every MSVC compatibility issue, you effectively require the portable API to be used by anyone, otherwise client code would not be portable to MSVC any more. In this case, (A) I very strongly suggest you officially break the API and ABI and never build the old POSIX-dependent interface anywhere by default, or at the very least deprecate it loudly (i.e. by a forced compiler deprecation warning). If the old API is supposed to be usable with MSVC, (B) compatibility issues should still get fixed.
It's either A or B. Anything in-between really does not make much sense to me.
I can provide a patch if desired.
Well, messing up use of plain lseek counts as part of the same game to me. But let's get down to the technical. We're only talking about this code, right?
With the corollary of
off64_t
being a thing or not. Since we contained all specific API already so far. I'd be fine with some path there for both_lseeki64
and_lseek
with explicit cast to long.Are you up to making (and crucially, testing) a patch of the
configure.ac
andports/cmake/src/CMakeLists.txt
parts to detect the MSVC variant ofLFS_LARGEFILE_64
, probably typedef ofoff64_t
toint64_t
while at that, and then have thelfs_wrap.c
code use the MSVC way for non-largefile and 64 bit access? The configure test could just skimp on the actual testing and check the platform string. Even better if it doesn't run needless tests on a POSIX system.With all the specific stuff contained in the LFS wrapper code, it indeed shouldn't be that hard. I expect minimal changes there. Remaining plain POSIX stuff in the mpg123 applications shouldn't bother MSVC library users.
I think we should not just do a hack to use
_lseek
instead oflseek
, but support proper 64 bit offsets while at that.Last edit: Thomas Orgis 2024-10-27
I honestly do not see how this would work.
The old
_64
-suffixed API functions assume aliasing ofoff_t
andoff64_t
iffoff_t
is 64bit, or a distinct 64bitoff64_t
otherwise.off_t
will always be 32bit with MSVC, and libmpg123 should never invent/define anyoff64_t
in a public API header itself. This would break immediately if any other library does the same thing. So, if the public API can neither change nor be extended (with the existing_64
-suffixed functions), is there any point in calling_lseeki64
at all (I may well be missing some call paths here, that code is not exactly easy to follow :))? If there is, would just calling_lseeki64
instead of_lseek
ininternal_lseek64
do the trick, or is more of theLFS_LARGEFILE_64
machinery needed? I also fail to see any benefit in inventing new_64
-suffixed declarations just for MSVC usingint64_t
instead ofoff64_t
. The portable API already covers this case in a way better way.Neither calling
_lseeki64
nor_lseek
ininternal_lseek64
would require any change in CMake or Autoconf, instead it would even consolidate some incomplete checks already done for_open
.Draft patch attached.
Without yet having looked at the patch (just read your message in the train), I want to make more clear what I meant: I was talking about
_lseeki64()
and some kind ofoff64_t
usage inlfs_wrap.c
only. This is the one place that implements seeks for any public API.Looking again … indeed, there should be no need to define any
off64_t
on MSVC. There is public 32 bit ABI withoff_t
, mapping to the_32
functions inlfs_wrap.c
.All further code paths use
int64_t
internally to pass things around.We just need
int64_t internal_lseek64()
implemented to trigger a 64 bit seek if it is available and check thatint INT123_wrap_open()
does the right thing throughINT123_compat_open()
to enable largefile support.This will only be usable through the
int64_t
API, not aoff_t
. This is the nature of things on a platform that doesn't do largefileoff_t
. We won't change that. But if there is explicit 64 bit API and we adapt to MSVC/CRT specifics, it would be strange not to enable 64 bit offsets internally.Now looking at what you proposed … looks a lot like what I described above;-)
I think I'd rather
for the trivial ones up top. Less noise in the code. But for the plain
_lseek()
, I rather see the explicit call because it strictly is not the same prototype thanlseek()
.We know that
offset < OFF_MIN || offset > OFF_MAX
will also be correct forlong
here … but maybe that bit should also be duplicated for clarity and coverLONG_MIN
andLONG_MAX
instead. It is a bit silly, but compilers are complaining about types that are identical but called differently nowadays. Speaking of which …The
r_lseek
pointer is usingoff_t
in the prototype, not matching_lseek()
. I guess we need a pointlessfallback_lseek()
wrapper just likefallback_read()
to ensure the pointer type matches. And yes, I guess I should add an explicit cast and possibly even an overflow check tofallback_read()
byte count argument.But all in all … I guess this should be it to fix the build and by the way enable a possible 64 bit offset code path in the iternal I/O that used to only do 32 bits. Counts as a bug fix, even, in my book.
Last edit: Thomas Orgis 2024-10-28
Is there no extra flag needed to make
_open()
open the file in 64 bit mode?I really do not like
at all. That would be redefining names that do not belong to mpg123.
Yeah, that was already wrong before for MSVCRT
lseek()
, which also useslong
. Fixed.No. MSVCRT does not need that.
O_LARGEFILE
(and friends) qualify as one of the most stupid API design decisions in the history of computing for me. It's solely a POSIX-ism, and frankly makes no sense.Fixed.
And I guess also
internal_read64()
.OK. Committed … with a bit of tweaking on top (attached). Does this work fine for you?
Yeah, works for me.
Looks like I missing switching to
#if defined(MPG123_COMPAT_MSVCRT_IO)
inINT123_compat_close
. Can you do that as well?OK, like that in trunk? We didn't discuss much the switch from
WIN32
to the more specific compiler identities. You think that's safer and some other runtime that doesn't defineUCRT
will also not share its peculiarities?I think the "demanding to use the
_
-variants" is Microsoft specific, I am not aware of any situation where the POSIX names do not exist while the_
-variants do exist.I really do not know if "
_WIN32
implies_
-variants" holds true in all situations, so defaulting to the POSIX names by default is probably a more conservative approach. Assuming all Windows C libraries are implementing_
-variants sounds somewhat fragile to me.On the other hand, with the current state there is a risk of missing some C libraries that mimic Microsoft's implementation (not a regression compared to what was there before, though).
Looking at documentation only, it looks like Watcom also provides the Microsoft-style names and would still be missing 64bit support. I do not have any deep experience with Watcom though.
Patch attached, based on https://open-watcom.github.io/open-watcom-v2-wikidocs/clib.pdf, https://en.wikipedia.org/wiki/Watcom_C/C%2B%2B#Release_history, https://open-watcom.github.io/open-watcom-v2-wikidocs/clr.html#Open_Watcom_CD16_and_CD32_Predefined_Macros, and https://github.com/cpredef/predef/blob/master/Compilers.md#watcom-c.
I do not know if Watcom's C/C99 support is even sufficient to build libmpg123.
Also, Watcom is using
off_t
like in POSIX instead of Microsoft'slong
. Making every situation hyper-correct is probably not worth the effort here, though.I guess you could add Autoconf and CMake checks for the
i64
variants if you really want to catch all situations.What I do know is: the 64bit variant is not available in all situations I care about. In particular not with MinGW targeting CRTDLL (the C library shipped with the first release of Windows 95).
OK, applied. But we indeed should not spend too much work on platforms we don't really test.
Diff: