Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save zhongdai/2ef42d81221703d2b50d588012a887bc to your computer and use it in GitHub Desktop.
Save zhongdai/2ef42d81221703d2b50d588012a887bc to your computer and use it in GitHub Desktop.
How to build tensorflow C API on a M1 (ARM) Macbook

Background

I tried to install the tensorflow C API on my Macbook Pro 2021 (M1) machine, by following this document. It seems all of the pre-built libraris are for x86, but not for the ARM chips. I got the same error as this post. It seems the linker complaints, and here is the error message.

ld: warning: ignoring file /usr/local/lib/libtensorflow.2.7.0.dylib, building for macOS-arm64 but attempting to link with file built for macOS-x86_64
Undefined symbols for architecture arm64:
  "_TF_Version", referenced from:
      _main in hello_tf-6f1778.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation

I understood the C API should be cross platform, and since I am able to install the Python binding by using pip install tensorflow on my M1 machine, I believe there is a way to build the C API library on the M1 machine. Here are the steps to build from source code and write the following example hello_tf.c code.

%%writefile hello_tf.c
#include <stdio.h>
#include <tensorflow/c/c_api.h>

int main() {
  printf("Hello from TensorFlow C library version %s\n", TF_Version());
  return 0;
}

Update:

  • Here is the document about using the libtensorflow in Go binding on a M1 machine

Prerequisites

Install XCode

I didn't have XCode on my machine, only have the Command Line Tools, but this time I need the full XCode. Just use the App Store to install the full version of Xcode. Then use the following command to agree the lincense.

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -license

You might need to verify the clang (C compiler) is installed and what is the version,

clang --version

You would see something like,

Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Please ensure the version is >15.0.0.

Install Bazel

You can install the bazel or bazelisk

brew install bazel

or

brew install bazelisk

To verify your installation, please use

bazel --version

Instal pkg-config (optional)

pkg-config is a tool on Mac OS to print the C complie and build flag, e.g. the -I, -L flags.

brew install pkg-config

If you decide to put the libtensorlfow to your /usr/local/lib directly, you don't need this tool.

Install Python and create virtual env

You need to have a Python virtual env and install the numpy before build the tensorflow

Steps

Clone the repo

Clone the repo to local, I am using the master branch, and it is working.

git clone git@github.com:tensorflow/tensorflow.git

Config the build

Run the following command in the tensorflow directory.

./configure

# this command asks you several questions, just provide the python interpreter path for your virtuial env
# e.g. ./.venv/bin/python

Build

Run the following command to start the build,

bazel build --jobs=10 --compilation_mode=opt --copt=-mcpu=apple-m1 //tensorflow/tools/lib_package:libtensorflow

The above command takes time (~30 minutes) for me. You should see this tar file after it completes bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz.

The flag --copt=-mcpu=apple-m1 is for the clang, and if you are using a different arm cpu, you can check all supported cpus,

clang --target=arm64 --print-supported-cpus

You would see a list of cpus, such as apple-m2

Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Available CPUs for this target:

	a64fx
	ampere1
	apple-a10
	apple-a11
	apple-a12
  
  ... (more)

Install the library

Install to a dedicated directory (need the pkg-config)

Make a directory in /usr/local/lib/,

# the directory name does not matter, but the version might different when you install
sudo mkdir -p /usr/local/lib/libtensorflow-cpu-darwin-arm64-2.17.0

Unpack the tarball file to the directory just created,

sudo tar -C /usr/local/lib/libtensorflow-cpu-darwin-arm64-2.17.0 -xzf bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz

Install to default location /usr/local/lib

sudo tar -C /usr/local/lib -xzf bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz

Use pkg-config to config the new library

If you don't have this directory ~/.pkg_configs, create it,

mkdir ~/.pkg_configs

and export the PKG_CONFIG_PATH,

export PKG_CONFIG_PATH=~/.pkg_configs

Save the following content to a file tensorflow.pc, and copy to ~/.pkg_configs,

prefix=/usr/local/lib/libtensorflow-cpu-darwin-arm64-2.17.0
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/tensorflow

Name: TensorFlow
Version: 2.17.0
Description: Library for computation using data flow graphs for scalable machine learning
Requires:
Libs: -L${libdir} -ltensorflow -ltensorflow_framework
Cflags: -I${includedir}

Make sure the prefix is correct, use the following command to verify,

pkg-config --libs --cflags tensorflow

You should see something like the following, basically they are the flags when we use gcc to compile the hello_tf.c

-I/usr/local/lib/libtensorflow-cpu-darwin-arm64-2.15.0/include/tensorflow -L/usr/local/lib/libtensorflow-cpu-darwin-arm64-2.15.0/lib -ltensorflow -ltensorflow_framework

Compile and run the hello_tf

Go to the directory that contains the hello_tf.c, you can refer to the above to find the code.

gcc hello_tf.c -o hello_tf `pkg-config --libs --cflags tensorflow`

Or you can grab the output of pkg-config command,

gcc hello_tf.c -o hello_tf -I/usr/local/lib/libtensorflow-cpu-darwin-arm64-2.15.0/include/tensorflow -L/usr/local/lib/libtensorflow-cpu-darwin-arm64-2.15.0/lib -ltensorflow -ltensorflow_framework

Those flags let your C complier and linker know where are the header files and libraries.

If you installed the library to default location, /usr/local/lib you don't need to use the pkg-config or provide the -I / -L option. The compile / build command should be,

gcc hello_tf.c -o hello_tf -ltensorflow

Now you should see a executable file hello_tf under the same directory, we cannot run it ./hello_tf, you need to tell where is the libraries in the run time.

DYLD_LIBRARY_PATH=/usr/local/lib/libtensorflow-cpu-darwin-arm64-2.15.0/lib ./hello_tf

or

DYLD_LIBRARY_PATH=/usr/local/lib ./hello_tf

I still don't know how to avoid set the DYLD_LIBRARY_PATH

Now you will see the output,

Hello from TensorFlow C library version 2.17.0

Reference and Credits

https://gist.github.com/wangjia184/f9ffb2782d0703ef3dbceec9b2bbc4b4 https://stackoverflow.com/questions/45276830/xcode-version-must-be-specified-to-use-an-apple-crosstool https://stackoverflow.com/questions/57916950/faulty-tensorflow-c-install-on-macos-dyld-errors-library-not-loaded-rpath-l

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment