]> SALOME platform Git repositories - tools/hxx2salome.git/blob - scripts/hxx2salome
Salome HOME
Merge GUI developments from BR_GUI
[tools/hxx2salome.git] / scripts / hxx2salome
1 #!/bin/bash
2 #
3 #
4 # salome2 environment file (.bash or .sh) - can also be specified with -e option
5 ENVIRON_FILE=
6 # if present, hxx2salome will try to compile new module, by sourcing ENVIRON_FILE file, and executing
7 # build_configure, configure, make & make install
8 # remark : hxx2salome has to be lanched with clean PATH, LD_LIBRARY_PATH & PYTHONPATH variables!
9 #
10 # options you want to pass to configure
11 CONFIGURE_OPTION=
12 #
13 #
14 usage()
15 {
16     echo -e "\n  Usage :\n"
17     echo -e "  Set HXX2SALOME_ROOT_DIR variable"
18     echo -e "  ${HXX2SALOME_ROOT_DIR}/hxx2salome [options] "
19     echo -e "             cppComponent_root_dir cppComponent.hxx"
20     echo -e "             libcppComponent.so salomeComponentRoot\n"
21     echo -e "     - cppComponent_root_dir : install directory (absolute path)"
22     echo -e "                               of the c++ component\n"
23     echo -e "     - cppComponent.hxx      : header of the component"
24     echo -e "     - libcppComponent.so    : library\n"
25     echo -e "       (cppComponent.hxx and libcppComponent.so have to be found"
26     echo -e "        in cppComponent_root_dir)\n"
27     echo -e "     - salomeComponentRoot   : directory of the source/build/install"
28     echo -e "                               of the Salome component\n"
29     echo -e "\n  Options :"
30     echo -e "    -h : help"
31     echo -e "    -e environment_script : to specify the name of a environment file that will be source for compiling"
32     echo -e "    -s script_extension   : to use if your environment file name doesn't have extension"
33     echo -e "    -c                    : to compile after generation"
34     echo -e "                            (use this option only if you don't have dependencies in your header or libraries"
35     echo -e "                             if it is the case, you'll have to adapt your Makefile.in" 
36     echo -e "    -l                    : to launch salome "
37     exit
38 }
39 #
40 welcome()
41 {
42     echo -e "\n\n"
43     echo  "----------------------------------------------------------------------------"
44     echo
45     echo  "                              hxx2salome"
46     echo
47     echo  "     Automatic generation of a Salome2 component from a C++ component"
48     echo 
49     echo  "----------------------------------------------------------------------------"
50     echo 
51     echo 
52     echo 
53 }
54
55 check_arguments()
56 {
57
58     # check if $1 is a directory
59     echo -e "-> check arguments\n"
60     if [ ! -d $1 ]
61     then
62        echo -e "Error : directory $1 does not exist!\n"
63        usage
64     fi
65     CPP_ROOT_DIR=${1%%/} # remove trailing slash if present 
66     echo "    C++ Component directory : ${CPP_ROOT_DIR}"
67
68     # look for include file $2 - check number of files found and extension
69     nb=`find ${CPP_ROOT_DIR} -name $2 | wc -l` # number of files found, should be equal to 1
70     extension=${2##*\.}
71     if [ $nb -eq 0 ]
72     then
73           echo -e "\n  Error:\n  Include file $2 not found in $1 directory!\n"
74           usage
75     elif [ $nb -ge 2 ]
76     then
77          echo -e "\n  Error:\n  More than one file named $2 was found in $1!\n  Include file should be unique!"
78          usage
79     elif [ $extension != "hxx" -a $extension != "hh" -a $extension != "h" ]
80     then
81          echo -e "\n  Error:\n  Extension=$extension\n  Include file $2 should have extension .hxx .hh or .h !\n"
82          usage
83     fi
84     hxx_file=`find ${CPP_ROOT_DIR} -name $2` # name of c++ header we will parse to generate salome module
85     hxx=$2
86     echo "    C++ Component header    : ${hxx_file}"
87     hxx_dir=`dirname ${hxx_file}`
88
89     # look for library $3
90     nb=`find ${CPP_ROOT_DIR} -name $3 | wc -l` # number of files found, should be equal to 1
91     if [ $nb -eq 0 ]
92     then
93         echo -e "\n  Error:\n  Library file $3 not found in $1 directory!\n"
94         usage
95     elif [ $nb -ge 2 ]
96     then
97         echo -e "\n  Error:\n  More than one file named $3 was found in $1!\n  Library file should be unique!"
98         usage
99     fi
100     so_file=`find ${CPP_ROOT_DIR} -name $3` # absolute path of library containing c++ module
101     echo "    C++ Component library   : ${so_file}"
102     lib_dir=`dirname ${so_file}`
103     lib_file=${3%.so} # name without .so
104     lib_file=${lib_file#lib} # name of library without lib and .so (needed by makefile)
105
106     # installation directory
107     if [[ ! -d $4 ]]
108     then
109        mkdir -p $4
110     fi
111     salomeComponentRoot=${4%%/} # remove trailing slash
112     echo "    Salome Component directory : ${salomeComponentRoot}"
113 }
114
115 # retrieve python test file ending up with _test.py
116 get_python_test_file()
117 {
118     cd ${CPP_ROOT_DIR}
119     for file in `find . -name "*_test.py"`
120     do
121        cp $file ${tmp_dir}/${CLASS_NAME}_SRC/src/${CLASS_NAME}
122        python_test_file=${python_test_file}" "`basename $file`
123     done
124     echo -e "\nList of exported python file test : $python_test_file \n"
125     cd -
126 }
127
128 create_component_tree()
129 {
130     INSTALL_DIR=${salomeComponentRoot}/${CLASS_NAME}
131
132     export NEW_COMPONENT_SRC_DIR=${INSTALL_DIR}/${CLASS_NAME}_SRC
133     export NEW_COMPONENT_BUILD_DIR=${INSTALL_DIR}/${CLASS_NAME}_BUILD
134     export NEW_COMPONENT_ROOT_DIR=${INSTALL_DIR}/${CLASS_NAME}_INSTALL
135
136     \rm -rf ${NEW_COMPONENT_SRC_DIR}
137     mkdir -p ${NEW_COMPONENT_SRC_DIR}
138 }
139
140
141 get_info_makefile()
142 {
143     makefile_lib="-L\${${CLASS_NAME}_CPP_ROOT}${lib_dir#${CPP_ROOT_DIR}} -l${lib_file}"
144     makefile_include="-I\${${CLASS_NAME}_CPP_ROOT}${hxx_dir#${CPP_ROOT_DIR}}"
145     
146     echo -e "\nlinking option : $makefile_lib"
147     echo -e "include option : $makefile_include"
148 }
149
150 generate_module_source()
151 {
152 #
153 # go in temporary directory to work on code generation
154     cd ${tmp_dir}
155 #
156 #
157 # -------------------------  parse hxx file and generate code  ---------------------------------------
158 #
159     echo -e "\n-> Extract public functions\n"
160     cat ${hxx_file} | awk -f ${gene_dir}/parse1.awk > ${CLASS_NAME}_public_functions
161     cat ${CLASS_NAME}_public_functions
162     if [ ! -s ${CLASS_NAME}_public_functions ]
163     then
164         echo -e "\nError:\n  Sorry - No compatible function was found!\n  Please check your header file\n"
165         exit
166     fi
167 #
168     echo -e "\n\n-> Parse public functions and generate Salome2 files\n\n  compatibility      function\n"
169     cat ${CLASS_NAME}_public_functions | awk -f ${gene_dir}/parse2.awk |\
170     awk -v class_name=${CLASS_NAME} -f ${gene_dir}/parse3.awk
171 #
172 # outputs
173     echo -e "\n  IDL file:"
174     cat parse_result > hxx2salome_journal
175     echo -e "\n----------------- IDL file ------------------\n">>hxx2salome_journal
176     cat code_idl >> hxx2salome_journal
177     cat code_idl
178     echo -e "\n----------------- hxx file ------------------\n" >> hxx2salome_journal
179     cat code_hxx >> hxx2salome_journal
180     echo -e "\n----------------- cxx file ------------------\n" >> hxx2salome_journal
181     cat code_cxx >> hxx2salome_journal
182     echo
183 #
184 #
185 # -------------------  duplicates template module and insert generated code  ------------------------------
186 #
187     echo -e "\n-> Duplicate template module" | tee hxx2salome_journal
188     tar xvfz ${gene_dir}/template_src.tgz >> hxx2salome_journal
189     mv TEMPLATE_SRC ${CLASS_NAME}_SRC
190     ${gene_dir}/renameSalomeModule -i TEMPLATE ${CLASS_NAME} ${CLASS_NAME}_SRC >> hxx2salome_journal
191 #
192     echo -e "\n-> Substitute generated code in idl file"
193     echo "// this idl file was generated by hxx2salome" > tmpfile
194     cat ${CLASS_NAME}_SRC/idl/${CLASS_NAME}_Gen.idl |awk ' 
195         $0 ~ "HXX2SALOME_IDL_CODE" {system("cat code_idl >> tmpfile")} 
196         $0 != "HXX2SALOME_IDL_CODE" { print $0 >> "tmpfile" }'
197     mv tmpfile ${CLASS_NAME}_SRC/idl/${CLASS_NAME}_Gen.idl
198 #
199     echo -e "\n-> Substitute generated code in hxx file"
200     echo "// this hxx file was generated by hxx2salome" > tmpfile
201     cat ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.hxx |awk '
202         $0 ~ "HXX2SALOME_HXX_CODE" {system("cat code_hxx >> tmpfile")}
203         $0 !~ "HXX2SALOME" { print $0 >> "tmpfile" }'
204     mv tmpfile ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.hxx
205 #
206     echo -e "\n-> Substitute generated code in cxx file"
207     echo "// this cxx file was generated by hxx2salome" > tmpfile
208     cat ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.cxx |awk -v cpp_include=$hxx '
209         $0 ~ "HXX2SALOME_CXX_CODE" {system("cat code_cxx >> tmpfile")}
210         $0 ~ "HXX2SALOME_CPP_INCLUDE" { printf "#include \"%s\"\n",cpp_include >> "tmpfile" }
211         $0 !~ "HXX2SALOME" { print $0 >> "tmpfile" }'
212     mv tmpfile ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.cxx
213 #
214 # add flags in makefile
215     get_python_test_file
216     get_info_makefile
217     
218     echo -e "\n-> Substitute flags in Makefile.in"
219     sed "s?HXX2SALOME_INCLUDE?${makefile_include}?g
220          s?HXX2SALOME_PYTHON_FILE?${python_test_file}?g
221          s?HXX2SALOME_LIB?${makefile_lib}?g
222         " ${CLASS_NAME}_SRC/src/${CLASS_NAME}/Makefile.in > tmpfile
223     mv tmpfile ${CLASS_NAME}_SRC/src/${CLASS_NAME}/Makefile.in
224 #
225 # generate component catalog
226     echo -e "\n-> Generate component catalog" | tee hxx2salome_journal
227     if [ -f ${KERNEL_ROOT_DIR}/bin/salome/runIDLparser ]
228     then
229        idlparser=${KERNEL_ROOT_DIR}/bin/salome/runIDLparser
230     else
231        idlparser=${gene_dir}/runIDLparser
232     fi
233     cd ${CLASS_NAME}_SRC/resources
234     VER=`cat ${KERNEL_ROOT_DIR}/bin/salome/VERSION | awk ' { print $NF }'` # extract number of version 
235     ${idlparser} -Wbcatalog=tmp.xml,icon=${CLASS_NAME}.png,version=${VER} -I${KERNEL_ROOT_DIR}/idl/salome -I${MED_ROOT_DIR}/idl/salome ../idl/${CLASS_NAME}_Gen.idl >& /dev/null | tee  hxx2salome_journal
236     cat tmp.xml | sed 's/_Gen//g' > ${CLASS_NAME}Catalog.xml
237     rm tmp.xml
238 #
239 }
240
241 compile()
242 {
243     echo "----------------- Configure -------------------"
244     
245     echo "----------------- Compile ---------------------"
246     make 
247     if [ $? -eq 0 ]
248     then
249         # compilation succeeded : we make install
250         echo
251         echo "----------------- Install ---------------------"
252         make install
253     else
254         exit 1
255     fi
256 }
257
258 update_environment()
259 {
260     if [ -z ${ENVIRON_FILE} ]
261     then
262         ENVIRON_FILE="${NEW_COMPONENT_SRC_DIR}/env_${CLASS_NAME}.${SHELL_EXT}"
263     fi
264
265     echo -e "\nEnvironment file : ", $ENVIRON_FILE
266     if [ -e ${ENVIRON_FILE} ]
267     then
268         cp ${ENVIRON_FILE} ${ENVIRON_FILE}.old
269     fi
270     touch ${ENVIRON_FILE}
271
272     if [ "${SHELL_EXT}" == "csh" ]
273     then
274         grep -q " ${CLASS_NAME}_SRC_DIR" ${ENVIRON_FILE}
275         res=$?
276         if [ $res == 1 ]
277         then
278             echo -e "###\n#------ ${CLASS_NAME}-Src ------" >>  ${ENVIRON_FILE}
279             echo -e "setenv ${CLASS_NAME}_BASE ${INSTALL_DIR}\n" >> ${ENVIRON_FILE}
280             echo -e "setenv ${CLASS_NAME}_SRC_DIR \${${CLASS_NAME}_BASE}/${CLASS_NAME}_SRC\n" >> ${ENVIRON_FILE}
281         fi
282         
283         grep -q " ${CLASS_NAME}_ROOT_DIR" ${ENVIRON_FILE}
284         res=$?
285         if [ $res == 1 ]
286         then
287             echo -e "###\n#------ ${CLASS_NAME}-Bin ------" >>  ${ENVIRON_FILE}
288             echo -e "setenv ${CLASS_NAME}_ROOT_DIR \${${CLASS_NAME}_BASE}/${CLASS_NAME}_INSTALL\n" >> ${ENVIRON_FILE}
289             echo -e "setenv ${CLASS_NAME}_CPP_ROOT ${CPP_ROOT_DIR}" >> ${ENVIRON_FILE}
290             echo -e "setenv LD_LIBRARY_PATH \${${CLASS_NAME}_CPP_ROOT}${lib_dir#${CPP_ROOT_DIR}}:\${LD_LIBRARY_PATH}" >> ${ENVIRON_FILE}
291         fi
292     fi
293     if [ "${SHELL_EXT}" == "sh" ]
294     then
295         grep -q " ${CLASS_NAME}_SRC_DIR=" ${ENVIRON_FILE}
296         res=$?
297         if [ $res == 1 ]
298         then
299             echo -e "###\n#------ ${CLASS_NAME}-Src ------" >>  ${ENVIRON_FILE}
300             echo -e "export ${CLASS_NAME}_BASE=${INSTALL_DIR}\n" >> ${ENVIRON_FILE}
301             echo -e "export ${CLASS_NAME}_SRC_DIR=\${${CLASS_NAME}_BASE}/${CLASS_NAME}_SRC\n" >> ${ENVIRON_FILE}
302         fi
303         
304         grep -q " ${CLASS_NAME}_ROOT_DIR=" ${ENVIRON_FILE}
305         res=$?
306         if [ $res == 1 ]
307         then
308             echo -e "###\n#------ ${CLASS_NAME}-Bin ------" >>  ${ENVIRON_FILE}
309             echo -e "export ${CLASS_NAME}_ROOT_DIR=\${${CLASS_NAME}_BASE}/${CLASS_NAME}_INSTALL\n" >> ${ENVIRON_FILE}
310             echo -e "export ${CLASS_NAME}_CPP_ROOT=${CPP_ROOT_DIR}" >> ${ENVIRON_FILE}
311             echo -e "export LD_LIBRARY_PATH=\${${CLASS_NAME}_CPP_ROOT}${lib_dir#${CPP_ROOT_DIR}}:\${LD_LIBRARY_PATH}" \
312             >> ${ENVIRON_FILE}
313         fi
314         
315     fi
316 }
317
318 copy_component_source()
319 {
320     mv ${tmp_dir}/${CLASS_NAME}_SRC/* ${NEW_COMPONENT_SRC_DIR}
321 }
322
323 good_bye()
324 {
325     echo -e "\n\nModule was created in ${NEW_COMPONENT_SRC_DIR}"
326     echo -e "\nTo compile it, do the following : \n"
327     echo -e "\tsource ${ENVIRON_FILE}"
328     echo -e "\tcd \${${CLASS_NAME}_SRC_DIR}"
329     echo -e "\t./build_configure"
330     echo -e "\tmkdir -p \${${CLASS_NAME}_BUILD_DIR}"
331     echo -e "\tcd \${${CLASS_NAME}_BUILD_DIR}"
332     echo -e "\t\${${CLASS_NAME}_SRC_DIR}/configure ${CONFIGURE_OPTION} --prefix=\${${CLASS_NAME}_ROOT_DIR}"
333     echo -e "\tmake"
334     echo -e "\tmake install"
335     echo -e "\nTo use it :\n"
336     echo -e "\tsource the Salome environment"
337     echo -e "\tsource the component environment file (${ENVIRON_FILE})"
338     echo -e "\trun Salome"
339     echo -e "\tadd ${CLASS_NAME} to the Salome modules list"
340     echo -e "\t\t(with the --modules option of the runSalome command or"
341     echo -e "\t\tby editing the ~/.salome_2.2.4/salome.launch file)"
342     echo -e "\nIf the header of your component includes other headers that are not in the same directories,"
343     echo -e "or if yout library has dependencies you want to specify,"
344     echo -e "you'll have to modify the following Makefile:in : "
345     echo -e "\t\${${CLASS_NAME}_SRC_DIR}/src/${CLASS_NAME}/Makefile.in"
346 }
347
348 launch_salome()
349 {
350     ${KERNEL_ROOT_DIR}/bin/salome/runSalome --gui --modules=GEOM,SMESH,VISU,SUPERV,MED,`echo ${CLASS_NAME}`  --containers=cpp,python --killall
351 }
352
353 compile_module()
354 {
355     if [ ! -d ${NEW_COMPONENT_BUILD_DIR} ]
356     then
357         mkdir -p ${NEW_COMPONENT_BUILD_DIR}
358     fi
359     if [ ! -d ${NEW_COMPONENT_ROOT_DIR} ]
360     then
361         mkdir -p ${NEW_COMPONENT_ROOT_DIR}
362     fi
363     \rm -rf ${NEW_COMPONENT_ROOT_DIR}/* ${NEW_COMPONENT_BUILD_DIR}/*
364
365     source ${ENVIRON_FILE}
366     echo 
367     echo -e "\n-> Build Configure"
368     cd ${NEW_COMPONENT_SRC_DIR}
369     ./build_configure
370     cd ${NEW_COMPONENT_BUILD_DIR}
371     echo -e "\n-> Configure in ${NEW_COMPONENT_BUILD_DIR}"
372     echo -e "\n-> Install in ${NEW_COMPONENT_ROOT_DIR}"
373     ${NEW_COMPONENT_SRC_DIR}/configure ${CONFIGURE_OPTION} --prefix=${NEW_COMPONENT_ROOT_DIR}
374     echo
375
376     if [[ $do_compile -eq 1 ]]
377     then
378         compile
379     fi
380     
381     if [[ $do_launch -eq 1 ]]
382     then
383         launch_salome
384     fi
385 }
386 #
387 #
388 # ------------------------------------------------------------------------
389 # --------------------------- MAIN PROGRAM -------------------------------
390 # ------------------------------------------------------------------------
391 #
392 CPP_ROOT_DIR=
393 NEW_COMPONENT_ROOT_DIR=
394 NEW_COMPONENT_SRC_DIR=
395 NEW_COMPONENT_BUILD_DIR=
396 do_compile=0
397 do_launch=0
398 #
399 welcome # print some welcome info
400 #
401 while getopts "cs:e:h:l" Option
402 do
403    case $Option in
404      h) usage
405         exit;;
406      e) ENVIRON_FILE=$OPTARG;;
407      s) case $OPTARG in
408             bash) SHELL_EXT=sh;;
409             csh)  SHELL_EXT=csh;;      
410             *)    SHELL_EXT=sh;;
411         esac;;
412      c) do_compile=1;;
413      l) do_launch=1;;
414      *) echo "Unimplemented option chosen : $Option."
415         usage
416         exit;;   # DEFAULT
417    esac
418 done
419
420 shift $(($OPTIND - 1))
421
422 # check number of other arguments
423 #
424 if [ $# -ne 4 ]
425 then
426    echo -e "\nBad number of arguments\n\n"
427    usage
428    exit
429 fi
430
431 check_arguments $1 $2 $3 $4
432
433 # if there is a sh compatible environment file, source it
434 if [[ -n ${ENVIRON_FILE} && -f ${ENVIRON_FILE} ]]
435 then
436    # analyse extension of environment file
437    case ${ENVIRON_FILE##*\.} in 
438        bash) SHELL_EXT=sh;;
439        ksh)  SHELL_EXT=sh;;
440        csh)  SHELL_EXT=csh;;
441        sh)   SHELL_EXT=sh;;
442    esac
443    if [ "${SHELL_EXT}" == "csh" ]
444    then
445        # source csh environment and retrieve it in bash father shell
446        cp ${ENVIRON_FILE} __tmp__env.csh
447        cat >>__tmp__env.csh<<-EOF
448 setenv | awk -F= '{print "export " \$1 "=\"" \$2 "\""}' >__tmp__env.sh
449 EOF
450        csh __tmp__env.csh
451        . __tmp__env.sh
452        rm -f __tmp__env.csh
453        rm -f __tmp__env.sh
454    else
455        source ${ENVIRON_FILE}
456    fi
457 else
458     echo -e "\nSorry - Cannot compile : Environment file shoud be set up for compiling!\n"
459     do_compile=0
460 fi
461 #
462 if [ ${HXX2SALOME_ROOT_DIR} ] && [ -d ${HXX2SALOME_ROOT_DIR} ]
463 then
464     gene_dir=${HXX2SALOME_ROOT_DIR}
465 else
466     if [ ! -f parse1.awk -o ! -f parse2.awk ]
467     then
468         echo -e "\nError : Variable HXX2SALOME_ROOT_DIR shoud be set, or hxx2salome should be launched localy"
469         usage
470     else
471         gene_dir=`pwd` # case where hxx2salome was launched from HXX2SALOME directory
472     fi
473 fi
474 #
475 # get class name
476 #
477 CLASS_NAME=`awk '$1 == "class" && $0 !~ /;/ {print $2}' ${hxx_file}`
478 echo "    Name of class :" $CLASS_NAME
479 if [ ! $CLASS_NAME ]
480 then
481     echo -e "\nError:\n  Sorry - No class definition was found!\n  Please check your header file\n"
482     exit
483 fi
484
485 #
486 # create temporary working directory
487 #
488 tmp_dir="/tmp/${USER}/${CLASS_NAME}"
489 if [ -d ${tmp_dir} ]
490 then
491     rm -rf ${tmp_dir}/*
492 else
493     mkdir -p ${tmp_dir}
494 fi
495
496 #
497 # ---------------------  Generation of module source from template ------------------------------------------
498 #
499 get_info_makefile
500 generate_module_source
501
502 #
503 # ---------------------- Installation of new module sources  ------------------------------------------------
504 #
505 create_component_tree
506
507 #
508 # ---------------------- Modification of Salome environment file  -------------------------------------------
509 #
510 update_environment
511 export `echo ${SOURCE_NAME}`_ROOT_DIR=${NEW_COMPONENT_ROOT_DIR}  # to avoid resource env for compiling and launching salome
512 #
513 # ---------------------- Copy the generated source from temp dir  -------------------------------------------
514 #
515 copy_component_source
516
517 #
518 # ---------------------- If requested, compilation of the Salome component ----------------------------------
519 if [ ${do_compile} -eq 1 ]
520 then
521     compile_module
522 else
523     good_bye
524 fi
525
526 echo -e "\nGeneration done\n"