4 Experimental scons (www.scons.org) building:
7 scons lily # build lily
8 LILYPONDPREFIX=out-scons/usr/share/lilypond lily/out-scons/lilypond-bin
9 scons doc # build web doc
11 scons # without args builds all targets below ./
12 # maybe catch this one and only build lily?
13 scons / # builds all possible targets
19 scons build=DIR # scrdir build, write to new tree =build
20 scons out=DIR # write output to deeper dir DIR
22 Optionally, make a custom.py. I have
29 os.path.join (os.getcwd (), '=install')
30 prefix=os.path.join (os.environ['HOME'], 'usr', 'pkg', 'lilypond')
36 # * separate environments?
37 # - compile environment checks headers and libraries
38 # - doc environment checks doc stuff
40 # * running from build-dir, without installing?
41 # - scons will not install, if PREFIX lives outside of CWD
42 # - build symlink tree
43 # + mimicking regular installation setup?
44 # + use tweaked scons 'install' target?
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
62 # put your favourite stuff in custom.py
63 opts = Options ('custom.py', ARGUMENTS)
64 #opts = Options (['config.cache', 'custom.py'], ARGUMENTS)
65 opts.Add ('prefix', 'Install prefix', '/usr/')
66 opts.Add ('out', 'Output directory', 'out-scons')
67 opts.Add ('build', 'Build directory', '.')
69 BoolOption ('warnings', 'compile with -Wall and similiar',
71 BoolOption ('debugging', 'compile with debugging symbols',
73 BoolOption ('optimising', 'compile with optimising',
75 BoolOption ('shared', 'build shared libraries',
77 BoolOption ('static', 'build static libraries',
79 BoolOption ('gui', 'build with GNOME backend (EXPERIMENTAL)',
81 BoolOption ('verbose', 'run commands with verbose flag',
85 Help (opts.GenerateHelpText (env))
87 env = Environment (options = opts)
90 #opts.Save ('config.cache', env)
93 env.CacheDir (os.path.join (env['build'], '=build-cache'))
96 sys.path.append (os.path.join ('.', 'stepmake', 'bin'))
98 package = packagepython.Package ('.')
100 env['version'] = packagepython.version_tuple_to_str (package.version)
101 env['bindir'] = os.path.join (env['prefix'], 'bin')
102 env['sharedir'] = os.path.join (env['prefix'], 'share')
103 env['libdir'] = os.path.join (env['prefix'], 'lib')
104 env['localedir'] = os.path.join (env['sharedir'], 'locale')
106 env['sharedir_package'] = os.path.join (env['sharedir'], package.name)
107 env['sharedir_package_version'] = os.path.join (env['sharedir_package'],
109 env['lilypondprefix'] = os.path.join (env['sharedir_package_version'])
113 env.Append (CFLAGS = '-g')
114 env.Append (CXXFLAGS = '-g')
115 if env['optimising']:
116 env.Append (CFLAGS = '-O2')
117 env.Append (CXXFLAGS = '-O2')
118 env.Append (CXXFLAGS = '-DSTRING_UTILS_INLINED')
120 env.Append (CFLAGS = '-W ')
121 env.Append (CFLAGS = '-Wall')
122 # what about = ['-W', '-Wall', ...]?
123 env.Append (CXXFLAGS = '-W')
124 env.Append (CXXFLAGS = '-Wall')
125 env.Append (CXXFLAGS = '-Wconversion')
127 env['MFMODE'] = 'ljfour'
130 conf = Configure (env)
133 vre = re.compile ('^.*[^-.0-9]([0-9][0-9]*\.[0-9][.0-9]*).*$', re.DOTALL)
134 def get_version (program):
135 command = '(%(program)s --version || %(program)s -V) 2>&1' % vars ()
136 pipe = os.popen (command)
137 output = pipe.read ()
140 v = re.sub (vre, '\\1', output)
141 return string.split (v, '.')
143 def assert_version (lst, program, minimal, description, package):
145 sys.stdout.write ('Checking %s version... ' % program)
146 actual = get_version (program)
149 lst.append ((description, package, minimal, program,
152 sys.stdout.write (string.join (actual, '.'))
153 sys.stdout.write ('\n')
154 if actual < string.split (minimal, '.'):
155 lst.append ((description, package, minimal, program,
156 string.join (actual, '.')))
159 assert_version (required, 'gcc', '2.8', 'GNU C compiler', 'gcc')
160 assert_version (required, 'g++', '3.0.5', 'GNU C++ compiler', 'g++')
161 assert_version (required, 'python', '2.1', 'Python (www.python.org)', 'python')
162 assert_version (required, 'guile-config', '1.6', 'GUILE development',
163 'libguile-dev or guile-devel')
164 # Do not use bison 1.50 and 1.75.
165 assert_version (required, 'bison', '1.25', 'Bison -- parser generator',
167 assert_version (required, 'flex', '0.0', 'Flex -- lexer generator', 'flex')
171 assert_version (optional, 'makeinfo', '4.7', 'Makeinfo tool', 'texinfo')
172 assert_version (optional, 'guile', '1.6', 'GUILE scheme',
173 'libguile-dev or guile-devel')
174 assert_version (optional, 'mftrace', '1.0.27', 'Metafont tracing Type1',
176 assert_version (optional, 'perl', '4.0',
177 'Perl practical efficient readonly language', 'perl')
178 #assert_version (optional, 'foo', '2.0', 'Foomatic tester', 'bar')
184 'TOPLEVEL_VERSION' : '"' + env['version'] + '"',
185 'PACKAGE': '"' + package.name + '"',
186 'DATADIR' : '"' + env['sharedir'] + '"',
187 'LILYPOND_DATADIR' : '"' + env['sharedir_package'] + '"',
188 'LOCAL_LILYPOND_DATADIR' : '"' + env['sharedir_package_version'] + '"',
189 'LOCALEDIR' : '"' + env['localedir'] + '"',
193 command = r"""python -c 'import sys; sys.stdout.write ("%s/include/python%s" % (sys.prefix, sys.version[:3]))'""" #"
194 PYTHON_INCLUDE = os.popen (command).read ()
195 env.Append (CPPPATH = PYTHON_INCLUDE)
197 headers = ('sys/stat.h', 'assert.h', 'kpathsea/kpathsea.h', 'Python.h')
199 if conf.CheckCHeader (i):
200 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
203 ccheaders = ('sstream',)
205 if conf.CheckCXXHeader (i):
206 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
209 functions = ('gettext', 'isinf', 'memmem', 'snprintf', 'vsnprintf')
211 if 0 or conf.CheckFunc (i):
212 key = re.sub ('[./]', '_', 'HAVE_' + string.upper (i))
215 key = 'HAVE_FLEXLEXER_YY_CURRENT_BUFFER'
217 sys.stdout.write('Checking for yy_current_buffer ... ')
219 res = conf.TryCompile ("""using namespace std;
220 #include <FlexLexer.h>
221 class yy_flex_lexer: public yyFlexLexer
226 yy_current_buffer = 0;
231 sys.stdout.write('yes\n')
233 sys.stdout.write('no\n')
236 if conf.CheckLib ('dl'):
239 if conf.CheckLib ('kpathsea'):
240 defines['KPATHSEA'] = '1'
243 if conf.CheckLib ('kpathsea', 'kpse_find_file'):
244 defines['HAVE_KPSE_FIND_FILE'] = '1'
245 if conf.CheckLib ('kpathsea', 'kpse_find_tfm'):
246 defines['HAVE_KPSE_FIND_TFM'] = '1'
248 #this could happen after flower...
249 env.ParseConfig ('guile-config compile')
251 #this could happen only for compiling pango-*
253 env.ParseConfig ('pkg-config --cflags --libs gtk+-2.0')
254 env.ParseConfig ('pkg-config --cflags --libs pango')
255 if conf.CheckCHeader ('pango/pangofc-fontmap.h'):
256 defines['HAVE_PANGO_PANGOFC_FONTMAP_H'] = '1'
258 if conf.CheckLib ('pango-1.0',
259 'pango_fc_font_map_add_decoder_find_func'):
260 defines['HAVE_PANGO_CVS'] = '1'
261 defines['HAVE_PANGO_FC_FONT_MAP_ADD_DECODER_FIND_FUNC'] = '1'
266 reldir = str (Dir ('.').srcnode ())
268 srcdir = os.getcwd ()
270 env['srcdir'] = srcdir
274 ##reldir = str (Dir ('.').srcnode ())
275 reldir = os.getcwd ()
276 outdir = os.path.join (env['build'], reldir, env['out'])
277 if not os.path.exists (outdir):
285 config = open (os.path.join (outdir, 'config.h'), 'w')
286 for i in list_sort (defines.keys ()):
287 config.write ('#define %s %s\n' % (i, defines[i]))
290 os.system (sys.executable \
291 + ' ./stepmake/bin/make-version.py VERSION > '\
292 + os.path.join (outdir, 'version.hh'))
294 if os.path.exists ('parser'):
295 env.Append (LIBPATH = ['#/flower', '#/lily', '#/parser', '#/gui',],
296 CPPPATH = [outdir, '#',])
298 env.Append (LIBPATH = ['#/flower/' + out,],
299 CPPPATH = [outdir, '#',])
303 print '********************************'
304 print 'Please install required packages'
306 print '%s: %s-%s or newer (found: %s %s)' % i
311 print '*************************************'
312 print 'Consider installing optional packages'
314 print '%s: %s-%s or newer (found: %s %s)' % i
316 #env['tarball'] = os.path.join (outdir,
317 # package.name + '-' + env['version'] + '.tar.gz')
319 env['tarball'] = os.path.join (os.environ['HOME'], 'tmp',
320 package.name + '-' + env['version'] + '.tar.gz')
323 if 'tar' in COMMAND_LINE_TARGETS:
324 #env.Default (env['tarball'])
326 env.Default (env['tarball'])
333 absbuild = os.getcwd ()
336 env['absbuild'] = absbuild
339 env['MAKEINFO'] = 'LANG= makeinfo'
340 env['PYTHON'] = 'python'
341 env['LILYPOND_BIN'] = os.path.join (absbuild, 'lily', out, 'lilypond-bin')
342 env['LILYPONDPREFIX'] = os.path.join (outdir, 'usr/share/lilypond')
343 env['LILYPOND_BOOK'] = srcdir + '/scripts/lilypond-book.py'
344 env['ABC2LY_PY'] = srcdir + '/scripts/abc2ly.py'
345 env['MF_TO_TABLE_PY'] = srcdir + '/buildscripts/mf-to-table.py'
346 env['LILYPOND_PY'] = srcdir + '/scripts/lilypond.py'
347 env['LILYPOND_BOOK_FLAGS'] = ''
348 env['LILYPOND_BOOK_FORMAT'] = 'texi-html'
350 env['LILYPOND_BOOK_PATH'] = ['.', '#/input', '#/input/regression',
351 '#/input/test', '#/input/tutorial',
352 os.path.join (absbuild, 'mf', out),
353 '#/Documentation/user',
354 os.path.join (absbuild, 'Documentation', out),
355 os.path.join (absbuild, 'Documentation/user', out),
358 env['MAKEINFO_PATH'] = ['.', '#/Documentation/user',
359 os.path.join (absbuild, 'Documentation/user', out)]
361 ## TEXINFO_PAPERSIZE_OPTION= $(if $(findstring $(PAPERSIZE),a4),,-t @afourpaper)
362 env['TEXINFO_PAPERSIZE_OPTION'] = '-t @afourpaper'
363 env.Append (PYTHONPATH = [os.path.join (outdir, 'usr/lib/python'),
364 os.path.join (srcdir, 'buildscripts'),
365 os.path.join (srcdir, 'python')])
367 # GS_FONTPATH, GS_LIB?
368 env.Append (ENV = { 'PYTHONPATH' : string.join (env['PYTHONPATH'],
370 # UGHR, lilypond.py uses lilypond-bin from PATH
371 env.Append (ENV = { 'PATH' : os.path.join (outdir, 'usr/bin') })
373 SConscript ('buildscripts/builder.py')
376 #subdirs = ['flower', 'lily', 'parser', 'gui', 'main',]
377 #subdirs = ['flower', 'lily', 'mf', 'scm', 'ly']
378 subdirs = ['flower', 'lily', 'mf', 'scm', 'ly', 'Documentation',
379 'Documentation/user', 'input']
381 b = os.path.join (build, d, out)
382 # Support clean sourctree build (srcdir build)
384 # TODO: figure out SConscript (dir, builddir, duplicate)) feature
385 if (build and build != '.') \
386 or (out and out != '.'):
387 env.BuildDir (b, d, duplicate=0)
388 SConscript (os.path.join (b, 'SConscript'))
390 readme_files = ['ChangeLog', 'COPYING', 'DEDICATION', 'ROADMAP', 'THANKS']
391 readme_txt = ['AUTHORS.txt', 'README.txt', 'INSTALL.txt', 'NEWS.txt']
392 # to be [re]moved after spit
393 patch_files = ['emacsclient.patch', 'server.el.patch', 'darwin.patch']
395 map (lambda x: env.Texi2txt (x, os.path.join ('Documentation/topdocs',
396 os.path.splitext (x)[0])),
400 env.Append (TARFLAGS = '-z --owner=0 --group=0')
401 env.Append (GZIPFLAGS = '-9')
402 all_sources = ['SConstruct',] + subdirs \
403 + ['VERSION', '.cvsignore']\
404 + readme_files + readme_txt + patch_files
406 tar = env.Tar (env['tarball'], all_sources)
409 def symlink_tree (prefix):
415 if not os.path.isdir (dir):
416 if os.path.exists (dir):
420 map (mkdir, string.split (dir, os.sep))
421 #srcdir = os.getcwd ()
422 def symlink (src, dst):
424 dir = os.path.dirname (dst)
427 frm = os.path.join (srcdir, src[1:])
430 depth = len (string.split (dir, '/'))
431 print 'depth: ' + `depth`
432 frm = os.path.join ('../' * depth, src, out)
433 print 'cwd: ' + `os.getcwd ()`
436 os.symlink (frm, os.path.basename (dst))
437 map (lambda x: symlink (x[0], os.path.join (prefix, x[1])),
438 (('python', 'lib/lilypond/python'),
439 # UGHR, lilypond.py uses lilypond-bin from PATH
441 ('#mf', 'share/lilypond/fonts/mf'),
442 ('mf', 'share/lilypond/fonts/afm'),
443 ('mf', 'share/lilypond/fonts/tfm'),
444 ('mf', 'share/lilypond/fonts/type1'),
445 ('#tex', 'share/lilypond/tex/source'),
446 ('mf', 'share/lilypond/tex/generate'),
447 ('#ly', 'share/lilypond/ly'),
448 ('#scm', 'share/lilypond/scm'),
449 ('#ps', 'share/lilypond/ps'),
450 ('elisp', 'share/lilypond/elisp')))
454 prefix = os.path.join (out, 'usr')
455 if not os.path.exists (prefix):
456 symlink_tree (prefix)