iOS/OSX universal binaries handling
See original GitHub issueuniversal (fat) binaries are pretty common for Apple platforms - that’s just binaries for several architectures combined together.
sorry for the long text - but I am trying to describe my use case as detailed as possible 😃 e.g. for OSX it’s common to have x86 + x64 universal binaries, while for iOS it’s usually armv7 + armv7s + arm64/armv8 combined together, plus optionally x86 and x64, if iOS simulator is requied (so from 3 to 5 architectues). same story for other Apple platforms, such as watchOS and tvOS. usually, universal binaries are produced by running multiple builds and then running lipo utility on resulting shared/static libraries. there is alternate approach to run single universal build, but it tends to be complicated and error-prone with configure (autotools) style projects - e.g. such configure scripts need to detect size of pointer, which is ambiguous in case of universal binaries (sizeof(void*) - 4 or 8?).
I need some advice on how to proceed with universal binaries in conan. there are several approaches how it could be done:
- conan receipt invokes N builds for N architectures and runs lipo to combine as postprocessing. this is the way I am currently using. typical conan file may look like:
if self.settings.os == "Windows":
self.build_with_msvc()
else:
self.build_with_configure()
and then for OSX/iOS it will become much more complicated, like:
if self.settings.os == "Windows":
self.build_with_msvc()
elif self.settings.os == "iOS":
arches = ["armv7", "armv7s", "arm64", "i386", "x86_64"]
for arch in arches :
self.build_with_configure(arch, "iphoneos")
self.lipo(arches)
elif self.settings.os == "Macos":
arches = ["i386", "x86_64"]
for arch in arches :
self.build_with_configure(arch, "macos")
self.lipo(arches)
else:
self.build_with_configure()
there are few disadvantages of such approach:
- conanfile has very special path for iOS and Macos, although build process is same as for other NIX* platforms
- lots of code copy-pasted from package to package for universal binaries handling
- package “arch” setting is no longer showing the truth, moreover, it’s confusing field in case of universal binaries
- build N conan packages for each architecture and then combine them somehow the idea is to build conan packages for each architecture (armv7, arm64, etc) as usual and then somehow combine them into aggregated multi-architecture conan package. I am not sure if it’s even possible now to have some approach for conan package to support multiple settings at the same time, but probably there are more use cases for such combined packages (e.g. Windows tools which may run on both x86 and x64, but not on ARM might have combined x86+x64 indication). probably this approach ends up in some new conan command line, like “conan combine” or “conan lipo” which will run lipo for all libraries from packages to be combined.
some unclear points about this approach:
- while binaries are in general easy to handle, headers might be tricky part if they are different for different arches (in my practice I just copy headers from sources, but some headers might be generated from the build process and contain definitions like SIZE_OF_VOIDP)
- anyway, conan somehow needs to know which binaries to process and where are they located (but in worst case, conan still can wildcard *so *a *dylib)
- some convention on how to identify and describe combined packages shall be developed
- new conan command will be too OS-specific which might be not good (or useless for other arches?)
- probably issues with conflict resolution may appear - e.g. if asked for x86 arch, what to install, x86 or x86+x64 package?
Issue Analytics
- State:
- Created 7 years ago
- Reactions:19
- Comments:29 (25 by maintainers)
Looks like CMake has direct support for fat binaries now https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html I have not tried it yet, but looks promising. If Conan would allow array of target architectures instead of single value it would match cmake (and Xcode) approach and make it easy to integrate
This kind of many to one flow is still needed on Android when building with the ndk provided cmake toolchain (which is required if you want to build for a recent NDK).
Another approach would be to allow requirements to specify settings. So I could create a parent package that would require a child with android abi armeabi-v7a and the same child with arm64-v8a. Then assemble them in an aar file for Android distribution.
so I could do a