[lld] Flavour option purpose

Hi all,

According to lld/docs/Driver.rst, Flavor command line option determines the style of lld command-line interface when invoked.

However, it looks like this option also determines the set of supported targets we are linking for. For example, lld -flavor gnu
cannot link mach-o binaries, and could not link PE binaries either (well, not until rL312926).

Is this really intended by the design of lld? It looks the flavours are merely legacy compatibility shims, but then why is there no
universal lld driver that is able to link binary for any platform using a unified CLI?

The -flavor option exists mostly for historical reasons. I think using ld.lld or lld-link is preferred way over “lld -flavor gnu” or “lld -flavor link”.

I think using ld.lld or lld-link is preferred way over "lld -flavor gnu" or "lld -flavor link".

-flavor seems to be still actively used in Clang… By the the way, there seems to be no special
command name for Darwin targets, so ld.lld (incorrectly) invokes the ELF linker there
(see https://bugs.llvm.org/show_bug.cgi?id=34792#c1)

Regardless, I would be interested in hearing the answer to the rest of the questions.

Martell recently added "ld64.lld" as a name for the Darwin driver.

As to why there's no driver that provides a unified command line arguments,
I can't speak for other people. But no one seems to have been interested in
it enough to actually invent and implement a set of unified command line
arguments.

I mean, there is such a universal driver – it’s called “clang”.

Thank you for your answers.

Indeed, Clang is universal, but only until one needs to pass some commands to the linker which are not
automatically passed by the driver. Then we are back to the same problem.

In my opinion, it would be great if lld had a unified, GNU-like interface. Of course, if nobody else is interested,
it's probably not even worth it drafting an RFC. :frowning:

Thank you for your answers.

Indeed, Clang is universal, but only until one needs to pass some commands to the linker which are not
automatically passed by the driver. Then we are back to the same problem.

Clang and GCC both support the `-Wl,` and `-Xlinker` flags...

Jon

I am aware of these flags, but this is not my point. I am talking about Darwin and Link lld drivers
not being on par with the GNU driver. While using clang for linking helps, as it provides some flags
to the linker, as soon as you want to do something clang does not automatically do, you still have
the issue of different flags for different drivers/targets.

Most command line options in GNU, macOS and MSVC are not just different in terms of notion but different in terms of semantics. For example, MSVC link.exe doesn’t have --start-group and --end-group options because their symbol resolution semantics are different than Unix. link.exe on the other hand doesn’t have --init or --fini options because that’s ELF-only concept. Linker scripts exist only in GNU. You cannot hide these differences even if you create a unified driver, which makes a unified driver less attractive to me.

Also, I think if we try to create a unified interface, I guess it would end up with this situation – https://xkcd.com/927/. We have three standards – GNU, Darwin and MSVC. I don’t know if we want another one.

The original design of lld had a single driver for all 3 formats that
compatibility drivers would target. It was eventually determined that this
didn't work in practice as the formats are each so different, so this was
dropped and was not carried over to the new COFF and ELF lld designs.

- Michael Spencer

For example, MSVC link.exe doesn't have --start-group and --end-group options because their symbol resolution semantics are different than Unix.

Yes, but this is specific for a linker, not for a target. For example, GNU ld supports this option for all binary formats. A linker with universal CLI would then
support this flag for all targets as well (or drop the support for all targets if recursive dependency resolution can be implemented without that flag).

link.exe on the other hand doesn't have --init or --fini options because that's ELF-only concept.

Yes, so a universal CLI would hide this flag when linking non-ELF binaries, as well as any other option not supported by the target currently linking for.
(This is not the same as using a separate flavour for that target.)

Linker scripts exist only in GNU.

My reasoning is the same as for `start-group'. In fact, lld does not achieve feature parity with GNU ld configured for mach-o here:
the latter can use scripts when linking a mach-o binary, but lld cannot use scripts at all unless GNU flavor is used, and then mach-o is
unsupported.

Also, I think if we try to create a unified interface, I guess it would end up with this situation -- https://xkcd.com/927/. We have three standards -- GNU, Darwin and MSVC. I don't know if we want another one.

This depends on whether the flavoured CLIs are removed upon merge. (Of course, it is probably impractical to remove them all at once.)

In my opinion, GNU ld has CLI closest to my description, so it is a good basis for a universal interface. In fact, GNU flavour can be universal if support
for more targets is added there, but then the other flavours will likely be redundant. One difference would be that a universal CLI need not maintain compatibility
with GNU ld CLI.

> For example, MSVC link.exe doesn't have --start-group and --end-group
options because their symbol resolution semantics are different than Unix.

Yes, but this is specific for a linker, not for a target. For example, GNU
ld supports this option for all binary formats. A linker with universal CLI
would then
support this flag for all targets as well (or drop the support for all
targets if recursive dependency resolution can be implemented without that
flag).

> link.exe on the other hand doesn't have --init or --fini options because
that's ELF-only concept.

Yes, so a universal CLI would hide this flag when linking non-ELF
binaries, as well as any other option not supported by the target currently
linking for.
(This is not the same as using a separate flavour for that target.)

> Linker scripts exist only in GNU.

My reasoning is the same as for `start-group'. In fact, lld does not
achieve feature parity with GNU ld configured for mach-o here:
the latter can use scripts when linking a mach-o binary, but lld cannot
use scripts at all unless GNU flavor is used, and then mach-o is
unsupported.

> Also, I think if we try to create a unified interface, I guess it would
end up with this situation -- https://xkcd.com/927/. We have three
standards -- GNU, Darwin and MSVC. I don't know if we want another one.

This depends on whether the flavoured CLIs are removed upon merge. (Of
course, it is probably impractical to remove them all at once.)

You can't really remove any native linker-compatible command line interface
unless you get agreement from all parties including Microsoft and Apple to
switch to the GNU command line as the universal interface in the future
versions of their toolchains. Our linker is designed to be a drop-in
replacement, so in that sense, we are just a follower. If you are really
aiming for a universal command line interface, I think you need to convince
not us but other first-party toolchain developers.

In my opinion, GNU ld has CLI closest to my description, so it is a good

You can't really remove any native linker-compatible command line interface unless you get agreement from all parties including Microsoft and Apple to switch to the GNU command line as the universal interface in the future versions of their toolchains.

I completely agree; that's why I said this is not feasible for the time being.

I am still wondering about a few things:

Is it desired to address the functional difference of the flavours at all?

Is it a bug if a flavour has a feature that its original counterpart does not have? For example, would it be
acceptable to add scripting support to the Darwin flavour, given that Apple ld64 does not support scripts?

> You can't really remove any native linker-compatible command line
interface unless you get agreement from all parties including Microsoft and
Apple to switch to the GNU command line as the universal interface in the
future versions of their toolchains.

I completely agree; that's why I said this is not feasible for the time
being.

I am still wondering about a few things:

Is it desired to address the functional difference of the flavours at all?

Is it a bug if a flavour has a feature that its original counterpart does
not have? For example, would it be
acceptable to add scripting support to the Darwin flavour, given that
Apple ld64 does not support scripts?

No and no. It is not desired and it is not a bug.

> You can't really remove any native linker-compatible command line
interface unless you get agreement from all parties including Microsoft and
Apple to switch to the GNU command line as the universal interface in the
future versions of their toolchains.

I completely agree; that's why I said this is not feasible for the time
being.

I am still wondering about a few things:

Is it desired to address the functional difference of the flavours at all?

Is it a bug if a flavour has a feature that its original counterpart does
not have? For example, would it be
acceptable to add scripting support to the Darwin flavour, given that
Apple ld64 does not support scripts?

No and no. It is not desired and it is not a bug.

Sorry, the last "no" is to your last sentence. We generally want to
implement all features to make lld drop-in replacements to the existing
linkers, but any additional features beyond that should be carefully
examined and discussed per-feature basis before being accepted.

I see! I hope we can return to this topic someday :slight_smile:

Once again, thanks for the answers and your patience.