XCode-iOS : What does this linker warning mean "file was built for unsupported file format " - ios

I am trying to get some a medium-to-large sized code base that is, frankly, well written with a high degree of portability.
I decided to package it as a loadable bundle (plugin) and piggy-backed off of one of the template app projects and followed some tutorials about adding a target for loadable bundles within an app.
Also, this loadable bundle depends on a custom framework which I built for iOS and added it as a dependent for the loadable bundle. ie. The plugin links to a framework wrapper for a static lib.
The custom framework built successfully. Granted I have not yet verified that it works. The idea is to test the integrated functionality.
My build settings are largely defaults with the exception of some preprocessor defines.
Because I don't really understand the code base yet, I am literally adding one file-at-a-time to the plugin target and building cleanly every 3-4 files added.
The build completes successfully but with many, many warnings as follows, with paths to intermediate build results...etc.:
"file was built for unsupported file format with a series of hex characters () which is not the architecture being linked (armv7s)". When I converted the hex chars to ascii it just showed "#1 /Users/my-username/? ".
When I do a 'file' on any .o in the intermediate build results, I get "ASCII c program text, with very long lines"
What am I doing wrong? What does that mean?
Thank you so much for your time.

The short answer is this:
If you get this message, then your project settings are messed up.
If you are linking your app against custom frameworks, make sure they are built as fat binaries
You will need to know very clearly the meanings of active architecture and how it is used and whether or not you want to only build the active architecture for your app, or all of the possible architectures.
If you are, like me, inheriting a slew of portable code that depended heavily on gcc and its extensions, expect to make changes around builtin* attributes and to make heavy use of __clang to make available macros that used to be defined through the GNUC et al.
Also, you will need to use the -E for clang to debug/understand the preprocessing and the file inclusion. That said, don't forget to take it out because effectively what will happen is that your .o will just contain text and the build may succeed, but the linker will give you the odd message subject of this question.
Finally, do understand that Xcode, like any piece of complex software, is buggy. Sometimes, it will keep settings that you get rid off. In my case, I included custom frameworks which I built after placing them in a local dir. Then I deleted them from the project and opted to trash when prompted. The build kept failing because the linker for some reason was looking for the local directory. You would have to edit the *.pbxproj and manually remove them.

Related

Are both static libraries and dynamic libraries compiled during the build process?

When you build an app,
You have to compile and then link.
Whether you link a framework dynamically or statically, you still have to compile them both.
It’s just that for a static library, you link at build time and pay its price through extra time.
With a dynamic library, you link at launch time i.e. defer the extra cost, but eventually you’ll have to endure the link time…
Like my question is, for dynamic linking, the compilation still happens during build time. It’s not like that the OS has a compiler and compiles and then links app launch time. I imagine if that was correct then app launches for dynamic linking would be terrible…
Do I have it right?
And if a library is pre-compiled, then while you save on the compilation step, it doesn't in any way affect the linking. Still — depending on if it's static vs. dynamic library you will have to pay the cost of linking eventually.
Not an IOS-specific question.
Libraries (static or dynamic) are not necessarily compiled at build time. Many are provided as binary files without source code and simply linked to your program. If you have the source code, you can set up your build process to build the libraries.
Statically-linked libraries are combined into your executable file at build time by the linker. Dynamically-linked libraries are not part of your executable file, and are linked to your program at run time by the operating system's program loader.
Dynamic linking is generally very fast. Modern compile-time linkers can be very sophisticated and can do exotic things like generate and compile code.
So far we're describing classic compilation and linking.
Now, there are newer languages that are a hybrid of compilation and interpretation. In these languages, a library contains an intermediate representation (IL) that is may be interpreted by a runtime, or compiled to native code just-in-time (JIT).
We haven't even discussed interpreted languages like Javascript.
Modern systems often blur the traditional distinctions between interpreted and compiled languages and do "all of the above". Sometimes the code running to accomplish something in an app is not even on your device, but is running on a server "in the cloud".
So, your homework now is to read up on the terms "native code", "assembly code", "intermediate language", "compiler", "JIT", "runtime", and "interpreted language".

Why doesn't -fvisibility hide symbols in .so file?

I've tried searching through existing answers, but didn't find anything that helps with this exact situation, so here goes ...
I'm working on a project with a deliverable .so file that contains a lot of proprietary IP, so we want to tightly control the export symbols that it exposes. Examining the .so with the nm and objdump tools actually shows no symbols exposed (which seems a bit odd, as a client app is able to link with it), but opening it with Ghidra shows absolutely everything imaginable in the 'Exports' tree.
The project is C/C++ code being built in Visual Studio 2019, using the Clang 5.0 toolset (release build for ARM64, android-27). Perhaps important to note that the library exposes a C API, so none of the functions/structs/enums intended to be exposed are namespaced. The -fvisibility=hidden switch is being set, which I understand should hide symbols by default, and __attribute__((visibility("default"))) is being specified only on the functions we want to expose. But it doesn't appear to be working as expected.
As a sanity-check experiment, I hacked the code to change the __attribute__((visibility("default"))) to __attribute__((visibility("hidden"))), just to see what effect that would have, and was pleasantly relieved to see that the relevant functions no longer appeared in the Ghidra view. This suggests that we could use that to hide things we don't want exposed, but:
It's just not really feasible to go through the entire codebase to retrofit that everywhere.
Surely that shouldn't be necessary because the -fvisibility=hidden switch should be doing that as the default for everything in the library.
For comparison, there is a Windows DLL build of the same project, which declares __declspec(dllexport) in the relevant places (usual approach of using a macro to handle the various different build scenarios), and when examining the DLL in Ghidra, only the relevant functions that we want exposed are visible as being exported.
I just want the .so build to do the same thing, but can't seem to make it happen.
As a last-ditch effort, I tried using the llvm-strip tool to try removing symbols from the .so file after building, but to no avail (probably because the other tools didn't actually list any symbols in the first place).
Any advice would be gratefully received!

How to compile my objective c++ project when modules are enabled?

My project uses objective c++. I have to enable modules but when I Set "Enable modules" to YES my project starts to prompt lots of errors that I don't know how to handle them. I have set "Build Active Architectures" to NO and added -fmodules and -fcxx-modules.
I have to mention that my project is pretty old (7 years).
Attached part of the error's log.
It looks like it messes up everything.
error log
There is a problem with your include paths somewhere. The system-supplied header tgmath.h has a line that says #include <complex.h>. That should be resolved as a "system" file. Instead, your log shows it referencing something in another path (.../dmz_files/Eigen/.../Complex.h).
Contributing to the problem is the Mac file system, which doesn't do a good job of distinguishing between "complex" and "Complex".
The actual errors are coming from trying to interpret C++ code in an Objective-C context, but those are rather irrelevant compared to referencing the wrong file.
(Why this should be specific to modules, I do not know.)

27MB IPA with just GStreamer iOS Framework... how do I make much smaller?

I'm very interested in using GStreamer's iOS framework http://docs.gstreamer.com/display/GstSDK/Installing+for+iOS+development for video streaming, but when I add the framework to a blank project and add a few lines of code to take advantage of its powerful features, the final IPA is 27MB. This is just way to big to be adding to my project, what is the best way to go about stripping this down the the bare necessities as I'm sure I'm only using a small percent of the code that is included in the SDK.
Here's a pic showing the package contents of the IPA:
Thanks!
In the gst_ios_main.h you can disable all the plugins that you don't need (make sure to enable linker optimizations so that unused code is removed). If that's not enough, you can build your own stripped down version of the iOS binaries with http://cgit.freedesktop.org/gstreamer/cerbero/ (you need to remove things from the .package and .recipe files to only build what you need). Just disabling things from gst_ios_main.h should be enough in 99% of the cases though.
Note that by default you'll build applications for multiple architectures, as such the resulting application will be rather large. Depending on your use case you can drop some architectures.
On another note, gstreamer.com is providing an completely outdated version of GStreamer and is in no way related to the GStreamer project. The official website is http://gstreamer.freedesktop.org .
SDKs have their source code encapsulated away from you, the user. You get access only to header files. Thus you just can't extract some class from it because you don't have access to the implementation file.
Of course if this library is opensource you can attempt to isolate one class, but sometimes everything is so deeply connected, that it is close to impossible.

iOS SDKs: Renaming a lot of classes

I'm developing an iOS SDK that integrates other SDKs (Facebook SDK 3.5, for example).
To prevent collisions and allow my customers to import those SDKs as well, I want to rename all of the classes/enums in my code (for example, rename FBSession to RDFBSession, etc).
Is there an easy way to do this instead of going class-by-class and using Xcode's rename feature?
Apple provide a command-line tool called tops(1) that is designed for scripting large-scale code refactoring (renaming C functions, Objective-C methods, classes, and other tokens):
tops -verbose replace "FBSession" with "RDFBSession" Sources/*.[hm]
If you have a lot of replacements, you can put all of the replace... commands into a file that you pass with the -scriptfile option. The man page has more information on the more complex commands/options (and examples).
Xcode also offers textual Search and Replace. This will be faster than individual refactors, but it is ultimately less automated. You can make the step by step refactoring faster by first minimizing the project to the relevant dependencies/sources (if possible).
However, renaming the declarations in a library will not alter the symbol names of its associated binary. If it is distributed with a binary, then renaming will just result in linker errors or (in some cases) runtime errors.
The best idea if you need to use a 3rd party library which your clients might also use is to simply inform them they need to link the library with their app, then publish the version(s) the current release supports so they know they have some extra testing if they go too far ahead with some libraries.
I think that a better approach than simply renaming your classes would be to download Facebook's open source code, rename the classes there and compile a new static library with a set of renamed header files. Then you can be sure that no collisions occur and that you're using symbols that you named yourself.
I must warn you though - working like this may make updating the SDK a nightmare regardless of how you tackle this specific issue.

Resources