Saturday, August 26, 2017

Build system comparison for C shared library: Manual vs. Makefile vs. Bazel

Here is a simple code for shared library (.so) and an executable that uses it:

Library Source files (libhello.c and libhello.h):


Source for the executable that uses the above library (main.c):

There are many ways to build and execute these sources. Lets look at three of them. The first one is a collection of manual commands that you need to execute in a particular order. The other two uses some form of build system. Before you proceed, make sure to have the C compiler installed on your Ubuntu PC. To do this, execute the following at the command prompt:

sudo apt-get install build-essential git


Manual build:

(Reference: http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html)
Place the three source files in the same directory. Open the command prompt, switch to the same directory and execute the following commands to compile, execute and clean:
  1. Compilation
    1. Compiling the library sources into object files with Position Independent Code:
      gcc -c -Wall -Werror -fpic libhello.c
    2. Creating a shared library from an object file
      gcc -shared -o libhello.so libhello.o
    3. Linking with a shared library
      (prefix "lib" will be automatically added to library name, -L is used to specify search folder)
      gcc -L$(pwd) -Wall -o main.exe main.c -lhello

      if there are any issues, use the command to debug linker: ld -lhello --verbose
  2. Running the executable
    1. Making the library available at runtime
      export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
    2.  Run the binary
      ./main.exe
  3. Cleaning
    1. Execute:
      rm -rf *.o *.so *.exe

Building using Makefile:

Place the three source files in the same directory. Also create and place a new file "Makefile" with the following contents in the same directory:

Open the command prompt, switch to the same directory and execute the following commands to compile, execute and clean:
  1. Compilation
    • make all
  2. Running the executable
    1. Making the library available at runtime
      export LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
    2.  Run the binary
      ./main.exe
  3. Cleaning
    • make clean

Building using Bazel:

To use Bazel (The build system from Google), you need to first install it. Do so using following commands:

  1. Install JDK 8
    • sudo apt-get install openjdk-8-jdk
  2. Add Bazel distribution URI as a package source (one time setup):
    • echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
    • curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
  3. Install and update Bazel
    • sudo apt-get update && sudo apt-get install bazel
Next, create a directory structure like so:

Current folder
├────WORKSPACE (Blank file)

└───main (folder)
     ├───BUILD (Bazel build script)
     ├───libhello.c
     ├───libhello.h
     └───main.c

The content of the BUILD file should be as follows:

Now carry out the following commands to build the file using Bazel from the command prompt after changing to the directory with blank "WORKSPACE" file:
  1. Compilation
    • bazel build //main:all
  2. Running the executable
    • ./bazel-bin/main/main.exe
  3. Cleaning
    • bazel clean
Compiling, running and cleaning using Bazel

Output files created in the working directory by Bazel
By default, (when linkstatic option is not specified in BUILD file), Bazel links libraries to executables statically. To disable that, specify linkstatic = 0

0 comments:

Post a Comment