-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoof2setuputils.py
More file actions
293 lines (249 loc) · 10.4 KB
/
Copy pathoof2setuputils.py
File metadata and controls
293 lines (249 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# -*- python -*-
# $RCSfile: oof2setuputils.py,v $
# $Revision: 1.14.8.9 $
# $Author: langer $
# $Date: 2014/09/17 21:39:33 $
# This software was produced by NIST, an agency of the U.S. government,
# and by statute is not subject to copyright in the United States.
# Recipients of this software assume all responsibilities associated
# with its operation, modification and maintenance. However, to
# facilitate maintenance we ask that before distributing modified
# versions of this software, you first contact the authors at
# oof_manager@nist.gov.
# This file contains routines used by the main OOF2 setup.py script.
# These routines are also used by oof2extutils.py, which is used by
# the authors of external OOF2 extensions.
import os, sys, string, stat, time, subprocess
# Utilities for running xxxxx-config programs that get the flags and
# libs required to link with external libraries. "clib" is a CLibInfo
# object. "cmd" is a command to run that returns the required data,
# such as "Magick++-config --cflags".
def add_third_party_includes(cmd, clib):
proc = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdoutdata, stderrdata = proc.communicate()
if stderrdata:
print "stderrdata=", stderrdata
print "Failed!"
sys.exit()
for flag in stdoutdata.split():
if flag[:2] == '-I':
clib.includeDirs.append(flag[2:])
else:
clib.extra_compile_args.append(flag)
def add_third_party_libs(cmd, clib):
proc = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdoutdata, stderrdata = proc.communicate()
for flag in stdoutdata.split():
if flag[:2] == '-l':
clib.externalLibs.append(flag[2:])
elif flag[:2] == '-L':
clib.externalLibDirs.append(flag[2:])
else:
clib.extra_link_args.append(flag)
# Check for packages that use pkg-config for their options. Include
# their compiler and linker flags if they're found, and complain if
# they're not.
def pkg_check(package, version, clib=None):
if check_exec('pkg-config'):
proc = subprocess.Popen(['pkg-config',
'--atleast-version=', version, package],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdoutdata, stderrdata = proc.communicate()
if stderrdata:
print stderrdata
print "Can't find %! Version %s or later required" % (package,
version)
sys.exit()
if clib:
add_third_party_libs("pkg-config --libs %s" % package, clib)
add_third_party_includes("pkg-config --cflags %s" % package,
clib)
else:
print "Can't find pkg-config!"
sys.exit()
# Check that an executable file exists in the environment's PATH.
pathdirs = os.getenv("PATH").split(":")
def check_exec(xfile): # is xfile an executable file in the path?
for dir in pathdirs:
try:
if os.path.exists(dir):
files = os.listdir(dir)
if xfile in files:
fullname = os.path.join(dir, xfile)
if os.access(fullname, os.X_OK):
# print >> sys.stderr, "Found", xfile, "as", fullname
return 1
except: # Ignore permission errors
pass
if sys.platform == 'cygwin' and not xfile.endswith('.exe'):
return check_exec(xfile + '.exe')
print "Warning!", xfile, "not found!"
# See if a given file exists in a list of directories. Return the
# directory containing the file, or None if the file can't be found.
def find_file(filename, dirs):
for dir in dirs:
if os.path.exists(os.path.join(dir, filename)):
return dir
# Add dirs to the given path environment variable.
def extend_path(envpath, *dirs):
try:
pathstring = os.environ[envpath]
except KeyError:
path = []
else:
path = pathstring.split(':')
# prepend directories to the path
path[0:0] = [d for d in dirs if os.path.exists(d)]
if path:
os.environ[envpath] = ':'.join(path)
#=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=#
SWIG = 'swig' # must be swig 1.1 build 883
SWIGARGS = ["-shadow", "-dnone", "-python", "-c++", "-c"]
def run_swig(srcdir, swigfile, destdir, cext="_.C", include_dirs=[],
dry_run=False, force=False, extra_args=[],
with_swig=None, DIM_3=0):
# srcdir is a directory. swigfile is the name of the input swig
# file, specfied *relative* to srcdir. The output files will go
# into destdir. If swigfile has subdirectories as part of its
# name, then those subdirectories will be created in destdir. For
# example, if srcdir is "A/B", swigfile is "C/swig.swg", and
# destdir is "E/F", then the file "A/B/C/swig.swg" will be swigged
# to create "E/F/C/swig_.C" and "E/F/C/swig.py".
# cext is the extension to use on the output C++ file.
swig = with_swig or SWIG
srcdir = os.path.abspath(srcdir)
destdir = os.path.abspath(destdir)
relpath = os.path.split(swigfile)[0]
infile = os.path.join(srcdir, swigfile)
indir = os.path.join(srcdir, relpath)
outdir = os.path.join(destdir, relpath)
swigfilename = os.path.split(swigfile)[1]
basename = os.path.splitext(swigfilename)[0]
cfile = os.path.join(destdir, relpath, basename + cext)
pyfile = os.path.join(destdir, relpath, basename + ".py")
infiletime = os.stat(infile)[stat.ST_MTIME]
uptodate = os.path.exists(cfile) and os.path.exists(pyfile) and \
(os.stat(cfile)[stat.ST_MTIME] > infiletime) and \
(os.stat(pyfile)[stat.ST_MTIME] > infiletime)
if DIM_3 and "-DDIM_3" not in extra_args:
extra_args.append("-DDIM_3")
if force or not uptodate:
# Make sure that outdir exists.
if not os.path.exists(outdir):
os.makedirs(outdir)
# Make sure that all directories from destdir to outdir
# contain __init__.py.
destdepth = len(destdir.split(os.sep))
outsplit = outdir.split(os.sep)[destdepth:]
addInitPy(destdir)
odir = destdir
for subdir in outsplit:
odir = os.path.join(odir, subdir)
addInitPy(odir)
incls = [os.path.abspath(dir) for dir in include_dirs]
if srcdir not in incls:
incls.append(srcdir)
if indir not in incls:
incls.append(indir)
# The following command cds to the source directory and runs
# swig. It uses absolute path names for all of the
# directories so that we don't have to worry about the effect
# of the cd. The cd is necessary because the swig
# 'pragma(python) include' lines don't seem to respect the -I
# flags.
cmd = 'cd %(indir)s; %(swig)s %(swigargs)s %(includes)s -module %(module)s -o %(cfile)s %(infile)s' \
% {'indir' : indir,
'swig': swig,
'swigargs' : string.join(SWIGARGS+extra_args, " "),
'includes' : string.join(['-I'+file for file in incls], ' '),
'module' : basename,
'cfile' : cfile,
'infile' : infile}
print cmd
if not dry_run:
## TODO: Check the return status of cmd and raise an
## exception (abort?) if it failed.
proc = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdoutdata, stderrdata = proc.communicate()
print stdoutdata
if stderrdata:
print stderrdata
print "swig failed!"
sys.exit()
# os.system(cmd)
return dict(basename=basename,
indir=indir,
outdir=outdir,
cfile=cfile
)
#=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=#
def addInitPy(subdir):
initpy = os.path.join(subdir, '__init__.py')
if not os.path.exists(initpy):
print >> sys.stderr, "Creating", initpy
initfile = open(initpy, 'w')
print >> initfile, "# This file no verb"
initfile.close()
#=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=##=--=#
class InstallationFile:
def __init__(self, stdout, stderr):
self.filename = None
self.saved = []
self.stdout = stdout # The original stdout
self.stderr = stderr # The original stderr
sys.stderr = self
sys.stdout = self
self.file = None
self.needHeader = False
## TODO: Add date and time to log file
def __del__(self):
self.close()
def setFilename(self, filename):
self.filename = filename
def close(self):
if self.file is not None:
self.file.close()
self.file = None
sys.stdout = self.stdout
sys.stderr = self.stderr
def flush(self):
if self.file is not None:
self.file.flush()
def mkdir(self):
if self.filename is not None:
head, tail = os.path.split(self.filename)
if not os.path.exists(head):
os.makedirs(head)
def clear(self):
if self.file is not None:
self.file.close()
self.file = None
if os.path.isfile(self.filename):
os.remove(self.filename)
self.saved = []
self.needHeader = True
def write(self, data):
self.stdout.write(data)
self.write_file(data)
def write_file(self, data):
if self.filename is not None and self.file is None:
self.mkdir()
self.file = open(self.filename, 'a')
if self.needHeader:
self.file.write("logdata = ")
self.file.write("\"" + time.ctime() + "\\n\"")
self.needHeader = False
for line in self.saved:
self.file.write("\"" + line.replace("\n", "\\n") + "\"")
self.saved = []
if self.file is None:
self.saved.append(data)
else:
self.file.write("\"" + data.replace("\n", "\\n") + "\"")
def fileno(self):
return self.file.fileno()