<?xml version="1.0" encoding="UTF-8"?>
<!--
 * Scilab ( https://www.scilab.org/ ) - This file is part of Scilab
 * Copyright (C) INRIA -
 *
 * Copyright (C) 2012 - 2016 - Scilab Enterprises
 *
 * This file is hereby licensed under the terms of the GNU GPL v2.0,
 * pursuant to article 5.3.4 of the CeCILL v.2.1.
 * This file was originally licensed under the terms of the CeCILL v2.1,
 * and continues to be available under such terms.
 * For more information, see the COPYING file which you should have received
 * along with this program.
 *
 -->
<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="ilib_build" xml:lang="en">
    <refnamediv>
        <refname>ilib_build</refname>
        <refpurpose>utility for shared library management</refpurpose>
    </refnamediv>
    <refsynopsisdiv>
        <title>Syntax</title>
        <synopsis>ilib_build(lib_name,table,files,libs [,makename,ldflags,cflags,fflags,ismex, cc])</synopsis>
    </refsynopsisdiv>
    <refsection>
        <title>Arguments</title>
        <variablelist>
            <varlistentry>
                <term>lib_name</term>
                <listitem>
                    <para>a character string, the generic name of the library without
                        path and extension.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>table</term>
                <listitem>
                    <para>2 column string matrix giving the table of pairs
                        'scilab-name', 'interface name'
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>files</term>
                <listitem>
                    <para>string matrix giving source files needed for shared library creation. Since Scilab 5.3.1, object files are deprecated.</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>libs</term>
                <listitem>
                    <para>string matrix giving extra libraries needed for shared library
                        creation
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>makename</term>
                <listitem>
                    <para>character string. The path of the Makefile file without extension.</para>
                    <para>This parameter is useless since Scilab 5.0. Default value to use: [].</para>
                    <para>A warning will be displayed in Scilab 5.3 if you use another value that the default.</para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>ldflags,cflags,fflags</term>
                <listitem>
                    <para>character strings to provide options for the loader, the C
                        compiler and the Fortran compiler.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>ismex</term>
                <listitem>
                    <para>Internal variable to specify if we are working with mex or
                        not.
                    </para>
                </listitem>
            </varlistentry>
            <varlistentry>
                <term>cc</term>
                <listitem>
                    <para>Provide the name of the C compiler.</para>
                </listitem>
            </varlistentry>
        </variablelist>
    </refsection>
    <refsection>
        <title>Description</title>
        <para>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 <literal>addinter</literal>
        </para>
        <para>Many examples are provided in
            <literal>SCI/modules/dynamic_link/examples</literal> directory. They are
            all released into the public domain.
        </para>
        <para>
            <emphasis role="bold">Note that a compiler must be available on the
                system to use this function.
            </emphasis>
        </para>
        <para>
            <emphasis role="bold">Languages handle by this function are: C, C++,
                Fortran and Fortran 90.
            </emphasis>
        </para>
        <para>
            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: <ulink url="https://scilab.gitlab.io/legacy_wiki/Full(20)technical(20)description(20)of(20)the(20)incremental(20)link.html">Full technical description of the incremental link / dynamic link</ulink>
        </para>
        <para>
            Since version 6.0.1, under GNU/Linux, Scilab detects where the libstdc++ is located (thanks to the command <emphasis role="italic">gcc -print-search-dirs|awk -F= '$1=="libraries: "{print $2}'</emphasis>). Previously, the dynamic link was using the libstdc++ embedded in Scilab.
        </para>
    </refsection>
    <refsection>
        <title>Examples (C code)</title>
        <programlisting role="example"><![CDATA[
//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)
]]></programlisting>
    </refsection>
    <refsection>
        <title>Examples (C++ code)</title>
        <programlisting role="example"><![CDATA[
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
 ]]></programlisting>
    </refsection>
    <refsection>
        <title>Examples (Fortran 90 code)</title>
        <programlisting role="example"><![CDATA[
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
 ]]></programlisting>
    </refsection>
    <refsection>
        <title>Example: How to use cflags arguments</title>
        <programlisting role="example"><![CDATA[
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 !!!


 ]]></programlisting>
    </refsection>
    <refsection role="see also">
        <title>See also</title>
        <simplelist type="inline">
            <member>
                <link linkend="addinter">addinter</link>
            </member>
            <member>
                <link linkend="link">link</link>
            </member>
            <member>
                <link linkend="ilib_compile">ilib_compile</link>
            </member>
            <member>
                <link linkend="ilib_gen_Make">ilib_gen_Make</link>
            </member>
            <member>
                <link linkend="ilib_gen_gateway">ilib_gen_gateway</link>
            </member>
            <member>
                <link linkend="ilib_gen_loader">ilib_gen_loader</link>
            </member>
            <member>
                <link linkend="ilib_for_link">ilib_for_link</link>
            </member>
            <member>
                <link linkend="api_scilab">api_scilab</link>
            </member>
        </simplelist>
    </refsection>
    <refsection>
        <title>History</title>
        <revhistory>
            <revision>
                <revnumber>5.4.0</revnumber>
                <revremark>This function no more accepts files with ".o" or ".obj" extensions as source files.</revremark>
            </revision>
        </revhistory>
    </refsection>
</refentry>
