May 11, 2006
Anders F Björklund wrote:
> I'm still naively hoping for both of "version (Unix)"

DMD supports Windows and Linux; Unix is neither. For a compiler which targets the Unix operating system, it should set the Unix version.

> and "version (!Windows)" to be defined and legal in D.

In C and C++, I often see:

	#if !WIN32

when what is really meant is:

	#if linux

i.e. the former is almost always a bug waiting to happen (when someone tries to compile for a third operating system). Versions should be "this build is for this configuration" rather than "this build is not for that configuration."

One can also write:
	version (ThisFeature)
	{
	}
	else
	{
		version = ThatFeature;
	}

...

	version (ThatFeature)
	...

For an example of why D is this way, see the sources to the Hans Boehm garbage collector, where the complex thicket of #if's makes it extremely difficult to see exactly what is being compiled.
May 11, 2006
Daniel Keep wrote:
> Well, I'll continue to hope that at some point it grows boolean
> expressions in version statements like "version(BSD | Linux)", but I can
> live without those :)

version (BSD)
{
	version = FEATURE1;
	version = FEATURE2;
}
version (linux)
{
	version = FEATURE1;
}

...

version (FEATURE1)
	...
May 11, 2006
Walter Bright wrote:

>> I'm still naively hoping for both of "version (Unix)"
> 
> DMD supports Windows and Linux; Unix is neither. For a compiler which targets the Unix operating system, it should set the Unix version.

It does... I was just hoping to be able to use the same code for both ?

GDC has chosen "Unix" as the name for all of them, while Ares uses "Posix". The naming doesn't matter as much, as long as it is defined.
Which one is better is just splitting hairs, and not so important to me.
For instance, Linux is a kernel - more than it is an operating system ?

But I take it that we need to continue to have at least three codepaths.

> i.e. the former is almost always a bug waiting to happen (when someone tries to compile for a third operating system). Versions should be "this build is for this configuration" rather than "this build is not for that configuration."

Thanks for the clarification on the official position on the matter.
I think it is unfortunate, but there are ways to use what we have...

--anders
May 11, 2006
Walter Bright wrote:
> Anders F Björklund wrote:
>> I'm still naively hoping for both of "version (Unix)"
> 
> DMD supports Windows and Linux; Unix is neither. For a compiler which targets the Unix operating system, it should set the Unix version.

For what it's worth, I think it would be useful for the 'Posix' version to be added, so any system supporting POSIX would have version 'Posix' automatically specified in addition to any OS version identifier.  This would be similar to how Windows platforms also have either 'Win32' or 'Win64' defined.  While a good bit of POSIX declarations are indeed implementation dependent, an equally large amount are not, and I believe it would be useful for a version identifier to reflect this.

>> and "version (!Windows)" to be defined and legal in D.
> 
> In C and C++, I often see:
> 
>     #if !WIN32
> 
> when what is really meant is:
> 
>     #if linux
> 
> i.e. the former is almost always a bug waiting to happen (when someone tries to compile for a third operating system). Versions should be "this build is for this configuration" rather than "this build is not for that configuration."

As much as I like the version idea, I'm beginning to feel that the C/C++ #ifdef method may actually be preferable in some situations.  For example, some portions of Posix are common and others are not, so I am faced with a few options:

- Define a separate set of Posix headers for each OS and have the user import the proper set manually.

- Define a separate set of Posix headers for each OS and do some fancy versioning in a common area to publicly import the proper set automatically.

- Define a common set of modules, each of which contains version blocks for each OS and may potentially result in multiple declarations of the same symbol occuring in the file (this is what I'm doing now for the Ares Posix headers as it's  the most readable, but I think it may become difficult to deal with when support for more OSes is added)

- Define a common set of modules with centralized logic for determining various things and use 'static if' in place of 'version' in a manner similar to #ifdef in C/C++

- Define a common set of modules but specify version identifiers in the makefile or via other means and move the complicated logic out of code and into a configure script or something similar

While preprocessor logic has proven to be an aboslute nightmare in terms of readability and maintainability in some cases, I truly believe that this is more attributable to a lack of programmer skill than anything else.  And while I love that D encourages 'good' style in many cases, I'm still undecided whether the current version scheme will prove to be sufficiently robust for large cross-platform projects.  Currently, I think the last option may be the best compromise (and would require no change to the language spec), but I'm still not certain whether it will prove more readable to do version checking outside of code as opposed to inside.

> One can also write:
>     version (ThisFeature)
>     {
>     }
>     else
>     {
>         version = ThatFeature;
>     }
> 
> ...
> 
>     version (ThatFeature)
>     ...
> 
> For an example of why D is this way, see the sources to the Hans Boehm garbage collector, where the complex thicket of #if's makes it extremely difficult to see exactly what is being compiled.

Yup, but doing this in every module isn't particularly desirable if such settings may be common for an entire package.  I'll admit I'm not entirely sure what the best approach is in this case.  I mentioned the options above mostly in hopes that doing so would help me think through the ideas a bit.


Sean
May 11, 2006
Anders F Björklund wrote:
> Walter Bright wrote:
> 
>>> I'm still naively hoping for both of "version (Unix)"
>>
>> DMD supports Windows and Linux; Unix is neither. For a compiler which targets the Unix operating system, it should set the Unix version.
> 
> It does... I was just hoping to be able to use the same code for both ?
> 
> GDC has chosen "Unix" as the name for all of them, while Ares uses "Posix". The naming doesn't matter as much, as long as it is defined.

For what it's worth, I chose "Posix" because it refers to the API rather than to a subset of systems that support that API.  But I agree that both are sufficiently general that they could be considered equivalent.

> Which one is better is just splitting hairs, and not so important to me.
> For instance, Linux is a kernel - more than it is an operating system ?

I think technically, the "Unix" moniker refers to the two derivatives of the code originally developed at Bell Labs: BSD Unix, and AT&T Unix. The other versions are Posix compliant, but not actually "Unix."


Sean
May 11, 2006
Sean Kelly wrote:

> For what it's worth, I think it would be useful for the 'Posix' version to be added, so any system supporting POSIX would have version 'Posix' automatically specified in addition to any OS version identifier.  This would be similar to how Windows platforms also have either 'Win32' or 'Win64' defined.  While a good bit of POSIX declarations are indeed implementation dependent, an equally large amount are not, and I believe it would be useful for a version identifier to reflect this.

GDC already uses (as in: actively, currently, in use) "Unix" for this:

Windows
- Win32
- Win64
Unix
- linux
- darwin
- freebsd
- cygwin
- solaris

Most if not all code currently including "std.c.linux.linux" with DMD,
can be compiled by using the portable "std.c.unix.unix" in GDC instead.

I was just hoping to avoid a fair amount of the needed copy and paste...

--anders

PS. See also http://www.digitalmars.com/d/archives/D/gnu/1208.html
    "I'm not planning on changing Unix to Posix." -- David Friedman
May 11, 2006
Anders F Björklund wrote:
> Walter Bright wrote:
> 
>>> I'm still naively hoping for both of "version (Unix)"
>>
>> DMD supports Windows and Linux; Unix is neither. For a compiler which targets the Unix operating system, it should set the Unix version.
> 
> It does... I was just hoping to be able to use the same code for both ?

I know it seems like the right thing to do to use the same code for both operating systems. I'm going to argue that this is a case where copy/paste might be better. Operating systems change all the time, but developers rarely test on all supported systems. So if there's common OS code, chances are good that improving support for, say, linux, will break existing support for, say, bsdunix. If the two are in separate source trees, the linux expert can keep the linux stuff maintained without worrying about breaking bsdunix, about which he may know nothing.

For example, look at the os support in the Hans Boehm gc. It's such a convoluted mess of #ifdef's, I don't see how anyone can modify it for one OS without trashing the other OS support. I'm also sure it didn't start out that way, it just evolved that way by accretion.
May 11, 2006
Sean Kelly wrote:
> I think technically, the "Unix" moniker refers to the two derivatives of the code originally developed at Bell Labs: BSD Unix, and AT&T Unix. The other versions are Posix compliant, but not actually "Unix."

That is one of my problems with "Unix" - nobody knows what it means. Such confusion will inevitably creep into code which multiple people will be maintaining. Posix makes more sense, because it is a defined standard.
May 11, 2006
Sean Kelly wrote:
> For what it's worth, I think it would be useful for the 'Posix' version to be added, so any system supporting POSIX would have version 'Posix' automatically specified in addition to any OS version identifier.  This would be similar to how Windows platforms also have either 'Win32' or 'Win64' defined.  While a good bit of POSIX declarations are indeed implementation dependent, an equally large amount are not, and I believe it would be useful for a version identifier to reflect this.

Having large parts of Posix be implementation dependent kinda shoots the whole idea of a standard in the foot.

> As much as I like the version idea, I'm beginning to feel that the C/C++ #ifdef method may actually be preferable in some situations.  For example, some portions of Posix are common and others are not, so I am faced with a few options:
> 
> - Define a separate set of Posix headers for each OS and have the user import the proper set manually.
> 
> - Define a separate set of Posix headers for each OS and do some fancy versioning in a common area to publicly import the proper set automatically.
> 
> - Define a common set of modules, each of which contains version blocks for each OS and may potentially result in multiple declarations of the same symbol occuring in the file (this is what I'm doing now for the Ares Posix headers as it's  the most readable, but I think it may become difficult to deal with when support for more OSes is added)
> 
> - Define a common set of modules with centralized logic for determining various things and use 'static if' in place of 'version' in a manner similar to #ifdef in C/C++
> 
> - Define a common set of modules but specify version identifiers in the makefile or via other means and move the complicated logic out of code and into a configure script or something similar

I suggest another possibility:

- Define a set of modules for each operating system, each in its own package
- Define an "os configuration module" that is edited by the user to import the correct os modules

I.e.:
	windows.foo.bar;
	linux.foo.bar;
	bsdunix.foo.bar;

and:

	foo.bar

the contents of foo.bar.d are:

	import windows.foo.bar;
	//import linux.foo.bar;
	//import bsdunix.foo.bar;

No version statements needed.


> While preprocessor logic has proven to be an aboslute nightmare in terms of readability and maintainability in some cases, I truly believe that this is more attributable to a lack of programmer skill than anything else.

Over time, I've been rewriting my use of #ifdef's in C++ to use the D style, and the results are worth it.

> Yup, but doing this in every module isn't particularly desirable if such settings may be common for an entire package.

True, but the way to do that is to create an import such as foo.bar above that imports or aliases the correct configuration. I think these will work out better than the usual C technique of having gobs of command line #defines. Just today, I have been having a miserable time attempting to compile the Boost test suite, and am being stymied trying to figure out which wretched set of #define's have to go on the command line just to get the freakin' default to work.

<flame on>
C++ was supposed to reduce the use of the preprocessor. Boost is peer-reviewed and written by the best and the brightest C++ developers. So why does even the simplest Boost code *heavily* rely on complex, obtuse, layer after layer of preprocessor macros?
<flame off>

> I'll admit I'm not entirely sure what the best approach is in this case.  I mentioned the options above mostly in hopes that doing so would help me think through the ideas a bit.

I agree that this has to be thought through very carefully.
May 11, 2006
"Derek Parnell" <derek@psych.ward> wrote in message news:op.s9d3gilp6b8z09@ginger...
> On Thu, 11 May 2006 19:32:07 +1000, Don Clugston <dac@nospam.com.au> wrote:
>
>
>> Since "static if" is now legal at module scope, it's now practically a superset of "version". So it shouldn't be very complicated to move some of the functionality across. (There's a problem with using 'static if' instead of 'version' : if there's an 'import' statement bracketed by a static if, potentially you have to compile the program to find out which files are included. Obviously 'build' can't cope with that).
>
> And I don't want to make Build be a compiler too ;-) So I don't think it will ever try to execute static if statements.
>
Just a random thought, but what about moving at least some of the project functionality of build directly in to the compiler; have it compile all current directory imports and link them together.  If -c is supplied, then the compiler would compile them only as opposed to linking, facilitating flexible build processes.  An advantage of this sort of approach is that the compiler already needs to know all about imports and locations, so the logical extension of that idea would be to have the compiler act on them. This is just something I came up with randomly while reading this thread; I don't know whether or not it's been proposed before.
>
> -- 
> Derek Parnell
> Melbourne, Australia