February 23, 2018
https://issues.dlang.org/show_bug.cgi?id=17596

--- Comment #19 from Cy Schubert <cy@FreeBSD.org> ---
That probably makes sense. I can restrict FreeBSD 10 and 11 to an old release of dmd. At least it addresses the issue going forward.

I'll rework the port the next time I visit it. I'm hoping to have this resolved by the time FreeBSD 12 is released.

--
May 24, 2018
https://issues.dlang.org/show_bug.cgi?id=17596

anonymous4 <dfj1esp02@sneakemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=18885

--
August 15, 2018
https://issues.dlang.org/show_bug.cgi?id=17596

Jonathan M Davis <issues.dlang@jmdavisProg.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |issues.dlang@jmdavisProg.co
                   |                            |m

--- Comment #20 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
(In reply to Vladimir Panteleev from comment #9)
> Alright, so how about:
> 
> - We add getosreldate and INO64_FIRST to druntime
> - We add both the old and new struct definitions
> - We add a stat wrapper which,when getosreldate() < INO64_FIRST, translates
> the old struct to the new struct and returns it.

I tried that with the functions from sys/mount.h that use statfs_t, and it doesn't work. The problem is that from what I can tell, if you build a program on FreeBSD 11, it runs just fine on FreeBSD 12 - at least it did with the functions in sys/mount.h. e.g. When running a program built on FreeBSD 11 on FreeBSD 12, fstatfs reports the same version with its f_version member that it does on FreeBSD 11, and it clearly calls the FreeBSD 11 version of fstafs. objdump confirms this. If you compile a C/C++ program which uses fstatfs on FreeBSD 12 and use objdump -t on it and grep for fstatfs, it has

00000000002013e0       F *UND*  0000000000000000              fstatfs

whereas if you compile it on FreeBSD 11, you get

0000000000000000       F *UND*  0000000000000011              fstatfs@@FBSD_1.0

Building a D program that does the same thing on FreeBSD 11 also results in

0000000000000000       F *UND*  0000000000000011              fstatfs@@FBSD_1.0

and it still says

0000000000000000       F *UND*  0000000000000011              fstatfs@@FBSD_1.0

if you run objdump on it in FreeBSD 12. And it runs just fine on FreeBSD 12.

If I create a wrapper in druntime so that it uses the FreeBSD 11 version of stat_t if getosreldate() < INO64_FIRST, then it works just fine on FreeBSD 11 but fails miserably when running that binary on FreeBSD 12, because the binary has the FreeBSD 11 version of the function in it, and it's the FreeBSD 11 version of stat_t that it's using even though it's running on FreeBSD 12.

So, from what testing I've done thus far, running D binaries built on FreeBSD 11 on FreeBSD 12 works just fine. What fails is when you try to build a program on FreeBSD 12 (including the compiler). The resulting binary doesn't work properly if it uses any of the structs that changed, because the definition in D does not match the definition in C.

It may be that taking a program built on FreeBSD 11 which uses a function like fstatfs and running it on FreeBSD 12 only works because the OS itself detects which version of the function your program is built with and therefore calls the old version of the syscall internally (I don't know), but building a D program on FreeBSD 11 and running it on 12 seems to work just fine right now, whereas if you build anything with dmd on FreeBSD 12 where the definition in druntime does not match the actual FreeBSD 12 definition, then it doesn't work.

So, my conclusion is that the only way to fully fix this is for the struct definitions to be versioned based on the version of FreeBSD the program is built on (which would then allow us to do the same thing that C/C++ does and have versioned headers). And arguably, assuming that there's only one version of the OS when creating bindings for the OS headers is a terrible idea to begin with. We only really get away with it like we do because of the fact that most of them don't change very often.

In any case, all of the extra stuff with detecting the version of FreeBSD at runtime in D and changing which version of a struct you use based on what getosreldate() says might make it possible to run a binary built on FreeBSD 12 (with the FreeBSD 12 versions of the structs) on FreeBSD 11 (I don't know), but it breaks running a FreeBSD 11 binary on FreeBSD 12.

As far as I can tell, we really only have two options:

1. Make it so that dmd actually provides a version identifier for different versions of FreeBSD (e.g. FreeBSD11 and FreeBSD12) so that we can version the definitions in druntime just like they would be in the actual C headers (since FreeBSD 11 gets different headers than FreeBSD 12). That way, we could version most stuff with FreeBSD like we always have but cleanly cope when definitions change between versions of FreeBSD by versioning those few symbols with identifiers such as FreeBSD11 or FreeBSD12.

2. Have a PR where we change all of the struct definitions that differ between FreeBSD 11 and FreeBSD 12, use a dmd binary built on FreeBSD 11 with the old code to build it, and then immediately require that everything built with that version of dmd and newer use FreeBSD 12. That's theoreticaly feasible, but it could be difficult to make work well with the auto-tester, and it would be fairly disruptive. This isn't like with Windows where we say that we support version X, but older versions work well enough for folks to get by during the transition. It's a distinct point where dmd either works with FreeBSD 11 or FreeBSD 12 but not both. Without versioning the definitions themselves, we can't provide a release of dmd that's going to work on both FreeBSD 11 and FreeBSD 12 even temporarily.

As such, I am strongly inclined to argue that we add version identifiers to D for FreeBSD11 and FreeBSD12 - either that or some function that provides the version that the code is being built on which can then be used with static if instead of version, but that can't be done without compiler support, because CTFE can't call stuff like getosreldate() or uname().

--
August 15, 2018
https://issues.dlang.org/show_bug.cgi?id=17596

--- Comment #21 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
This adds version identifiers for the version of FreeBSD, which will make it possible to version OS bindings for the version of FreeBSD where necessary:

https://github.com/dlang/dmd/pull/8567

--
August 16, 2018
https://issues.dlang.org/show_bug.cgi?id=17596

Martin Nowak <code@dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code@dawg.eu

--- Comment #22 from Martin Nowak <code@dawg.eu> ---
What happened to the idea of runtime compat checks mentioned in comment 9?
In particular it seems that FreeBSD's dealing with the ABI change in C should
be fully understood before taking any measures.
Also there are versioned symbols in FBSD12 that use the old struct layouts
(e.g. `stat@FBSD_1.0`). We could always use those for now.
As another option you might use the new functions and struct layouts if running
on >=12, but translate the structs to the old layout and explicitly call the
old versioned symbols if running on <12.

--
August 18, 2018
https://issues.dlang.org/show_bug.cgi?id=17596

--- Comment #23 from Jonathan M Davis <issues.dlang@jmdavisProg.com> ---
And this is my PR with the binding changes that are required to get the druntime and Phobos unit tests and the dmd test suite passing:

https://github.com/dlang/druntime/pull/2280

(In reply to Martin Nowak from comment #22)
> What happened to the idea of runtime compat checks mentioned in comment 9?
> In particular it seems that FreeBSD's dealing with the ABI change in C
> should be fully understood before taking any measures.
> Also there are versioned symbols in FBSD12 that use the old struct layouts
> (e.g. `stat@FBSD_1.0`). We could always use those for now.
> As another option you might use the new functions and struct layouts if
> running on >=12, but translate the structs to the old layout and explicitly
> call the old versioned symbols if running on <12.

Rather than repeating myself, I'll let anyone read the discussion in the dmd PR to get the full answer to that.

--
August 11, 2019
https://issues.dlang.org/show_bug.cgi?id=17596

--- Comment #24 from Cy Schubert <cy@FreeBSD.org> ---
I've had no choice but to deorbit the dmd2 port as it has been marked broken for more than 6 months. We can always resurrect it later though.

--
November 13, 2020
https://issues.dlang.org/show_bug.cgi?id=17596

--- Comment #25 from Dlang Bot <dlang-bot@dlang.rocks> ---
@ibuclaw created dlang/druntime pull request #3271 "Issue 17596: Version bindings so that they work for both FreeBSD 11 and 12" mentioning this issue:

- Issue 17596: Version bindings so that they work for both FreeBSD 11 and 12.

https://github.com/dlang/druntime/pull/3271

--
November 24, 2020
https://issues.dlang.org/show_bug.cgi?id=17596

--- Comment #26 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/druntime pull request #3271 "Issue 17596: Version bindings so that they work for both FreeBSD 11 and 12" was merged into master:

- 0dd4243100275a6969b5cdc24da68831d3f65599 by Iain Buclaw:
  Issue 17596: Version bindings so that they work for both FreeBSD 11 and 12.

https://github.com/dlang/druntime/pull/3271

--
November 24, 2020
https://issues.dlang.org/show_bug.cgi?id=17596

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ibuclaw@gdcproject.org

--- Comment #27 from Iain Buclaw <ibuclaw@gdcproject.org> ---
So, I'm not having any trouble building dmd on FreeBSD 12.2 using AUTO_BOOTSTRAP=1 DFLAGS=-version=TARGET_FREEBSD12

After the half dozen or so PRs, the CI pipeline for FreeBSD 12 is not reporting any testsuite or unittest failures either, so I think this is now resolved.

--