4 Experimental scons (www.scons.org) building:
8 scons lily # build lily
10 LILYPONDPREFIX=out-scons/usr/share/lilypond lily/out-scons/lilypond-bin
11 scons doc # build web doc
13 scons fonts # build all font stuff (split this? )
15 scons config # reconfigure
17 scons / # builds all possible targets
23 scons build=DIR # scrdir build, write to new tree =build
24 scons out=DIR # write output to deeper dir DIR
26 Optionally, make a custom.py. I have
33 os.path.join (os.getcwd (), '=install')
34 prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
43 # * separate environments?
44 # - compile environment checks headers and libraries
45 # - doc environment checks doc stuff
47 # * commandline targets:
49 # * more fine-grained config.h -- move lilypondprefix to version.hh?
50 # - config.h: changes after system upgrades, affects all files
51 # - version.hh: prefix, version etc? affects few
59 subdirs = ['flower', 'lily', 'mf', 'scm', 'ly', 'Documentation',
60 'Documentation/user', 'input']
63 scons [KEY=VALUE].. [TARGET]..
65 where TARGET is config|lily|all|fonts|doc|tar|dist|release
70 # Without target arguments, build lily only
71 if not COMMAND_LINE_TARGETS:
74 # All builds everything (all directories)
75 env.Alias ('all', ['lily', 'mf', 'input', 'Documentation'])
78 ## FIXME: opts in function
80 # Put your favourite stuff in custom.py
81 opts = Options (['config.cache', 'custom.py'], ARGUMENTS)
82 opts.Add ('prefix', 'Install prefix', '/usr/')
83 opts.Add ('out', 'Output directory', 'out-scons')
84 opts.Add ('build', 'Build directory', '.')
86 BoolOption ('warnings', 'compile with -Wall and similiar',
88 BoolOption ('debugging', 'compile with debugging symbols',
90 BoolOption ('optimising', 'compile with optimising',
92 BoolOption ('shared', 'build shared libraries',
94 BoolOption ('static', 'build static libraries',
96 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
98 BoolOption ('verbose', 'run commands with verbose flag',
102 Help (usage + opts.GenerateHelpText (env))
104 env = Environment (options = opts)
107 opts.Save ('config.cache', env)
109 env.CacheDir (os.path.join (env['build'], '=build-cache'))
112 sys.path.append (os.path.join ('.', 'stepmake', 'bin'))
114 package = packagepython.Package ('.')
116 env['version'] = packagepython.version_tuple_to_str (package.version)
117 env['bindir'] = os.path.join (env['prefix'], 'bin')
118 env['sharedir'] = os.path.join (env['prefix'], 'share')
119 env['libdir'] = os.path.join (env['prefix'], 'lib')
120 env['localedir'] = os.path.join (env['sharedir'], 'locale')
122 env['sharedir_package'] = os.path.join (env['sharedir'], package.name)
123 env['sharedir_package_version'] = os.path.join (env['sharedir_package'],
125 env['lilypondprefix'] = os.path.join (env['sharedir_package_version'])
129 env.Append (CFLAGS = '-g')
130 env.Append (CXXFLAGS = '-g')
131 if env['optimising']:
132 env.Append (CFLAGS = '-O2')
133 env.Append (CXXFLAGS = '-O2')
134 env.Append (CXXFLAGS = '-DSTRING_UTILS_INLINED')
136 env.Append (CFLAGS = '-W ')
137 env.Append (CFLAGS = '-Wall')
138 # what about = ['-W', '-Wall', ...]?
139 env.Append (CXXFLAGS = '-W')
140 env.Append (CXXFLAGS = '-Wall')
141 env.Append (CXXFLAGS = '-Wconversion')
147 reldir = str (Dir ('.').srcnode ())
149 srcdir = os.getcwd ()
151 ##outdir = os.path.join (env['build'], reldir, env['out'])
152 outdir = os.path.join (env['build'], env['out'])
154 env['srcdir'] = srcdir
164 env['MFMODE'] = 'ljfour'
165 config_h = os.path.join (outdir, 'config.h')
166 env.Alias ('config', config_h)
169 conf = Configure (env)
171 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
172 def get_version (program):
173 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
174 pipe = os.popen (command)
175 output = pipe.read ()
178 v = re.sub (vre, '\\1', output)
179 return string.split (v, '.')
181 def assert_version (lst, program, minimal, description, package):
183 sys.stdout.write ('Checking %s version... ' % program)
184 actual = get_version (program)
187 lst.append ((description, package, minimal, program,
190 sys.stdout.write (string.join (actual, '.'))
191 sys.stdout.write ('\n')
192 if actual < string.split (minimal, '.'):
193 lst.append ((description, package, minimal, program,
194 string.join (actual, '.')))
197 assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
198 assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
199 assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
200 assert_version (required, 'guile-config', '1.6', 'GUILE development',
201 'libguile-dev or guile-devel')
202 # Do not use bison 1.50 and 1.75.
203 assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
205 assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
209 assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
210 assert_version (optional, 'guile', '1.6', 'GUILE scheme',
211 'libguile-dev or guile-devel')
212 assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
214 assert_version (optional, 'perl', '4.0',
215 'Perl practical efficient readonly language', 'perl')
216 #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
222 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
223 'PACKAGE': '"' + package.name + '"',
224 'DATADIR' : '"' + env['sharedir'] + '"',
225 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
226 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
227 'LOCALEDIR' : '"' + env['localedir'] + '"',
231 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
232 PYTHON_INCLUDE = os.popen (command).read ()
233 env.Append (CPPPATH = PYTHON_INCLUDE)
235 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
237 if conf.CheckCHeader (i):
238 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
241 ccheaders = ('sstream',)
243 if conf.CheckCXXHeader (i):
244 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
247 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
249 if 0 or conf.CheckFunc (i):
250 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
253 key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
255 sys.stdout.write('Checking for yy_current_buffer ... ')
257 res = conf.TryCompile ("""using namespace std;
258 #include <FlexLexer.h>
259 class yy_flex_lexer: public yyFlexLexer
264 yy_current_buffer = 0;
269 sys.stdout.write('yes\n')
271 sys.stdout.write('no\n')
274 if conf.CheckLib ('dl'):
277 if conf.CheckLib ('kpathsea'):
278 defines['KPATHSEA'] = '1'
281 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
282 defines['HAVE_KPSE_FIND_FILE'] = '1'
283 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
284 defines['HAVE_KPSE_FIND_TFM'] = '1'
286 #this could happen after flower...
287 env.ParseConfig ('guile-config compile')
289 #this could happen only for compiling pango-*
291 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
292 env.ParseConfig ('pkg-config --cflags --libs pango')
293 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
294 defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
296 if conf.CheckLib ('pango-1.0',
297 'pango_fc_font_map_add_decoder_find_func'):
298 defines['HAVE_PANGO_CVS'] = '1'
299 defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
301 # ugh - needed at all? make Builder/Command for config.h!
302 if not os.path.exists (outdir):
305 config = open (config_h, 'w')
306 for i in list_sort (defines.keys ()):
307 config.write ('#define %s %s\n' % (i, defines[i]))
311 os.system (sys.executable \
312 + ' ./stepmake/bin/make-version.py VERSION > '\
313 + os.path.join (outdir, 'version.hh'))
317 print '********************************'
318 print 'Please install required packages'
320 print '%s: %s-%s or newer (found: %s %s)' % i
325 print '*************************************'
326 print 'Consider installing optional packages'
328 print '%s: %s-%s or newer (found: %s %s)' % i
330 return conf.Finish ()
332 # Hmm. Must configure when building lily, to get compiler and linker
335 if not os.path.exists (config_h) or 'config' in COMMAND_LINE_TARGETS\
336 or 'lily' in BUILD_TARGETS or 'all' in BUILD_TARGETS:
337 env = configure (env)
339 if os.path.exists ('parser'):
340 env.Append (LIBPATH = ['#/flower', '#/lily', '#/parser', '#/gui',],
341 CPPPATH = [outdir, '#',])
343 env.Append (LIBPATH = ['#/flower/' + out,],
344 CPPPATH = [outdir, '#',])
350 absbuild = os.getcwd ()
353 env['absbuild'] = absbuild
356 env['MAKEINFO'] = 'LANG= makeinfo'
357 env['PYTHON'] = 'python'
358 env['LILYPOND_BIN'] = os.path.join (absbuild, 'lily', out, 'lilypond-bin')
359 env['LILYPONDPREFIX'] = os.path.join (outdir, 'usr/share/lilypond')
360 env['LILYPOND_BOOK'] = srcdir + '/scripts/lilypond-book.py'
361 env['ABC2LY_PY'] = srcdir + '/scripts/abc2ly.py'
362 env['MF_TO_TABLE_PY'] = srcdir + '/buildscripts/mf-to-table.py'
363 env['LILYPOND_PY'] = srcdir + '/scripts/lilypond.py'
364 env['LILYPOND_BOOK_FLAGS'] = ''
365 env['LILYPOND_BOOK_FORMAT'] = 'texi-html'
367 env['LILYPOND_BOOK_PATH'] = ['.', '#/input', '#/input/regression',
368 '#/input/test', '#/input/tutorial',
369 os.path.join (absbuild, 'mf', out),
370 '#/Documentation/user',
371 os.path.join (absbuild, 'Documentation', out),
372 os.path.join (absbuild, 'Documentation/user', out),
375 env['MAKEINFO_PATH'] = ['.', '#/Documentation/user',
376 os.path.join (absbuild, 'Documentation/user', out)]
378 ## TEXINFO_PAPERSIZE_OPTION= $(if $(findstring $(PAPERSIZE),a4),,-t @afourpaper)
379 env['TEXINFO_PAPERSIZE_OPTION'] = '-t @afourpaper'
381 SConscript ('buildscripts/builder.py')
384 b = os.path.join (build, d, out)
385 # Support clean sourctree build (srcdir build)
387 # TODO: figure out SConscript (dir, builddir, duplicate)) feature
388 if (build and build != '.') \
389 or (out and out != '.'):
390 env.BuildDir (b, d, duplicate=0)
391 SConscript (os.path.join (b, 'SConscript'))
394 def symlink_tree (prefix):
400 if not os.path.isdir (dir):
401 if os.path.exists (dir):
405 map (mkdir, string.split (dir, os.sep))
406 def symlink (src, dst):
408 dir = os.path.dirname (dst)
411 frm = os.path.join (srcdir, src[1:])
413 depth = len (string.split (dir, '/'))
414 frm = os.path.join ('../' * depth, src, out)
415 os.symlink (frm, os.path.basename (dst))
416 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
417 (('python', 'lib/lilypond/python'),
418 # UGHR, lilypond.py uses lilypond-bin from PATH
420 ('#mf', 'share/lilypond/fonts/mf'),
421 ('mf', 'share/lilypond/fonts/afm'),
422 ('mf', 'share/lilypond/fonts/tfm'),
423 ('mf', 'share/lilypond/fonts/type1'),
424 ('#tex', 'share/lilypond/tex/source'),
425 ('mf', 'share/lilypond/tex/generate'),
426 ('#ly', 'share/lilypond/ly'),
427 ('#scm', 'share/lilypond/scm'),
428 ('#ps', 'share/lilypond/ps'),
429 ('elisp', 'share/lilypond/elisp')))
433 prefix = os.path.join (out, 'usr')
434 if not os.path.exists (prefix):
435 symlink_tree (prefix)
438 src_files = ['ChangeLog', '.cvsignore', 'Documentation/index.html.in',
442 entries = open (os.path.join (dir, 'CVS/Entries')).readlines ()
443 files = filter (lambda x: x[0] != 'D', entries)
444 return map (lambda x: os.path.join (dir, x[1:x[1:].index ('/')+1]),
447 readme_files = ['AUTHORS', 'README', 'INSTALL', 'NEWS']
448 foo = map (lambda x: env.Texi2txt (x + '.txt',
449 os.path.join ('Documentation/topdocs',
452 txt_files = map (lambda x: x + '.txt', readme_files)
453 src_files = reduce (lambda x, y: x + y, map (cvs_files, subdirs))
454 tar_base = package.name + '-' + env['version']
455 tar_name = tar_base + '.tar.gz'
456 ball_prefix = os.path.join (outdir, tar_base)
457 tar_ball = os.path.join (outdir, tar_name)
459 dist_files = src_files + txt_files
460 ball_files = map (lambda x: os.path.join (ball_prefix, x), dist_files)
461 map (lambda x: env.Depends (tar_ball, x), ball_files)
462 map (lambda x: env.Command (os.path.join (ball_prefix, x), x,
463 'ln $SOURCE $TARGET'), dist_files)
464 tar = env.Command (tar_ball, src_files,
465 'tar czf $TARGET -C $TARGET.dir %s' % tar_base)
466 env.Alias ('tar', tar)
468 dist_ball = os.path.join (package.release_dir, tar_name)
469 env.Command (dist_ball, tar_ball,
470 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
471 + 'ln $SOURCE $TARGET')
472 env.Depends ('dist', dist_ball)
473 patch_name = os.path.join (outdir, tar_base + '.diff.gz')
474 patch = env.PATCH (patch_name, tar_ball)
475 env.Depends (patch_name, dist_ball)
476 env.Alias ('release', patch)