Linking libMacportsLegacySupport privately?
Fred Wright
fw at fwright.net
Tue Apr 1 18:40:46 UTC 2025
On Sun, 30 Mar 2025, Chris Jones wrote:
>> On 28 Mar 2025, at 6:01 pm, Fred Wright <fw at fwright.net> wrote:
>>> On Fri, 28 Mar 2025, Chris Jones via macports-dev wrote:
>>>> On 27/03/2025 10:08 pm, Fred Wright wrote:
[...]
>>>> If libc++ is statically linked with legacy-support, then it will of course
>>>> contain any legacy-support symbols that it references. If it's dynamically linked, then it won't unless it's been explicitly configured to do so.
>>>
>>> They intentionally link statically.
>>>
>>> https://github.com/macports/macports-ports/blob/master/lang/llvm-20/Portfile#L15
>>
>> For what's almost certainly an obsolete reason. Can you provide any
>> justification beyond "it used to be necessary" or "that's the way it's
>> always been done, for reasons nobody remembers"?
>
> Not at all. LLVM primarily provides static libraries, and in order to
> get these to use legacy support features where required they need to be
> linked statically as well.
I think you're right, but not for the reason you state. There's no need
for a static library to statically link libMacportsLegacySupport to "use
legacy support features", any more than it would need to statically link
libSystem to "use OS features". The only issue is with dependency
tracking, and the only difference between the two is that the run
dependency on libSystem is implicit.
The problem is that there's no current way to correctly declare a
dependency on a static library in the general case. Consider a case where
port A statically links port B, which dynamically links port C. The
available options for the A->B dependency are:
1) A library dependency. This correctly provides a build dependency on B,
while also incorrectly providing a run dependency on B. But the latter
also recursively creates the needed run dependency on C.
2) A build dependency. This correctly provides a build dependency on B
(duh), and correctly does not provide a run dependency on B. But it fails
to get the needed run dependency on C, since there's no run dependency on
B to recurse through.
What's needed is a new 'depends_staticlib' to handle this case correctly.
This would:
1) Create a build dependency on the target, just as in depends_lib.
2) *Not* create a run dependency on the target.
3) At the time of the dependent's build, capture the target's current run
dependencies and add them to the dependent.
In the above example, if B were later updated to add a run dependency on
D, that wouldn't immediately affect A, since what matters to A is what
dependencies were in effect at the time it was built. But if A were
subsequently rebuilt, it would pick up the new dependency. The same would
apply if B dropped a run dependency.
Note that 'depends_staticlib' would be completely equivalent to
'depends_build' whenever the target has no run dependencies. Hence, it
would always be the correct choice for static libraries, so that the
dependent needs no knowledge of whether the target uses any dynamic
linking.
It might be possible to do this with a PortGroup, but making it a base
feature would be cleaner.
>> A proper Portfile comment doesn't merely explain *what* it's doing, but
>> also *why* it's doing it (if it isn't obvious). The comment in that
>> case is clearly deficient.
>
> Here I agree, the comment could explain that rationale better.
Particularly since misunderstanding the rationale seems to persist. :-)
Fred Wright
More information about the macports-dev
mailing list