ilib_build utility for shared library management

## Syntax

    ilib_build(lib_name,table,files,libs [,makename,ldflags,cflags,fflags,ismex, cc])

## Arguments

lib_name

  a character string, the generic name of the library without path and extension.

table

  2 column string matrix giving the table of pairs 'scilab-name', 'interface name'

files

  string matrix giving source files needed for shared library creation. Since Scilab 5.3.1, object files are deprecated.

libs

  string matrix giving extra libraries needed for shared library creation

makename

  character string. The path of the Makefile file without extension.

  This parameter is useless since Scilab 5.0. Default value to use: [].

  A warning will be displayed in Scilab 5.3 if you use another value that the default.

ldflags,cflags,fflags

  character strings to provide options for the loader, the C compiler and the Fortran compiler.

ismex

  Internal variable to specify if we are working with mex or not.

cc

  Provide the name of the C compiler.

## Description

This tool is used to create shared libraries and to generate a loader file which can be used to dynamically load the shared library into Scilab with `addinter`

Many examples are provided in `SCI/modules/dynamic_link/examples` directory. They are all released into the public domain.

Note that a compiler must be available on the system to use this function.

Languages handle by this function are: C, C++, Fortran and Fortran 90.

On the internal technical level, under GNU/Linux and Mac OS X, the ilib_* function are based on the autotools. First, a configure is executed to detect compilers available. Then, a make is launched with the provided arguments. For more information: Full technical description of the incremental link / dynamic link

Since version 6.0.1, under GNU/Linux, Scilab detects where the libstdc++ is located (thanks to the command gcc -print-search-dirs|awk -F= '$1=="libraries: "{print $2}'). Previously, the dynamic link was using the libstdc++ embedded in Scilab.

## Examples (C code)

    //Here with give a complete example on adding new primitive to Scilab
    //create the procedure files

    cd TMPDIR;
    mkdir('example_ilib_build_c');
    cd('example_ilib_build_c');

    f1=['extern double fun2();'
        'void fun1(double *x, double *y)'
        '{*y=fun2(*x)/(*x);}'];

    mputl(f1,TMPDIR + '/example_ilib_build_c/fun1.c');

    f2=['#include <math.h>'
        'double fun2(double x)'
        '{ return( sin(x+1.));}'];
    mputl(f2,TMPDIR + '/example_ilib_build_c/fun2.c');

    //creating the interface file
    i=['#include <stdlib.h>'
       '#include <api_scilab.h>'
       '#include <Scierror.h>'
       '#include <localization.h>'
       ''
       'extern int fun1 ( double *x, double *y);'
       ''
       'int sci_fun1(char *fname, void* pvApiCtx)'
       '{'
       '  int iType1 = 0;'
       '  SciErr sciErr;'
       '  int m1 = 0, n1 = 0;'
       '  double *pdVarOne = NULL;'
       '  int *piAddressVarOne = NULL;'
       ''
       '  CheckRhs(1,1);'
       '  CheckLhs(0,1);'
       ''
       '  sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);'
       '  if(sciErr.iErr)'
       '  {'
       '    printError(&sciErr, 0);'
       '    return 0;'
       '  }'
       ''
       '  sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);'
       '  if(sciErr.iErr)'
       '  {'
       '    printError(&sciErr, 0);'
       '    return 0;'
       '  }'
       ''
       '  if (iType1 != sci_matrix)'
       '  {'
       '     Scierror(999,_(""%s: Wrong type for input argument #%d: string expected.\n""), fname, 1);'
       '     return 0;'
       '  }'
       ''
       '  sciErr = getMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &pdVarOne);'
       '  if(sciErr.iErr)'
       '  {'
       '    printError(&sciErr, 0);'
       '    return 0;'
       '  }'
       ''
       '  fun1(pdVarOne, pdVarOne);'
       '  LhsVar(1) = 1;'
       '  return 0;'
       '}'];
    mputl(i,TMPDIR + '/example_ilib_build_c/sci_fun1.c');

    //creating the shared library (a gateway, a Makefile and a loader are
    //generated.

    files=['fun1.c','fun2.c','sci_fun1.c'];
    ilib_build('build_c',['fun1','sci_fun1'],files,[]);

    // load the shared library

    exec loader.sce;

    //using the new primitive
    fun1(33)

## Examples (C++ code)

    cd TMPDIR;
    mkdir('example_ilib_build_cpp');
    cd('example_ilib_build_cpp');

    i=['#include <string>'
       'extern ""C"" {'
       '#include <stdlib.h>'
       '#include <api_scilab.h>'
       '#include <localization.h>'
       '#include <Scierror.h>'
       ''
       'int sci_cppfind(char *fname, void* pvApiCtx)'
       '{'
       ''
       ' SciErr sciErr;'
       ' int *piAddressVarOne = NULL;'
       ' char *pStVarOne = NULL;'
       ' int iType1 = 0;'
       ' int lenStVarOne = 0;'
       ' int m1 = 0, n1 = 0;'
       ''
       ' int *piAddressVarTwo = NULL;'
       ' char *pStVarTwo = NULL;'
       ' int iType2 = 0;'
       ' int lenStVarTwo = 0;'
       ' int m2 = 0, n2 = 0;'
       ''
       ' int m_out = 0;'
       ' int n_out = 0;'
       ''
       ' sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' if (iType1 != sci_strings)'
       ' {'
       '   Scierror(999,_(""%s: Wrong type for input argument #%d: string expected.\n""), fname, 1);'
       '   return 0;'
       ' }'
       ''
       ' sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddressVarTwo);'
       ' if(sciErr.iErr)'
       ' {'
       '  printError(&sciErr, 0);'
       '  return 0;'
       ' }'
       ''
       ' sciErr = getVarType(pvApiCtx, piAddressVarTwo, &iType2);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' if (iType2 != sci_strings)'
       ' {'
       '   Scierror(999,_(""%s: Wrong type for input argument #%d: string expected.\n""), fname, 2);'
       '   return 0;'
       ' }'
       ''
       ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarOne, &m1, &n1, &lenStVarOne, &pStVarOne);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' pStVarOne = new char[lenStVarOne + 1];'
       ' if (pStVarOne == NULL)'
       ' {'
       '   Scierror(999,_(""%s: Memory allocation error.\n""),fname);'
       '   return 0;'
       ' }'
       ''
       ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo, &m2, &n2, &lenStVarTwo, &pStVarTwo);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' pStVarTwo = new char[lenStVarTwo + 1];'
       ' if (pStVarTwo == NULL)'
       ' {'
       '   Scierror(999,_(""%s: Memory allocation error.\n""),fname);'
       '   return 0;'
       ' }'
       ''
       ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarOne, &m1, &n1, &lenStVarOne, &pStVarOne);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo, &m2, &n2, &lenStVarTwo, &pStVarTwo);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' std::string myMessage(pStVarOne);'
       ' std::string search(pStVarTwo);'

       ' delete pStVarTwo;'
       ' delete pStVarOne;'

       ' double dOut = 0.0;'
       ''
       ' if (myMessage.find(search) != std::string::npos) {'
       '     dOut = myMessage.find(search); /* The actual operation */'
       ' } else {'
       '     dOut = -1; /* Substring not found */'
       ' }'

       ' m_out = 1;'
       ' n_out = 1;'
       ' sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, m_out, n_out, &dOut);'
       ' if(sciErr.iErr)'
       ' {'
       '   printError(&sciErr, 0);'
       '   return 0;'
       ' }'
       ''
       ' LhsVar(1) = Rhs + 1;'
       ' return 0;'
       '} /* extern ""C"" */'
       '}'];

    mputl(i,TMPDIR + '/example_ilib_build_cpp/sci_cppfind.cxx');

    //creating the shared library (a gateway, a Makefile and a loader are
    //generated.

    files = ['sci_cppfind.cxx'];
    ilib_build('ilib_build_cpp',['cppfind','sci_cppfind'],files,[]);

    // load the shared library

    exec loader.sce;

    // Small test to see if the function is actually working.
    if cppfind("my very long string","long") <> 8 pause, end
    if cppfind("my very long string","very") <> 3 pause, end
    if cppfind("my very long string","short") <> -1 pause, end

## Examples (Fortran 90 code)

    cd TMPDIR;
    mkdir('example_ilib_build_f90');
    cd('example_ilib_build_f90');

    sourcecode=['subroutine incrdoublef90(x,y)'
                '  implicit none'
                '  double precision, intent(in) :: x'
                '  double precision, intent(out) :: y'
                '  y=x+1'
                'end subroutine incrdoublef90'];
    mputl(sourcecode,'incrdoublef90.f90');
    libpath=ilib_for_link('incrdoublef90','incrdoublef90.f90',[],'f');
    exec loader.sce
    n=1.;
    m=call("incrdoublef90",n,1,"d","out",[1,1],2,"d");
    if abs(m-2.)>%eps then pause,end
    n=2.;
    m=call("incrdoublef90",n,1,"d","out",[1,1],2,"d");
    if abs(m-3.)>%eps then pause,end

## Example: How to use cflags arguments

    cd TMPDIR;
    mkdir('example_ilib_build_cflag');
    cd('example_ilib_build_cflag');

    csource = ['#include <stdlib.h>'
       '#include <api_scilab.h>'
       '#include <sciprint.h>'
       ''
       'int sci_examplecflag(char *fname, void* pvApiCtx)'
       '{'
       ''
       '#ifdef __MYDEF_FOR_THIS_FUNCTION__'
       'sciprint(""__MYDEF_FOR_THIS_FUNCTION__ detected !!!\n"");'
       '#else'
       'sciprint(""__MYDEF_FOR_THIS_FUNCTION__ not detected !!!\n"");'
       '#endif'
       ''
       ' LhsVar(1) = 0;'
       ' return 0;'
       '}'];

    mputl(csource, TMPDIR + '/example_ilib_build_cflag/sci_cflags.c');

    //creating the shared library (a gateway, a Makefile and a loader are
    //generated.)

    files=['sci_cflags.c'];

    // here we uses cflags argument and we define __MYDEF_FOR_THIS_FUNCTION__
    ilib_build('gw_c_flags',['examplecflag','sci_examplecflag'], files, [], [], '', '-D__MYDEF_FOR_THIS_FUNCTION__');

    // load the shared library
    exec loader.sce;

    //using the new primitive
    examplecflag() // __MYDEF_FOR_THIS_FUNCTION__ detected !!!

    ulink();
    exec cleaner.sce;

    // and now
    ilib_build('gw_c_flags',['examplecflag','sci_examplecflag'], files, []);
    exec loader.sce;
    examplecflag() // __MYDEF_FOR_THIS_FUNCTION__ not detected !!!

## See also

- addinter
- link
- ilib_compile
- ilib_gen_Make
- ilib_gen_gateway
- ilib_gen_loader
- ilib_for_link
- api_scilab

## History

5.4.0 This function no more accepts files with ".o" or ".obj" extensions as source files.