This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Remove tools copied into LLDB.framework before install
ClosedPublic

Authored by JDevlieghere on Jan 4 2023, 4:46 PM.

Details

Summary

CMake supports building Framework bundles for Apple platforms. We rely
on this functionality to create LLDB.framework. From CMake's
perspective, a framework is associated with a single target. In reality,
this is often not the case. In addition to a main library (liblldb) the
frameworks often contains associated resources that are their own CMake
targets, such as debugserver and lldb-argdumper.

When building and using the framework to run the test suite, those
binaries are expected to be in LLDB.framework. We have a function
(lldb_add_to_buildtree_lldb_framework) that copies those targets into
the framework.

When CMake installs a framework, it copies over the content of the
framework directory and "installs" the associated target. In addition to
copying the target, installing also means updating the RPATH. However,
the RPATH is only updated for the target associated with the framework.
Everything else is naively copied over, including executables or
libraries that have a different build and install RPATH. This means that
those tools need to have their own install rules.

If the framework is installed
first, the aforementioned tools are copied over with build RPATHs from
the build tree. And when the tools themselves are installed, the
binaries get overwritten and the RPATHs updated to the install RPATHs.

The problem is that CMake provides no guarantees when it comes to the
order in which components get installed. If those tools get installed
first, the inverse happens and the binaries get overwritten with the
ones that have build RPATHs.

lldb_add_to_buildtree_lldb_framework has a comment correctly stating
that those copied binaries should be removed before install.
Unfortunately, there's nothing in place today to do that. This patch
adds a custom target (lldb-framework-cleanup) that must will be run
before the install phase of LLDB.framework.

Diff Detail

Event Timeline

JDevlieghere created this revision.Jan 4 2023, 4:46 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 4 2023, 4:46 PM
JDevlieghere requested review of this revision.Jan 4 2023, 4:46 PM

I think this idea will work but I have a few comments and questions:

Based on my understanding of this change, we're supposed to manually run the build system with the target lldb-framework-cleanup before we perform an install. Is this the case? This seems most useful when you have a script that controls the build process (e.g. swift's build-script).
I suppose this doesn't really change anything if you don't know about this new target, but it would be useful to document this somewhere (perhaps in docs/resources/build.rst?)

Making this a dependency of the install target is not sufficient as the target needs to be build before the install phase.

I can see why making the install target depend on lldb-framework-cleanup is not good, but what about making it a dependency of the target that installs the framework? I think it's something like install-liblldb? You could then guarantee that the cleanup happens before we install the framework. Maybe this is still too naïve or brittle though, what do you think?

mib added inline comments.Jan 9 2023, 2:59 PM
lldb/cmake/modules/AddLLDB.cmake
247–249

The comment here is confusing to me. May be you can try to re-phrase it.

JDevlieghere added a comment.EditedJan 9 2023, 5:01 PM

I think this idea will work but I have a few comments and questions:

Based on my understanding of this change, we're supposed to manually run the build system with the target lldb-framework-cleanup before we perform an install. Is this the case? This seems most useful when you have a script that controls the build process (e.g. swift's build-script).
I suppose this doesn't really change anything if you don't know about this new target, but it would be useful to document this somewhere (perhaps in docs/resources/build.rst?)

Making this a dependency of the install target is not sufficient as the target needs to be build before the install phase.

I can see why making the install target depend on lldb-framework-cleanup is not good, but what about making it a dependency of the target that installs the framework? I think it's something like install-liblldb? You could then guarantee that the cleanup happens before we install the framework. Maybe this is still too naïve or brittle though, what do you think?

Interesting, I tried the exact thing that you described and my custom command wasn't run, but I cannot reproduce that anymore. The only reason I tried again was so I could say: "see, this doesn't work, it won't get executed", but then it did...

I don't know what I did differently then, but as this seems to work and is clearly more desirable, I'll update the patch.

JDevlieghere marked an inline comment as done.

Make lldb-framework-cleanup a dependency of install-liblldb.

JDevlieghere retitled this revision from [lldb] Add lldb-framework-cleanup target to [lldb] Remove tools copied into LLDB.framework before install.Jan 9 2023, 5:40 PM
JDevlieghere edited the summary of this revision. (Show Details)
bulbazord added inline comments.Jan 10 2023, 10:39 AM
lldb/source/API/CMakeLists.txt
215–216 ↗(On Diff #487613)

I think you need to add it as a dependency of install-liblldb-stripped as well?

Add dependency to install-liblldb-stripped.

bulbazord accepted this revision.Jan 10 2023, 11:20 AM
This revision is now accepted and ready to land.Jan 10 2023, 11:20 AM
This revision was landed with ongoing or failed builds.Jan 10 2023, 11:22 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptJan 10 2023, 11:22 AM
labath added a subscriber: labath.Jan 11 2023, 6:04 AM

Does this mean that the in-tree lldb will cease to be functional once someone "installs" it? (at least until the next rebuild)

Does this mean that the in-tree lldb will cease to be functional once someone "installs" it? (at least until the next rebuild)

I believe so, but only in the case where you are building the LLDB framework on a macOS machine. I don't think this is ideal behavior but I personally think the tradeoff is worth it since you have deterministic installations behavior w.r.t. RPATHs.

I don't dispute the value of determinism, but it seems like there ought to be a way to achieve this with corrupting the build tree (which in itself is not very 'deterministic').
What if we had two copies of the framework in the build-tree? One pristine copy, which would only contain liblldb (and any stuff that cmake puts there by default), and then another one which would be used for running, and which would contain all of the manually added stuff (with the right rpaths and all). When installing, one would use the pristine copy as the source instead of the adulterated one.