Clang(Llvm) Compile with Frameworks

Clang(LLVM) compile with frameworks

Compiling for iOS without using Xcode is not easy. In your case, you're trying to use an iOS framework but you're using neither the iOS toolchain's compiler nor the iOS SDK.

If you look at the compile transcript for an Xcode project you'll see some of the flags that are necessary. Things you'll need include:

  • xcrun -sdk iphoneos clang to choose the correct compiler and SDK
  • -arch armv7s to choose the correct CPU architecture
  • -mios-version-min=6.1 to set a minimum deployment target

Some older versions of Xcode also require -isysroot=/path/to/iPhoneOS6.1.sdk to choose the correct SDK because xcrun did not do it automatically.

How can I make macOS frameworks available to clang in a Nix environment?

Apparently Nix both provides packages for standard Apple frameworks and sandboxes the environment enough that standard frameworks are unavailable.

Most of what I discovered for this solution came from Use proper SDK and command-line tools on OS X 10.11 and then from examining vim-plugins nix derivation.

First step is to actually install the frameworks that my project needs. They all live in nixpkgs.darwin.apple_sdk.frameworks.

Doing that gets most of the link working, but then _CFURLResourceIsReachable is an undefined symbol on my platform. I solve that with an updated NIX_LDFLAGS variable (as suggested in the vim-plugins nix derivation). The end result for my project is this shell.nix file:

let
pkgs = import <stable> {};
frameworks = pkgs.darwin.apple_sdk.frameworks;
in pkgs.stdenv.mkDerivation {
name = "orizentic";

buildInputs = [ pkgs.rustc
pkgs.cargo
frameworks.Security
frameworks.CoreFoundation
frameworks.CoreServices
];

shellHook = ''
export PS1="[$name] \[$txtgrn\]\u@\h\[$txtwht\]:\[$bldpur\]\w \[$txtcyn\]\$git_branch\[$txtred\]\$git_dirty \[$bldylw\]\$aws_env\[$txtrst\]\$ "
export NIX_LDFLAGS="-F${frameworks.CoreFoundation}/Library/Frameworks -framework CoreFoundation $NIX_LDFLAGS";
'';
}

This gives me the cargo-watch package (which depends on CoreServices and CoreFoundation). It also apparently resolves the dependency jsonwebtoken has on Security though I have not managed to validate that yet.

How do you tell a Clang CompilerInvocation to use a framework?

I haven't found the way to do it through the CompilerInvocation object, but you can get a CompilerInvocation from command-line arguments using clang:: createInvocationFromCommandLine. When using -framework arguments, the resulting invocation can correctly #include framework headers. This isn't awesome, but it works (other than the compiler will complain that the frameworks are unused linker input, probably because no linking phase occurs).

Of course, this means that a way through the CompilerInvocation has to exist, because that's the only thing that's returned. I could believe that the logic to get frameworks from the framework path is private, though.

clang Can't find any frameworks

Reinstall the developer tools. It will take a lot less time than tracking down whatever you broke.

Defining Framework path relative to executable in gnu/clang compiler on mac

It took me a while but I now finally understand how to use @rpath.

@rpath on a library/framework means that the executable can provide a path, which we can set using -rpath, and we can set it in terms of @executable_path.

In this case, when compiling my main_test executable I would need to do the following:

clang++ -framework SDL2 -F ./Frameworks Source/main.cpp -o ./Output/main_test -rpath @executable_path/

Then when running main_test, because @rpath is going to be the path to the executable (@executable_path), the library will load correctly from its relative location.

Compile Objective-C with clang in macOS 10.14?

I suspect since it appears the version clang used is non-Apple headers cannot be located. You can likely tell it where to look for the Foundation framework by adding isysroot to your compile command with the xcrun --show-sdk-path option:

clang -Wall -framework Foundation -isysroot `xcrun --show-sdk-path` first_program.m 

Xcode 3.2.1 GCC CLANG and LLVM demystification

In a nutshell:

Compilers are basically split into two parts. One being the front-end that contains the parser and semantic analysis for the programming language. The front-end produces some kind of intermediate representation of your code. Then there's the backend which takes the stuff the front-end produced, optimizes it, and eventually generates assembly code.

  • GCC: well known compiler, contains both front-ends for various languages and back-ends for many processor architectures
  • LLVM: a set of back-ends for various architectures (and other low-level stuff)
  • clang: a new front-end for C, Objective-C, and C++; uses the LLVM back-ends. You'll get more readable errors and warnings from your compiler and shorter compile times. You might also encounter incompatibilities or bugs; clang is a very young project.
  • LLVM-GCC: GCC's front-end with LLVM's back-end. LLVM's back-end is faster than GCC's.

clang's (Objective-)C++ support is far from being complete so it calls llvm-gcc when it encounters a C++ source file. It also contains the static analyzer that is now integrated into Xcode. Some people say LLVM's back-end generates better code than GCC's but your mileage may vary. LLVM also supports link-time optimizations (which you can enable in Xcode's project settings). They may produce faster code.

Apple wants to replace GCC with clang in the future because they have a policy against GPLv3 licensed code (GCC 4.2 is the last version that's licensed under GPLv2).



Related Topics



Leave a reply



Submit