SDL_stdinc.h inlines problematic when application not compiled in exact same feature environment

not compiled in exact same feature environment
Message-ID: <20130613231058.GA7385 at quail.dasyatidae.internal>
Content-Type: text/plain; charset=us-ascii

Quoth Sik the hedgehog <sik.the.hedgehog at gmail.com>, on 2013-06-13 05:54:39
-0300:

In other words, it means that for some reason SDL is being told those
functions exist, but the system headers say otherwise. Maybe that’s
the issue? Note that on some platforms the system headers will declare
functions depending on the standards mode in use.

This is pretty much what I said upthread regarding different
compilation environments for the SDL library and its consumer. Sorry
if I was unclear.

My main question for upstream is in what ways consumers of SDL rely on
the SDL_-prefixed versions of these functions (either in the explicit
API or /de facto/). I’d prefer to be able to drop them from my
compilation environment completely, either by default or with a macro
setting. My current feeling from looking at SDL_stdinc.h is that that
whole pile is mainly intended for use within SDL and therefore
exposing all this transitive dependency to consumers is unintentional.

The setenv function might be required on some platforms to prepare the
local environment before loading libraries that depend on it. In which
case, you really might as well expose it to the programmer. It’s
"conventional" use would be to communicate with programs that you’ll
be launching (directly or otherwise) from the program that uses
setenv. I think the “launch” step could be done with C’s system()
function, and I have some incomplete code to provide SDL with a
pipe-command system, so this is actually something that could come up.

Theoretically.

Eventually.

Maybe.

Theoretical uses for the function would be launcher programs
(SDLTerminal, anyone?), and programs that (bear in mind, I don’t claim
to know why you would want to do things like this) detect the current
environment in a STRICT sense, and then re-start themselves
accordingly.> Date: Thu, 13 Jun 2013 18:10:58 -0500

From: Drake Wilson
To: SDL Development List
Subject: Re: [SDL] SDL_stdinc.h inlines problematic when application

Quoth Jared Maddox , on 2013-06-13 21:37:52 -0500:

The setenv function might be required on some platforms to prepare the
local environment before loading libraries that depend on it.

Well, in that case there’s actually a specific use, namely that SDL
itself can pick up on environment variables at init time (which is
after process start time), and so using SDL_-prefixed versions of
envvar manipulation functions to massage them seemed popular at least
for 1.2 for things like defaulting to centered window placement or
fiddling with which audio device to use (hopefully being sure not to
override the user).

(That’s not performance-sensitive enough for the inlining to be a
significant win, though.)

—> Drake Wilson

I don’t have a link handy, Google will find one. You can
also get online copies of the draft C++ standards (but not
the final one).

Sorry, but the burden of proof is the responsibility of the accuser :wink:

I’m not required to prove it tho :slight_smile:

And as a former member of ISO/IEC/SC22/WG21 for over a decade
and WG14 for a year I have learned a little about conformance issues.On 14/06/2013, at 7:18 AM, Nikos Chantziaras wrote:


john skaller
@john_skaller
http://felix-lang.org

…is this going off-topic?

I don’t think so: the issues we’re discussing (whether Sam takes
any notice or not) regard where to position SDL in terms of
specifications.

If SDL mandates C99, the relevant C++ TR, then
testing for “int32_t” in the standard headers is not
only not required … its wrong.

And clearly it matters to game developers using SDL who
may have issues with multiple libraries being used by their
app, what switches they have to use to set the standards
base of their compiler tool.

I think this discussion is highly revelant at this point in time
because SDL 2.X.Y family is about to be released and it already
breaks SDL 1.X.Y family. So now is the time to make any
changes in respect of requirements and demands on
compilers. In todays more complex world, one can expect
lots of libraries to be used in an app, and getting them to
play together is no mean feat.On 14/06/2013, at 7:29 AM, Sik the hedgehog wrote:


john skaller
@john_skaller
http://felix-lang.org

2013/6/14, john skaller :

If SDL mandates C99, the relevant C++ TR, then
testing for “int32_t” in the standard headers is not
only not required … its wrong.

I think SDL still supports pre-C99, so don’t count on that. In
particular, Visual Studio 2008 is… rather horrible in that sense.
And yes, many people still use that.

SDL_stdinc.h is designed to provide all the C library functionality used by
SDL, for platforms that don’t have the standard C library, or where you
don’t want C library dependencies for some reason.

I made a change so you can define SDL_STDINC_NO_INLINES, and SDL_stdinc.h
won’t define inline versions of the C library functions it provides.

Cheers!On Mon, Jun 10, 2013 at 8:39 PM, Drake Wilson wrote:

This is “interesting” behavior (and breaks my build, but then, I’m doing
something a bit weird):

I’m building SDL 2.0.0 on my main development box, which runs Debian sid
AMD64
with GCC 4.7.3 (Debian 4.7.3-4). The autoconf-based configure for it
detects
functions like strdup and setenv being available, which they are,
provided
the correct feature test macros are active. However, trying to build a
test
application results in:

SDL_stdinc.h: In function ?SDL_setenv_inline?:
SDL_stdinc.h:282:1: error: implicit declaration of function ?setenv?
[-Werror=implicit-function-declaration]
SDL_stdinc.h: In function ?SDL_strdup_inline?:
SDL_stdinc.h:485:1: error: implicit declaration of function ?strdup?
[-Werror=implicit-function-declaration]
SDL_stdinc.h:485:61: error: return makes pointer from integer without a
cast [-Werror]

I’m guessing this is because I’m compiling my application with -std=c99.
If I
use -std=gnu99, for instance, the errors go away, but don’t I lose my more
explicit portability control that way. I’d just as soon not have so much
transitive header cruft anyway (cf. SDL_syswm.h not being included by
default),
but a lot of the public headers depend on SDL_stdinc.h; a cursory glance
suggests that they mainly depend on it for types, so I’m not sure why all
the
inlines are stuffed in there too.

My current intended workaround is to just strip all the inline functions
from
that file manually, but this seems fragile as well and might wind up
requiring
me to keep a local fork if I juggle build environments enough.

Any recommendation on how best to handle this?

—> Drake Wilson


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I am not at all interested in being told by john skaller et al. that
my problem is irrelevant because I should be using C++ instead.

I think you must have misunderstood my comments entirely.

I agree with you completely. I simply observe that C++ is a better
standard than fixing C89 or C99. IF it had been chosen things
would be easier.

The question now is what standard to choose.

It is in fact YOU that objects to the current choice, namely
the one implied by

-D_GNU_SOURCE

and I entirely agree.

Nor
am I interested in screwing with the feature test macro rules of one
of my main target platforms. If the API is going to really state “you
have to compile under the same conditions as SDL itself and we won’t
bother minimizing it”, I don’t like that, but I’ll accept it and use
a minor local fork if that’s the authoritative answer.

This depends on what is in the header files.

If the headers use inline function with “inline” keyword,
C89 is out. C++ and C99 both support “inline” keyword.

If the headers use macros, there’s a possibility of a clash.

Unfortunately, it is not possible to define and undefine
macros safely since previous definitions might exist.
The workaround is to use a prefix.

So you could #define SDL_inline … then #undef at the end
of the headers to conditionally support inline keyword.

SDL does something more grotesque, it defines SDL_function’s
as macros AND as functions. The macro definition contains
the body so if the macro is set, you get inlining. If you want
the address of the function, or just external linkage you can
#undef the macro or define it as itself.

With functions defined in that style your argument about them not
being defined unless used would not hold: the functions are always
defined, its just that if the macro is called it doesn’t expand
to calling the function but to replacing the macro with the
body of the function. Either way, the function is defined.On 14/06/2013, at 9:10 AM, Drake Wilson wrote:


john skaller
@john_skaller
http://felix-lang.org

Theoretical uses for the function would be launcher programs
(SDLTerminal, anyone?),

Actually … I am seriously thinking of that :slight_smile:

I was actually thinking about an X11 environment and how
to feed local client keypresses to a server on another box,
and have it make OpenGL calls that get transported back
to the client … so your SDL application could actually run
on a remote server.–
john skaller
@john_skaller
http://felix-lang.org

You know… I’m surprised nobody mentioned that these days toolchains
can do inline optimization cross object boundaries (inline linking).
Wouldn’t that render explicit inline functions useless? (seriously,
inline lost its usefulness long ago as compiler now ignore it and just
use heuristics - it’s pretty much in the same boat as the register
keyword)

2013/6/14, john skaller :>

On 14/06/2013, at 9:10 AM, Drake Wilson wrote:

I am not at all interested in being told by john skaller et al. that
my problem is irrelevant because I should be using C++ instead.

I think you must have misunderstood my comments entirely.

I agree with you completely. I simply observe that C++ is a better
standard than fixing C89 or C99. IF it had been chosen things
would be easier.

The question now is what standard to choose.

It is in fact YOU that objects to the current choice, namely
the one implied by

-D_GNU_SOURCE

and I entirely agree.

Nor
am I interested in screwing with the feature test macro rules of one
of my main target platforms. If the API is going to really state “you
have to compile under the same conditions as SDL itself and we won’t
bother minimizing it”, I don’t like that, but I’ll accept it and use
a minor local fork if that’s the authoritative answer.

This depends on what is in the header files.

If the headers use inline function with “inline” keyword,
C89 is out. C++ and C99 both support “inline” keyword.

If the headers use macros, there’s a possibility of a clash.

Unfortunately, it is not possible to define and undefine
macros safely since previous definitions might exist.
The workaround is to use a prefix.

So you could #define SDL_inline … then #undef at the end
of the headers to conditionally support inline keyword.

SDL does something more grotesque, it defines SDL_function’s
as macros AND as functions. The macro definition contains
the body so if the macro is set, you get inlining. If you want
the address of the function, or just external linkage you can
#undef the macro or define it as itself.

With functions defined in that style your argument about them not
being defined unless used would not hold: the functions are always
defined, its just that if the macro is called it doesn’t expand
to calling the function but to replacing the macro with the
body of the function. Either way, the function is defined.


john skaller
skaller at users.sourceforge.net
http://felix-lang.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

You know… I’m surprised nobody mentioned that these days toolchains
can do inline optimization cross object boundaries (inline linking).

Only in theory … :slight_smile:

Wouldn’t that render explicit inline functions useless?

No, inlining within a translation unit is more likely.

In this case the inline keyword in both C and C++
has different semantics. In C++ it is easier to understand:
inline allows multiple definitions of a function with external linkage,
provided they’re the same, without the inline keyword this would
be an automatic breach of the ODR (One Definition Rule).

In C, WG14 chose a different path. In C, inline simply gives
the compiler licence to pick any definition it choses.On 14/06/2013, at 4:10 PM, Sik the hedgehog wrote:


john skaller
@john_skaller
http://felix-lang.org

not compiled in exact same feature environment
Message-ID:

Content-Type: text/plain; charset=us-ascii

Theoretical uses for the function would be launcher programs
(SDLTerminal, anyone?),

Actually … I am seriously thinking of that :slight_smile:

I was actually thinking about an X11 environment and how
to feed local client keypresses to a server on another box,
and have it make OpenGL calls that get transported back
to the client … so your SDL application could actually run
on a remote server.

If you want, I can upload the file (actually two, I basically
scratched it out twice if I remember right) to Sourceforge. Be warned
that I never tried to compile it so there are certain to be bugs, and
a hexadecimal constant is needed to specify the SDL_RWops variant (I
put in some random sequence that uses non-hexadecimal characters, so
invalid). One of the big unknowns is whether Windows GUI apps can
actually have default streams: console apps CAN allocated & use
windows, and gui apps (MSBuild supposedly has a .com console version
that just allocates a terminal & execs to the .exe version) can
supposedly have default input streams if you do things right, but
until someone succeeds at it I won’t QUITE trust it to work
(especially post WinXP~Win7).

My second version only has Windows code, but the earlier one has some
*nix code. Not that it matters, since “fork & exec” should tell you
everything you need to know about that version.

My particular use case will eventually be
launcher-daemon/message-router/auto-updater (Windows locks executables
until all running instances exit, so a second application is needed to
update the core .exe files). I haven’t tried compiling either version
because I don’t need auto-updating yet (I’m slow), it’s a “for future
use” type of thing for me.> Date: Fri, 14 Jun 2013 15:41:21 +1000

From: john skaller
To: SDL Development List
Subject: Re: [SDL] SDL_stdinc.h inlines problematic when application

SDL_stdinc.h is designed to provide all the C library functionality used by SDL, for platforms that don’t have the standard C library, or where you don’t want C library dependencies for some reason.

Right. But it shouldn’t be part of SDL.h.

If users have a broken system, they can include this file if they want,
or use some other solution, such as their own local copy of stdint.h.

Fixing broken compilers is a project wide problem NOT a library
problem. SDL is a library. If you want to provide a project framework
for simple games fine, but please separate this from the library.On 14/06/2013, at 3:33 PM, Sam Lantinga wrote:


john skaller
@john_skaller
http://felix-lang.org

It’s used by other libraries that are companion libraries to SDL and games
that use SDL and want to avoid C runtime dependencies on Windows.

You’re welcome to define the inline avoidance macro, or just
#define _SDL_stdinc_h if you want it avoided entirely for your setup.

If there are conflicts with system headers or this causes other problems,
please file bugs on bugzilla and we’ll evaluate them. At this point at the
RC stage I’m not changing something that people may be depending on.

Cheers,On Fri, Jun 14, 2013 at 3:22 AM, john skaller <skaller at users.sourceforge.net wrote:

On 14/06/2013, at 3:33 PM, Sam Lantinga wrote:

SDL_stdinc.h is designed to provide all the C library functionality used
by SDL, for platforms that don’t have the standard C library, or where you
don’t want C library dependencies for some reason.

Right. But it shouldn’t be part of SDL.h.

If users have a broken system, they can include this file if they want,
or use some other solution, such as their own local copy of stdint.h.

Fixing broken compilers is a project wide problem NOT a library
problem. SDL is a library. If you want to provide a project framework
for simple games fine, but please separate this from the library.


john skaller
skaller at users.sourceforge.net
http://felix-lang.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Visual Studio, regardless of version, does not support C99. VS 2012
lacks C99 support just the same as VS 2008. Microsoft has already
stated that VS is a C++ environment, and a C89 compiler is shipped with
it only for compatibility reasons:

http://www.infoq.com/news/2012/05/vs_c99_support

So it’s not really an option for SDL to require C99.On 14/06/13 08:25, Sik the hedgehog wrote:

2013/6/14, john skaller :

If SDL mandates C99, the relevant C++ TR, then
testing for “int32_t” in the standard headers is not
only not required … its wrong.

I think SDL still supports pre-C99, so don’t count on that. In
particular, Visual Studio 2008 is… rather horrible in that sense.
And yes, many people still use that.

Newer versions do implement some C99 features though. But even then,
many people are still stuck using VS2008, which in C mode implements a
bastardized version of C89 (which is also important to know, it isn’t
even C89 compliant!).

I wish people would just upgrade sigh

2013/6/14, Nikos Chantziaras :> On 14/06/13 08:25, Sik the hedgehog wrote:

2013/6/14, john skaller :

If SDL mandates C99, the relevant C++ TR, then
testing for “int32_t” in the standard headers is not
only not required … its wrong.

I think SDL still supports pre-C99, so don’t count on that. In
particular, Visual Studio 2008 is… rather horrible in that sense.
And yes, many people still use that.

Visual Studio, regardless of version, does not support C99. VS 2012
lacks C99 support just the same as VS 2008. Microsoft has already
stated that VS is a C++ environment, and a C89 compiler is shipped with
it only for compatibility reasons:

http://www.infoq.com/news/2012/05/vs_c99_support

So it’s not really an option for SDL to require C99.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Visual Studio, regardless of version, does not support C99. VS 2012 lacks
C99 support just the same as VS 2008. Microsoft has already stated that VS
is a C++ environment, and a C89 compiler is shipped with it only for
compatibility reasons:

http://www.infoq.com/news/2012/05/vs_c99_support

So it’s not really an option for SDL to require C99.

Actually SDL could use this nifty tool https://github.com/rbultje/c99-to-c89
which converts most c99 to compatible c89 for visual studio.
It’s widely used in libav (and ffmpeg I think) to provide compatibility
with those less advanced tools without renouncing to more advanced language
features.

VittorioOn 15/giu/2013, at 03:41, Nikos Chantziaras wrote:

What platform that SDL targets does not have memset(), strdup(), abs(), etc.?On 06/16/2013 06:59 AM, Vittorio Giovara wrote:

On 15/giu/2013, at 03:41, Nikos Chantziaras <realnc at gmail.com <mailto:realnc at gmail.com>> wrote:

Visual Studio, regardless of version, does not support C99. VS 2012 lacks C99
support just the same as VS 2008. Microsoft has already stated that VS is a
C++ environment, and a C89 compiler is shipped with it only for compatibility
reasons:

http://www.infoq.com/news/2012/05/vs_c99_support

So it’s not really an option for SDL to require C99.

Actually SDL could use this nifty tool https://github.com/rbultje/c99-to-c89
which converts most c99 to compatible c89 for visual studio.
It’s widely used in libav (and ffmpeg I think) to provide compatibility with
those less advanced tools without renouncing to more advanced language features.

Vittorio


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I don’t think Windows has strdup, that’s how this issue appeared in
the first place.

2013/6/16, John :> What platform that SDL targets does not have memset(), strdup(), abs(),

etc.?

On 06/16/2013 06:59 AM, Vittorio Giovara wrote:

On 15/giu/2013, at 03:41, Nikos Chantziaras <realnc at gmail.com <mailto:realnc at gmail.com>> wrote:

Visual Studio, regardless of version, does not support C99. VS 2012
lacks C99
support just the same as VS 2008. Microsoft has already stated that VS
is a
C++ environment, and a C89 compiler is shipped with it only for
compatibility
reasons:

http://www.infoq.com/news/2012/05/vs_c99_support

So it’s not really an option for SDL to require C99.

Actually SDL could use this nifty tool
https://github.com/rbultje/c99-to-c89
which converts most c99 to compatible c89 for visual studio.
It’s widely used in libav (and ffmpeg I think) to provide compatibility
with
those less advanced tools without renouncing to more advanced language
features.

Vittorio


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Well, it’s easy to address these SDL_xxx functions individually instead of
treating the collection of them as one immovable object.

(1) The following are directly supported on all platforms that SDL targets,
as-is. These functions require no portability layer, and could be completely
removed from SDL_stdinc.h:

 abs atan atan2 atof atoi calloc ceil cos cosf fabs
 floor free getenv isdigit isspace log malloc memcmp
 memcpy memmove memset pow qsort realloc sin sinf
 sqrt sscanf strchr strcmp strlen strncmp strrchr
 strstr strtod strtol strtoul tolower toupper wcslen

(2) The following are supported on Windows, but prefixed with an underscore,
e.g., “_strdup”. These could be supported by SDL with a simple #define.

 copysign itoa ltoa snprintf strdup strlwr strrev strupr ultoa vsnprintf

(3) The following appear to be unused and could be removed from SDL_stdinc.h:

 lltoa ulltoa uitoa // remove or replace with snprintf
 scalbn  // removed or #define scalbn _scalb

(4) The following are easily solved odds and ends:

 setenv   // don't call. Use _putenv instead.
 strcasecmp // #define strcasecmp _stricmp
 strncasecmp // #define strncasecmp _strnicmp
 strtoll // use sscanf
 strtoull // use sscanf

(5) The following are BSD/MacOSX-specific.

 strlcat strlcpy wcslcat wcslcpy

(6) The following probably doesn’t belong in SDL_stdinc anyway. It’s not a
standard for any platform. Also, it’s only used in one place.

 utf8strlcpy

-JohnOn 06/16/2013 01:37 PM, Sik the hedgehog wrote:

I don’t think Windows has strdup, that’s how this issue appeared in
the first place.

2013/6/16, John <@John6>:

What platform that SDL targets does not have memset(), strdup(), abs(),
etc.?

On 06/16/2013 06:59 AM, Vittorio Giovara wrote:

On 15/giu/2013, at 03:41, Nikos Chantziaras <realnc at gmail.com <mailto:realnc at gmail.com>> wrote:

Visual Studio, regardless of version, does not support C99. VS 2012
lacks C99
support just the same as VS 2008. Microsoft has already stated that VS
is a
C++ environment, and a C89 compiler is shipped with it only for
compatibility
reasons:

http://www.infoq.com/news/2012/05/vs_c99_support

So it’s not really an option for SDL to require C99.

Actually SDL could use this nifty tool
https://github.com/rbultje/c99-to-c89
which converts most c99 to compatible c89 for visual studio.
It’s widely used in libav (and ffmpeg I think) to provide compatibility
with
those less advanced tools without renouncing to more advanced language
features.

Vittorio


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Well, it’s easy to address these SDL_xxx functions individually instead of treating the collection of them as one immovable object.

Good idea.

(1) The following are directly supported on all platforms that SDL targets,
as-is. These functions require no portability layer, and could be completely removed from SDL_stdinc.h:

abs atan atan2 atof atoi calloc ceil cos cosf fabs
floor free getenv isdigit isspace log malloc memcmp
memcpy memmove memset pow qsort realloc sin sinf
sqrt sscanf strchr strcmp strlen strncmp strrchr
strstr strtod strtol strtoul tolower toupper wcslen

Which of these are ISO C89? That’s a stronger condition because
SDL might target another platform one day.

(2) The following are supported on Windows, but prefixed with an underscore, e.g., “_strdup”. These could be supported by SDL with a simple #define.

copysign itoa ltoa snprintf strdup strlwr strrev strupr ultoa vsnprintf

Macros are a bad idea. What happens if another library tries
the same thing? What happens if another library defines it?

For example:

//SDL
#define strdup _strdup

//Another library
void strdup (...) // woops, just defined _strdup !

Now, the other library’s interface is broken by SDL.

Macros are EVIL. Macros starting with SDL_ are the lesser
evil we have to tolerate if we want to support broken
systems.

There’s no need to use the system strdup tho, one could also provide,
unconditionally, SDL_strdup since it’s easy to define, and there’s no
particular reason to think a user definition would be particularly
less efficient: C string functions are often inefficient anyhow (since they
waste time searching for the terminating 0 char).

AFAIK vsnprintf is not available at all on Windows:
To cite MSDN:

“If buffer or format is NULL, or if count is less than or equal to zero,
these functions invoke the invalid parameter handler,
as described in Parameter Validation.
If execution is allowed to continue, these functions
return -1 and set errno to EINVAL.”

The problem is unix vsnprintf is allowed to take a NULL buffer
I think, and can certainly take an inadequate count,
and then returns the required buffer size, windows one doesn’t.

This makes the windows version fairly useless because the general
unix idiom is to print twice, once with no space to get the length,
then one malloc()'s the buffer and does the real thing.

The only way to do this on Windows is to use a trial and error,
for example “have a go and if the buffer isn’t big enough double
its length and try again”. Can be done but is pretty awful.

In Felix … I just throw up my hands and allocate a big buffer
and hope no one will be insane enough to use that
function with long %s arguments (the only realistic
way to get a large output).On 17/06/2013, at 12:59 PM, John wrote:


john skaller
@john_skaller
http://felix-lang.org