Search code examples
sconsgoogle-nativeclient

Compiling static library for Google Native Client using SCons


I'm working on a few multi platform projects that all depend on common framework. I want to add support for Google Native-Client (NaCl). The way I aproached the problem is first to compile the framework as static library (this is how I've been doing it on all other platforms).

I have to say that I have never used SCons before. I think I start grasping it. Starting from a build.scons from a tutorial I can get some code compiling and linking. Now I would want to skip the linking process but seems like the nacl_env was never intended to compile static libraries.

Reading the SCons help didn't help me much since the Library node is missing from the nacl_env.

I don't think I understand SCons enough to write the whole build process from scratch so I was hopping to not have to do so.

1. Am I approaching the problem correctly?

2. Any tips or sample nacl static libs, build using SCons?


Solution

  • Ok, what I did is way more trickery than what you probably need.

    I wanted my static library to handle the initialization steps of the NaCl module, and then call some project-specific function.

    I ended up turning my whole framework and the contents of the built-in libppapi_cpp.a into a single .o file, and then that into a single .a file, a static library.

    I needed a single .o file, because otherwise I would run into dependency problems releated to initialization, I could not solve.

    build_lib.sh (framework):

    #!/bin/bash -e
    
    SDK="/home/kalmi/ik/nacl_sdk/pepper_15"
    
    function create_allIn_a {
    TMPDIR="`mktemp -d`"
      echo $TMPDIR
      cp $O_FILES $TMPDIR
      pushd $TMPDIR &> /dev/null
      $AR x $LIBPPAPI_CPP_A
      $LD -Ur * -o ALL.o
      $AR rvs $OUTPUT_NAME ALL.o
      $RANLIB $OUTPUT_NAME
      popd &> /dev/null
    }
    
    ./scons
    
    
    BIN_BASE="$SDK/toolchain/linux_x86/bin"
    LD="$BIN_BASE/i686-nacl-ld"
    AR="$BIN_BASE/i686-nacl-ar"
    RANLIB="$BIN_BASE/i686-nacl-ranlib"
    LIBPPAPI_CPP_A="$SDK/toolchain/linux_x86_newlib/x86_64-nacl/lib32/libppapi_cpp.a"
    O_FILES="`find $(pwd)/opt_x86_32 | grep .o$ | grep --invert-match my_main.o | tr "\n" " "`"
    LIBDIR="../../../bin/lib/lib32"
    mkdir -p $LIBDIR
    if [ -f $LIBDIR/libweb2grid_framework.a ]; then
      rm $LIBDIR/libweb2grid_framework.a
    fi
    OUTPUT_NAME="`readlink -m $LIBDIR/libweb2grid_framework.a`"
    create_allIn_a
    
    
    BIN_BASE="$SDK/toolchain/linux_x86/bin"
    LD="$BIN_BASE/x86_64-nacl-ld"
    AR="$BIN_BASE/x86_64-nacl-ar"
    RANLIB="$BIN_BASE/x86_64-nacl-ranlib"
    LIBPPAPI_CPP_A="$SDK/toolchain/linux_x86_newlib/x86_64-nacl/lib64/libppapi_cpp.a"
    O_FILES="`find $(pwd)/opt_x86_64 | grep .o$ | grep --invert-match my_main.o | tr "\n" " "`"
    LIBDIR="../../../bin/lib/lib64"
    mkdir -p $LIBDIR
    if [ -f $LIBDIR/libweb2grid_framework.a ]; then
      rm $LIBDIR/libweb2grid_framework.a
    fi
    OUTPUT_NAME="`readlink -m $LIBDIR/libweb2grid_framework.a`"
    create_allIn_a
    
     ./scons -c
    

    The my_main.o file is excluded from the static library, because that file contains the function that is to be provided by the project that uses this framework.

    The build.scons file for the framework is truly ordinary.

    build.scons (for some project that uses this framework):

    #! -*- python -*-
    
    #What to compile:
    sources = [ 'src/something.cpp', 'src/something_helper.cpp' ]
    
    
    ###############################################################x
    
    import make_nacl_env
    import nacl_utils
    import os
    
    nacl_env = make_nacl_env.NaClEnvironment(
        use_c_plus_plus_libs=False,
        nacl_platform=os.getenv('NACL_TARGET_PLATFORM'))
    
    nacl_env.Append(
        # Add a CPPPATH that enables the full-path #include directives, such as
        # #include "examples/sine_synth/sine_synth.h"
        CPPPATH=[os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd())))],
        LIBS=['web2grid_framework','srpc'],
        LIBPATH=['../../../bin/lib/lib32','../../../bin/lib/lib64'],
        LINKFLAGS=['-pthread']
       )
    
    nacl_env.AllNaClModules(sources, 'client')
    

    Some lines worth highlighting:

    • use_c_plus_plus_libs=False,
    • LIBS=['web2grid_framework','srpc'],
    • LIBPATH=['../../../bin/lib/lib32','../../../bin/lib/lib64'],
    • LINKFLAGS=['-pthread']

    I am not saying that this is a clean method, but it gets the job done.