Ticket #9210: sage-location

File sage-location, 7.8 KB (added by jason, 11 years ago)

new sage-location file (after patch) - do not apply; only for reviewing convenience

Line 
1#!/usr/bin/env python
2
3import os, sys
4
5OLD_SAGE_ROOT = None
6SAGE_ROOT     = os.path.realpath(os.environ['SAGE_ROOT'])
7
8location_file = os.path.join(SAGE_ROOT, 'local', 'lib', 'sage-current-location.txt')
9flags_file    = os.path.join(SAGE_ROOT, 'local', 'lib', 'sage-flags.txt')
10
11# The flags we care about recording in the local/lib/sage-flags.txt file
12# In SAGE_FAT_BINARY mode we only require that ['sse', 'sse2', '3d',
13#  'mmx', 'cmov'] be available, and in particular, don't require pni
14#  or ssse3.
15
16try:
17    SAGE_FAT_BINARY = os.environ['SAGE_FAT_BINARY']
18except:
19    SAGE_FAT_BINARY = ""
20
21if SAGE_FAT_BINARY == "yes":
22    FLAGS = ['sse', 'sse2', '3d', 'mmx', 'cmov']
23else:
24    FLAGS = ['sse', 'sse2', 'ssse3', '3d', 'mmx', 'pni', 'cmov']
25
26
27def write_location_file():
28    """
29    Write the location file with the current SAGE_ROOT
30    """
31    # Write new location file.
32    O = open(location_file,'w')
33    O.write(SAGE_ROOT)
34    O.close()
35
36def read_location_file():
37    """
38    If the location file exists, return the real path contained in it.  Otherwise, return None.
39    """
40    if os.path.exists(location_file):
41        # The install moved and we had written the flags and location files.
42        O = open(location_file)
43        R = O.read().strip()
44        O.close()
45        return os.path.realpath(R)
46    else:
47        return None
48
49def install_moved():
50    """
51    Check whether or not this install of Sage moved.  If it hasn't
52    moved make sure the location and processor flags files are
53    written.
54
55    Returns True if location possibly moved, and sets the global
56    OLD_SAGE_ROOT variable to the old SAGE_ROOT path.
57
58    Returns False if location has not moved.
59    """
60    # Write the flags file if it isn't there.
61    if not os.path.exists(flags_file):
62        f=open(flags_file,'w')
63        f.write(get_flags_info())
64        f.close()
65
66    path=read_location_file()
67    if path is None:
68        # first time checked (during the build)
69        write_location_file()
70        initialize_pkgconfig_files()
71        return False
72    elif path != SAGE_ROOT:
73        # location moved
74        global OLD_SAGE_ROOT
75        OLD_SAGE_ROOT=path
76        write_location_file()
77        return True
78    else:
79        # path didn't change
80        return False
81
82def get_flags_info():
83    """
84    Return a space-separated string that lists the flags supported by
85    this CPU from /proc/cpuinfo.
86    """
87    try:
88        r = open('/proc/cpuinfo').read()
89        i = r.find('flags')
90        r = r[i:]
91        i = r.find(':')
92        r = r[i+1:]
93        i = r.find('\n')
94        r = r[:i]
95
96        # This line restricts the flags to just ones that start with sse, 3d or mmx.
97        # We do not want *all* flags, since some like "up" are not relevant (up = uniprocessor).
98        return ' '.join(set(x for x in r.split() if x in FLAGS))
99
100    except IOError:
101        # On a system without /proc/cpuinfo, so don't bother. In
102        # particular, for non Linux systems I have no clue how to get
103        # the processor flags, and we so far have never ever had any
104        # problem with processor flags on such machines.  So we don't
105        # bother.
106        return ''
107
108def check_processor_flags():
109    """
110    Make sure all processor flags from the build machine are on this machine.
111    If the sage-flags.txt file is missing, don't bother to do this check.
112    """
113    if not os.path.exists(flags_file): return
114    # We check that the processor flags of the original build are a
115    # subset of the new machine.  If not, we print a massive warning.
116    X = set(open(flags_file).read().split()).intersection(FLAGS)
117    Y = set(get_flags_info().split())
118    if not X.issubset(Y):
119        print ""
120        print "*"*70
121        print "WARNING!  This Sage install was built on a machine that supports"
122        print "instructions that are not available on this computer.  Sage will"
123        print "likely fail with ILLEGAL INSTRUCTION errors! The following processor"
124        print "flags were on the build machine but are not on this computer:\n"
125        for a in X:
126            if a not in Y:
127                print a,
128        print ""
129        print ""
130        print "Email http://groups.google.com/group/sage-support for help."
131        print "To remove this warning and make Sage start, just delete"
132        print "     %s"%flags_file
133        print "*"*70
134        sys.exit(1)
135
136def update_library_files():
137    """
138    Run ranlib on the library directory and manually change the path
139    in .la library files.
140    """
141    LIB = os.path.join(os.path.abspath(SAGE_ROOT), 'local', 'lib')
142    # The .a files should be re-ranlib'd
143    os.system('cd "%s"; ranlib *.a 1>/dev/null 2>/dev/null'%LIB)
144
145    # The .la files hardcode path info, so we manually fix the path
146    # info
147    for F in os.listdir(LIB):
148       if os.path.splitext(F)[1]==".la":
149           G = open(os.path.join(LIB,F)).read()
150           i = G.find('libdir=')
151           j = i+8 + G[i+8:].find("'")
152           z = G[i+8:j].strip().strip("'")
153           i = z.rfind('local/')
154           if i != -1:
155               z = z[:i]
156               H = G.replace(z, os.path.abspath(SAGE_ROOT) + '/')
157               open(os.path.join(LIB, F),'w').write(H)
158
159
160def initialize_pkgconfig_files():
161    """
162    Insert a sage_local variable in each pkg_config file and replace
163    them to make the paths portable.
164    """
165    LIB = os.path.join(os.path.abspath(SAGE_ROOT), 'local', 'lib')
166    PKG = os.path.join(LIB,'pkgconfig')
167    for name in os.listdir(PKG):
168        filename=os.path.join(PKG,name)
169        if os.path.splitext(filename)[1]==".pc":
170            with open(filename) as file:
171                config = file.read()
172               
173            new_config = config.replace(os.path.abspath(SAGE_ROOT), "${SAGE_ROOT}")
174
175            new_config = 'SAGE_ROOT=%s\n'%os.path.abspath(SAGE_ROOT)+new_config
176
177            with open(filename, 'w') as file:
178                file.write(new_config)
179
180   
181
182def update_pkgconfig_files():
183    """
184    Change paths in package configuration files.
185    """
186    LIB = os.path.join(os.path.abspath(SAGE_ROOT), 'local', 'lib')
187    PKG = os.path.join(LIB,'pkgconfig')
188    for name in os.listdir(PKG):
189        filename=os.path.join(PKG,name)
190        if os.path.splitext(filename)[1]==".pc":
191            with open(filename) as file:
192                config = file.read()
193               
194            prefix_start=config.find('SAGE_ROOT=')
195            prefix_end=config.find('\n', prefix_start)
196            new_prefix='SAGE_ROOT=%s'%os.path.abspath(SAGE_ROOT)
197            new_config=config[:prefix_start]+new_prefix+config[prefix_end:]
198
199            with open(filename, 'w') as file:
200                file.write(new_config)
201   
202
203def remove_files(path, remove_extensions):
204    """
205    Walk the tree starting at path and remove all files with
206    extensions in remove_ext.  The extensions in remove_extensions
207    should start with a period, i.e., remove_files(path, ('.pyc',
208    '.pyo')).
209    """
210    for root, dirs, files in os.walk(path):
211        for file in files:
212            filename=os.path.join(root,file)
213            if os.path.splitext(filename)[1] in remove_extensions:
214                try:
215                    os.unlink(filename)
216                except OSError, msg:
217                    print msg
218           
219def __mysig(a,b):
220    raise KeyboardInterrupt, "computation timed out because alarm was set for %s seconds"%__alarm_time
221
222if __name__ ==  '__main__':
223   
224    check_processor_flags()
225    if install_moved():
226        print "The Sage install tree may have moved"
227        print "(from %s to %s)"%(OLD_SAGE_ROOT, SAGE_ROOT)
228        print "Changing various hardcoded paths"
229        print "(please wait at most a few minutes)..."
230        print "Do not interrupt this."
231        update_library_files()
232        update_pkgconfig_files()
233        # Compiled python files need to be regenerated, so we remove them
234        remove_files(os.path.join(SAGE_ROOT, 'local', 'lib', 'python'), 
235                     remove_extensions=('.pyc', '.pyo'))
236        print "Done resetting paths"