4 Experimental scons (www.scons.org) building:
8 LILYPONDPREFIX=out-scons/usr/share/lilypond lily/out-scons/lilypond-bin
14 scons build=DIR # scrdir build, write to new tree =build
15 scons out=DIR # write output to deeper dir DIR
17 Optionally, make a custom.py. I have
24 os.path.join (os.getcwd (), '=install')
25 prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
31 # * separate environments?
32 # - compile environment checks headers and libraries
33 # - doc environment checks doc stuff
35 # * running from build-dir, without installing?
36 # - scons will not install, if PREFIX lives outside of CWD
37 # - build symlink tree
38 # + mimicking regular installation setup?
39 # + use tweaked scons 'install' target?
40 # * commandline targets:
42 # - dist, tar => env.Tar
43 # * Documentation, scripts
45 # * more fine-grained config.h -- move lilypondprefix to version.hh?
46 # - config.h: changes after system upgrades, affects all files
47 # - version.hh: prefix, version etc? affects few
57 # put your favourite stuff in custom.py
58 opts = Options ('custom.py', ARGUMENTS)
59 #opts = Options (None, ARGUMENTS)
60 opts.Add ('prefix', 'Install prefix', '/usr/')
61 opts.Add ('out', 'Output directory', 'out-scons')
62 opts.Add ('build', 'Build directory', '.')
64 BoolOption ('warnings', 'compile with -Wall and similiar',
66 BoolOption ('debugging', 'compile with debugging symbols',
68 BoolOption ('optimising', 'compile with optimising',
70 BoolOption ('shared', 'build shared libraries',
72 BoolOption ('static', 'build static libraries',
74 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
76 BoolOption ('verbose', 'run commands with verbose flag',
80 Help (opts.GenerateHelpText (env))
82 env = Environment (options = opts)
84 env.CacheDir (os.path.join (env['build'], '=build-cache'))
87 sys.path.append (os.path.join ('.', 'stepmake', 'bin'))
89 package = packagepython.Package ('.')
91 env['version'] = packagepython.version_tuple_to_str (package.version)
92 env['bindir'] = os.path.join (env['prefix'], 'bin')
93 env['sharedir'] = os.path.join (env['prefix'], 'share')
94 env['libdir'] = os.path.join (env['prefix'], 'lib')
95 env['localedir'] = os.path.join (env['sharedir'], 'locale')
97 env['sharedir_package'] = os.path.join (env['sharedir'], package.name)
98 env['sharedir_package_version'] = os.path.join (env['sharedir_package'],
100 env['lilypondprefix'] = os.path.join (env['sharedir_package_version'])
104 env.Append (CFLAGS = '-g')
105 env.Append (CXXFLAGS = '-g')
106 if env['optimising']:
107 env.Append (CFLAGS = '-O2')
108 env.Append (CXXFLAGS = '-O2')
109 env.Append (CXXFLAGS = '-DSTRING_UTILS_INLINED')
111 env.Append (CFLAGS = '-W ')
112 env.Append (CFLAGS = '-Wall')
113 # what about = ['-W', '-Wall', ...]?
114 env.Append (CXXFLAGS = '-W')
115 env.Append (CXXFLAGS = '-Wall')
116 env.Append (CXXFLAGS = '-Wconversion')
118 env['MFMODE'] = 'ljfour'
121 conf = Configure (env)
124 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
125 def get_version (program):
126 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
127 pipe = os.popen (command)
128 output = pipe.read ()
131 v = re.sub (vre, '\\1', output)
132 return string.split (v, '.')
134 def assert_version (lst, program, minimal, description, package):
136 sys.stdout.write ('Checking %s version... ' % program)
137 actual = get_version (program)
140 lst.append ((description, package, minimal, program,
143 sys.stdout.write (string.join (actual, '.'))
144 sys.stdout.write ('\n')
145 if actual < string.split (minimal, '.'):
146 lst.append ((description, package, minimal, program,
147 string.join (actual, '.')))
150 assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
151 assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
152 assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
153 assert_version (required, 'guile-config', '1.6', 'GUILE development',
154 'libguile-dev or guile-devel')
155 # Do not use bison 1.50 and 1.75.
156 assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
158 assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
162 assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
163 assert_version (optional, 'guile', '1.6', 'GUILE scheme',
164 'libguile-dev or guile-devel')
165 assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
167 assert_version (optional, 'perl', '4.0',
168 'Perl practical efficient readonly language', 'perl')
169 #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
175 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
176 'PACKAGE': '"' + package.name + '"',
177 'DATADIR' : '"' + env['sharedir'] + '"',
178 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
179 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
180 'LOCALEDIR' : '"' + env['localedir'] + '"',
184 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
185 PYTHON_INCLUDE = os.popen (command).read ()
186 env.Append (CPPPATH = PYTHON_INCLUDE)
188 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
190 if conf.CheckCHeader (i):
191 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
194 ccheaders = ('sstream',)
196 if conf.CheckCXXHeader (i):
197 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
200 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
202 if 0 or conf.CheckFunc (i):
203 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
206 key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
208 sys.stdout.write('Checking for yy_current_buffer ... ')
210 res = conf.TryCompile ("""using namespace std;
211 #include <FlexLexer.h>
212 class yy_flex_lexer: public yyFlexLexer
217 yy_current_buffer = 0;
222 sys.stdout.write('yes\n')
224 sys.stdout.write('no\n')
227 if conf.CheckLib ('dl'):
230 if conf.CheckLib ('kpathsea'):
231 defines['KPATHSEA'] = '1'
234 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
235 defines['HAVE_KPSE_FIND_FILE'] = '1'
236 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
237 defines['HAVE_KPSE_FIND_TFM'] = '1'
239 #this could happen after flower...
240 env.ParseConfig ('guile-config compile')
242 #this could happen only for compiling pango-*
244 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
245 env.ParseConfig ('pkg-config --cflags --libs pango')
246 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
247 defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
249 if conf.CheckLib ('pango-1.0',
250 'pango_fc_font_map_add_decoder_find_func'):
251 defines['HAVE_PANGO_CVS'] = '1'
252 defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
257 reldir = str (Dir ('.').srcnode ())
259 srcdir = os.getcwd ()
261 env['srcdir'] = srcdir
265 ##reldir = str (Dir ('.').srcnode ())
266 reldir = os.getcwd ()
267 outdir = os.path.join (env['build'], reldir, env['out'])
268 if not os.path.exists (outdir):
276 config = open (os.path.join (outdir, 'config.h'), 'w')
277 for i in list_sort (defines.keys ()):
278 config.write ('#define %s %s\n' % (i, defines[i]))
281 os.system (sys.executable \
282 + ' ./stepmake/bin/make-version.py VERSION > '\
283 + os.path.join (outdir, 'version.hh'))
285 if os.path.exists ('parser'):
286 env.Append (LIBPATH = ['#/flower', '#/lily', '#/parser', '#/gui',],
287 CPPPATH = [outdir, '#',])
289 env.Append (LIBPATH = ['#/flower/' + out,],
290 CPPPATH = [outdir, '#',])
294 print '********************************'
295 print 'Please install required packages'
297 print '%s: %s-%s or newer (found: %s %s)' % i
302 print '*************************************'
303 print 'Consider installing optional packages'
305 print '%s: %s-%s or newer (found: %s %s)' % i
307 #env['tarball'] = os.path.join (outdir,
308 # package.name + '-' + env['version'] + '.tar.gz')
310 env['tarball'] = os.path.join (os.environ['HOME'], 'tmp',
311 package.name + '-' + env['version'] + '.tar.gz')
314 if 'tar' in COMMAND_LINE_TARGETS:
315 #env.Default (env['tarball'])
317 env.Default (env['tarball'])
324 absbuild = os.getcwd ()
327 env['absbuild'] = absbuild
330 env['MAKEINFO'] = 'LANG= makeinfo'
331 env['PYTHON'] = 'python'
332 env['LILYPOND_BIN'] = os.path.join (absbuild, 'lily', out, 'lilypond-bin')
333 env['LILYPONDPREFIX'] = os.path.join (outdir, 'usr/share/lilypond')
334 env['LILYPOND_BOOK'] = srcdir + '/scripts/lilypond-book.py'
335 env['ABC2LY_PY'] = srcdir + '/scripts/abc2ly.py'
336 env['MF_TO_TABLE_PY'] = srcdir + '/buildscripts/mf-to-table.py'
337 env['LILYPOND_PY'] = srcdir + '/scripts/lilypond.py'
338 env['LILYPOND_BOOK_FLAGS'] = ''
339 env['LILYPOND_BOOK_FORMAT'] = 'texi-html'
341 env['LILYPOND_BOOK_PATH'] = ['.', '#/input', '#/input/regression',
342 '#/input/test', '#/input/tutorial',
343 os.path.join (absbuild, 'mf', out),
344 '#/Documentation/user',
345 os.path.join (absbuild, 'Documentation', out),
346 os.path.join (absbuild, 'Documentation/user', out),
349 env['MAKEINFO_PATH'] = ['.', '#/Documentation/user',
350 os.path.join (absbuild, 'Documentation/user', out)]
352 ## TEXINFO_PAPERSIZE_OPTION= $(if $(findstring $(PAPERSIZE),a4),,-t @afourpaper)
353 env['TEXINFO_PAPERSIZE_OPTION'] = '-t @afourpaper'
354 #FIXME: ./python isn't sconsed yet, add scrdir/python for lilylib.py ...
355 env.Append (PYTHONPATH = [os.path.join (outdir, 'usr/lib/python'),
356 os.path.join (srcdir, 'buildscripts'),
357 os.path.join (srcdir, 'python')])
359 env.Append (ENV = { 'PYTHONPATH' : string.join (env['PYTHONPATH'],
362 # GS_FONTPATH, GS_LIB?
363 SConscript ('buildscripts/builder.py')
366 #subdirs = ['flower', 'lily', 'parser', 'gui', 'main',]
367 #subdirs = ['flower', 'lily', 'mf', 'scm', 'ly']
368 subdirs = ['flower', 'lily', 'mf', 'scm', 'ly', 'Documentation',
369 'Documentation/user', 'input']
371 b = os.path.join (build, d, out)
372 # Support clean sourctree build (srcdir build)
374 # TODO: figure out SConscript (dir, builddir, duplicate)) feature
375 if (build and build != '.') \
376 or (out and out != '.'):
377 env.BuildDir (b, d, duplicate=0)
378 SConscript (os.path.join (b, 'SConscript'))
380 readme_files = ['ChangeLog', 'COPYING', 'DEDICATION', 'ROADMAP', 'THANKS']
381 readme_txt = ['AUTHORS.txt', 'README.txt', 'INSTALL.txt', 'NEWS.txt']
382 # to be [re]moved after spit
383 patch_files = ['emacsclient.patch', 'server.el.patch', 'darwin.patch']
385 map (lambda x: env.Texi2txt (x, os.path.join ('Documentation/topdocs',
386 os.path.splitext (x)[0])),
390 env.Append (TARFLAGS = '-z --owner=0 --group=0')
391 env.Append (GZIPFLAGS = '-9')
392 all_sources = ['SConstruct',] + subdirs \
393 + ['VERSION', '.cvsignore']\
394 + readme_files + readme_txt + patch_files
396 tar = env.Tar (env['tarball'], all_sources)
399 def symlink_tree (prefix):
405 if not os.path.isdir (dir):
406 if os.path.exists (dir):
410 map (mkdir, string.split (dir, os.sep))
411 #srcdir = os.getcwd ()
412 def symlink (src, dst):
413 dir = os.path.dirname (dst)
416 frm = os.path.join (srcdir, src[1:])
418 depth = len (string.split (dir))
419 frm = os.path.join ('../' * depth, src, out)
420 os.symlink (frm, os.path.basename (dst))
422 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
423 (('python', 'lib/lilypond/python'),
424 ('#mf', 'share/lilypond/fonts/mf'),
425 ('mf', 'share/lilypond/fonts/amf'),
426 ('mf', 'share/lilypond/fonts/tfm'),
427 ('mf', 'share/lilypond/fonts/type1'),
428 ('#tex', 'share/lilypond/tex/source'),
429 ('mf', 'share/lilypond/tex/generate'),
430 ('#ly', 'share/lilypond/ly'),
431 ('#scm', 'share/lilypond/scm'),
432 ('#ps', 'share/lilypond/ps'),
433 ('elisp', 'share/lilypond/elisp')))
436 prefix = os.path.join (outdir, 'usr')
437 if not os.path.exists (prefix):
438 symlink_tree (prefix)