fix: macOS universal build#1171
Conversation
ASTC encoder library with matching SIMD instruction set will be added as dependency per architecture. When using the Xcode generator to build a universal binary, SSE 4.1 is enabled for x86_64 architecture only.
…her than Xcode as well.
…)`, which is known to generate broken linking paths in conjunction with object library dependencies.
…lds. chore: Removed outdated description about falling back to disabling SSE for Basis Universal on universal builds.
…_type`. Updated comments describing the outdated BasisU SSE behavior for multi-arch builds.
|
I noticed legacy code that sets compiler option It's effectively redundant now, and the per-arch block accidentally proves it. The target_compile_options at line 495 fires when The empirical evidence that it isn't actually needed even in that remaining case comes from the per-arch override
So the same logic applies to the single-arch x86_64 case: ktx doesn't need -msse4.1 either, only basisu_encoder does, Tradeoff: it's defensive code that's been there a long time, so removing it has a small chance of breaking some |
|
I noticed that currently it's not possible to force SSE off via To solve it I suggest to introduce option After that change the last message about the legacy compiler option may become obsolete. edit: Can confirm that the |
…ing support for SSE 4.1 in Basis Universal. The now internal `BASISU_SSE` used to be exposed prior.
|
@atteneder, I'll be away for the next 5 days. I will review when I return. I am puzzled by your statement that it is not possible to force SSE off via BASISU_SSE. I can see no deliberate reason for that. Perhaps there is an error in basis_universal's CMakeLists.txt. Make sure the CMake cache is cleared before running your tests. Maybe the value is coming from there. |
…ctice of using auto-dereferencing.
When cross-compiling to platforms other than iOS/tvOS/visionOS (e.g. Android) this was wrongfully set to `ON` leading to follow-up errors.
Much appreciated! No rush.
Apologies for the confusing statements. Of course if(APPLE_MAC_OS AND LIBKTX_FEATURE_BASISU_SSE)
####################################################
# Per-architecture SSE 4.1 in universal macOS builds.
####################################################
# basisu_encoder cannot enable SSE for the whole project in a universal build
# (the -msse4.1 flag would break the arm64 slice). With BASISU_SSE OFF, basisu
# emits BASISU_SUPPORT_SSE=0 PUBLIC and no -msse4.1; we then use clang's
# -Xarch_<arch> driver option to inject -msse4.1 and override
# BASISU_SUPPORT_SSE to 1 only for the x86_64 sub-invocation. -Xarch_x86_64
# applies to the immediately-following argument only, so each flag needs its
# own prefix. Works with any generator (Xcode, Ninja, Make) on Apple.
if(APPLE_MAC_OS_UNIVERSAL AND APPLE_MAC_OS_ARCH_x86_64)
# SHELL: prevents CMake from deduplicating the repeated -Xarch_x86_64
# tokens, which would otherwise leave only the first flag arch-qualified.
target_compile_options(basisu_encoder PRIVATE
"SHELL:-Xarch_x86_64 -msse4.1"
"SHELL:-Xarch_x86_64 -UBASISU_SUPPORT_SSE"
"SHELL:-Xarch_x86_64 -DBASISU_SUPPORT_SSE=1"
)
foreach(t ktx ktx_read)
if(TARGET ${t})
target_compile_options(${t} PRIVATE
"SHELL:-Xarch_x86_64 -UBASISU_SUPPORT_SSE"
"SHELL:-Xarch_x86_64 -DBASISU_SUPPORT_SSE=1"
)
endif()
endforeach()
endif()
endif()This ensures SSE is enabled for I needed to introduce I opened the PR as soon as the macOS universal builds were functional. There's still issues with some (cross-compiling) platform builds that I'm trying to address now. What to do with
|
|
Update: I've tested macOS Universal with Xcode and Ninja generators, but Unix Makefiles did not succeed. edit: I personally think that's not a blocker, but you be the judge. |
Supposed to fix compilation of ktx/ktxdiff tools against dynamic library (Windows).
MarkCallow
left a comment
There was a problem hiding this comment.
Looks okay but I have a lot of questions. Please answer them.
| # Building for iOS, iPadOS, etc. Since we don't care what | ||
| # type of ARM processor, arbitrarily set armv8. | ||
| # It should be arm64 but there is a check in tests/CMakeLists.txt | ||
| # that is dropping loadtests for Apple Silicon arm64. |
There was a problem hiding this comment.
Probably should fix this and tests/CMakeLists.txt. I don't recall why it wants to drop loadtests for Apple Silicon arm64.
| Macs are either based on Intel or the newer Apple Silicon architecture. By default CMake configures to build for your host's platform, whichever it is. If you want to cross compile universal binaries (that support both platforms), add the parameter `-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"` to cmake. | ||
|
|
||
| > **Known limitations:** | ||
| > - Intel Macs have support for SSE, but if you're building universal binaries, |
There was a problem hiding this comment.
This limitation is now outdated. Delete.
| set(APPLE_MAC_OS_UNIVERSAL OFF) | ||
| if(APPLE_MAC_OS) | ||
| # Check CMAKE_OSX_ARCHITECTURES for multiple architectures. | ||
| list_contains(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD)" APPLE_MAC_OS_ARCH_STANDARD) |
There was a problem hiding this comment.
I thought we can't use $(ARCHS_STANDARD).
| if(APPLE_MAC_OS_UNIVERSAL) | ||
| if(APPLE_MAC_OS_ARCH_x86_64h) | ||
| list(APPEND ASTCENC_LIB_TARGETS astcenc-avx2-static) | ||
| elseif(APPLE_MAC_OS_ARCH_x86_64 OR APPLE_MAC_OS_ARCH_STANDARD) |
There was a problem hiding this comment.
By using APPLE_MAC_OS_ARCH_STANDARD aren't you enshrining the problem you mentioned somewhere else of failing to handle a new architecture added to $(ARCH_STANDARD)?
There was a problem hiding this comment.
Good observation. I'll make sure not to put APPLE_MAC_OS_ARCH_STANDARD directly in conditions anywhere.
|
I think you are correct about the I originally introduced set_target_processor_type to determine whether the BASISU_SSE option should be shown or not, to remove a possible point of confusion for users. It wasn't connected to universal builds. I still want to avoid showing this option when it is of no use. I had hoped it would be temporary until basisu_encoder was changed to use compiler pre-defined macros and run-time queries to determine if SSE could be used and what variant. It doesn't look as if that is going to happen. They key here is to not show the BASISU_SSE option, now LIBKTX_FEATURE_BASISU_SSE, if the target processor does not support it. |
…utypetest.cmake` to `CMakeLists.txt`.
… target on macOS.
…ting.
Instead it's substituted by the currently known value ('arm64;x86_64') and a custom Xcode pre-build command certifies that that's still correct.
This reverts commit 7a67f3d. Android linking failed, because astc_codec.cpp depends on ASTC encoder targes.
… for libktx into `lib` subfolder.
This reverts commit 4de37d0.
…C_OS_UNIVERSAL, likely a find and replace by mistake.
…(ARCHS_STANDARD)` represents.
Will do.
Thanks for explaining. As far as I can see after my changes it's still used for:
I guess it's worth keeping, at the very least for point 4 and 3. I just saw some level of redundancy in arch detection across |
f14acf5 to
8c266a4
Compare
This came after |
|
Please note that I will not merge this until after v5.0.0 is released which I hope will be RSN. |
| # same set of target_definitions each time so in this case we have | ||
| # to choose BASISU_SUPPORT_SSE=OFF or the arm64 compile will fail. | ||
| # For macOS the caller may set CMAKE_OSX_ARCHITECTURES to a single | ||
| # arch (e.g. "x86_64" or "arm64") or to a list ("arm64;x86_64")/to |
There was a problem hiding this comment.
s#or to a list ("arm64;x86_64")/to#, to a list ("arm64;x86_64") or to#
… so no need to force it off along with `APPLE_MAC_OS_UNIVERSAL` builds.
Understood. Good luck for the release and thanks for all the great work! |
Summary
Since ~4.4.0 I was not able to build a universal
libktxorlibktx_readmacOS binary anymore. Even though those will fade out with Apple deprecating Intel CPU support, I still want to support that for the time being.Here's what this PR does to fix that:
astc-encoder*targets may get added as dependency (in most casesastcenc-sse4.1-staticandastcenc-neon-static).x86_64only (so not forarm64)Test
On a Mac navigate to the root of this repository clone and run:
Verify SSE instructions:
Behavioral change
Due to a (presumably CMake) limitation the build only succeeds if
CMAKE_OSX_ARCHITECTURESis set explicitly toarm64;x86_64. Using$(ARCHS_STANDARD)leads to linking errors.Since before it did not compile at all, I consider this an acceptable improvement.
To reduce confusion I added an explicit configuration error that instructs users to use
arm64;x86_64explicitly. I prefer that option over silently overriding the value, which would eventually lead to future problems should Apple decide to change that standard arch set in the future.Not Addressed
I verified building universal iOS simulator binaries works, but have not checked whether the x86_64 arch has SSE enabled. I presume not, but do not consider this a blocker.
History
This picks up the previous attempt from #1043 , which was not accepted since the BasisU was built without SSE optimization in that one.