-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Added support for Freestanding Bundles reverse lookup #1570
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
Added support for Freestanding Bundles reverse lookup #1570
Conversation
- This enables to find freestanding bundles directories. - Unifies Windows and other platforms approach. - Initial implementation (there are some leaks).
| return executableURL; | ||
| } | ||
|
|
||
| static CFStringRef _CFStringRemovePrefixSuffix(CFStringRef str, CFStringRef prefix, CFStringRef suffix) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to have a Create in the name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe _CFBundleCopyNameByRemovingExcutablePlatformPrefixSuffix?
| kCFCompareAnchored|kCFCompareBackwards); | ||
|
|
||
| CFStringReplace(mutableString, suffixRange, CFSTR("")); | ||
| return mutableString; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this function be calculating the range then just calling CFStringCreateWithSubstring instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's a lot better, thanks!
| CFIndex extensionLength = CFStringGetLength(_CFBundleSiblingResourceDirectoryExtension); | ||
| buffLen -= 4; | ||
| // If this is an _debug, we should strip that before looking for the bundle | ||
| if (buffLen >= 7 && (_wcsnicmp((wchar_t *)&buff[buffLen-6], L"_debug", 6) == 0)) buffLen -= 6; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like support for _debug may have been lost in this code and above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is this still required by Core Foundation on Windows?
|
|
||
| // Otherwise, use the executable name as bundle name (CF). | ||
| if (!bundleName) { | ||
| bundleName = executableName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a CFRetain(executableName) here and CFRelease(bundleName) below to avoid leaking.
| } | ||
|
|
||
| // Find the sibling `.resources` directory (CF.resources). | ||
| CFURLRef parentDirectory = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, executableURL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leak
| #if FREESTANDING_BUNDLES | ||
| if (!url) { | ||
| CFURLRef executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, PLATFORM_PATH_STYLE, false); | ||
| CFStringRef executableName = CFURLCopyLastPathComponent(executableURL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaked
| if (buffLen >= 7 && (_wcsnicmp((wchar_t *)&buff[buffLen-6], L"_debug", 6) == 0)) buffLen -= 6; | ||
| #if FREESTANDING_BUNDLES | ||
| if (!url) { | ||
| CFURLRef executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, PLATFORM_PATH_STYLE, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaked
|
|
||
| // Find the sibling `.resources` directory (CF.resources). | ||
| CFURLRef parentDirectory = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, executableURL); | ||
| CFStringRef siblingResourceDirectoryName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@.%@"), bundleName, _CFBundleSiblingResourceDirectoryExtension); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More leaks... these all should be taken care of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I am aware, work in progress :)
| #endif | ||
|
|
||
| // Freestanding bundles are supported on all platforms. | ||
| #if TRUE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be enabled on Darwin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be useful for things like CLI tools that may require some resources without being in an app bundle. In any case I will disable in Darwin for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CLI that require resources have their own mechanism on Darwin. Freestanding bundles are for FHS OSes and Windows only.
|
What's the plan here? Mainly a refactoring? |
|
Yes, a bit of cleaning, unifying the old freestanding Windows bundles with the new cross-platform implementation and allow reverse bundle lookup (finding the bundle resources folder from the executable location) which was not available. This will enable using |
|
@millenomi No, you implemented the logic to search the Bundle executable from the Bundle directory for Freestanding and FHS bundles (in This is required for things like Of course the #1568 fix is required, but this PR extends the implementation. |
| if (CFStringHasSuffix(exeName, CFSTR(".dylib"))) { | ||
| CFStringRef bareExeName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, exeName, CFRangeMake(0, CFStringGetLength(exeName)-6)); | ||
| newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@.dylib"), exeName, imageSuffix); | ||
| newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@.dylib"), bareExeName, imageSuffix); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This, I suppose was a bug due a typo. Am I correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we split fixes to the core from refactoring? The more that changes in a single PR, the more confusing differential diagnosis can be in the future.
Tests ability to find bundle path from executable path
|
@millenomi Also, the reverse lookup for FHS Installed bundles remains undone, so you cannot retrieve resources from a Executable installed in |
millenomi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have a more focused patch for each issue than a single redo that tries to address multiple things at once.
| #endif | ||
|
|
||
| #if !DEPLOYMENT_RUNTIME_OBJC && !DEPLOYMENT_TARGET_WINDOWS && !DEPLOYMENT_TARGET_ANDROID | ||
| #if FHS_BUNDLES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it looks cleaner, the use of explicit platforms was intentional — we need to see what code is called on what paths, and obscuring those platforms makes us no favor. It's long but useful.
(In addition, as a note for the future since we should remove this: we do not introduce macros without prefixes. If we wanted to keep this, it should've been _CF_… since it's internal.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed it but added a comment (/* FHS_BUNDLES */ or /* FREESTANDING_BUNDLES */) in each appearance so all cases are easily searchable. They were already out of sync (some of the FHS_BUNDLES cases had not the DEPLOYMENT_TARGET_ANDROID and some had them).
| if (CFStringHasSuffix(exeName, CFSTR(".dylib"))) { | ||
| CFStringRef bareExeName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, exeName, CFRangeMake(0, CFStringGetLength(exeName)-6)); | ||
| newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@.dylib"), exeName, imageSuffix); | ||
| newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@.dylib"), bareExeName, imageSuffix); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we split fixes to the core from refactoring? The more that changes in a single PR, the more confusing differential diagnosis can be in the future.
| newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@"), exeName, imageSuffix); | ||
| } | ||
| executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, newExeName, kCFURLPOSIXPathStyle, false, urlPath); | ||
| executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, newExeName, PLATFORM_PATH_STYLE, false, urlPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not needed, because this region is Darwin only. Using it can confuse the waters a bunch (why are we using a cross-platform macro here? What platforms does this code run on?)
| CFRelease(newExeName); | ||
| CFRelease(imageSuffix); | ||
| } | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since these blocks are long-ish, it's probably a good idea to decorate the #endifs.
| if (!executableURL) { | ||
| executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, exeName, kCFURLPOSIXPathStyle, false, urlPath); | ||
| // Try finding the executable with input name. | ||
| executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, exeName, PLATFORM_PATH_STYLE, false, urlPath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code would be executed on Windows.
| if (_CFURLExists(siblingResourceDirectoryURL)) { | ||
| url = siblingResourceDirectoryURL; | ||
| } | ||
| else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nit: same line as preceding }.
TestFoundation/TestBundle.swift
Outdated
| func test_bundleReverseBundleLookup() { | ||
| _withEachPlaygroundLayout { (playground) in | ||
| if playground.layout == .fhsInstalled { | ||
| // Pending to be implemented. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same TODO.
|
|
||
| import CoreFoundation | ||
|
|
||
| #if DEPLOYMENT_RUNTIME_OBJC || os(Linux) || os(Android) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have consolidated these imports elsewhere. Isn't it working?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, unfortunately I need internal symbols that are not available with the @_exported import Foundation line in TestImports.swift. I also tried there to add @testable but it does not work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A change that needs to be made after the last few updates to CI building: you need to guard use of @testable import like this:
#if NS_FOUNDATION_ALLOWS_TESTABLE_IMPORT
#if DEPLOYMENT…
@testable import …
// etc
#endif
#endifTests that make use of internal symbols must also be bracketed by #if NS_FOUNDATION_ALLOWS_TESTABLE_IMPORT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Support for this to actually run those tests once bracketed is coming in the next attempt at #1597. Unfortunately, it has been temporarily reverted.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! So, after that change is merged we should start a new test for this PR as the current test won't test anything, I suppose 🤔
| #endif | ||
|
|
||
| // FHS bundles are supported on the Swift and C runtimes, except on Windows. | ||
| // Freestanding bundles are not supported on Darwin. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above for the discussion about feature flags. (Short: no.)
| #define FREESTANDING_BUNDLES 0 | ||
| #endif | ||
|
|
||
| // FHS bundles are not supported on Darwin, Windows and Android. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect: they're supported on Darwin if we build with the Swift runtime. See earlier comment.
|
Can anyone start the test, please? Also, any feedback after the last changes? |
|
@swift-ci please test |
…NDATION_ALLOWS_TESTABLE_IMPORT
|
@swift-ci please test |
|
@millenomi Are |
|
@pvieito they aren't yet, but you can wrap code in a |
|
@millenomi Ok, I already did it! Could you start a CI build/test to ensure the PR builds successfully, please? |
|
@swift-ci please test |
|
Could we merge this? I was waiting for #1600 to add |
|
@millenomi @parkera can you review the changes you requested and approve where appropriate? |
|
@pvieito Sorry for the long wait; it's been an intense summer. Are you still interested in chaperoning this patch? |
|
@millenomi Yes, I have merged the master changes and tested it locally. |
|
@swift-ci please test |
|
@swift-ci please test |
|
@millenomi Any idea why the tests did not start? |
|
@swift-ci please test |
2 similar comments
|
@swift-ci please test |
|
@swift-ci please test |
|
The macOS test seems to have failed due to external problems |
|
@swift-ci please test |
|
@swift-ci please test // cc. @spevans Thanks! @millenomi If the tests complete successfully the PR should be prepared for merging. |
|
@swift-ci please test |
|
The tests have succeeded (even though GitHub is not reporting them): |
|
@millenomi Could you review and merge it (if ok)? |
|
Closing this PR as it is superseded by #2093. |
Uh oh!
There was an error while loading. Please reload this page.