This is somewhat true, but not entirely. You have to remember that FreeBSD and Linux share no common ancestors, and FreeBSD defines its ABI at the libc level, whereas Linux defines it at the syscall level. There are also subtle differences in how various internal kernel mechanisms work (such as flag definitions for calls). See linux_common_open() for an example of an "easy" straight mapping. https://github.com/freebsd/freebsd/blob/68a4c41e983228d54619...
This is true even between OSes that share a common ancestor. I was the maintainer of FreeBSD/alpha, and did the compat layer for OSF/1 / DEC UNIX / Tru64 starting with NetBSD's version and adding new calls, etc. The very easiest calls were the simple ones that both inherited from 4.3BSD or earlier (read, write). Medium were things that had diverged in different ways (stat, mmap), and for me the harder things were ABI handlers for the OSF/1 executable format (ecoff).
The hardest stuff was things at almost worked, except for maybe one flag was different, and it was hard to notice because an OSF/1 program would run for 5 minutes, and then coredump.
> FreeBSD defines its ABI at the libc level, whereas Linux defines it at the syscall level
Actually, this really does make it more impressive than I'd realized, especially since FreeBSD didn't just shim libc in - I've run an Alpine Linux (musl-based) chroot on FreeBSD and that worked, which it wouldn't have if they just made a glibc-like wrapper. (I think.)
This is true even between OSes that share a common ancestor. I was the maintainer of FreeBSD/alpha, and did the compat layer for OSF/1 / DEC UNIX / Tru64 starting with NetBSD's version and adding new calls, etc. The very easiest calls were the simple ones that both inherited from 4.3BSD or earlier (read, write). Medium were things that had diverged in different ways (stat, mmap), and for me the harder things were ABI handlers for the OSF/1 executable format (ecoff).
The hardest stuff was things at almost worked, except for maybe one flag was different, and it was hard to notice because an OSF/1 program would run for 5 minutes, and then coredump.