3 # Copyright (C) CEA, EDF
4 # Author : Nicolas Crouzet (CEA)
8 # salome2 environment file (.bash or .sh) - can also be specified with -e option
10 # if present, hxx2salome will try to compile new module, by sourcing ENVIRON_FILE file, and executing
11 # build_configure, configure, make & make install
12 # remark : hxx2salome has to be lanched with clean PATH, LD_LIBRARY_PATH & PYTHONPATH variables!
14 # options you want to pass to configure
20 echo -e "\n Usage :\n"
21 echo -e " Set HXX2SALOME_ROOT_DIR variable"
22 echo -e " ${HXX2SALOME_ROOT_DIR}/hxx2salome [options] "
23 echo -e " cppComponent_root_dir cppComponent.hxx"
24 echo -e " libcppComponent.so salomeComponentRoot\n"
25 echo -e " - cppComponent_root_dir : install directory (absolute path)"
26 echo -e " of the c++ component\n"
27 echo -e " - cppComponent.hxx : header of the component"
28 echo -e " - libcppComponent.so : library\n"
29 echo -e " (cppComponent.hxx and libcppComponent.so have to be found"
30 echo -e " in cppComponent_root_dir)\n"
31 echo -e " - salomeComponentRoot : directory of the source/build/install"
32 echo -e " of the Salome component\n"
33 echo -e "\n Options :"
35 echo -e " -e environment_script : to specify the name of a environment file that will be updated with new necessary commands"
36 echo -e " (this file is also used for sourcing environment before compilation if it has sh or bash syntax,"
37 echo -e " if the syntax is csh, it is not sourced and for compiling (-c option) environment must be set up before)"
38 echo -e " -s script_extension : to use if your environment file name doesn't have extension"
39 echo -e " -g : to create a gui part in your component building tree"
40 echo -e " -c : to compile after generation"
41 echo -e " (use this option only if you don't have dependencies in your header or libraries"
42 echo -e " if it is the case, you'll have to adapt your Makefile.am"
43 echo -e " -l : to launch salome "
50 echo "----------------------------------------------------------------------------"
54 echo " Automatic generation of a Salome2 component from a C++ component"
56 echo "----------------------------------------------------------------------------"
65 # check if $1 is a directory
66 echo -e "-> check arguments\n"
69 echo -e "Error : directory $1 does not exist!\n"
72 CPP_ROOT_DIR=${1%%/} # remove trailing slash if present
73 echo " C++ Component directory : ${CPP_ROOT_DIR}"
75 # look for include file $2 - check number of files found and extension
76 nb=`find ${CPP_ROOT_DIR} -name $2 | wc -l` # number of files found, should be equal to 1
80 echo -e "\n Error:\n Include file $2 not found in $1 directory!\n"
84 echo -e "\n Error:\n More than one file named $2 was found in $1!\n Include file should be unique!"
86 elif [ $extension != "hxx" -a $extension != "hh" -a $extension != "h" ]
88 echo -e "\n Error:\n Extension=$extension\n Include file $2 should have extension .hxx .hh or .h !\n"
91 hxx_file=`find ${CPP_ROOT_DIR} -name $2` # name of c++ header we will parse to generate salome module
93 echo " C++ Component header : ${hxx_file}"
94 hxx_dir=`dirname ${hxx_file}`
97 nb=`find ${CPP_ROOT_DIR} -name $3 | wc -l` # number of files found, should be equal to 1
100 echo -e "\n Error:\n Library file $3 not found in $1 directory!\n"
104 echo -e "\n Error:\n More than one file named $3 was found in $1!\n Library file should be unique!"
107 so_file=`find ${CPP_ROOT_DIR} -name $3` # absolute path of library containing c++ module
108 echo " C++ Component library : ${so_file}"
109 lib_dir=`dirname ${so_file}`
110 lib_file=${3%.so} # name without .so
111 lib_file=${lib_file#lib} # name of library without lib and .so (needed by makefile)
113 # installation directory
118 salomeComponentRoot=${4%%/} # remove trailing slash
119 echo " Salome Component directory : ${salomeComponentRoot}"
122 # retrieve python test file ending up with _test.py
123 get_python_test_file()
126 for file in `find . -name "*_test.py"`
128 cp $file ${tmp_dir}/${CLASS_NAME}_SRC/src/${CLASS_NAME}
129 python_test_file=${python_test_file}" "`basename $file`
131 echo -e "\nList of exported python file test : $python_test_file \n"
135 create_component_tree()
137 INSTALL_DIR=${salomeComponentRoot}/${CLASS_NAME}
139 export NEW_COMPONENT_SRC_DIR=${INSTALL_DIR}/${CLASS_NAME}_SRC
140 export NEW_COMPONENT_BUILD_DIR=${INSTALL_DIR}/${CLASS_NAME}_BUILD
141 export NEW_COMPONENT_ROOT_DIR=${INSTALL_DIR}/${CLASS_NAME}_INSTALL
143 \rm -rf ${NEW_COMPONENT_SRC_DIR}
144 mkdir -p ${NEW_COMPONENT_SRC_DIR}
150 makefile_lib="-L\${${CLASS_NAME}CPP_ROOT_DIR}${lib_dir#${CPP_ROOT_DIR}} -l${lib_file}"
151 makefile_include="-I\${${CLASS_NAME}CPP_ROOT_DIR}${hxx_dir#${CPP_ROOT_DIR}}"
153 echo -e "\nlinking option : $makefile_lib"
154 echo -e "include option : $makefile_include"
157 generate_module_source()
160 # go in temporary directory to work on code generation
164 # ------------------------- parse hxx file and generate code ---------------------------------------
166 echo -e "\n-> Extract public functions\n"
167 # we get first rid of the c like comments (parse01), then of the excetion specification (sed filter), finnaly we extract public functions (parse1)
168 cat ${hxx_file} | awk -f ${gene_dir}/parse01.awk | sed 's/throw.*;/;/g' | awk -f ${gene_dir}/parse1.awk > ${CLASS_NAME}_public_functions
169 cat ${CLASS_NAME}_public_functions
170 if [ ! -s ${CLASS_NAME}_public_functions ]
172 echo -e "\nError:\n Sorry - No compatible function was found!\n Please check your header file\n"
176 echo -e "\n\n-> Parse public functions and generate Salome2 files\n\n compatibility function\n"
177 cat ${CLASS_NAME}_public_functions | awk -f ${gene_dir}/parse2.awk |\
178 awk -v class_name=${CLASS_NAME} -f ${gene_dir}/parse3.awk
181 echo -e "\n IDL file:"
182 cat parse_result > hxx2salome_journal
183 echo -e "\n----------------- IDL file ------------------\n" >> hxx2salome_journal
184 cat code_idl >> hxx2salome_journal
186 echo -e "\n----------------- hxx file ------------------\n" >> hxx2salome_journal
187 cat code_hxx >> hxx2salome_journal
188 echo -e "\n----------------- cxx file ------------------\n" >> hxx2salome_journal
189 cat code_cxx >> hxx2salome_journal
192 # select archive for MEDMEM or MEDCoupling
193 grep MEDCoupling code_idl >& /dev/null
196 template_component_archive=${gene_dir}/template_coupling_src.tgz
198 template_component_archive=${gene_dir}/template_src.tgz
202 # ------------------- duplicates template module and insert generated code ------------------------------
204 echo -e "\n-> Duplicate template module" | tee hxx2salome_journal
205 tar xvfz ${template_component_archive} >> hxx2salome_journal
206 mv HXX2SALOME_GENERIC_CLASS_NAME_SRC ${CLASS_NAME}_SRC
207 ${gene_dir}/renameSalomeModule -i HXX2SALOME_GENERIC_CLASS_NAME ${CLASS_NAME} ${CLASS_NAME}_SRC
208 ###>> hxx2salome_journal
209 ${gene_dir}/renameSalomeModule -i hxx2salome_generic_class_name ${class_name} ${CLASS_NAME}_SRC
210 ###>> hxx2salome_journal
212 if [ $make_gui -eq 0 ]
214 echo -e "\n-> Delete GUI part from the tree" >> hxx2salome_journal
215 'rm' -rf ${CLASS_NAME}_SRC/src/${CLASS_NAME}GUI
216 sed "s/${CLASS_NAME}GUI//" < ${CLASS_NAME}_SRC/src/Makefile.am > /tmp/h2smkf.$$
217 mv /tmp/h2smkf.$$ ${CLASS_NAME}_SRC/src/Makefile.am
218 cat ${CLASS_NAME}_SRC/configure.ac | awk ' $0 !~ "^.*GUI/Makefile" { print $0}' > /tmp/h2scac.$$
219 mv /tmp/h2scac.$$ ${CLASS_NAME}_SRC/configure.ac
222 echo -e "\n-> Substitute generated code in idl file"
223 echo "// this idl file was generated by hxx2salome" > tmpfile
224 cat ${CLASS_NAME}_SRC/idl/${CLASS_NAME}_Gen.idl |awk '
225 $0 ~ "HXX2SALOME_IDL_CODE" {system("cat code_idl >> tmpfile")}
226 $0 != "HXX2SALOME_IDL_CODE" { print $0 >> "tmpfile" }'
227 mv tmpfile ${CLASS_NAME}_SRC/idl/${CLASS_NAME}_Gen.idl
229 echo -e "\n-> Substitute generated code in hxx file"
230 echo "// this hxx file was generated by hxx2salome" > tmpfile
231 cat ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.hxx |awk '
232 $0 ~ "HXX2SALOME_HXX_CODE" {system("cat code_hxx >> tmpfile")}
233 $0 !~ "HXX2SALOME" { print $0 >> "tmpfile" }'
234 mv tmpfile ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.hxx
236 echo -e "\n-> Substitute generated code in cxx file"
237 echo "// this cxx file was generated by hxx2salome" > tmpfile
238 cat ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.cxx |awk -v cpp_include=$hxx '
239 $0 ~ "HXX2SALOME_CXX_CODE" {system("cat code_cxx >> tmpfile")}
240 $0 ~ "HXX2SALOME_CPP_INCLUDE" { printf "#include \"%s\"\n",cpp_include >> "tmpfile" }
241 $0 !~ "HXX2SALOME" { print $0 >> "tmpfile" }'
242 mv tmpfile ${CLASS_NAME}_SRC/src/${CLASS_NAME}/${CLASS_NAME}_i.cxx
244 # add flags in makefile
248 echo -e "\n-> Substitute flags in Makefile.am"
249 sed -i "s?HXX2SALOME_INCLUDE?${makefile_include}?g
250 s?HXX2SALOME_PYTHON_FILE?${python_test_file}?g
251 s?HXX2SALOME_LIB?${makefile_lib}?g
252 " ${CLASS_NAME}_SRC/src/${CLASS_NAME}/Makefile.am
255 # generate component catalog
256 echo -e "\n-> Generate component catalog" | tee hxx2salome_journal
257 if [ -f ${KERNEL_ROOT_DIR}/bin/salome/runIDLparser ]
259 idlparser=${KERNEL_ROOT_DIR}/bin/salome/runIDLparser
261 idlparser=${gene_dir}/runIDLparser
263 cd ${CLASS_NAME}_SRC/resources
264 VER=`cat ${KERNEL_ROOT_DIR}/bin/salome/VERSION | awk ' { print $NF }'` # extract number of version
265 export PYTHONPATH=${PYTHONPATH}:${KERNEL_ROOT_DIR}/bin/salome # to be sure IDLparser is in PYTHONPATH
266 #${idlparser} -Wbcatalog=${CLASS_NAME}Catalog.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
267 ${idlparser} -Wbcatalog=${CLASS_NAME}Catalog.xml,icon=${CLASS_NAME}.png,version=${VER} -I${KERNEL_ROOT_DIR}/idl/salome -I${MED_ROOT_DIR}/idl/salome ../idl/${CLASS_NAME}_Gen.idl
268 if [ -f ${CLASS_NAME}Catalog.xml ]
271 s?SALOME/vectorOfDouble?dblevec?g
272 s?SALOME/vectorOfLong?intvec?g
273 s?${CLASS_NAME}_ORB/StrSeq?stringvec?g" ${CLASS_NAME}Catalog.xml
275 echo Error with runIDLparser - the catalog was not generated
282 echo "----------------- Configure -------------------"
284 echo "----------------- Compile ---------------------"
288 # compilation succeeded : we make install
290 echo "----------------- Install ---------------------"
299 if [ -z ${ENVIRON_FILE} ]
301 ENVIRON_FILE="${NEW_COMPONENT_SRC_DIR}/env_${CLASS_NAME}.${SHELL_EXT}"
304 echo -e "\nEnvironment file : ", $ENVIRON_FILE
305 if [ -e ${ENVIRON_FILE} ]
307 cp ${ENVIRON_FILE} ${ENVIRON_FILE}.old
309 touch ${ENVIRON_FILE}
311 if [ "${SHELL_EXT}" == "csh" ]
313 grep -q " ${CLASS_NAME}_SRC_DIR" ${ENVIRON_FILE}
317 echo -e "###\n#------ ${CLASS_NAME}-Src ------" >> ${ENVIRON_FILE}
318 echo -e "setenv ${CLASS_NAME}_BASE ${INSTALL_DIR}" >> ${ENVIRON_FILE}
319 echo -e "setenv ${CLASS_NAME}_SRC_DIR \${${CLASS_NAME}_BASE}/${CLASS_NAME}_SRC\n" >> ${ENVIRON_FILE}
322 grep -q " ${CLASS_NAME}_ROOT_DIR" ${ENVIRON_FILE}
326 echo -e "###\n#------ ${CLASS_NAME}-Bin ------" >> ${ENVIRON_FILE}
327 echo -e "setenv ${CLASS_NAME}_ROOT_DIR \${${CLASS_NAME}_BASE}/${CLASS_NAME}_INSTALL" >> ${ENVIRON_FILE}
328 echo -e "setenv ${CLASS_NAME}CPP_ROOT_DIR ${CPP_ROOT_DIR}" >> ${ENVIRON_FILE}
329 echo -e "setenv LD_LIBRARY_PATH \${${CLASS_NAME}CPP_ROOT_DIR}${lib_dir#${CPP_ROOT_DIR}}:\${LD_LIBRARY_PATH}" >> ${ENVIRON_FILE}
332 if [ "${SHELL_EXT}" == "sh" ]
334 grep -q " ${CLASS_NAME}_SRC_DIR=" ${ENVIRON_FILE}
338 echo -e "###\n#------ ${CLASS_NAME}-Src ------" >> ${ENVIRON_FILE}
339 echo -e "export ${CLASS_NAME}_BASE=${INSTALL_DIR}" >> ${ENVIRON_FILE}
340 echo -e "export ${CLASS_NAME}_SRC_DIR=\${${CLASS_NAME}_BASE}/${CLASS_NAME}_SRC\n" >> ${ENVIRON_FILE}
343 grep -q " ${CLASS_NAME}_ROOT_DIR=" ${ENVIRON_FILE}
347 echo -e "###\n#------ ${CLASS_NAME}-Bin ------" >> ${ENVIRON_FILE}
348 echo -e "export ${CLASS_NAME}_ROOT_DIR=\${${CLASS_NAME}_BASE}/${CLASS_NAME}_INSTALL" >> ${ENVIRON_FILE}
349 echo -e "export ${CLASS_NAME}CPP_ROOT_DIR=${CPP_ROOT_DIR}" >> ${ENVIRON_FILE}
350 echo -e "export LD_LIBRARY_PATH=\${${CLASS_NAME}CPP_ROOT_DIR}${lib_dir#${CPP_ROOT_DIR}}:\${LD_LIBRARY_PATH}" \
357 copy_component_source()
359 mv ${tmp_dir}/${CLASS_NAME}_SRC/* ${NEW_COMPONENT_SRC_DIR}
360 mkdir -p ${NEW_COMPONENT_BUILD_DIR}
361 mkdir -p ${NEW_COMPONENT_ROOT_DIR}
366 echo -e "\n\nModule was created in ${NEW_COMPONENT_SRC_DIR}"
367 echo -e "\nTo compile it, do the following : \n"
368 echo -e "\tsource ${ENVIRON_FILE}"
369 echo -e "\tcd \${${CLASS_NAME}_SRC_DIR}"
370 echo -e "\t./build_configure"
371 echo -e "\tmkdir -p \${${CLASS_NAME}_BUILD_DIR}"
372 echo -e "\tcd \${${CLASS_NAME}_BUILD_DIR}"
373 echo -e "\t\${${CLASS_NAME}_SRC_DIR}/configure ${CONFIGURE_OPTION} --prefix=\${${CLASS_NAME}_ROOT_DIR}"
375 echo -e "\tmake install"
376 echo -e "\nTo use it :\n"
377 echo -e "\tsource the Salome environment"
378 echo -e "\tsource the component environment file (${ENVIRON_FILE})"
379 echo -e "\trun Salome"
380 echo -e "\tadd ${CLASS_NAME} to the Salome modules list"
381 echo -e "\t\t(with the --modules option of the runSalome command or"
382 echo -e "\t\tby editing your own per-user configuration file ~/.SalomeApprc.3.x.x)"
383 echo -e "\nIf the header of your component includes other headers that are not in the same directories,"
384 echo -e "or if your library has dependencies you want to specify,"
385 echo -e "you'll have to modify the following files Makefile.am: "
386 echo -e "\t\${${CLASS_NAME}_SRC_DIR}/src/${CLASS_NAME}/Makefile.am"
387 echo -e "\t\${${CLASS_NAME}_SRC_DIR}/src/${CLASS_NAME}GUI/Makefile.am"
392 ${KERNEL_ROOT_DIR}/bin/salome/runSalome --gui --modules=GEOM,SMESH,VISU,SUPERV,MED,`echo ${CLASS_NAME}` --containers=cpp,python --killall
397 if [ ! -d ${NEW_COMPONENT_BUILD_DIR} ]
399 mkdir -p ${NEW_COMPONENT_BUILD_DIR}
401 if [ ! -d ${NEW_COMPONENT_ROOT_DIR} ]
403 mkdir -p ${NEW_COMPONENT_ROOT_DIR}
405 \rm -rf ${NEW_COMPONENT_ROOT_DIR}/* ${NEW_COMPONENT_BUILD_DIR}/*
407 # source ${ENVIRON_FILE}
409 echo -e "\n-> Build Configure"
410 cd ${NEW_COMPONENT_SRC_DIR}
412 cd ${NEW_COMPONENT_BUILD_DIR}
413 echo -e "\n-> Configure in ${NEW_COMPONENT_BUILD_DIR}"
414 echo -e "\n-> Install in ${NEW_COMPONENT_ROOT_DIR}"
415 ${NEW_COMPONENT_SRC_DIR}/configure ${CONFIGURE_OPTION} --prefix=${NEW_COMPONENT_ROOT_DIR}
418 if [[ $do_compile -eq 1 ]]
423 if [[ $do_launch -eq 1 ]]
430 # ------------------------------------------------------------------------
431 # --------------------------- MAIN PROGRAM -------------------------------
432 # ------------------------------------------------------------------------
435 NEW_COMPONENT_ROOT_DIR=
436 NEW_COMPONENT_SRC_DIR=
437 NEW_COMPONENT_BUILD_DIR=
443 welcome # print some welcome info
445 gene_dir=`dirname $0`
446 if [ ! -f ${gene_dir}/parse3.awk -o ! -f ${gene_dir}/template_src.tgz ] # final check
448 echo -e "\nError : scripts parse3.awk or template_src.tgz not present in hxx2salome directory : $gene_dir"
452 while getopts "cs:e:h:lg" Option
457 e) ENVIRON_FILE=$OPTARG;;
466 *) echo "Unimplemented option chosen : $Option."
472 shift $(($OPTIND - 1))
474 # check number of other arguments
478 echo -e "\nBad number of arguments\n\n"
483 check_arguments $1 $2 $3 $4
485 # if there is a sh compatible environment file, source it
486 if [[ -n ${ENVIRON_FILE} && -f ${ENVIRON_FILE} ]]
488 # analyse extension of environment file
489 case ${ENVIRON_FILE##*\.} in
497 # Environment policy :
498 # - an existing sh file was specified : we source environment file
499 # - else (no file or csh syntax) : we don't source environment file, and do compile
500 # only if KERNEL_ROOT_DIR and MED_ROOT_DIR are defined
501 if [ "${SHELL_EXT}" == "sh" ] && [ ${ENVIRON_FILE} ] && [ -f ${ENVIRON_FILE} ]
504 echo -e "\n Environment file with sh syntax specified => we source ${ENVIRON_FILE}"
505 cat ${ENVIRON_FILE} | sed "s/ENV_FOR_LAUNCH=1/ENV_FOR_LAUNCH=0/g" > ${ENVIRON_FILE}.tmp
506 source ${ENVIRON_FILE}.tmp
507 #rm ${ENVIRON_FILE}.tmp
508 #source ${ENVIRON_FILE}
510 if [ ${KERNEL_ROOT_DIR} ] && [ -d ${KERNEL_ROOT_DIR} ] && [ ${MED_ROOT_DIR} ] && [ -d ${MED_ROOT_DIR} ]
512 # if KERNEL_ROOT_DIR and MED_ROOT_DIR are defined, we consider that environment is set
513 echo -e "\n Environment already set (KERNEL_ROOT_DIR and MED_ROOT_DIR are defined)"
515 if [ $do_compile -eq 1 ]
517 echo -e "\n Warning - Cannot compile : Environment shoud be set up before, or specify a environment file with sh syntax!\n"
525 CLASS_NAME=`awk '$1 == "class" && $0 !~ /;/ {print $2}' ${hxx_file}|awk -F: '{print $1}'`
526 echo " Name of class :" $CLASS_NAME
527 class_name=`echo ${CLASS_NAME} | awk '{print tolower($0)}'`
528 echo class_name = ${class_name}
532 echo -e "\nError:\n Sorry - No class definition was found!\n Please check your header file\n"
537 # create temporary working directory
539 tmp_dir="/tmp/${USER}/${CLASS_NAME}"
548 # --------------------- Generation of module source from template ------------------------------------------
551 generate_module_source
554 # ---------------------- Installation of new module sources ------------------------------------------------
556 create_component_tree
559 # ---------------------- Modification of Salome environment file -------------------------------------------
562 export `echo ${CLASS_NAME}`_ROOT_DIR=${NEW_COMPONENT_ROOT_DIR} # to avoid resource env for compiling and launching salome
563 export `echo ${CLASS_NAME}`CPP_ROOT_DIR=${CPP_ROOT_DIR} # idem
565 # ---------------------- Copy the generated source from temp dir -------------------------------------------
567 copy_component_source
570 # ---------------------- If requested, compilation of the Salome component ----------------------------------
571 if [ ${do_compile} -eq 1 ]
578 echo -e "\nGeneration done\n"