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 ('custom.py', ARGUMENTS)
82 #opts = Options (['config.cache', 'custom.py'], ARGUMENTS)
83 opts.Add ('prefix', 'Install prefix', '/usr/')
84 opts.Add ('out', 'Output directory', 'out-scons')
85 opts.Add ('build', 'Build directory', '.')
87 BoolOption ('warnings', 'compile with -Wall and similiar',
89 BoolOption ('debugging', 'compile with debugging symbols',
91 BoolOption ('optimising', 'compile with optimising',
93 BoolOption ('shared', 'build shared libraries',
95 BoolOption ('static', 'build static libraries',
97 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
99 BoolOption ('verbose', 'run commands with verbose flag',
103 Help (usage + opts.GenerateHelpText (env))
105 env = Environment (options = opts)
108 #opts.Save ('config.cache', env)
110 env.CacheDir (os.path.join (env['build'], '=build-cache'))
113 sys.path.append (os.path.join ('.', 'stepmake', 'bin'))
115 package = packagepython.Package ('.')
117 env['version'] = packagepython.version_tuple_to_str (package.version)
118 env['bindir'] = os.path.join (env['prefix'], 'bin')
119 env['sharedir'] = os.path.join (env['prefix'], 'share')
120 env['libdir'] = os.path.join (env['prefix'], 'lib')
121 env['localedir'] = os.path.join (env['sharedir'], 'locale')
123 env['sharedir_package'] = os.path.join (env['sharedir'], package.name)
124 env['sharedir_package_version'] = os.path.join (env['sharedir_package'],
126 env['lilypondprefix'] = os.path.join (env['sharedir_package_version'])
130 env.Append (CFLAGS = '-g')
131 env.Append (CXXFLAGS = '-g')
132 if env['optimising']:
133 env.Append (CFLAGS = '-O2')
134 env.Append (CXXFLAGS = '-O2')
135 env.Append (CXXFLAGS = '-DSTRING_UTILS_INLINED')
137 env.Append (CFLAGS = '-W ')
138 env.Append (CFLAGS = '-Wall')
139 # what about = ['-W', '-Wall', ...]?
140 env.Append (CXXFLAGS = '-W')
141 env.Append (CXXFLAGS = '-Wall')
142 env.Append (CXXFLAGS = '-Wconversion')
148 reldir = str (Dir ('.').srcnode ())
150 srcdir = os.getcwd ()
152 ##outdir = os.path.join (env['build'], reldir, env['out'])
153 outdir = os.path.join (env['build'], env['out'])
155 env['srcdir'] = srcdir
165 env['MFMODE'] = 'ljfour'
166 config_h = os.path.join (outdir, 'config.h')
167 env.Alias ('config', config_h)
170 conf = Configure (env)
172 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
173 def get_version (program):
174 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
175 pipe = os.popen (command)
176 output = pipe.read ()
179 v = re.sub (vre, '\\1', output)
180 return string.split (v, '.')
182 def assert_version (lst, program, minimal, description, package):
184 sys.stdout.write ('Checking %s version... ' % program)
185 actual = get_version (program)
188 lst.append ((description, package, minimal, program,
191 sys.stdout.write (string.join (actual, '.'))
192 sys.stdout.write ('\n')
193 if actual < string.split (minimal, '.'):
194 lst.append ((description, package, minimal, program,
195 string.join (actual, '.')))
198 assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
199 assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
200 assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
201 assert_version (required, 'guile-config', '1.6', 'GUILE development',
202 'libguile-dev or guile-devel')
203 # Do not use bison 1.50 and 1.75.
204 assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
206 assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
210 assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
211 assert_version (optional, 'guile', '1.6', 'GUILE scheme',
212 'libguile-dev or guile-devel')
213 assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
215 assert_version (optional, 'perl', '4.0',
216 'Perl practical efficient readonly language', 'perl')
217 #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
223 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
224 'PACKAGE': '"' + package.name + '"',
225 'DATADIR' : '"' + env['sharedir'] + '"',
226 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
227 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
228 'LOCALEDIR' : '"' + env['localedir'] + '"',
232 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
233 PYTHON_INCLUDE = os.popen (command).read ()
234 env.Append (CPPPATH = PYTHON_INCLUDE)
236 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
238 if conf.CheckCHeader (i):
239 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
242 ccheaders = ('sstream',)
244 if conf.CheckCXXHeader (i):
245 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
248 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
250 if 0 or conf.CheckFunc (i):
251 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
254 key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
256 sys.stdout.write('Checking for yy_current_buffer ... ')
258 res = conf.TryCompile ("""using namespace std;
259 #include <FlexLexer.h>
260 class yy_flex_lexer: public yyFlexLexer
265 yy_current_buffer = 0;
270 sys.stdout.write('yes\n')
272 sys.stdout.write('no\n')
275 if conf.CheckLib ('dl'):
278 if conf.CheckLib ('kpathsea'):
279 defines['KPATHSEA'] = '1'
282 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
283 defines['HAVE_KPSE_FIND_FILE'] = '1'
284 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
285 defines['HAVE_KPSE_FIND_TFM'] = '1'
287 #this could happen after flower...
288 env.ParseConfig ('guile-config compile')
290 #this could happen only for compiling pango-*
292 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
293 env.ParseConfig ('pkg-config --cflags --libs pango')
294 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
295 defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
297 if conf.CheckLib ('pango-1.0',
298 'pango_fc_font_map_add_decoder_find_func'):
299 defines['HAVE_PANGO_CVS'] = '1'
300 defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
302 # ugh - needed at all? make Builder/Command for config.h!
303 if not os.path.exists (outdir):
306 config = open (config_h, 'w')
307 for i in list_sort (defines.keys ()):
308 config.write ('#define %s %s\n' % (i, defines[i]))
312 os.system (sys.executable \
313 + ' ./stepmake/bin/make-version.py VERSION > '\
314 + os.path.join (outdir, 'version.hh'))
318 print '********************************'
319 print 'Please install required packages'
321 print '%s: %s-%s or newer (found: %s %s)' % i
326 print '*************************************'
327 print 'Consider installing optional packages'
329 print '%s: %s-%s or newer (found: %s %s)' % i
331 return conf.Finish ()
333 # 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 tarbase = package.name + '-' + env['version']
382 tarname = tarbase + '.tar.gz'
385 ballprefix = os.path.join (outdir, tarbase)
386 tarball = os.path.join (outdir, tarname)
388 ballprefix = os.path.join (os.getcwd (), tarbase)
389 tarball = os.path.join (os.getcwd (), tarname)
390 env['tarball'] = tarball
391 env['ballprefix'] = ballprefix
393 SConscript ('buildscripts/builder.py')
395 readme_files = ['ChangeLog', 'COPYING', 'DEDICATION', 'ROADMAP', 'THANKS']
396 readme_txt = ['AUTHORS.txt', 'README.txt', 'INSTALL.txt', 'NEWS.txt']
397 # to be [re]moved after spit
398 patch_files = ['emacsclient.patch', 'server.el.patch', 'darwin.patch']
401 env.Append (TARFLAGS = '-z --owner=0 --group=0')
402 env.Append (GZIPFLAGS = '-9')
403 #all_sources = ['SConstruct', 'VERSION', '.cvsignore']\
404 # + readme_files #+ patch_files # + readme_txt
405 all_sources = ['SConstruct', 'VERSION']\
407 # + readme_files + readme_txt
408 # + readme_files + patch_files + readme_txt
410 env['sources'] = all_sources
412 map (lambda x: env.Texi2txt (x, os.path.join ('Documentation/topdocs',
413 os.path.splitext (x)[0])),
417 b = os.path.join (build, d, out)
418 # Support clean sourctree build (srcdir build)
420 # TODO: figure out SConscript (dir, builddir, duplicate)) feature
421 if (build and build != '.') \
422 or (out and out != '.'):
423 env.BuildDir (b, d, duplicate=0)
424 SConscript (os.path.join (b, 'SConscript'))
427 def symlink_tree (prefix):
433 if not os.path.isdir (dir):
434 if os.path.exists (dir):
438 map (mkdir, string.split (dir, os.sep))
439 #srcdir = os.getcwd ()
440 def symlink (src, dst):
442 dir = os.path.dirname (dst)
445 frm = os.path.join (srcdir, src[1:])
447 depth = len (string.split (dir, '/'))
448 frm = os.path.join ('../' * depth, src, out)
449 os.symlink (frm, os.path.basename (dst))
450 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
451 (('python', 'lib/lilypond/python'),
452 # UGHR, lilypond.py uses lilypond-bin from PATH
454 ('#mf', 'share/lilypond/fonts/mf'),
455 ('mf', 'share/lilypond/fonts/afm'),
456 ('mf', 'share/lilypond/fonts/tfm'),
457 ('mf', 'share/lilypond/fonts/type1'),
458 ('#tex', 'share/lilypond/tex/source'),
459 ('mf', 'share/lilypond/tex/generate'),
460 ('#ly', 'share/lilypond/ly'),
461 ('#scm', 'share/lilypond/scm'),
462 ('#ps', 'share/lilypond/ps'),
463 ('elisp', 'share/lilypond/elisp')))
467 prefix = os.path.join (out, 'usr')
468 if not os.path.exists (prefix):
469 symlink_tree (prefix)
471 #ball = Builder (prefix = ballprefix + '/', action = 'ln $SOURCE $TARGET')
472 #et = env.Copy (BUILDERS = {'BALL': ball})
473 #ballize = map (et.BALL, all_sources)
474 #tar = env.Tar (tarball, map (lambda x: os.path.join (env['ballprefix'], x),
476 tar = env['baller'] ('', all_sources, env)
477 env.Alias ('tar', tar)
479 distball = os.path.join (package.release_dir, tarname)
480 env.Command (distball, tarball,
481 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
482 + 'ln $SOURCE $TARGET')
483 env.Depends ('dist', distball)
484 patchfile = os.path.join (outdir, tarbase + '.diff.gz')
485 patch = env.PATCH (patchfile, tarball)
486 env.Depends (patchfile, distball)
487 env.Alias ('release', patch)