Option -fembed-bitcode disappear when linking shared library - ios

I try to compile several open-source libraries for iOS as shared libraries with bitcode. I've added flag -fembed-bitcode into CFLAGS and LDFLAGS. Compilation completes normally but some of resulting libraries (curl for example) has no bitcode in them (I've checked it with otool -l lib.dylib | grep LLVM).
My investigation shows that flag -fembed-bitcode simply disappears from linker command line when dylib is linking though in Makefile there is direct usage of LDFLAGS in this place. How -fembed-bitcode can be dissapear from LDFLAGS?

The reason for -fembed-bitcode flag disappearing is that library use libtool for linking and it strips unknown flags by default:
When creating a shared library, but not when compiling or creating a
program, libtool drops some flags from the command line provided by
the user. This is done because flags unknown to libtool may interfere
with library creation or require additional support from libtool, and
because omitting flags is usually the conservative choice for a
successful build.
If you encounter flags that you think are useful to pass, as a
work-around you can prepend flags with -Wc, or -Xcompiler to allow
them to be passed through to the compiler driver (see Link mode).
Another possibility is to add flags already to the compiler command at
configure run time:
./configure CC='gcc -m64'
So I've just add -Wc,-fembed-bitcode flag to LDFLAGS in addition to -fembed-bitcode and library compiles with bitcode.

Related

Building FFmpeg for use in Swift

With the new XCode/Swift release comes the ability to use binary dependencies. This seems to me to be an ideal time to create an SPM package for FFMpeg.
However, while I've spent the last year learning to code i Swift, I'm actually not all that familiar with how to build libraries, especially those as complex as FFmpeg with all the configurable libraries and third-party dependencies.
There's kewlbear's iOS build scripts, but these are for iOS/tvOS and ideally an FFMpeg SPM package would be usable for MacOS also. It's also not updated for the newest Xcode and Swift versions.
My personal interest is simply in audio and I don't need a lot of bells and whistles, but I figure the ideal situation would be a full package with the entire source and whatever dependencies it needs, and then when it's used as a package dependency, the compiler will just use the parts it needs.
I guess my question is...how would I ideally compile the ffmpeg code for this purpose. I'm trying to follow the directions for compiling yourself, but I'm stuck at the point of compiling gettext because I'm not sure if I should follow the directions (in the gettext source code) for compiling a fat binary for multiple architectures, and when I try to run:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
I get the following error:
checking whether the C compiler works... no configure: error: in
`/Users/nolainecrusher/Downloads/FFMpeg-source/gettext-0.21/gettext-runtime':
configure: error: C compiler cannot create executables See
`config.log' for more details configure: error: ./configure failed for
gettext-runtime
and config.log doesn't really tell me anything useful:
This is what I see at the end of the log:
mkdir_p='$(MKDIR_P)' oldincludedir='/usr/include' pdfdir='${docdir}'
prefix='/usr/local' program_transform_name='s,x,x,' psdir='${docdir}'
sbindir='${exec_prefix}/sbin' sharedstatedir='${prefix}/com' subdirs='
gettext-runtime libtextstyle gettext-tools' sysconfdir='${prefix}/etc'
target_alias=''
I feel like maybe I'm going about this the wrong way, but I'm not sure what the right way is.
See the following:
A Swift wrapper package for FFmpeg and
A C wrapper package for FFmpeg
SwiftFFmpeg assumes ffmpeg is installed locally and will link with those libraries. Also, SwiftFFmpeg uses CFFmpeg as a package dependency, and your app can use SwiftFFmpeg as a dependency.
If you want to see a build script for compiling ffmpeg (x86_64 and arm64), check out my own audio player project.

ld: building for tvOS, but linking in object file built for iOS, for architecture arm64

I'm building a project (the target is a framework if it's important) for tvOS and getting the error from the linker:
ld: building for tvOS, but linking in object file built for iOS, for architecture arm64
I ran otool -l *.o in OBJECTS_FILE_DIR_normal and figured out one of .o files is actually built for iOS instead of tvOS.
The problem is that there is no corresponding source file (*.mm or *.cpp) for that .o. It is called <ProjectName>_lto.o and I don't see any compiler invocations for that file in the build log. It appears only once in linker command line:
-Xlinker -object_path_lto -Xlinker /Full/path/to/<ProjectName>.build/Debug-appletvos/tvOS.build/Objects-normal/arm64/<ProjectName>_lto.o
LLVM_LTO build settings is not set explicitly, but it defaults to NO. Setting it to NO explicitly doesn't help.
I'm using Xcode 8.3.2 (8E2002).
So my question is: why is this object file created at all and why is it created for wrong target platform?
Not sure if this should be the answer to my own question or the edit, as it doesn't answer the original question "why that _lto.o file is generated at all for wrong arch with LLVM_LTO=NO", but it may help others troubleshoot this issue.
So I decided to try enabling LTO in the project. LLVM_LTO=YES_THIN behaved identically to LLVM_LTO=NO. LLVM_LTO=YES made linker produce tons of warnings like the following:
ld: warning: Linking two modules of different target triples: /path/to/one/of/3rdpary/libs/libproblematic.a(file1.o)' is 'arm64-apple-ios7.0.0' whereas 'ld-temp.o' is 'arm64-apple-tvos9.0.0'
ld: warning: Linking two modules of different target triples: /path/to/one/of/3rdpary/libs/libproblematic.a(file2.o)' is 'arm64-apple-ios7.0.0' whereas 'ld-temp.o' is 'arm64-apple-tvos9.0.0'
But with all those warnings for some weird reason the link succeeded. The interesting thing is that if I run otool -l libproblematic.a, I only see cmd LC_VERSION_MIN_TVOS lines and no cmd LC_VERSION_MIN_IPHONEOS and linker didn't complain on any of the objects from that library that they were built for wrong target platform. Also file1, file2, etc. do not appear in the output of otool -l libproblematic.a.

How to compile C into a universal library that works with iOS architectures

I'm trying to compile a very small amount of C source into a library that I can use in XCode for an iOS application.
The files are a single .c file and three header files. I'm very new to C, and no matter what I try I can't seem to get them to compile into a library that supports iOS architectures.
The files depend on the openssl library, and I've got that installed and working fine.
I just need to know the process of compiling these four files into a single library. I've found a plethora of information on the subject online, but I can't decipher which parts are necessary for what I'm trying to do.
I've tried the following:
gcc -fPIC -c main.c
gcc -shared -o mylib.so main.o -lcrypto -lssl
which seems to compile it for x86_64, (I've not tested the resulting file, just checked it's arch).
I've also tried
./configure --disable-shared --enable-utf8 --host=arm-apple-darwin CFLAGS="-arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk" CXXFLAGS="-arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk" LDFLAGS="-L." CC="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc" CXX="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++"
which only gives me errors
checking for arm-apple-darwin-gcc... no
checking for gcc... gcc
checking whether the C compiler works... no
configure: error: in `/Users/nathanf/compilec':
configure: error: C compiler cannot create executables
I've been scouring the internet for the last few days trying to figure this out, but it's so convoluted to cross compile just a few files and I'm frustrated so I came here for some input.
Any help would be greatly appreciated.

iOS SDK 5.1 linker error for non_lazy_ptr in Xcode 4.4.1

(I posted this question to the VideoLAN forum, but have had no takers yet. I know the SO community won't let me down.)
I am trying to build the MobileVLC project for iOS. I have gone through the command line process to build the project, and after a couple of tweaks as described in http://forum.videolan.org/viewtopic.php?f=12&t=103331 and http://forum.videolan.org/viewtopic.php?f=12&t=103271, the build script runs almost to completion. It errors out when it tries to get Xcode to build the final project. So I load it into Xcode and try to build, and I can see the error, here is what I get when I use the -v linker flag:
Ld /Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos/VLC.app/VLC normal armv7
cd /Users/bp/Desktop/vlc/MobileVLC
setenv IPHONEOS_DEPLOYMENT_TARGET 5.1
setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk -L/Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos -L/Users/bp/Desktop/vlc/MobileVLC/External/MobileVLCKit -L/Users/bp/Desktop/vlc/MobileVLC/External/MediaLibraryKit -F/Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos -filelist /Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Intermediates/MobileVLC.build/Debug-iphoneos/MobileVLC.build/Objects-normal/armv7/VLC.LinkFileList -dead_strip -Wl,-no_pie,-v -fobjc-link-runtime -miphoneos-version-min=5.1 -framework Foundation -framework UIKit -framework CoreGraphics -framework OpenGLES -framework AudioToolbox -framework QuartzCore -liconv -lz /Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos/libMobileMediaLibraryKit.a -lsqlite3 -lstdc++.6 -lbz2 -lxml2 -framework CoreData -framework CoreText -framework MediaPlayer /Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos/libMobileVLCKit.a -o /Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos/VLC.app/VLC
#(#)PROGRAM:ld PROJECT:ld64-133.3
configured to support archs: armv6 armv7 i386 x86_64
Library search paths:
/Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos
/Users/bp/Desktop/vlc/MobileVLC/External/MobileVLCKit
/Users/bp/Desktop/vlc/MobileVLC/External/MediaLibraryKit
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib
Framework search paths:
/Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/
LLVM version 3.1svn, from Apple Clang 4.0 (build 421.0.60)
ld: 'non_lazy_ptr' in /Users/bp/Library/Developer/Xcode/DerivedData/MobileVLC-ctcjnpeqzuhulxcmjlhrjnyzpzil/Build/Products/Debug-iphoneos/libMobileVLCKit.a(libdeinterlace_plugin_la-deinterlace.o) contains undefined reference for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As far as I can tell, the libMobileVLCKit.a file is linked into the MobileVLC project, so I am unsure what to look for next, as I cannot find any references to non_lazy_ptr anywhere in any code, and the framework references all look good. Even if you do not know the solution, any ideas as to where to look for the problem would be appreciated. Thanks.
EDIT: Here is a screen capture showing everything in the Build Phases tab of the MobileVLC project.
EDIT 2: My posting on the VideoLAN forums has gotten some "me too" replies, along with an error that is very similar looking to my error from another user. Here is the final line with the error message:
ld: '_AmplifyFloat' in /Users/**/MobileVLC/ImportedSources/VLCKit/build/Release-iphoneos/libMobileVLCKit.a(libvolume_neon_plugin_la-volume.o) contains undefined reference for architecture armv7
Here is the posting on the VideoLAN forum: http://forum.videolan.org/viewtopic.php?f=12&t=103433
EDIT 3: I grabbed a fresh copy of the source from VideoLAN's git repository and went through the answer provided below by user1071136, and ended up with the same exact error that they got as well.
I found a similar looking error on Stack Overflow that indicated the solution was to check to make sure that the Generate Position-Dependent Code option in the Apple LLVC compiler 4.0 - Code Generation build setting was set to No. But as usual in trying to get VLC running on iOS, that was a dead end also as the build setting is already set to No for that.
Here is a link to that question and answer: (null): In section __TEXT,__text reloc 3: section For Address(0x7C6C) address not in any section for architecture armv7
I haven't been able to successfully build it, but I've overcome some hurdles which might be useful.
Hurdle 1: ARM Thumb2
Summary: Even though advertised as fully supporting thumb, it appears Apple's provided clang, as well as LLVM 3.2's one fail to translate some valid thumb instructions which appear in libav's ARM-assembler code.
Details: libav (a fork of ffmpeg) has some functionality implemented in assembler. When building for iOS, files from MobileVLC/ImportedSources/vlc/contrib/iPhoneOS/ffmpeg/libavcodec/arm are used. The first compile error one will probably encounter is something similar to
libavcodec/arm/aacpsdsp_neon.S:132:21: error: invalid operand for instruction
add r4, r0, #38*64*4
According to ARM Thumb2's reference, the above instruction is a valid ADD{S} Rd, Rn, <Operand2> instruction, where <Operand2> in thumb mode is "a 32-bit constant, formed by left-shifting an 8-bit value by any number of bits". Since #38*64*4 equals 38 left-shifted 8 times, clang should accept it. It seems that clang won't recognize it's possible, therefore attempting to interpret the instruction as a ADD Rd, Rn, #<imm12> one, for which the immediate argument must be smaller than 4096.
If somebody with more confidence on the subject can relate - is it a bug in clang?
Workaround: As noted in http://forum.videolan.org/viewtopic.php?f=12&t=103271, thumb should be disabled when configuring ffmpeg (which is in fact libav).
Hurdle 2: libtool cannot infer tag
Summary: MobileVLC's libtool is configured to infer C++ compilations, which expects an invokation of clang++. When the build system calls gas-preprocessor.pl xcrun clang instead, libtool throws an error.
Details: MobileVLC configures a copy of libtool (which is just a bash script) at MobileVLC/ImportedSources/vlc/build-ios-OS. On line 1681, the function func_infer_tag is responsible for, well, inferring the tag. For each tag that appears in the variable $available_tags defined on line 38, libtool itself is searched for a tag configuration section. For example, the CXX (=C++) tag configuartion begins on line 9258. As can be seen on line 9271, the compiler command which is expected of a C++ compilation is xcrun clang++.
The build system calls something like libtool --mode=compile gas-preprocessor.pl xcrun clang …, and since xcrun clang++ does not prefix the command, the C++ mode cannot be inferred. (gas-preprocessor.pl translates GNU Assembler into something Apple's assembler can work with)
Workaround: As noted in http://forum.videolan.org/viewtopic.php?f=12&t=103331, MobileVLC/ImportedSources/vlc/modules/video_filter/Modules.am can be modified to force libtool to infer a C compilation. If it doesn't work for you, like it didn't for me, you can call libtool yourself.
cd into MobileVLC/ImportedSources/vlc/build-ios-OS/modules/video_filter; typing make should cause the error to appear. Typing make V=1 will also show the command being executed. It will start with source='deinterlace/merge_arm.S' o…. You can now copy it and call it manually, adding --tag=CC after ../../libtool.
Hurdle 3: CopyStringsFile
Summary: Building MobileVLC fails with the error,
The following build commands failed:
CopyStringsFile build/Release-iphoneos/VLC.app/pl.lproj/Localizable.strings Resources/pl.lproj/Localizable.strings
Details: The offending file, MobileVLC/Resources/pl.lproj/Localizable.strings is a UTF-16-LE file missing a byte-order-mark (BOM), which confuses Xcode for some reason.
Workaround: cd into MobileVLC/Resources/pl.lproj/ and execute
mv -n Localizable.strings Localizable.strings.backup && python -c "import sys; sys.stdout.write(chr(0xFF)+chr(0xFE))" > Localizable.strings && cat Localizable.strings.backup >> Localizable.strings
This will add the BOM to the beginning of the file.
Hurdle 4: non_lazy_ptr + AmplifyFloat
Summary: This error should read: "An internal data structure of the linker ld has a non-lazy pointer which contains the address of a symbol ld cannot find". The missing symbols cannot be found because they are not prefixed with an underscore.
Details: It is obviously a shame that ld won't indulge us with the knowledge of what exactly it can't find, but we're not here to rant.
Consider the following simple bla.c file,
int bla();
int foo() { return bla(); }
Compiling this file (clang -c bla.c) and then listing its symbols (nm bla.o) reveals that the linker expects some other compilation unit to provide the symbol _bla (note the underscore). The underscore is presumably added to signify bla should be called in the C calling convention. The problem arises when bla is defined in an assembler file; the assembler does not add an underscore, resulting in a bla symbol, leading to linking failure.
An interesting detail is that this behaviour is different to Linux, where an underscore is not added to symbol names, which probably helped the problem escape the attention of VLC's devs. Still, the underscoring behavior appears in MinGW as far as I know, so the solution could be similar.
Workaround: The simplest solution, even if ad-hoc, is to use a symbol alias list. Create a file symbol-alias.txt with the following contents,
merge16_arm_neon _merge16_arm_neon
merge8_arm_neon _merge8_arm_neon
amplify_float_arm_neon _amplify_float_arm_neon
This file is enough depending on flags and configurations; it was enough for me, though. Type open MobileVLC.xcodeproj when in the MobileVLC/ directory. This should laungh Xcode. In project settings, choose the MobileVLC target, and then Build Settings. In Other Linker Flags, add
-Wl,-alias_list
-Wl,<absoluate-path-to-symbol_aliases.txt>
Save and build. Congratulations. You now have reached the Hurdle I don't know how to overcome :)
Hurdle 5: Address not in any section
Summary: The linker fails with the cryptic error
ld: in section __TEXT,__text reloc 13: sectionForAddress(0xE142) address not in any section for architecture armv7
I'm not sufficiently familiar with linking to figure out what's wrong, but I guess it all boils down to code written in assembler.
See you require target dependencies libMobileVLCKit

Pass "-stdlib=libc++" to c++ linker with autotools

I'm trying to compile ImageMagick (in particular Magick++) with clang++ and libc++. Therefore I need to pass -stdlib=libc++ to both compiler and linker.
While CXXFLAGS="-stdlib=libc++" works fine for compiling, LDFLAGS="-stdlib=libc++" seems to only affect the C linker.
How to correctly tell ./configure or make to use this flag when linking C++ libraries?
Use both — CXXFLAGS for the C++ compiler and LDFLAGS for the linker:
./configure CXXFLAGS="-O2 -g -stdlib=libc++" LDFLAGS="-stdlib=libc++"
You could try:
LDFLAGS="-Wl,-stdlib=libc++"

Resources