Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deployment of keepassxc-cli and keepassxc-proxy and the autotype plugin #7479

Conversation

alcroito
Copy link
Contributor

@alcroito alcroito commented Mar 1, 2022

Fixes: #7475

Testing strategy

Tested manually

Type of change

  • ✅ Bug fix (non-breaking change that fixes an issue)

@alcroito alcroito force-pushed the fix_macos_cli_rpath_embedding branch from e124b2b to 9166373 Compare March 1, 2022 17:35
@alcroito alcroito changed the title Fix rpath embedding of keepassxc-cli Fix deployment handling of keepassxc-cli and keepassxc-proxy Mar 1, 2022
@phoerious
Copy link
Member

phoerious commented Mar 1, 2022

Thanks. The same procedure should probably be applied here as well:

add_custom_command(TARGET keepassxc-autotype-cocoa
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libkeepassxc-autotype-cocoa.so ${PLUGIN_INSTALL_DIR}/libkeepassxc-autotype-cocoa.so
COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassxc-autotype-cocoa.so -no-plugins 2> /dev/null
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Deploying autotype plugin")

Also, do you have any idea why it works for the main binary?

add_custom_command(TARGET ${PROGNAME}
POST_BUILD
COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app 2> /dev/null
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Deploying app bundle")

I am also confused about what has changed for this to be a problem at all. The POST_BUILD fixup definitely worked when I implemented it.

@alcroito
Copy link
Contributor Author

alcroito commented Mar 1, 2022

Thanks. The same procedure should probably be applied here as well:

I guess i'll introduce a function to reuse the logic.

Also, do you have any idea why it works for the main binary?

I didn't investigate. If this is a recent regression, maybe i can bisect to see when it broke and figure out why.

@varjolintu
Copy link
Member

Also, do you have any idea why it works for the main binary?

This is what I wondered as well. It always worked for the main binary, even with package or without.

@alcroito alcroito force-pushed the fix_macos_cli_rpath_embedding branch from 9166373 to 50d717f Compare March 2, 2022 10:29
@alcroito
Copy link
Contributor Author

alcroito commented Mar 2, 2022

So i went ahead and investigated what's going on. The commit message has the full explanation.
But the gist of it is that the cli/proxy helpers in the .dmg had broken rpaths since the change that switched to using macdeployqt.

Also, do you have any idea why it works for the main binary?

The main binary does not do any POST_BUILD copies, so the install(TARGETS ${PROGNAME}) called implicitly by cpack successfully installed the app with proper rpaths into the staging area for .dmg creation.

The POST_BUILD cli / proxy copies are initially installed by install(TARGETS ${PROGNAME}) because installing a bundle installs all its contents, including the copies, but then they got overridden again by the install(TARGETS cli/proxy) calls, which would copy the non-macdeployqt'ed binaries.

@alcroito alcroito changed the title Fix deployment handling of keepassxc-cli and keepassxc-proxy Fix deployment of keepassxc-cli and keepassxc-proxy and the autotype plugin Mar 2, 2022
@alcroito
Copy link
Contributor Author

alcroito commented Mar 2, 2022

Note that while the current PR fixes the immediate issue, there is potential for improvement by delaying the macdeployqt call on the main app to install time.
That would improve incremental build times (no more POST_BUILD macdeployqt calls), and we can likely merge all 4 macdeployqt calls into a single one taking multiple -executable parameters, also speeding up install time.
I can try to implement that if it would be deemed acceptable.

@phoerious
Copy link
Member

But the gist of it is that the cli/proxy helpers in the .dmg had broken rpaths since the change that switched to using macdeployqt.

I can say with certainty that that is not the case. First, because I tested it and the paths were fixed. And secondly because users would have been unable to use KeePassXC-Browser or the CLI on macOS.

@alcroito
Copy link
Contributor Author

alcroito commented Mar 2, 2022

But the gist of it is that the cli/proxy helpers in the .dmg had broken rpaths since the change that switched to using macdeployqt.

I can say with certainty that that is not the case.

That's my assessment at least, you are free to think otherwise :)

I confirmed it by checking out the commit that introduced the usage of macdeployqt and doing a clean build and .dmg using it
af55d1b

I also tried the commit before it, which directly called install_name_tool -change instead of macdeployqt.
Note that in that case, the rpath was changed directly in the initial binary, not the POST_BUILD copy, so those changes are preserved during make install -> .dmg creation.

I did not try using older CMake versions, but I am skeptical that CMake/cpack changed their behavior / order of installation for .dmg creation.
You can also confirm my assessment about install overriding the macdeployqt'ed binaries by running cpack in --trace mode and grepping for the installation of the app bundle and the binaries (specifically the source of the copy).

If you still don't believe my assessment, you can try checking out that commit and do a .dmg build yourself. I would be happy to be proven wrong, in which case we'd have more data on whether this is somehow depended on the environment.

First, because I tested it and the paths were fixed. And secondly because users would have been unable to use KeePassXC-Browser or the CLI on macOS.

Yes, they would have been unable to use them. But how many users were using a 2.7.0 .dmg snapshot? Was there any snapshot up until recently? Wouldn't most testers build it from source, and not use the .dmg?
The cli/proxy macdeployqt change was not shipped in 2.6.6.

@droidmonkey
Copy link
Member

I believe your assessment FWIW

@phoerious
Copy link
Member

phoerious commented Mar 2, 2022

The issue was originally posted against 2.6.4 (#6042) and we definitely fixed it for follow-up stable versions (we kind of skipped 2.6.5 iirc, but 2.6.6 most certainly works). But you are right, this has apparently never been backported to the branch. The master branch still has the manual install_name_tool fixes.

@droidmonkey
Copy link
Member

@phoerious ready to merge this?

@phoerious
Copy link
Member

Go for it.

CPack by default invokes the 'make install' target to install
all project files into a staging area for further packaging.

The order of installation follows the order of install() commands.

One of the first install() commands is the one that installs the
KeePassXC.app bundle and all the contents inside of it,
which includes POST_BUILD copied binaries like keepassxc-cli
and keepassxc-proxy.

Subsequent install(TARGETS) commands would then override the
keepassxc-cli and keepassxc-proxy binaries inside the staging area
with the ones which didn't have macdeployqt run on them (the ones from
src/cli and src/proxy).
Launching the binaries would then fail because of missing rpath
adjustments.

The libkeepassxc-autotype-cocoa.so library was working fine because
there is no install(TARGETS) command for it in a WITH_APP_BUNDLE build,
so the POST_BUILD copy with the adjusted rpaths was preserved.

To fix the issue and make the handling consistent, macdeployqt is no
longer run at POST_BUILD time, but instead at 'make install' time,
after each binary is installed by install(TARGETS).

libkeepassxc-autotype-cocoa.so also has its install command run
unconditionally now.

The build dir binaries that are POST_BUILD copied into
src/KeePassXC.app continue to run because they use the build dir
rpaths that CMake embeds by default. They don't macdeployqt run for
them anymore, which slightly speeds up the build time.

Fixes: keepassxreboot#7475
@droidmonkey droidmonkey force-pushed the fix_macos_cli_rpath_embedding branch from 50d717f to db7bbb2 Compare March 5, 2022 16:03
@droidmonkey droidmonkey changed the base branch from develop to release/2.7.0 March 5, 2022 16:03
@droidmonkey droidmonkey merged commit abfebea into keepassxreboot:release/2.7.0 Mar 5, 2022
@alcroito alcroito deleted the fix_macos_cli_rpath_embedding branch March 5, 2022 18:16
@phoerious
Copy link
Member

@droidmonkey @alcroito I think we have to revert this and find another solution. The patch made it impossible to run the binary on the fly on macOS, because of signature mismatches. Running the binary through the debugger is already the only way to start KeePassXC from my IDE on ARM64, but with this patch even that doesn't work anymore.

@droidmonkey
Copy link
Member

droidmonkey commented Mar 12, 2022

Ahhh so that's why appbundle was crashing on me...

@phoerious
Copy link
Member

Yes, all binaries are signed locally and modifications create signature mismatches. I tested #7509 and it fixes the issue by deferring such changes until install time, which allows me to run binaries from my IDE again. I guess that settles it. In fact, it's even better than before, because I can finally run it without the debugger again. Previously, running KeePassXC from my IDE without the debugger would crash with a signature error.

@phoerious
Copy link
Member

Seems like you can also run the binary from the local build directory directly again with the post-install method, but not from the DMG generated by make package. I suppose the ad-hoc signature is applied in between these steps now.

@alcroito
Copy link
Contributor Author

Do you observe these issues only on an m1 mac? What's the exact error you get, so I can know what to look out for.

Also, which ad-hoc signing are you referring to? Afaik ad-hoc signing is done by the linker when linking the binaries / shared libraries.
And afaik, the CPack DragNDrop generator (.dmg) does no signing by default.

@phoerious
Copy link
Member

The linker adds an ad-hoc signature, but when you patch a binary's rpath, the hash doesn't match anymore, so Apple Silicon Macs will kill the process immediately. Luckily, with your follow-up PR, it's only a problem with the binaries installed into a bundle, not with the binaries inside the build dir.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

keepassxc-cli and keepassxc-proxy won't launch — incorrect dylib load paths
4 participants