-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Do not depend on the HAVE_STRLCAT and HAVE_STRLCPY preprocessor definitions. #5013
base: main
Are you sure you want to change the base?
Conversation
These checks are required because glibc 2.38+ added strlcat and strlcpy functions. swift-corelibs-foundation should use these functions if they are available. The checks originally existed in commit 8d1a679, but were not added to the new CMakeLists.txt in commit c772413. Fixes swiftlang#5012
CMakeLists.txt
Outdated
include(CheckLinkerFlag) | ||
|
||
check_symbol_exists(strlcat "string.h" HAVE_STRLCAT) | ||
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY) |
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.
Is there a way that we can replicate this behavior in the package manifest as well so that when building via SwiftPM we get the same behavior? Or a way that we can add this check into the code itself rather than on the CMake/SwiftPM side?
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.
Generally, no, SwiftPM doesn't have a way to add such checks or generate "config.h" files.
However, in these cases (HAVE_STRLCAT and HAVE_STRLCPY in Swift), I think we can change swift-corelibs-foundation (and other projects) to use local versions of these functions only if certain conditions are not met. Below is an example of how we can do this:
#if !TARGET_OS_MAC
#if defined(__linux__) && ((defined(__GLIBC__) && __GLIBC__ >= 2 && defined(__GLIBC_MINOR__) && __GLIBC_MINOR__ >= 38) || !defined(__GLIBC__))
// strlcat and strlcpy are available in the system
#else
// Define local versions of strlcpy and strlcat for glibc < 2.38
CF_INLINE size_t
strlcpy(char * dst, const char * src, size_t maxlen) {
...
}
#endif
#endif // !TARGET_OS_MAC
This code assumes the following things:
- Swift is supported on macOS (and other Apple platforms), Linux, and Windows.
- Android's bionic supports strlcpy and strlcat. Link
- Other than Android, Linux uses glibc or musl. Musl supports strlcpy and strlcat. Link
- glibc 2.38 and later supports strlcpy and strlcat.
- Windows doesn't have strlcpy and strlcat.
This approach is somewhat error-prone and may not be the best way to handle this, but I think this is the only way to handle this in SwiftPM. Also, I don't think supported platforms change frequently, so this approach should be fine with appropriate compile flags. Do you think this approach is acceptable?
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 is an alright way to right this given that SwiftPM can't perform a check - assuming there's no other macro defined in the header that we can use to indicate the presence or lack of this function. @parkera had to do something similar for CURL: https://github.com/apple/swift-corelibs-foundation/blob/15ee5c32d2b808fd912c586c535feaf9af2eb2d5/Sources/_CFURLSessionInterface/include/CFURLSessionInterface.h#L39-L57
The only tweak I'd suggest - rather than doing this for !TARGET_OS_MAC
, should we just only do this for TARGET_OS_LINUX
(or whatever the right macro is for that)? In other words, do we need to define strlcpy
for Windows/Android or does the source code in Foundation already handle not calling that function?
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.
If you think it is a good idea to remove autoconf-style feature test preprocessor macros and check features in the code for compatibility with SwiftPM, I'll revisit this patch to do so.
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 since the alternative would break the SwiftPM build of this project, checking conditionally in the code is the way to go here to avoid breaking the build
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 definitely seems like a good improvement once we add the Swift case as well.
CMakeLists.txt
Outdated
endif() | ||
if(HAVE_STRLCPY) | ||
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:HAVE_STRLCPY>) | ||
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.
I think that we need to have an entry for Swift as well to pass this to the ClangImporter. Something like $<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xcc -DHAVE_STRLCPY>
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.
All changes within CMakeLists.txt were reverted in the latest commit. Please check the header file for the changes.
…itions. While checking whether the system provides the `strlcat` and `strlcpy` functions, using an autoconf-style check to determine their availability does not seem to be a good idea. This is because the code is also used with SwiftPM, which does not have a similar feature test. Instead, we should directly check the availability of these functions in the system. Given that `strlcpy` and `strlcat` are not standard C functions, we should check whether the system is macOS, Linux with Bionic or Musl libc, or glibc version 2.38 or later. This patch adds the necessary checks in the header file so that SwiftPM can use these checks as well. Fixes swiftlang#5012
@swift-ci test |
#if !TARGET_OS_MAC | ||
#if !HAVE_STRLCPY | ||
#if TARGET_OS_MAC || \ | ||
(TARGET_OS_LINUX && \ |
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.
Is this going to be a problem for platforms which are not Linux but do have strlcat
(FreeBSD, e.g.)?
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 not depending on the definition of __GLIBC__
but I'm unsure of where that's set)
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.
That's the weakness of this approach, and that's also why every project has a list of supporting platforms. From what I know, Swift isn't officially supported on BSD variants (obviously, except for Darwin). So, I think it's not a problem. I don't even have a FreeBSD machine to test it. But if it is absolutely necessary, I may add another check for BSD variants based on https://sourceforge.net/p/predef/wiki/OperatingSystems/ and other sources, but honestly, I don't think it's necessary.
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.
FreeBSD does have a port as does Haiku, PS4, etc. I think that the target os macros do not work even on Linux. Does this cover uclibc and newlib? There is a plethora of libcs, and the fact that this "breaks" on SPM is fine - you can mirror this into SPM as:
cSettings: [
.define("HAVE_STRLCAT", .when(platforms: [.linux]))),
.define("HAVE_STRLCPY", .when(platforms: [.linux]))),
]
@jmschonfeld - I think that this is a sufficient means of mapping this in SPM, which will need to be changed if your environment is different as SPM does not have the necessary flexibility.
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.
What if this (swift-corelibs-foundation) library is used as a transitive dependency in a Swift Package Manager project? Since SPM can't replace dependencies on the consumer side, it is extremely annoying to patch existing projects, as all dependent projects need to be patched as well. If we had a similar mechanism like go mod replace
or npm's override mechanism, it would be much easier to handle this kind of situation, but that is a different topic.
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.
You would need to update the dependency. Fortunately, swift-corelibs-foundation cannot be used as a package dependency and is shipped as part of the toolchain.
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 seems that the annoyance of replacing transitive dependencies is not a problem for the swift-corelibs-foundation repository. However, I'm still unsure about defining HAVE_STRLCAT
and HAVE_STRLCPY
in the SwiftPM manifest file. Even though it's the same OS (Linux), the actual availability of these functions can vary. I think it would be better to define these macros in the source code, even though it might be a bit messy.
I also wish Swift had clearer documentation on which platforms are supported and which are not, so we can avoid confusions with platforms like FreeBSD. I have made a post on the Swift forums to clarify this: https://forums.swift.org/t/clarifying-supported-platforms-for-swift/73309
While checking whether the system provides the
strlcat
andstrlcpy
functions, using an autoconf-style check to determine their availability
does not seem to be a good idea. This is because the code is also
used with SwiftPM, which does not have a similar feature test.
Instead, we should directly check the availability of these functions
in the system.
Given that
strlcpy
andstrlcat
are not standard C functions,we should check whether the system is macOS, Linux with Bionic or
Musl libc, or glibc version 2.38 or later. This patch adds the necessary
checks in the header file so that SwiftPM can use these checks as well.
Fixes #5012