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 XXX scons # without args builds all targets below ./
16 XXX # maybe catch this one and only build lily?
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')
40 # * separate environments?
41 # - compile environment checks headers and libraries
42 # - doc environment checks doc stuff
43 # * - help for targets?
44 # - build symlink tree
45 # * commandline targets:
47 # - dist, tar => env.Tar
48 # * Documentation, scripts
50 # * more fine-grained config.h -- move lilypondprefix to version.hh?
51 # - config.h: changes after system upgrades, affects all files
52 # - version.hh: prefix, version etc? affects few
60 subdirs = ['flower', 'lily', 'mf', 'scm', 'ly', 'Documentation',
61 'Documentation/user', 'input']
65 scons [KEY=VALUE].. [TARGET]..
67 where TARGET is lily|all|fonts|doc|tar|dist|release
72 # Without target arguments, build lily only
73 if not COMMAND_LINE_TARGETS:
76 # Target 'all' builds everything
77 #if 'all' in COMMAND_LINE_TARGETS:
80 env.Alias ('all', ['lily', 'mf', 'input', 'Documentation'])
82 # Put your favourite stuff in custom.py
83 opts = Options ('custom.py', ARGUMENTS)
84 #opts = Options (['config.cache', 'custom.py'], ARGUMENTS)
85 opts.Add ('prefix', 'Install prefix', '/usr/')
86 opts.Add ('out', 'Output directory', 'out-scons')
87 opts.Add ('build', 'Build directory', '.')
89 BoolOption ('warnings', 'compile with -Wall and similiar',
91 BoolOption ('debugging', 'compile with debugging symbols',
93 BoolOption ('optimising', 'compile with optimising',
95 BoolOption ('shared', 'build shared libraries',
97 BoolOption ('static', 'build static libraries',
99 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
101 BoolOption ('verbose', 'run commands with verbose flag',
105 Help (usage + opts.GenerateHelpText (env))
107 env = Environment (options = opts)
110 #opts.Save ('config.cache', env)
113 env.CacheDir (os.path.join (env['build'], '=build-cache'))
116 sys.path.append (os.path.join ('.', 'stepmake', 'bin'))
118 package = packagepython.Package ('.')
120 env['version'] = packagepython.version_tuple_to_str (package.version)
121 env['bindir'] = os.path.join (env['prefix'], 'bin')
122 env['sharedir'] = os.path.join (env['prefix'], 'share')
123 env['libdir'] = os.path.join (env['prefix'], 'lib')
124 env['localedir'] = os.path.join (env['sharedir'], 'locale')
126 env['sharedir_package'] = os.path.join (env['sharedir'], package.name)
127 env['sharedir_package_version'] = os.path.join (env['sharedir_package'],
129 env['lilypondprefix'] = os.path.join (env['sharedir_package_version'])
133 env.Append (CFLAGS = '-g')
134 env.Append (CXXFLAGS = '-g')
135 if env['optimising']:
136 env.Append (CFLAGS = '-O2')
137 env.Append (CXXFLAGS = '-O2')
138 env.Append (CXXFLAGS = '-DSTRING_UTILS_INLINED')
140 env.Append (CFLAGS = '-W ')
141 env.Append (CFLAGS = '-Wall')
142 # what about = ['-W', '-Wall', ...]?
143 env.Append (CXXFLAGS = '-W')
144 env.Append (CXXFLAGS = '-Wall')
145 env.Append (CXXFLAGS = '-Wconversion')
147 env['MFMODE'] = 'ljfour'
150 conf = Configure (env)
153 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
154 def get_version (program):
155 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
156 pipe = os.popen (command)
157 output = pipe.read ()
160 v = re.sub (vre, '\\1', output)
161 return string.split (v, '.')
163 def assert_version (lst, program, minimal, description, package):
165 sys.stdout.write ('Checking %s version... ' % program)
166 actual = get_version (program)
169 lst.append ((description, package, minimal, program,
172 sys.stdout.write (string.join (actual, '.'))
173 sys.stdout.write ('\n')
174 if actual < string.split (minimal, '.'):
175 lst.append ((description, package, minimal, program,
176 string.join (actual, '.')))
179 assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
180 assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
181 assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
182 assert_version (required, 'guile-config', '1.6', 'GUILE development',
183 'libguile-dev or guile-devel')
184 # Do not use bison 1.50 and 1.75.
185 assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
187 assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
191 assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
192 assert_version (optional, 'guile', '1.6', 'GUILE scheme',
193 'libguile-dev or guile-devel')
194 assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
196 assert_version (optional, 'perl', '4.0',
197 'Perl practical efficient readonly language', 'perl')
198 #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
204 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
205 'PACKAGE': '"' + package.name + '"',
206 'DATADIR' : '"' + env['sharedir'] + '"',
207 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
208 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
209 'LOCALEDIR' : '"' + env['localedir'] + '"',
213 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
214 PYTHON_INCLUDE = os.popen (command).read ()
215 env.Append (CPPPATH = PYTHON_INCLUDE)
217 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
219 if conf.CheckCHeader (i):
220 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
223 ccheaders = ('sstream',)
225 if conf.CheckCXXHeader (i):
226 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
229 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
231 if 0 or conf.CheckFunc (i):
232 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
235 key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
237 sys.stdout.write('Checking for yy_current_buffer ... ')
239 res = conf.TryCompile ("""using namespace std;
240 #include <FlexLexer.h>
241 class yy_flex_lexer: public yyFlexLexer
246 yy_current_buffer = 0;
251 sys.stdout.write('yes\n')
253 sys.stdout.write('no\n')
256 if conf.CheckLib ('dl'):
259 if conf.CheckLib ('kpathsea'):
260 defines['KPATHSEA'] = '1'
263 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
264 defines['HAVE_KPSE_FIND_FILE'] = '1'
265 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
266 defines['HAVE_KPSE_FIND_TFM'] = '1'
268 #this could happen after flower...
269 env.ParseConfig ('guile-config compile')
271 #this could happen only for compiling pango-*
273 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
274 env.ParseConfig ('pkg-config --cflags --libs pango')
275 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
276 defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
278 if conf.CheckLib ('pango-1.0',
279 'pango_fc_font_map_add_decoder_find_func'):
280 defines['HAVE_PANGO_CVS'] = '1'
281 defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
287 reldir = str (Dir ('.').srcnode ())
289 srcdir = os.getcwd ()
291 ##outdir = os.path.join (env['build'], reldir, env['out'])
292 outdir = os.path.join (env['build'], env['out'])
294 env['srcdir'] = srcdir
299 if not os.path.exists (outdir):
307 config = open (os.path.join (outdir, 'config.h'), 'w')
308 for i in list_sort (defines.keys ()):
309 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'))
316 if os.path.exists ('parser'):
317 env.Append (LIBPATH = ['#/flower', '#/lily', '#/parser', '#/gui',],
318 CPPPATH = [outdir, '#',])
320 env.Append (LIBPATH = ['#/flower/' + out,],
321 CPPPATH = [outdir, '#',])
325 print '********************************'
326 print 'Please install required packages'
328 print '%s: %s-%s or newer (found: %s %s)' % i
333 print '*************************************'
334 print 'Consider installing optional packages'
336 print '%s: %s-%s or newer (found: %s %s)' % i
342 absbuild = os.getcwd ()
345 env['absbuild'] = absbuild
348 env['MAKEINFO'] = 'LANG= makeinfo'
349 env['PYTHON'] = 'python'
350 env['LILYPOND_BIN'] = os.path.join (absbuild, 'lily', out, 'lilypond-bin')
351 env['LILYPONDPREFIX'] = os.path.join (outdir, 'usr/share/lilypond')
352 env['LILYPOND_BOOK'] = srcdir + '/scripts/lilypond-book.py'
353 env['ABC2LY_PY'] = srcdir + '/scripts/abc2ly.py'
354 env['MF_TO_TABLE_PY'] = srcdir + '/buildscripts/mf-to-table.py'
355 env['LILYPOND_PY'] = srcdir + '/scripts/lilypond.py'
356 env['LILYPOND_BOOK_FLAGS'] = ''
357 env['LILYPOND_BOOK_FORMAT'] = 'texi-html'
359 env['LILYPOND_BOOK_PATH'] = ['.', '#/input', '#/input/regression',
360 '#/input/test', '#/input/tutorial',
361 os.path.join (absbuild, 'mf', out),
362 '#/Documentation/user',
363 os.path.join (absbuild, 'Documentation', out),
364 os.path.join (absbuild, 'Documentation/user', out),
367 env['MAKEINFO_PATH'] = ['.', '#/Documentation/user',
368 os.path.join (absbuild, 'Documentation/user', out)]
370 ## TEXINFO_PAPERSIZE_OPTION= $(if $(findstring $(PAPERSIZE),a4),,-t @afourpaper)
371 env['TEXINFO_PAPERSIZE_OPTION'] = '-t @afourpaper'
373 tarbase = package.name + '-' + env['version']
374 tarname = tarbase + '.tar.gz'
375 tarball = os.path.join (outdir, tarname)
376 env['tarball'] = tarball
379 ballprefix = os.path.join (outdir, tarbase)
381 ballprefix = os.path.join (os.getcwd (), tarbase)
382 env['ballprefix'] = ballprefix
384 SConscript ('buildscripts/builder.py')
386 readme_files = ['ChangeLog', 'COPYING', 'DEDICATION', 'ROADMAP', 'THANKS']
387 readme_txt = ['AUTHORS.txt', 'README.txt', 'INSTALL.txt', 'NEWS.txt']
388 # to be [re]moved after spit
389 patch_files = ['emacsclient.patch', 'server.el.patch', 'darwin.patch']
392 env.Append (TARFLAGS = '-z --owner=0 --group=0')
393 env.Append (GZIPFLAGS = '-9')
394 #all_sources = ['SConstruct', 'VERSION', '.cvsignore']\
395 # + readme_files #+ patch_files # + readme_txt
396 all_sources = ['SConstruct', 'VERSION']\
398 # + readme_files + readme_txt
399 # + readme_files + patch_files + readme_txt
401 env['sources'] = all_sources
403 map (lambda x: env.Texi2txt (x, os.path.join ('Documentation/topdocs',
404 os.path.splitext (x)[0])),
408 b = os.path.join (build, d, out)
409 # Support clean sourctree build (srcdir build)
411 # TODO: figure out SConscript (dir, builddir, duplicate)) feature
412 if (build and build != '.') \
413 or (out and out != '.'):
414 env.BuildDir (b, d, duplicate=0)
415 SConscript (os.path.join (b, 'SConscript'))
418 def symlink_tree (prefix):
424 if not os.path.isdir (dir):
425 if os.path.exists (dir):
429 map (mkdir, string.split (dir, os.sep))
430 #srcdir = os.getcwd ()
431 def symlink (src, dst):
433 dir = os.path.dirname (dst)
436 frm = os.path.join (srcdir, src[1:])
438 depth = len (string.split (dir, '/'))
439 frm = os.path.join ('../' * depth, src, out)
440 os.symlink (frm, os.path.basename (dst))
441 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
442 (('python', 'lib/lilypond/python'),
443 # UGHR, lilypond.py uses lilypond-bin from PATH
445 ('#mf', 'share/lilypond/fonts/mf'),
446 ('mf', 'share/lilypond/fonts/afm'),
447 ('mf', 'share/lilypond/fonts/tfm'),
448 ('mf', 'share/lilypond/fonts/type1'),
449 ('#tex', 'share/lilypond/tex/source'),
450 ('mf', 'share/lilypond/tex/generate'),
451 ('#ly', 'share/lilypond/ly'),
452 ('#scm', 'share/lilypond/scm'),
453 ('#ps', 'share/lilypond/ps'),
454 ('elisp', 'share/lilypond/elisp')))
458 prefix = os.path.join (out, 'usr')
459 if not os.path.exists (prefix):
460 symlink_tree (prefix)
462 ball = Builder (prefix = ballprefix + '/', action = 'ln $SOURCE $TARGET')
463 et = env.Copy (BUILDERS = {'BALL': ball})
464 ballize = map (et.BALL, all_sources)
465 tar = env.Tar (tarball, map (lambda x: os.path.join (env['ballprefix'], x),
467 env.Alias ('tar', env['tarball'])
469 distball = os.path.join (package.release_dir, tarname)
470 env.Command (distball, tarball,
471 'if [ -e $SOURCE -a -e $TARGET ]; then rm $TARGET; fi;' \
472 + 'ln $SOURCE $TARGET')
473 env.Depends ('dist', distball)
474 patchfile = os.path.join (outdir, tarbase + '.diff.gz')
475 patch = env.PATCH (patchfile, tarball)
476 env.Depends (patchfile, distball)
477 env.Alias ('release', patch)