From the recent PR-related discussion I gather that FreeBSD 12 has made
some breaking changes to file primitives such as stat.
Do binaries built for pre-v12 crash on v12? If that's the case we should
have two distinct build platforms, FreeBSD "legacy" and FreeBSD 12. They
would be selected statically.
IF older binaries don't crash, what mechanism is FreeBSD 12 using to
identify old API calls?
Thanks,
Andrei

From the recent PR-related discussion I gather that FreeBSD 12 has made
some breaking changes to file primitives such as stat.
Do binaries built for pre-v12 crash on v12? If that's the case we should
have two distinct build platforms, FreeBSD "legacy" and FreeBSD 12. They
would be selected statically.
IF older binaries don't crash, what mechanism is FreeBSD 12 using to
identify old API calls?

Technically speaking, with how FreeBSD deals with its API/ABI, it promises
compatibility across major releases but not minor ones, so _any_ time you go
up a major version, there's a risk of breakage (though I don't know how
often APIs get changed in practice). In that respect, the fact that we've
been doing FreeBSD releases that don't target a particular version of
FreeBSD is kind of crazy, though for the most part, I think that the API and
ABI have not changed sufficiently in the areas that matter to dmd or Phobos
for it to be a big issue, though occasionally, fixes have had to be made
because something worked on one version of FreeBSD but not another. But we
don't currently have a way to version code for a particular version of
FreeBSD even if we wanted to. So, while we could do separate builds for
different versions of FreeBSD (and thus handle ABI changes), the source code
would have to be the same. AFAIK, the closest that we can currently come to
versioning the source code based on the version of FreeBSD is to check the
uname at runtime and run different code depending on the version, but that
obviously doesn't work in all situations.
Right now, what we have mostly works on FreeBSD 10.x and 11.x (it looks like
64-bit has a dmd test failure, and 32-bit has a Phobos test failure) as well
as older versions of 12-to-be (that's what I run locally, since that's what
TrueOS is based on), but several months ago, FreeBSD did make changes to
stat and related functions so that inodes are 64-bit, and that obviously
changed the API. They did a lot of work to make that compatible so that
programs didn't just break, but the compatibility stuff that they did was
for C/C++, and we don't use C/C++ headers; we duplicate their declarations
in D. So, we have to do work of some kind to be compatible, and I'm not
familiar enough with the details to know what needs doing. The related bug
report is
https://issues.dlang.org/show_bug.cgi?id=17596
and some work has been done to figure out what needs doing including a
suggested way to wrap the API changes at least until we're only supporting
FreeBSD 12+ (which is quite a ways off, since it hasn't even been released
yet). I don't know exactly what the situation with that currently is. I keep
hoping that it will be sorted out by December, since that's when the next
TrueOS update happens, and then it'll be based on a new enough version of
FreeBSD 12 that D will break if I upgrade, but I haven't had time to look
into it, and clearly those who looked into it previously haven't finished
doing whatever needs doing.
- Jonathan M Davis

Right now, what we have mostly works on FreeBSD 10.x and 11.x (it looks like
64-bit has a dmd test failure, and 32-bit has a Phobos test failure) as well
as older versions of 12-to-be (that's what I run locally, since that's what
TrueOS is based on), but several months ago, FreeBSD did make changes to
stat and related functions so that inodes are 64-bit, and that obviously
changed the API. They did a lot of work to make that compatible so that
programs didn't just break, but the compatibility stuff that they did was
for C/C++, and we don't use C/C++ headers;

Well, that is only header compatibility, not binary compatibility. In
other words, that still means if you use C or C++, you need to recompile
if you are on FreeBSD 12. You can't have one binary that supports both
platforms.
If this is the only compatibility they support, then I think we do need
to have multiple versions.
-Steve

Well, that is only header compatibility, not binary compatibility. In
other words, that still means if you use C or C++, you need to recompile
if you are on FreeBSD 12. You can't have one binary that supports both
platforms.

Thanks, this is the kind of hard data we're looking for. Do you have a
link to support this?

If this is the only compatibility they support, then I think we do need
to have multiple versions.

Well, that is only header compatibility, not binary compatibility. In
other words, that still means if you use C or C++, you need to
recompile if you are on FreeBSD 12. You can't have one binary that
supports both platforms.

Thanks, this is the kind of hard data we're looking for. Do you have a
link to support this?

Sorry, I don't have any experience with FreeBSD. I was reacting to
Jonathan's claim that "They did a lot of work to make that compatible so
that programs didn't just break, but the compatibility stuff that they
did was for C/C++, and we don't use C/C++ headers"
That lead me to believe that marking the headers differently is all they
did. As I said, this is not binary compatibility.
Sure, we can do this too, we don't use C/C++ headers, but we can port
our headers. The question to answer is, "can we create a binary that
runs on both versions of FreeBSD?".
The answer to that question, I don't know. Is it possible on FreeBSD to
detect this at runtime and call the right binding? Not sure. It might
not even be detectable (see codephantom's post on how FreeBSD 12 may be
compiled with the older binding anyway!)
Another possible option, if it existed, would be to simply call a
function that does the right thing. Perhaps a .so that can be swapped
out based on which version of the OS you are on?
But the only thing I can think of currently, that will definitely
"solve" the problem, is to treat each version as a different OS with a
new version statement. This doesn't scale well, so I'm not sure if
that's the road we want to go down.
-Steve

But the only thing I can think of currently, that will
definitely "solve" the problem, is to treat each version as a
different OS with a new version statement. This doesn't scale
well, so I'm not sure if that's the road we want to go down.

That seems to be the road version statements are already going
down...There is Playstation and Playstation4. There is SysV3 and
SysV4. There are 5 different ARM versions. Posix groups together
FreeBSD, OSX, Solaris, etc, which also exist on their own.

Well, that is only header compatibility, not binary compatibility. In
other words, that still means if you use C or C++, you need to
recompile if you are on FreeBSD 12. You can't have one binary that
supports both platforms.

Thanks, this is the kind of hard data we're looking for. Do you have a
link to support this?

Sorry, I don't have any experience with FreeBSD. I was reacting to
Jonathan's claim that "They did a lot of work to make that compatible so
that programs didn't just break, but the compatibility stuff that they
did was for C/C++, and we don't use C/C++ headers"
That lead me to believe that marking the headers differently is all they
did. As I said, this is not binary compatibility.
Sure, we can do this too, we don't use C/C++ headers, but we can port
our headers. The question to answer is, "can we create a binary that
runs on both versions of FreeBSD?".
The answer to that question, I don't know. Is it possible on FreeBSD to
detect this at runtime and call the right binding? Not sure. It might
not even be detectable (see codephantom's post on how FreeBSD 12 may be
compiled with the older binding anyway!)

The bug report I linked to has an example of how it might be fixed with a
wrapper function that calls a different version of stat depending on what
version of FreeBSD it looks like is running at runtime. But I have no idea
how complete that is. I keep meaning to find the time to look into this in
detail but haven't gotten around to it yet. I believe that what
codephantom's post means is that with that build option, the compatibility
stuff is in place which allows the 32-bit inode stuff to be used but in
spite of the fact that they've now switched to 64-bit inodes (certainly,
that's my understanding of what the compatibility stuff does), but I haven't
dug deep enough to figure out the details.
Given that this issue hasn't been sorted out yet and that if it's not sorted
out by next month, I'm going to be stuck between not upgrading my desktop
and not having a working D setup (due to the TrueOS-stable update to a newer
version of FreeBSD 12), it's looking like I'm going to have to find the time
to dig deeper.

Another possible option, if it existed, would be to simply call a
function that does the right thing. Perhaps a .so that can be swapped
out based on which version of the OS you are on?
But the only thing I can think of currently, that will definitely
"solve" the problem, is to treat each version as a different OS with a
new version statement. This doesn't scale well, so I'm not sure if
that's the road we want to go down.

Well, in the case of FreeBSD, it's not terrible, especially since it doesn't
make much sense to support versions of FreeBSD that the FreeBSD guys don't
support. And in that case, the most you'd get is probably 3 versions
(currently FreeBSD10, FreeBSD11, and FreeBSD12), and they would shift over
time, so while there would be more in the compiler if they weren't removed,
druntime or Phobos wouldn't get an ever growing number of them. But from
what I can tell, the API changes rarely enough that it usually wouldn't even
be needed. I think that it's usually a greater risk that you'd need to build
for a newer system because of ABI changes than that the API changed in a way
that requires versioning druntime or Phobos. This inode situation is an
extreme case, and they've been working for years on getting it done in a way
that minimizes the level of disruption and breakage that it causes.
The bigger problem with separate versions is that the autotester would then
really need to be running at least a FreeBSD 10.x and FreeBSD 11.x box (and
later 11.x and 12.x once 12 is released), and we'd need to release different
packages for each (though we could arguably just rely on the ports tree for
the releases so long as someone is maintaining the FreeBSD port). The fact
that we don't test multiple versions of FreeBSD has occasionally been a
problem already, but the bigger problem has been that the auto-testers just
haven't gotten updated often (IIRC they're on 8.x and not even 9.x, whereas
10.3 is currently the oldest supported release), and now several things have
needed to get fixed towards being able to update them, because several
things broke.
If we _can_ continue to do just do one release of dmd for FreeBSD that works
across several versions, then that's ideal, but the way that FreeBSD is
released, I think that it's normally expected that you're going to have to
rebuild stuff for each major release even if APIs don't change, and if we're
not testing multiple versions, then we're going to miss it when we manage to
break something.
In any case, we need a clear picture of exactly what needs to be done for
the inode64 breakage to know whether we absolutely need to have separate
builds or whether we can get away with playing tricks at runtime to work
around it. The bug report makes it sound like we _might_ be able to work
around this with runtime tricks.
- Jonathan M Davis

But we
don't currently have a way to version code for a particular version of
FreeBSD even if we wanted to.

The FreeBSD version can be detected at runtime, and different code
executed.

Sure, but you can't actually compile different code based on the FreeBSD
version, and if a type or function API changes, then that doesn't work.
Wouldn't you get a linker error for the stuff that isn't actually defined on
the C side of things? If so, then you can't really provide both the old and
new versions of a function or type and switch between code that uses one or
the other based on the version of the OS at runtime. You'd have to be able
to have the source code differ depending on the FreeBSD version.
Depending on what was done with the compatibility layer for the 64-bit inode
stuff, we may be able to do something in this case to choose which to use
based on the version of the OS at runtime, because you'd have both the
direct API and the compatibility API to use and thus there are different
symbols to link against, but in the general case, if an API is simply
updated, then you only have one version to link against. So, while we may be
able to deal with this particular issue with something that makes the choice
at runtime, I don't see how that would work in general any time that there's
a breaking API change. Any time that happens, we'd need to be able to
statically differentiate which version of FreeBSD we'd be compiling for.
And that may not actually ever come up, since it's not like the FreeBSD
folks change APIs for the fun of it, but it still looks to me like not being
able to version the source code based on the version of FreeBSD your
compiling for is potentially a showstopper for having code work with
multiple versions of FreeBSD. I think that we're more likely to get away
with it with dmd, druntime, and Phobos, because we mostly use POSIX APIs,
which they aren't going to be changing much, but if you're dealing with
something that isn't POSIX, then the odds are that it would matter more.
In such a case, you'd probably be forced to either provide different
versions of a module depending on the OS version, and have the build system
differentiate for you, or you'd have to provide custom version identifiers
as part of the build so that the code could be versioned appropriately.
- Jonathan M Davis

But we
don't currently have a way to version code for a particular version of
FreeBSD even if we wanted to.

The FreeBSD version can be detected at runtime, and different code
executed.

Sure, but you can't actually compile different code based on the FreeBSD
version, and if a type or function API changes, then that doesn't work.
Wouldn't you get a linker error for the stuff that isn't actually defined on
the C side of things? If so, then you can't really provide both the old and
new versions of a function or type and switch between code that uses one or
the other based on the version of the OS at runtime. You'd have to be able
to have the source code differ depending on the FreeBSD version.

But we
don't currently have a way to version code for a particular version of
FreeBSD even if we wanted to.

The FreeBSD version can be detected at runtime, and different code
executed.

Sure, but you can't actually compile different code based on the FreeBSD
version, and if a type or function API changes, then that doesn't work.
Wouldn't you get a linker error for the stuff that isn't actually
defined on the C side of things? If so, then you can't really provide
both the old and new versions of a function or type and switch between
code that uses one or the other based on the version of the OS at
runtime. You'd have to be able to have the source code differ depending
on the FreeBSD version.

I know in Windows the imports can be dynamically loaded at runtime.

I thought that that was just when explicitly loading a .dll or .so file via
something like dlopen or LoadLibrary instead of linking against it, and you
normally link against system libraries rather than dlopening them. But
Windows is pretty weird about how it dynamically links stuff, so I could be
misunderstanding something in Windows' case. Regardless, it wouldn't be the
case with static linking, and there are cases where it's definitely
preferable to statically link.
So, I fully expect that there are times when being able to version the
source code based on the OS version (or the libc version if you're talking
about Linux) would be needed. However, I don't know if it's needed often
enough for the compiler to directly support it rather than using custom
version specifiers for those code bases that do. Technically, I think that
the versioning that they do in C/C++ for this sort of thing with #includes
is more or less equivalent to using custom version specifiers rather than
actually doing anything special with the compiler.
Regardless, it would be nice if we could avoid the need to statically
version any code in dmd, druntime, or Phobos based on OS version.
- Jonathan M Davis

So, I fully expect that there are times when being able to version the
source code based on the OS version (or the libc version if you're talking
about Linux) would be needed. However, I don't know if it's needed often
enough for the compiler to directly support it rather than using custom
version specifiers for those code bases that do. Technically, I think that
the versioning that they do in C/C++ for this sort of thing with #includes
is more or less equivalent to using custom version specifiers rather than
actually doing anything special with the compiler.
Regardless, it would be nice if we could avoid the need to statically
version any code in dmd, druntime, or Phobos based on OS version.

I don't know all the details, just throwing some ideas out there:
* macOS went through a similar transition, perhaps have a look at how
Apple did that. There some information here [1], scroll down to the
documentation for the _DARWIN_FEATURE_64_BIT_INODE macro
* Fully statically link the binaries, including the C standard library.
Might work assuming the kernel did not change
* Do something similar to what AppImage [2] is doing on Linux. AppImage
works by creating a binary with an executable header and a disk image
that holds the payload. In the case of AppImage the payload would be the
application including all the files necessary to run it. Perhaps we
could instead build something like universal binaries on macOS. Embed
two separate executables and run one of the depending on the current system
[1]
https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/stat.2.html
[2] https://appimage.org
--
/Jacob Carlborg

I thought that that was just when explicitly loading a .dll or .so file via
something like dlopen or LoadLibrary instead of linking against it,

That's right.
But given our resource limitations, I suggest the most pragmatic thing to do is
support the latest FreeBSD, and leave older versions enabled in Druntime with
`version` statements. That way the user could recompile Phobos for earlier
versions if he needed it, but it wouldn't be officially supported.
Note that dmd still runs on Windows XP, though it is not officially supported.
You just need to be careful about using TLS variables on it :-(

Note that dmd still runs on Windows XP, though it is not
officially supported. You just need to be careful about using
TLS variables on it :-(

Please keep it that way ;-)
btw. dmd runs just fine on FreeBSD 12 too, as I just tested it.
Mind you, I just compile my own stuff, and that's all.
I don't have extensive unit tests, so some things may well not
work.

Note that dmd still runs on Windows XP, though it is not
officially supported. You just need to be careful about using
TLS variables on it :-(

Please keep it that way ;-)

I think that there's a decent chance that some of Phobos won't work with XP
though. A lot of API calls were added in Vista, some of which were major
improvements. Plenty of stuff will probably continue to work on XP, but we
don't support it, and as time goes by, the odds of stuff not working on it
are going to increase. So, feel free to use XP if you want to, but you're
using it at your own risk, and if something doesn't work, then you're just
going to be out of luck.

btw. dmd runs just fine on FreeBSD 12 too, as I just tested it.
Mind you, I just compile my own stuff, and that's all.
I don't have extensive unit tests, so some things may well not
work.

It definitely crashed the last time I tested it, and the aforementioned bug
report has someone testing it, and it crashing. So, either they've changed
something that somehow magically made our stuff work as-is, or you just got
lucky.
But regardless of whether it currently crashes, it's clear that we're going
to need to make stat and friends work with 64-bit inodes rather than simply
using the 32-bit inodes, even if they still happen to work for the moment,
since at some point, the 32-bit inodes are going to be going away (though
I'm sure not until at least FreeBSD 13).
- Jonathan M Davis

So, feel free to use XP if you want to, but you're using it at
your own risk, and if something doesn't work, then you're just
going to be out of luck.

that's ok, if it works great, if not, oh well.
at least it executes ;-)
e.g clang etc won't even execute on xp.

It definitely crashed the last time I tested it, and the
aforementioned bug report has someone testing it, and it
crashing. So, either they've changed something that somehow
magically made our stuff work as-is, or you just got lucky.

Yes, **do** your own testing, as my concept of testing is at
best, dodgy...
i.e. I just grabbed all my .d files off FreeBSD 11, put them on
FreeBSD 12, and executed this: for f in *.d; do echo $f;dmd $f;
done
;-)

I think that there's a decent chance that some of Phobos won't
work with XP though....

Same for FreeBSD ;-)
e.g: below compile fine on Windows, but on FreeBSD (11 and 12), I
get a compile time error: Error: template instance to!string to
is not a template declaration, it is a module. I've come across a
few others too.... so Phobos developers need to test on FreeBSD
too.
------------------
import std.stdio;
import std.conv;
void main()
{
auto i = to!string(55);
writeln("i is a ", typeof(i).stringof);
}
-----------------------

I think that there's a decent chance that some of Phobos won't
work with XP though....

Same for FreeBSD ;-)
e.g: below compile fine on Windows, but on FreeBSD (11 and 12), I
get a compile time error: Error: template instance to!string to
is not a template declaration, it is a module. I've come across a
few others too.... so Phobos developers need to test on FreeBSD
too.
------------------
import std.stdio;
import std.conv;
void main()
{
auto i = to!string(55);
writeln("i is a ", typeof(i).stringof);
}
-----------------------

Well, I won't deny that most of the core devs don't use FreeBSD, and the
auto-tester situation with FreeBSD needs to be improved, but that code
compiles just fine on my TrueOS system with dmd master, and that code is not
the sort of thing that I would expect to have issues that depended on the OS
it was on. What version of dmd are you running?
- Jonathan M Davis

Well, I won't deny that most of the core devs don't use
FreeBSD, and the auto-tester situation with FreeBSD needs to be
improved, but that code compiles just fine on my TrueOS system
with dmd master, and that code is not the sort of thing that I
would expect to have issues that depended on the OS it was on.
What version of dmd are you running?
- Jonathan M Davis

That is strange, that it compiles ok on TrueOS.
I don't think it's a FreeBSD issue as such, maybe more a posix
issue??
I **cannot** compile that code that I mentioned on FreeBSD-11/12,
Debian 8.5.0, or Centos 7.3.1611. In all those cases, DMD gives
the same strange message. The only way I got it to work (on both
Debian and Centos) was to compile with GDC instead.
On FreeBSD-11/12, it just won't compile whether I use DMD or LDC
(and of course i don't have GDC on FreeBSD so don't know would
happen if I did).
But: auto i = to!string(55);
Gee...that's a pretty simply piece of code, and shouldn't be
failing at all, anywhere.

I don't know what to tell you. I just tested your example with
dmd 2.073.2
dmd 2.074.1
dmd 2.075.1
dmd 2.076.1
dmd master
on both TrueOS stable and Arch Linux, and it compiled just fine with all of
them. And that example is so basic that something is seriously wrong if it
doesn't work. So, that implies that you're doing something funny, but if
you're installing dmd with an installer or package manager, then I would
think that it would at least be set up correctly.
You might want to try
dmd --version
to make sure that you're running the
version you think you are and
which dmd
to make sure you're running the binary that you think you're running - e.g.
maybe you did something previously with dmd that resulted in a borked
install that has precedence in the path over the properly installed one -
though I wouldn't think that you'd manage that on multiple systems like
that. So, I don't know, but it's a thought.
- Jonathan M Davis

maybe you did something previously with dmd that resulted in a
borked install that has precedence in the path over the
properly installed one - though I wouldn't think that you'd
manage that on multiple systems like that. So, I don't know,
but it's a thought.
- Jonathan M Davis

nope. it cannot be any easier to install dmd
I also verified all the versions using dmd --version. They are
all the same version, straight off the dlang website.
My TrueOS download just completed, so I'll give that a go later
today.
btw. I discovered that a small change to the code, and it will
compile ok:
--------------------------------------------------
import std.stdio;
//import std.conv; // this will *not* compile.
import std.conv : to; // this will compile ok.
void main()
{
auto i = to!string(55);
writeln("i is a ", typeof(i).stringof);
}
-----------------------------------------------

So, that implies that you're doing something funny, but if
you're installing dmd with an installer or package manager,
then I would think that it would at least be set up correctly.

ok. I worked it out.
my file was named: to.d
so that caused dmd some confusion it seems.
change the name to something else, then dmd is ok with that code.
There's some real 'gotchas' when it comes to file names and
dmd... I'm not sure I like it.
Interestingly, gdc didn't care that my file was named to.d, it
did what I wanted the code to do. Would like dmd to do the same
;-)
But ldc does the same thing as dmd...neither likes a file named
to.d when you're calling a template with the same name.

So, that implies that you're doing something funny, but if
you're installing dmd with an installer or package manager,
then I would think that it would at least be set up correctly.

ok. I worked it out.
my file was named: to.d
so that caused dmd some confusion it seems.
change the name to something else, then dmd is ok with that code.
There's some real 'gotchas' when it comes to file names and
dmd... I'm not sure I like it.
Interestingly, gdc didn't care that my file was named to.d, it
did what I wanted the code to do. Would like dmd to do the same
;-)
But ldc does the same thing as dmd...neither likes a file named
to.d when you're calling a template with the same name.

Per the spec, if you don't give a module declaration, the name of the module
is the name of the file (minus the extension). So, if you just give a module
name (which you generally would in any real program rather than a quick test
program), then it's not a problem - unless you give the module a name which
conflicts with something that you're trying to use. If you'd had
module to;
at the top of the module, then you'd have the same problem regardless of the
file name. The module name wins out over the imported name when there's a
conflict, because the module name is a local symbol. In practice, that's
rarely a problem, though poor module-naming practices could certainly make
it a problem.
You can also work around it by using the fully qualified name (std.conv.to
in this case) or by aliasing the symbol to a new name (I think that you can
also statically import a symbol with a new name, but if so, that's basically
the same as statically importing it and then aliasing it).
If gdc doesn't have the same behavior, it's either a bug, and/or it's
related to the fact that the last released version of gdc matched dmd 2.068
(IIRC). So, right now, gdc is a terrible compiler to use unless you don't
care about using a really old version of D. I think that they're getting
close to releasing an update that's much closer to the current version of
dmd, but IIUC, the switch of the frontend from C++ to D was a huge roadblock
for them, since they had a lot of redesign work to do (they also don't have
much manpower). So, it's taken them quite a while to get back up-to-date.
- Jonathan M Davis

Per the spec, if you don't give a module declaration, the name
of the module is the name of the file (minus the extension).
So, if you just give a module name (which you generally would
in any real program rather than a quick test program), then
it's not a problem - unless you give the module a name which
conflicts with something that you're trying to use.

Thanks. I had actually read that spec, but forgot all about it.
Having only used D for a month or so, I'm only writing snippets
(107 so far), not actual programs.
I actually had to edit the source code of my editor, so that when
I create/save a .d file, if I happen to use hypens, then my
editor will now automatically replace them with underscores
(again, just because the way D deals with files).
I think I'll do some more editing, and have my editor insert a
default module name as well.
Still, I don't like the spec. I would prefer that dmd did not
implictly do stuff like that. Then I could regain the freedom to
name my files however I wanted.

Per the spec, if you don't give a module declaration, the name
of the module is the name of the file (minus the extension).
So, if you just give a module name (which you generally would
in any real program rather than a quick test program), then
it's not a problem - unless you give the module a name which
conflicts with something that you're trying to use.

Thanks. I had actually read that spec, but forgot all about it.
Having only used D for a month or so, I'm only writing snippets
(107 so far), not actual programs.
I actually had to edit the source code of my editor, so that when
I create/save a .d file, if I happen to use hypens, then my
editor will now automatically replace them with underscores
(again, just because the way D deals with files).
I think I'll do some more editing, and have my editor insert a
default module name as well.
Still, I don't like the spec. I would prefer that dmd did not
implictly do stuff like that. Then I could regain the freedom to
name my files however I wanted.

Well, the modules need names. So, either, the compiler is going to have to
pick a name for you, or you're going to have to give it one. In general
though, D was designed with the idea that modules would match files and
packages would match directories - and that the names on disk would match
the ones in the file. Overall, things are much simpler that way. On some
level, you can get around that by giving module names that don't match the
file names, but in general, you're just begging for trouble if you don't
make your file names and module names match (at least some stuff is going to
be looking for modules by looking at the file system for them with the
assumption that the package names match folders and the module names match
files). So, in the long run, you'll just have fewer problems if you make
your file names and module names match.
- Jonathan M Davis

Well, the modules need names. So, either, the compiler is going
to have to pick a name for you, or you're going to have to give
it one. In general though, D was designed with the idea that
modules would match files and packages would match directories
- and that the names on disk would match the ones in the file.
Overall, things are much simpler that way. On some level, you
can get around that by giving module names that don't match the
file names, but in general, you're just begging for trouble if
you don't make your file names and module names match (at least
some stuff is going to be looking for modules by looking at the
file system for them with the assumption that the package names
match folders and the module names match files). So, in the
long run, you'll just have fewer problems if you make your file
names and module names match.
- Jonathan M Davis

Yes. All that makes complete sense I guess.
It might also make sense, that if a source code file does not
contain a module statement, then it should not be treated as a
module, and the compiler should look to the import statements
instead of implicitly making in a module.
btw. That bug in gdc, which appear to do just that, is a nice bug
;-)

Yes. All that makes complete sense I guess.
It might also make sense, that if a source code file does not
contain a module statement, then it should not be treated as a
module, and the compiler should look to the import statements
instead of implicitly making in a module.
btw. That bug in gdc, which appear to do just that, is a nice
bug ;-)

I should add one more thing.
Both Andrei's book (The D Programming Language), and Ali's book
(Programming in D), provide the usual 'hello world' thing, at the
beginning. In both cases, the 'module' statement is not part of
that example. That is consistent with other 'hello world' I've
seen in D. All the other code in both book also consistently
leaves out the 'module' statement.
My point being, given that "D is serious about modularity" (as
Andrei put it in his book), then I think all 'hello world'
examples should include the 'module' specifier as well, and
explain why it's there too. I think that would really aid those
who are new to the language..

It might also make sense, that if a source code file does not contain a
module statement, then it should not be treated as a module, and the
compiler should look to the import statements instead of implicitly
making in a module.

I should add one more thing.
Both Andrei's book (The D Programming Language), and Ali's book
(Programming in D), provide the usual 'hello world' thing, at the
beginning. In both cases, the 'module' statement is not part of that
example. That is consistent with other 'hello world' I've seen in D. All
the other code in both book also consistently leaves out the 'module'
statement.
My point being, given that "D is serious about modularity" (as Andrei
put it in his book), then I think all 'hello world' examples should
include the 'module' specifier as well, and explain why it's there too.
I think that would really aid those who are new to the language..

Many people seem to leave the module statement out of their main.d/app.d
files; I think it's a way to say "this is the main thing - don't import it
from somewhere else." Basically, it's easier to act like that code isn't
in a module than it is to have the compiler support code not in a module.

Many people seem to leave the module statement out of their
main.d/app.d files; I think it's a way to say "this is the main
thing - don't import it from somewhere else." Basically, it's
easier to act like that code isn't in a module than it is to
have the compiler support code not in a module.

I think maybe, the compiler should just refuse to compile
anything, unless the module namespace is explicitely stated. I
don't know what the effects of that would be in total, but it
would avoid compilation errors when, for example, you do what I
do - which is create 100's of snippets of code, save each snippet
with a name corresponding to the thing 'snipped' (so I can easily
find them again), and then discovering that they won't compile.
(i.e. D having neither a default global namespace, and then the
compiler making implicit assumptions about what namespace to use,
based on the file name, seems problematic. Better to just 'refuse
to compile' a file, unless it explicitely states a module
namespace.
e.g. (the .d files further below, without any module name
specified, will not compile - presumably because the compiler is
having problems resolving the namespace.
So why is the compiler forced to do that anyway? Why not just
refuse to compile simply because no module namespace was provided
- then a nice clear message stating that, could be provided back
to the user, instead of the cryptic message: " Error: function
expected before (), not module writeln of type void"
-----save this as writeln.d and it will not compile
-----------------
import std.stdio;
void main()
{
writeln("Hello World!");
}
-------------------------------
-----save this as to.d and it will not compile -----------------
import std.stdio;
import std.conv;
void main()
{
auto i = to!string(55);
}
----------------------------------------

Well, the modules need names. So, either, the compiler is going
to have to pick a name for you, or you're going to have to give
it one. In general though, D was designed with the idea that
modules would match files and packages would match directories
- and that the names on disk would match the ones in the file.
Overall, things are much simpler that way. On some level, you
can get around that by giving module names that don't match the
file names, but in general, you're just begging for trouble if
you don't make your file names and module names match (at least
some stuff is going to be looking for modules by looking at the
file system for them with the assumption that the package names
match folders and the module names match files). So, in the
long run, you'll just have fewer problems if you make your file
names and module names match.
- Jonathan M Davis

Yes. All that makes complete sense I guess.
It might also make sense, that if a source code file does not
contain a module statement, then it should not be treated as a
module, and the compiler should look to the import statements
instead of implicitly making in a module.

The language has no concept of any D code not being in a module. Not only
would adding such a concept complicate things, but it wouldn't help real
world programs. Having the module name infered from the file name was a
simple solution to the problem and usually doesn't cause problems (at least
as long as you're just dealing with toy programs).
Personally, I think that we would have been better off just requiring the
module statements (especially since it doesn't work to have modules in
packages without the module statements), but I doubt that that change would
be accepted at this point, particularly since it wouldn't matter for much
other than toy programs. Mostly all it would do is force folks to use module
statements up front when learning the language instead of trying to go
without like some do and then inevitably hitting issues when they start to
use packages. And that has value, but I doubt that it would be enough of an
argument to get such a change made.
- Jonathan M Davis

Well, the modules need names. So, either, the compiler is going
to have to pick a name for you, or you're going to have to give
it one.

ok..just one more ... I can't help myself..
I know that D does not have a 'global namespace', but what if did?
Then, if a file does not declare its own module namespace (like
none of my 109 snippets) then what's the big deal with having the
compiler just use that (statically known) global name space.
I wonder what the implication would be, if any.
oh..and it would save a few keystrokes...which seems to be a main
focus of numerous DIPs ;-)

I thought that that was just when explicitly loading a .dll or .so
file via
something like dlopen or LoadLibrary instead of linking against it,

That's right.
But given our resource limitations, I suggest the most pragmatic thing
to do is support the latest FreeBSD, and leave older versions enabled in
Druntime with `version` statements. That way the user could recompile
Phobos for earlier versions if he needed it, but it wouldn't be
officially supported.
Note that dmd still runs on Windows XP, though it is not officially
supported. You just need to be careful about using TLS variables on it :-(

to avoid spreading this false information: TLS in D works in dynamically
loaded DLLs on WinXP since 2010.

Note that dmd still runs on Windows XP, though it is not officially supported.
You just need to be careful about using TLS variables on it :-(

to avoid spreading this false information: TLS in D works in dynamically
loaded
DLLs on WinXP since 2010.

The fact that we haven't officially tested that it works for years means be
careful about attesting that it does work.
Even simple DLL support in Windows keeps breaking because it is not part of the
autotester test suite.

Note that dmd still runs on Windows XP, though it is not officially
supported. You just need to be careful about using TLS variables on it
:-(

to avoid spreading this false information: TLS in D works in dynamically
loaded DLLs on WinXP since 2010.

The fact that we haven't officially tested that it works for years means
be careful about attesting that it does work.
Even simple DLL support in Windows keeps breaking because it is not part
of the autotester test suite.

Just the other day, a fix for std.experimental.allocator that was supposed
to fix FreeBSD 10.x/11.x fixed 32-bit but broke 64-bit - and it had no
effect on FreeBSD 8.4 or whatever it is that's running on the main
autotester FreeBSD boxes. The problem was caught and fixed, but for any
given platform, unless we're running it as part of the autotester, or
someone runs the tests locally and reports any breakages that occur, it's
trivial for bugs to creep in, as annoying as that is.
As such, I don't think that the odds are good at all that running modern D
programs on Windows XP is going to work correctly in general. I don't expect
that it's completely broken, but I sure wouldn't trust it without running
the complete test suite in XP to verify whatever version of dmd, druntime,
and Phobos you're trying to use - and I think that we may even be using some
Windows API calls in Phobos which were introduced in Vista, since a lot of
improved API calls were added in Vista, and it's certainly the case that
_those_ won't work in XP.
I confess that I have little sympathy if D doesn't work in XP though given
that the fact that Microsoft doesn't support it anymore makes it completely
unsafe to run unless it's not connected to the Internet.
- Jonathan M Davis

Note that dmd still runs on Windows XP, though it is not officially
supported. You just need to be careful about using TLS variables on it :-(

to avoid spreading this false information: TLS in D works in dynamically
loaded DLLs on WinXP since 2010.

The fact that we haven't officially tested that it works for years means be
careful about attesting that it does work.

It is working in Visual D since that time.

Ok, but does that mean you're testing the TLS support on XP?
I run dmd regularly on an XP box, but that just means dmd itself runs on XP. (I
converted the front end of DMC++ to D, using DMD in -betterC mode, and XP is
the
last operating system that supports DOS programs. XP has the DOS DMC++ test
suite on it.)

Even simple DLL support in Windows keeps breaking because it is not part of
the autotester test suite.

Note that dmd still runs on Windows XP, though it is not
officially supported. You just need to be careful about
using TLS variables on it :-(

to avoid spreading this false information: TLS in D works in
dynamically loaded DLLs on WinXP since 2010.

The fact that we haven't officially tested that it works for
years means be careful about attesting that it does work.

It is working in Visual D since that time.

Ok, but does that mean you're testing the TLS support on XP?
I run dmd regularly on an XP box, but that just means dmd
itself runs on XP. (I converted the front end of DMC++ to D,
using DMD in -betterC mode, and XP is the last operating system
that supports DOS programs. XP has the DOS DMC++ test suite on
it.)

I don't think that's true. It's a 32bit/64bit division, not a
Windows version thing. A 32 bits installation can run 16 bits and
32 bits programs, a 64 bits version can run natively 32 bits and
64 bits programs. None can run all 3 modes natively.
I know with certainty that Windows 8.1 32 bits installation could
still run DOS and Windows 16 bits apps. I haven't seen evidence
to the contrary for Windows 10.
Windows XP was the last version that was installed massively in
32 bits mode. From Vista on, the proportion of 32 bits
installations (and thus losing 16 bits support) dwindeled.

I run dmd regularly on an XP box, but that just means dmd itself runs on XP.
(I converted the front end of DMC++ to D, using DMD in -betterC mode, and XP
is the last operating system that supports DOS programs. XP has the DOS DMC++
test suite on it.)

I don't think that's true. It's a 32bit/64bit division, not a Windows version
thing. A 32 bits installation can run 16 bits and 32 bits programs, a 64 bits
version can run natively 32 bits and 64 bits programs. None can run all 3
modes
natively.

Is that an issue with the CPU, or the operating system?

I know with certainty that Windows 8.1 32 bits installation could still run
DOS
and Windows 16 bits apps. I haven't seen evidence to the contrary for Windows
10.
Windows XP was the last version that was installed massively in 32 bits mode.
From Vista on, the proportion of 32 bits installations (and thus losing 16
bits
support) dwindeled.

Windows 7 64 bit will not run 16 bit programs. Try it and you get a dialog box
"Unsupported 16-Bit Application". I haven't tried Win 7 32, but some googling
around shows you are correct.

Interestingly, all I actually need to test the 16 bit code
generation is an 8088 emulator with some of the DOS API
interrupts supported. The CPU is simple enough that should be
easy :-)

I still have 'actual' pc's here at home, from the 90's, running
MS-DOS.
So, don't listen to the naysayers...there is actually a market
(small as it is) for 'DMD for MS-DOS'.
Then I can finally retire Borland C++ 3.1 ... may it rest in
peace.

I run dmd regularly on an XP box, but that just means dmd
itself runs on XP. (I converted the front end of DMC++ to D,
using DMD in -betterC mode, and XP is the last operating
system that supports DOS programs. XP has the DOS DMC++ test
suite on it.)

I don't think that's true. It's a 32bit/64bit division, not a
Windows version thing. A 32 bits installation can run 16 bits
and 32 bits programs, a 64 bits version can run natively 32
bits and 64 bits programs. None can run all 3 modes natively.

Is that an issue with the CPU, or the operating system?

CPU officially V86 is not supported in 64 bit mode. But I read a
long time ago in c't that it was technically possible to invoke
V86 mode when running 32 bit code in loing mode, but that it was
quite tricky and required quite some planning to do in all cases
(page table tricks [1]). Microsoft decided to not do these kind
of tricks and allows only V86 mode in 32 bits installations.
Furthermore, neither AMD not Intel really document that it is
possible and it could be that future version of the CPU will not
allow for it (the issue with VME mode in Ryzen seem to show that
the manufacturers test these exotic legacy modes less and less
[2][3]).

I know with certainty that Windows 8.1 32 bits installation
could still run DOS and Windows 16 bits apps. I haven't seen
evidence to the contrary for Windows 10.
Windows XP was the last version that was installed massively
in 32 bits mode.
From Vista on, the proportion of 32 bits installations (and
thus losing 16 bits support) dwindeled.

Windows 7 64 bit will not run 16 bit programs. Try it and you
get a dialog box "Unsupported 16-Bit Application". I haven't
tried Win 7 32, but some googling around shows you are correct.

From the recent PR-related discussion I gather that FreeBSD 12
has made some breaking changes to file primitives such as stat.
Do binaries built for pre-v12 crash on v12? If that's the case
we should have two distinct build platforms, FreeBSD "legacy"
and FreeBSD 12. They would be selected statically.
IF older binaries don't crash, what mechanism is FreeBSD 12
using to identify old API calls?
Thanks,
Andrei

Targetted versioning should be implemented. Full stop ;-)
Pre ino64 ABI compatibility can be obtained in 12, **if** the
kernel is compiled with option COMPAT_FREEBSD11 (presumably this
option is enabled in the DEFAULT kernel)...
That option enables 'several techniques' that can mitigate for
ABI breakage, but it won't work for all cases - really depends on
what the application is doing with struct stat.
https://svnweb.freebsd.org/base/head/sys/sys/stat.h?view=markup#l158

From the recent PR-related discussion I gather that FreeBSD 12 has made
some breaking changes to file primitives such as stat.
Do binaries built for pre-v12 crash on v12? If that's the case we should
have two distinct build platforms, FreeBSD "legacy" and FreeBSD 12. They
would be selected statically.
IF older binaries don't crash, what mechanism is FreeBSD 12 using to
identify old API calls?

Thanks to all who answered. From what I gathered from the two on-topic
responses, it seems binary compatibility is not provided across major
versions. Like Walter, I'd be in favor of supporting the latest only.
Going slightly off-topic (ironically as will become obvious in a
second), a sign of maturity in our community would be to use forum
discussions as a catalyst and driver for work on new and existing
projects. This thread seems to suggest we could improve on that, seeing
that the majority of answers are off-topic and there is very little
factual information or work items once this thread lives its course.
I've been asked why I have reduced my presence in this forum - and
politely told it's being missed :o) - and the simple answer is I've
noticed the forum discussions produce few results outside the forum. I'm
still looking for the perfect formula that combines good forum
engagement with palpable work.
Thanks,
Andrei

I've been asked why I have reduced my presence in this forum -
and politely told it's being missed :o) - and the simple answer
is I've noticed the forum discussions produce few results
outside the forum. I'm still looking for the perfect formula
that combines good forum engagement with palpable work.
Thanks,
Andrei

Well.. all I can say..is be careful.
If you make this forum like the FreeBSD forums, then people will
stop engaging, and there goes your community....(i.e go off topic
in those forums and see what happens to you).
Disussions lead to discusions..lead to discussions...that's
normal human behaviour.
Unexpected (OT) results can be useful for the D community too...
Perhaps some way to mark our thread as OT would be good. Then one
could filter out OT discussion. But any attempt to stop OT
discussion will come back and bite the community I believe.
Humans' like discussing things too.
This thread did lead to some unintended outcomes, like me finding
that gdc will compile code that dmd and ldc will not -
apparentaly a bug in gdc, but a bug that I actually like. It lead
(I hope) to a greater understanding of the importance of FreeBSD
and the need for D to pro-actively support it (remember FreeBSD
really is the only mature open source alternative to gpl Linux -
but it gets treated as a second class citizen by far too many
(e.g. the latested LDC release anouncement provides binaries for
all platforms except FreeBSD??).
And most importantly, OT discussion in this thread may lead to a
DMD for DOS! Now tell me that wasn't worth some OT discussion ;-)

It lead (I hope) to a greater understanding of the
importance of FreeBSD and the need for D to pro-actively support it (remember
FreeBSD really is the only mature open source alternative to gpl Linux - but
it
gets treated as a second class citizen by far too many

The FreeBSD port came from me having a soft spot for it :-) and also because
Jan
Knepper, our server provider, runs our web sites on a FreeBSD server.

Correction: ABI changes 'may' occur between major releases, and
your binary may or may not run correctly, depending on whether
those ABI changes are related to anything your binaries does -
that is my understanding anyway. You can certainly take the DMD
binaries and run them on 12 though. Beyond that, it just depends
on what they're doing with regards to any change in the ABI. So
one must study those ABI changes carefully, and consider their
impact on DMD/PHOBOS etc...
e.g does DMD/PHOBOS make of the inode struct? If so, where? And,
what types are being used for storing the elements of that
struct? I'm not sure many of us are in a position to investigate
that any further.

Like Walter, I'd be in favor of supporting the latest only.

Can I presume, by 'latest' you mean the latest 'release branch'
(which would be the 11.x branch).
If 'latest' actually means the CURRENT branch (aka HEAD), then
that is 12, and it would be a mistake if that's is only what D
was going to support (since most people wisely prefer to run a
stable release branch (e.g 10.x, 11,x).
If resources are limited, then I believe resources should be
prioritised towards the latest release branch (which is the 11.x
branch).