Salome HOME
Add Builder class
[tools/sat.git] / src / fileEnviron.py
1 #!/usr/bin/env python
2 #-*- coding:utf-8 -*-
3 #  Copyright (C) 2010-2013  CEA/DEN
4 #
5 #  This library is free software; you can redistribute it and/or
6 #  modify it under the terms of the GNU Lesser General Public
7 #  License as published by the Free Software Foundation; either
8 #  version 2.1 of the License.
9 #
10 #  This library is distributed in the hope that it will be useful,
11 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  Lesser General Public License for more details.
14 #
15 #  You should have received a copy of the GNU Lesser General Public
16 #  License along with this library; if not, write to the Free Software
17 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18
19 import os
20
21 batch_header="""@echo off
22
23 rem The following variables are used only in case of a sat package
24 set out_dir_Path=%~dp0
25 set PRODUCT_OUT_DIR=%out_dir_Path%
26 set prereq_install_Path=%out_dir_Path%\PREREQUISITES\INSTALL
27 set prereq_build_Path=%out_dir_Path%\PREREQUISITES\BUILD
28 """
29
30
31 bash_header="""#!/bin/bash
32 ##########################################################################
33 #
34 #### cleandup ###
35 # cleanup a path (first parameter) from duplicated entries;
36 # second parameter is the separator
37 cleandup() {
38 out_var=`echo $1 | awk -v sep=$2 '{                      \\
39      na = split($1,a,sep);                               \\
40      k=0;                                                \\
41      for(i=0;i<=na;i++) {                                \\
42        found=0;                                          \\
43        for(j=0;j<k;j++) {                                \\
44          if(a[i]==aa[j])                                 \\
45          {                                               \\
46            found=1;                                      \\
47            break;                                        \\
48          };                                              \\
49        };                                                \\
50        if(found==0) {                                    \\
51          aa[k++]=a[i];                                   \\
52        };                                                \\
53      };                                                  \\
54      ORS=sep;                                            \\
55      for(i=0;i<k;i++) {                                  \\
56        print aa[i];                                      \\
57      }                                                   \\
58    }' | sed -e 's|\\(.*\\)$1|\\1|g' -e 's|^[:;]||' -e 's|[:;]$||'`
59 echo $out_var
60 }
61 ### clean ###
62 clean ()
63 {
64 xenv=`printenv $1`
65 out_var=`cleandup $xenv $2`
66 export $1=$out_var
67 }
68
69 # The 3 following variables are used only in case of a sat package
70 export out_dir_Path=`dirname "${BASH_SOURCE[0]}"`
71 export PRODUCT_OUT_DIR=${out_dir_Path}
72 export PRODUCT_ROOT_DIR=${PRODUCT_OUT_DIR}
73 export prereq_install_Path=${out_dir_Path}/PREREQUISITES/INSTALL
74 export prereq_build_Path=${out_dir_Path}/PREREQUISITES/BUILD
75
76 ###########################################################################
77 """
78
79
80 cfgForPy_header='''# a generated SALOME Configuration file in python syntax from "sat application %s"
81 '''
82
83 ##
84 # Instantiate correct FileEnvironment sub-class.
85 def get_file_environ(output, shell, environ=None, config=None):
86     if shell == "bash":
87         return BashFileEnviron(output, environ)
88     if shell == "batch":
89         return BatchFileEnviron(output, environ)
90     if shell == "cfgForPy":
91         return CfgForPyFileEnviron(output, environ, config)
92     raise Exception("FileEnviron: Unknown shell = %s" % shell)
93
94 ##
95 # Base class for shell environment.
96 class FileEnviron:
97     def __init__(self, output, environ=None):
98         self._do_init(output, environ)
99
100     def _do_init(self, output, environ=None):
101         self.output = output
102         self.toclean = []
103         if environ is not None:
104             self.environ = environ
105         else:
106             self.environ = os.environ
107
108     def add_line(self, number):
109         self.output.write("\n" * number)
110
111     def add_comment(self, comment):
112         self.output.write("# %s\n" % comment)
113
114     def add_echo(self, text):
115         self.output.write('echo %s"\n' % text)
116
117     def add_warning(self, warning):
118         self.output.write('echo "WARNING %s"\n' % warning)
119
120     def append_value(self, key, value, sep=os.pathsep):
121         self.set(key, self.get(key) + sep + value)
122         if (key, sep) not in self.toclean:
123             self.toclean.append((key, sep))
124
125     def append(self, key, value, sep=os.pathsep):
126         if isinstance(value, list):
127             self.append_value(key, sep.join(value), sep)
128         else:
129             self.append_value(key, value, sep)
130
131     def prepend_value(self, key, value, sep=os.pathsep):
132         self.set(key, value + sep + self.get(key))
133         if (key, sep) not in self.toclean:
134             self.toclean.append((key, sep))
135
136     def prepend(self, key, value, sep=os.pathsep):
137         if isinstance(value, list):
138             self.prepend_value(key, sep.join(value), sep)
139         else:
140             self.prepend_value(key, value, sep)
141
142     def is_defined(self, key):
143         return (key in self.environ)
144
145
146     def set(self, key, value):
147         raise NotImplementedError("set is not implement for this shell!")
148
149     def get(self, key):
150         return '${%s}' % key
151
152     def command_value(self, key, command):
153         raise NotImplementedError("command_value is not implement for this shell!")
154
155     def finish(self, required=True):
156         for (key, sep) in self.toclean:
157             if sep != ' ':
158                 self.output.write('clean %s "%s"\n' % (key, sep))
159
160 ##
161 # Class for bash shell.
162 class BashFileEnviron(FileEnviron):
163     def __init__(self, output, environ=None):
164         self._do_init(output, environ)
165         self.output.write(bash_header)
166
167     def set(self, key, value):
168         self.output.write('export %s="%s"\n' % (key, value))
169         self.environ[key] = value
170
171     def command_value(self, key, command):
172         self.output.write('export %s=$(%s)\n' % (key, command))
173
174     def finish(self, required=True):
175         if not required:
176             return
177         FileEnviron.finish(self, required)
178         
179 ##
180 # Class for Windows batch shell.
181 class BatchFileEnviron(FileEnviron):
182     def __init__(self, output, environ=None):
183         self._do_init(output, environ)
184         self.output.write(batch_header)
185
186     def add_comment(self, comment):
187         self.output.write("rem %s\n" % comment)
188     
189     def get(self, key):
190         return '%%%s%%' % key
191     
192     def set(self, key, value):
193         self.output.write('set %s=%s\n' % (key, value))
194         self.environ[key] = value
195
196     def command_value(self, key, command):
197         self.output.write('%s > tmp.txt\n' % (command))
198         self.output.write('set /p %s =< tmp.txt\n' % (key))
199
200     def finish(self, required=True):
201         return
202
203 ##
204 # Base class for cfg environment file.
205 class FileCfg:
206     def __init__(self, output, environ=None):
207         self._do_init(output, environ)
208
209     def _do_init(self, output, environ=None):
210         self.output = output
211         self.toclean = []
212         if environ is not None:
213             self.environ = environ
214         else:
215             self.environ = os.environ
216         if not self.environ.has_key("PATH"):
217             self.environ["PATH"]=""
218         if not self.environ.has_key("LD_LIBRARY_PATH"):
219             self.environ["LD_LIBRARY_PATH"]=""
220         if not self.environ.has_key("PYTHONPATH"):
221             self.environ["PYTHONPATH"]=""
222         if not self.environ.has_key("TCLLIBPATH"):
223             self.environ["TCLLIBPATH"]=""
224         if not self.environ.has_key("TKLIBPATH"):
225             self.environ["TKLIBPATH"]=""
226
227
228     def add_line(self, number):
229         self.output.write("\n" * number)
230
231     def add_comment(self, comment):
232         self.output.write("# %s\n" % comment)
233
234     def add_echo(self, text):
235         self.output.write('# %s"\n' % text)
236
237     def add_warning(self, warning):
238         self.output.write('# "WARNING %s"\n' % warning)
239
240     def append_value(self, key, value, sep=":"):
241         if self.is_defined(key) :
242             self.add(key, value)
243         else :
244             self.set(key, value)
245
246     def append(self, key, value, sep=":"):
247         if isinstance(value, list):
248             self.append_value(key, sep.join(value), sep)
249         else:
250             self.append_value(key, value, sep)
251
252     def prepend_value(self, key, value, sep=":"):
253         if self.is_defined(key) :
254             self.add(key, value)
255         else :
256             self.set(key, value)
257
258     def prepend(self, key, value, sep=":"):
259         if isinstance(value, list):
260             self.prepend_value(key, sep.join(value), sep)
261         else:
262             self.prepend_value(key, value, sep)
263
264     def is_defined(self, key):
265         return self.environ.has_key(key)
266
267     def set(self, key, value):
268         raise NotImplementedError("set is not implement for file .cfg!")
269
270     def get(self, key):
271         return '${%s}' % key
272
273     def command_value(self, key, command):
274         raise NotImplementedError("command_value is not implement for file .cfg!")
275
276     def finish(self, required=True):
277         #for (key, sep) in self.toclean:
278         #   if sep != ' ':
279         #       self.output.write('clean %s "%s"\n' % (key, sep))
280         #self.output.write("# finish\n")
281         pass
282
283
284 def specialPathSeparator(name):
285     """TCLLIBPATH, TKLIBPATH, PV_PLUGIN_PATH environments variables needs some exotic path separator"""
286     specialBlanksKeys=["TCLLIBPATH", "TKLIBPATH"]
287     specialSemicolonKeys=["PV_PLUGIN_PATH"]
288     res=os.pathsep
289     if name in specialBlanksKeys: res=" "
290     if name in specialSemicolonKeys: res=";"
291     return res
292
293 ##
294 #
295 ##
296 # Class for generate a cfg file script (in python syntax) SalomeContext API.
297 class CfgForPyFileEnviron(FileCfg):
298     def __init__(self, output, environ=None, config=None):
299         self.config=config
300         self._do_init(output, environ)
301
302         self.indent="    " # four whitespaces for first indentation in a python script
303         self.prefix="context."
304         self.setVarEnv="setVariable"
305         
306         self.begin=self.indent+self.prefix
307         self.output.write((cfgForPy_header) % config['VARS']['product'])
308         self.specialKeys={"PATH": "Path", "LD_LIBRARY_PATH": "LdLibraryPath", "PYTHONPATH": "PythonPath"}
309
310     def changeToCfg(self, value):
311         res=value
312         return res
313
314     def set(self, key, value):
315         self.output.write(self.begin+self.setVarEnv+'(r"%s", r"%s", overwrite=True)\n' % (key, self.changeToCfg(value)))
316         self.environ[key] = value
317
318     def add(self, key, value):        
319         if key in self.specialKeys.keys():
320             self.output.write(self.begin+'addTo%s(r"%s")\n' % (self.specialKeys[key], self.changeToCfg(value)))
321             self.environ[key]+=":"+value
322             return
323         sep=specialPathSeparator(key)
324         self.output.write(self.indent+'#temporary solution!!! have to be defined in API a ?dangerous? addToSpecial(r"%s", r"%s")\n' % (key, value))
325         #pathsep not precised because do not know future os launch?
326         self.output.write(self.begin+'addToSpecial(r"%s", r"%s")\n' % (key, self.changeToCfg(value)))
327         self.environ[key]+=sep+value #here yes we know os for current execution
328
329     def command_value(self, key, command):
330         #self.output.write('%s=`%s`\n' % (key, command))
331         self.output.write(self.indent+'#`%s`\n' % command)
332
333         import shlex, subprocess
334         args = shlex.split(command)
335         res=subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
336         out, __ = res.communicate()
337         self.output.write(self.begin+self.setVarEnv+'(r"%s", r"%s", overwrite=True)\n' % (key, out))       
338         pass
339
340     def add_comment(self, comment):
341         if comment=="DISTENE license":
342             self.output.write(self.indent+"#"+self.prefix+self.setVarEnv+'(r"%s", r"%s", overwrite=True)\n' % ('DISTENE_LICENSE_FILE', self.changeToCfg('Use global envvar: DLIM8VAR')))
343             self.output.write(self.indent+"#"+self.prefix+self.setVarEnv+'(r"%s", r"%s", overwrite=True)\n' % ('DISTENE_LICENCE_FILE_FOR_MGCLEANER', self.changeToCfg('<path to your license>')))
344             self.output.write(self.indent+"#"+self.prefix+self.setVarEnv+'(r"%s", r"%s", overwrite=True)\n' % ('DISTENE_LICENCE_FILE_FOR_YAMS', self.changeToCfg('<path to your license>')))
345             return
346         if "setting environ for" in comment:
347             self.output.write(self.indent+"#[%s]\n" % comment.split("setting environ for ")[1])
348             return
349         if "PRODUCT environment" in comment:
350             self.output.write(self.indent+"#[SALOME Configuration]\n\n")
351             self.output.write(self.indent+"# PRODUCT environment\n")
352             tmp=","
353             for i in self.config['PRODUCT']['modules']: tmp+=i+','
354             self.output.write(self.indent+"#only for information:\n")
355             self.output.write(self.indent+'#'+self.setVarEnv+'("SALOME_MODULES", r"%s", overwrite=True)\n\n' % tmp[1:-1])
356             try:
357                 #tmp1=self.config['APPLI']['module_appli']
358                 #tmp2=self.config.TOOLS.common.module_info[tmp1].install_dir
359                 tmp3=self.config.APPLI.module_appli_install_dir
360                 relpath=os.path.relpath("/",os.getenv("HOME"))
361                 tmp=relpath[0:-1]+tmp3
362                 self.output.write(self.indent+"#only for information: ${APPLI} is preset and have to be relative to $HOME\n")
363                 self.output.write(self.indent+'#'+self.setVarEnv+'("APPLI", r"%s", overwrite=True)\n\n' % tmp)
364             except:
365                 self.output.write(self.indent+"#only for information: ${APPLI} is by default\n")
366             return
367         self.output.write(self.indent+"# %s\n" % comment)
368