]> git.donarmstrong.com Git - lilypond.git/blob - SConstruct
(assert_version): Add.
[lilypond.git] / SConstruct
1 # -*-python-*-
2
3 '''
4 Experimental scons (www.scons.org) building:
5
6 Usage:
7     scons
8     scons install
9     scons -c              # clean
10     scons -h              # help
11
12     scons build=DIR       # scrdir build, write to new tree =build
13     scons out=DIR         # write output to deeper dir DIR
14
15 Optionally, make a custom.py.  I have
16
17 import os
18 out='out-scons'
19 optimising=0
20 debugging=1
21 gui=1
22 os.path.join (os.getcwd (), '=install')
23
24 '''
25
26
27 # TODO:
28 #   * running from build-dir, without installing?
29 #     - scons will not install, if PREFIX lives outside of CWD
30 #     - build symlink tree
31 #       + mimicking regular installation setup?
32 #       + use tweaked scons 'install' target?
33 #   * commandline targets:
34 #      - clean => -c
35 #      - dist, tar => env.Tar
36 #   * Documentation, scripts
37 #   * env.Tar
38 #   * more fine-grained config.h -- move lilypondprefix to version.hh?
39 #     - config.h:   changes after system upgrades, affects all files
40 #     - version.hh:  prefix, version etc?  affects few
41
42 import re
43 import glob
44 import os
45 import sys
46 import string
47
48 env = Environment ()
49
50 # put your favourite stuff in custom.py
51 opts = Options ('custom.py', ARGUMENTS)
52 opts.Add ('prefix', 'Install prefix', '/usr/')
53 opts.Add ('out', 'Output directory', 'out-scons')
54 opts.Add ('build', 'Build directory', '.')
55 opts.AddOptions (
56         BoolOption ('warnings', 'compile with -Wall and similiar',
57                    1),
58         BoolOption ('debugging', 'compile with debugging symbols',
59                     0),
60         BoolOption ('optimising', 'compile with optimising',
61                     1),
62         BoolOption ('shared', 'build shared libraries',
63                     0),
64         BoolOption ('static', 'build static libraries',
65                     1),
66         BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
67                     1),
68         BoolOption ('verbose', 'run commands with verbose flag',
69                     0),
70         )
71
72 Help (opts.GenerateHelpText (env))
73
74 env = Environment (options = opts)
75
76 env.CacheDir (os.path.join (env['build'], '=build-cache'))
77
78 #ugh
79 sys.path.append (os.path.join ('.', 'stepmake', 'bin'))
80 import packagepython
81 package = packagepython.Package ('.')
82
83 env['version'] = packagepython.version_tuple_to_str (package.version)
84 env['bindir'] = os.path.join (env['prefix'], 'bin')
85 env['sharedir'] = os.path.join (env['prefix'], 'share')
86 env['libdir'] = os.path.join (env['prefix'], 'lib')
87 env['localedir'] = os.path.join (env['sharedir'], 'locale')
88
89 env['sharedir_package'] = os.path.join (env['sharedir'], package.name)
90 env['sharedir_package_version'] = os.path.join (env['sharedir_package'],
91                                                  env['version'])
92 env['lilypondprefix'] = os.path.join (env['sharedir_package_version'])
93
94
95 if env['debugging']:
96         env.Append (CFLAGS = '-g')
97         env.Append (CXXFLAGS = '-g')
98 if env['optimising']:
99         env.Append (CFLAGS = '-O2')
100         env.Append (CXXFLAGS = '-O2')
101         env.Append (CXXFLAGS = '-DSTRING_UTILS_INLINED')
102 if env['warnings']:
103         env.Append (CFLAGS = '-W ')
104         env.Append (CFLAGS = '-Wall')
105         # what about = ['-W', '-Wall', ...]?
106         env.Append (CXXFLAGS = '-W')
107         env.Append (CXXFLAGS = '-Wall')
108         env.Append (CXXFLAGS = '-Wconversion')
109
110 env['MFMODE'] = 'ljfour'
111
112
113 conf = Configure (env)
114
115
116 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
117 def get_version (program):
118         command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
119         pipe = os.popen (command)
120         output = pipe.read ()
121         if pipe.close ():
122                 return None
123         v = re.sub (vre, '\\1', output)
124         return string.split (v, '.')
125
126 def assert_version (lst, program, minimal, description, package):
127         global required
128         sys.stdout.write ('Checking %s version... ' % program)
129         actual = get_version (program)
130         if not actual:
131                 print 'not found'
132                 lst.append ((description, package, minimal, program,
133                              'not installed'))
134                 return
135         sys.stdout.write (string.join (actual, '.'))
136         sys.stdout.write ('\n')
137         if actual < string.split (minimal, '.'):
138                 lst.append ((description, package, minimal, program,
139                              string.join (actual, '.')))
140
141 required = []
142 assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
143 assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
144 assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
145 assert_version (required, 'guile-config', '1.6', 'GUILE development',
146                 'libguile-dev or guile-devel')
147 # Do not use bison 1.50 and 1.75.
148 assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
149                 'bison')
150 assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
151
152
153 optional = []
154 assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
155 assert_version (optional, 'guile', '1.6', 'GUILE scheme',
156                 'libguile-dev or guile-devel')
157 assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
158                 'mftrace')
159 assert_version (optional, 'perl', '4.0',
160                 'Perl practical efficient readonly language', 'perl')
161 #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
162
163
164 defines = {
165    'DIRSEP' : "'/'",
166    'PATHSEP' : "':'",
167    'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
168    'PACKAGE': '"' + package.name + '"',
169    'DATADIR' : '"' + env['sharedir'] + '"',
170    'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
171    'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
172    'LOCALEDIR' : '"' + env['localedir'] + '"',
173 }
174
175
176 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
177 PYTHON_INCLUDE = os.popen (command).read ()
178 env.Append (CPPPATH = PYTHON_INCLUDE)
179
180
181 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
182 for i in headers:
183         if conf.CheckCHeader (i):
184                 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
185                 defines[key] = '1'
186
187 ccheaders = ('sstream',)
188 for i in ccheaders:
189         if conf.CheckCXXHeader (i):
190                 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
191                 defines[key] = '1'
192
193 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
194 for i in functions:
195         if 0 or conf.CheckFunc (i):
196                 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
197                 defines[key] = '1'
198
199
200 key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
201 defines[key] = conf.TryCompile ("""using namespace std;
202 #include <FlexLexer.h>
203 class yy_flex_lexer: public yyFlexLexer
204 {
205   public:
206     yy_flex_lexer ()
207     {
208       yy_current_buffer = 0;
209     }
210 };""", 'cc')
211
212 if conf.CheckLib ('dl'):
213         pass
214
215 if conf.CheckLib ('kpathsea'):
216         defines['KPATHSEA'] = '1'
217
218 # huh? 
219 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
220         defines['HAVE_KPSE_FIND_FILE'] = '1'
221 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
222         defines['HAVE_KPSE_FIND_TFM'] = '1'
223
224 #this could happen after flower...
225 env.ParseConfig ('guile-config compile')
226
227 #this could happen only for compiling pango-*
228 if env['gui']:
229         env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
230         env.ParseConfig ('pkg-config --cflags --libs pango')
231         if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
232                 defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
233
234         if conf.CheckLib ('pango-1.0',
235                           'pango_fc_font_map_add_decoder_find_func'):
236                 defines['HAVE_PANGO_CVS'] = '1'
237                 defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
238
239 env = conf.Finish ()
240
241 build = env['build']
242 out = env['out']
243 ##reldir = str (Dir ('.').srcnode ())
244 reldir = os.getcwd ()
245 outdir = os.path.join (env['build'], reldir, env['out'])
246 if not os.path.exists (outdir):
247         os.mkdir (outdir)
248
249 def list_sort (lst):
250         sorted = lst
251         sorted.sort ()
252         return sorted
253         
254 config = open (os.path.join (outdir, 'config.h'), 'w')
255 for i in list_sort (defines.keys ()):
256         config.write ('#define %s %s\n' % (i, defines[i]))
257 config.close ()
258
259 os.system (sys.executable \
260            + ' ./stepmake/bin/make-version.py VERSION > '\
261            + os.path.join (outdir, 'version.hh'))
262
263 if os.path.exists ('parser'):
264         env.Append (LIBPATH = ['#/flower', '#/lily', '#/parser', '#/gui',],
265                     CPPPATH = [outdir, '#',])
266 else:   
267         env.Append (LIBPATH = ['#/flower/' + out,],
268                     CPPPATH = [outdir, '#',])
269
270 if required:
271         print
272         print '********************************'
273         print 'Please install required packages'
274         for i in required:
275                 print '%s:      %s-%s or newer (found: %s %s)' % i
276         sys.exit (1)
277
278 if optional:
279         print
280         print '*************************************'
281         print 'Consider installing optional packages'
282         for i in optional:
283                 print '%s:      %s-%s or newer (found: %s %s)' % i
284
285 #env['tarball'] = os.path.join (outdir,
286 #                              package.name + '-' + env['version'] + '.tar.gz')
287
288 env['tarball'] = os.path.join (os.environ['HOME'], 'tmp',
289                                package.name + '-' + env['version'] + '.tar.gz')
290
291 # huh?
292 if 'tar' in COMMAND_LINE_TARGETS:
293         #env.Default (env['tarball'])
294         #env.Default (tar)
295         env.Default (env['tarball'])
296         #Default (tar)
297
298 Export ('env')
299
300
301 #subdirs = ['mf',]
302 #subdirs = ['flower', 'lily', 'parser', 'gui', 'main',]
303 subdirs = ['flower', 'lily', 'mf', 'scm', 'ly']
304 for d in subdirs:
305         b = os.path.join (build, d, out)
306         # Support clean sourctree build (srcdir build)
307         # and outdir build.
308         # TODO: figure out SConscript (dir, builddir, duplicate)) feature
309         if (build and build != '.') \
310            or (out and out != '.'):
311                 env.BuildDir (b, d, duplicate=0)
312         SConscript (os.path.join (b, 'SConscript'))
313
314
315 readmes = ['AUTHORS.txt', 'ChangeLog', 'NEWS.txt']
316
317 #testing
318 env.Append (TARFLAGS = '-z --owner=0 --group=0')
319 env.Append (GZIPFLAGS = '-9')
320 all_sources = ['SConstruct',] + readmes + subdirs
321 tar = env.Tar (env['tarball'], all_sources)