root/trunk/Sconstruct @ 693

Revision 693, 15.6 KB (checked in by mauser, 4 years ago)

added support for coreaudio / several osx improvements

Line 
1#
2# Hydrogen build script
3#
4
5# vim: set filetype=python
6# kate: syntax python
7
8import urllib
9import os
10import subprocess
11import sys
12import glob
13
14def printStatus( value ):
15    if str(value) == "1":
16        return "enabled"
17    else:
18        return "disabled"
19
20def recursiveDirs(root) :
21        return filter( ( lambda a : a.rfind( ".svn") == -1 ),  [ a[0] for a in os.walk( root ) ] )
22
23def unique( list ) :
24        return dict.fromkeys( list ).keys()
25
26def scanFiles(dir, accept=[ "*.cpp" ], reject=[] ) :
27        sources = []
28        paths = recursiveDirs( dir )
29        for path in paths:
30                for pattern in accept:
31                        sources += glob.glob( path + "/" + pattern )
32        for pattern in reject:
33                sources = filter( ( lambda a : a.rfind( pattern ) == -1 ),  sources )
34        return unique( sources )
35
36def subdirsContaining( root, patterns ):
37        dirs = unique( map( os.path.dirname, scanFiles( root, patterns ) ) )
38        dirs.sort()
39        return dirs
40
41
42
43def get_platform_flags( opts ):
44        includes = []
45        cppflags = []
46        ldflags = []
47
48        env = Environment( options = opts )
49
50        if sys.platform == "linux2" or sys.platform == "darwin":
51                if str(env['debug']) == "1":
52                        cppflags += ['-Wall',  '-g2', '-ggdb', '-O0']
53                else:
54                        cppflags += ['-O3', '-fomit-frame-pointer', '-funroll-loops']
55                        #cppflags += " %s" % get_optimized_flags( target_cpu )
56
57                #add support for C0X standard
58                cppflags += ['-std=c++0x']
59
60                if str(env['oss']) == "1": cppflags.append('-DOSS_SUPPORT')
61                if str(env['alsa']) == "1": cppflags.append('-DALSA_SUPPORT')
62                if str(env['jack']) == "1": cppflags.append('-DJACK_SUPPORT')
63                if str(env['lash']) == "1": cppflags.append('-DLASH_SUPPORT')
64                if str(env['lrdf']) == "1": cppflags.append('-DLRDF_SUPPORT')
65                if str(env['portaudio']) == "1": cppflags.append('-DPORTAUDIO_SUPPORT')
66                if str(env['portmidi']) == "1": cppflags.append('-DPORTMIDI_SUPPORT')
67               
68                if sys.platform == "darwin" and str(env['coreaudio']) == "1": cppflags.append('-DCOREAUDIO_SUPPORT')
69
70                cppflags.append('-DFLAC_SUPPORT')
71                cppflags.append('-DLADSPA_SUPPORT')
72               
73
74                if str(env['lash']) == "1": includes.append( '/usr/lib/lash-1.0' )
75
76        if str(env['libarchive']) == "1": cppflags.append('-DLIBARCHIVE_SUPPORT')
77
78        includes.append( './' )
79        includes.append( 'gui/src/' )
80        includes.append( '3rdparty/install/include' )
81
82        if sys.platform == 'linux2':
83                ldflags.append('-lasound')
84
85        elif sys.platform == 'darwin':
86                includes.append( [ '/sw/include', '/usr/local/include' ] )
87                ldflags.append( [ '-L/sw/lib', '-F/sw/lib', '-F/sw/lib/qt4-mac/lib', '-L/usr/local/lib' ] )
88
89        elif sys.platform == "win32":
90                includes.append( '3rdparty\libsndfile-1_0_17' )
91                includes.append( 'build\pthreads\include' )
92                includes.append( '3rdparty\libarchive\include' )
93                includes.append( 'windows\timeFix' )
94        else:
95                raise Exception( "Platform '%s' not supported" % sys.platform )
96
97        return (includes, cppflags, ldflags)
98
99
100
101def download_3rdparty_libs():
102        print " * Downloading required 3rdparty libraries"
103
104        curdir = os.path.abspath( os.path.curdir )
105
106        if sys.platform != "win32":
107                prefix = os.path.abspath( os.path.curdir ) + "/3rdparty/install"
108        else:
109                prefix = os.path.abspath( os.path.curdir ) + "\3rdparty\install"
110
111
112        compile_flags = "--enable-static --disable-shared"
113
114
115        if not os.path.exists( "3rdparty" ):
116                os.mkdir( "3rdparty" )
117       
118
119
120        if not os.path.exists( "3rdparty/install" ):
121                os.mkdir( "3rdparty/install" )
122
123        if not os.path.exists( "3rdparty/install/lib" ):
124                os.mkdir( "3rdparty/install/lib" )
125
126
127
128
129        if not os.path.exists( "3rdparty/libsndfile.tar.gz" ) and not os.path.exists("3rdparty/libsndfile.zip"):
130                if sys.platform != "win32":
131                        print " * Downloading libsndfile.tar.gz"
132                        urllib.urlretrieve("http://www.mega-nerd.com/libsndfile/libsndfile-1.0.17.tar.gz", "3rdparty/libsndfile.tar.gz")
133                else:
134                        print " * Downloading libsndfile.zip"
135                        urllib.urlretrieve("http://www.mega-nerd.com/libsndfile/libsndfile-1_0_17.zip", "3rdparty/libsndfile.zip")
136
137
138        if sys.platform != "win32":
139                #unix commands
140                if not os.path.exists( "3rdparty/install/lib/libsndfile.a" ):
141                        Execute( "cd 3rdparty; tar xzf libsndfile.tar.gz" )
142                        Execute( "cd 3rdparty/libsndfile-1.0.17; ./configure --disable-flac --prefix=%s %s" % (prefix, compile_flags) )
143                        res = Execute( "cd 3rdparty/libsndfile-1.0.17; make -j2; make install" )
144                        if res != 0:
145                                raise Exception( "Error compiling 3rdparty libraries" )
146        else:
147                #windows
148                if not os.path.exists( "3rdparty\install\lib\libsndfile-1.dll" ):
149                        Execute( "unzip 3rdparty\libsndfile.zip -d 3rdparty" )
150                        Execute( "copy 3rdparty\libsndfile-1_0_17\libsndfile-1.dll 3rdparty\install\lib")
151                        Execute( "copy 3rdparty\libsndfile-1_0_17\sndfile.h 3rdparty\install\lib")
152
153
154
155
156def get_svn_revision():
157       
158        if sys.platform != "win32":
159                p = subprocess.Popen("svnversion -n", shell=True, stdout=subprocess.PIPE)
160                return p.stdout.read()
161        else:
162                return "win32 build"
163
164
165def get_hydrogen_lib( opts ):
166        includes, cppflags, ldflags = get_platform_flags( opts )
167
168        includes.append( "libs/hydrogen/include" )
169        includes.append( "/usr/include/lash-1.0")
170
171
172        #location of qt4.py
173        qt4ToolLocation="."
174
175        env = Environment(options = opts , tools=['default','qt4'], toolpath=[qt4ToolLocation], ENV=os.environ, CPPPATH = includes, CPPFLAGS = cppflags, CCFLAGS = "", LINKFLAGS=ldflags )
176        env.EnableQt4Modules( ['QtCore', 'QtGui'], debug=False)
177        env.CacheDir( "scons_cache" )
178       
179        if str(env['jack']) == "1":
180            env.ParseConfig('pkg-config --modversion jack', get_jack_api_flags)
181
182        #env.Decider is not known in older scons version
183        try:
184                env.Decider( "MD5-timestamp" )
185        except AttributeError:
186                env.SourceSignatures('MD5')
187
188
189        src = scanFiles( "libs/hydrogen", ['*.cpp', '*.cc', '*.c' ], [ 'moc_'] )
190        src.append( "version.cpp" )
191
192        static_lib = env.StaticLibrary(target = 'hydrogen', source = src )
193        return static_lib
194
195
196def get_hydrogen_gui( lib_hydrogen , opts ):
197        includes, cppflags, ldflags = get_platform_flags( opts )
198
199        includes.append( "libs/hydrogen/include" )
200        includes.append( "gui/src/UI" )
201        includes.append( "/usr/include/lash-1.0")
202
203        #location of qt4.py
204        qt4ToolLocation="."
205
206        env = Environment(options = opts , tools=['default','qt4'], toolpath=[qt4ToolLocation], ENV=os.environ, CPPPATH = includes, CPPFLAGS = cppflags, CCFLAGS = "", LINKFLAGS=ldflags )
207       
208        env.EnableQt4Modules( ['QtCore', 'QtGui','QtNetwork','QtXml'], debug=False)
209        #
210        env.CacheDir( "scons_cache" )
211       
212        #env.Decider is not known in older scons version
213        try:
214                env.Decider( "MD5-timestamp" )
215        except AttributeError:
216                env.SourceSignatures('MD5')
217
218        # rcc needs a -name flag because examples use identified resource files
219        def takebasename(file):
220                return os.path.splitext(os.path.basename(file))[0]
221
222
223        directory = "gui"
224
225        resources = [ env.Qrc( qrc, QT4_QRCFLAGS = '-name ' + takebasename( qrc ) ) for qrc in scanFiles(directory, ['*.qrc'] ) ]
226        interfaces = [ env.Uic4( uic ) for uic in scanFiles(directory, ['*.ui'] ) ]
227
228
229        src = scanFiles( directory, ['*.cpp', '*.cc', '*.c' ], [ 'moc_'] )
230
231        env.Append( LIBS = lib_hydrogen )
232        env.Append( LIBS = ["sndfile"] )
233       
234        if str(env['lrdf']) == "1": env.Append( LIBS = ["lrdf"] )
235        if str(env['flac']) == "1": env.Append( LIBS = ["FLAC","FLAC++"] )
236        if str(env['lash']) == "1": env.Append( LIBS = ["lash"])
237        if str(env['jack']) == "1": env.Append( LIBS = ["jack"])
238        if str(env['alsa']) == "1": env.Append( LIBS = ["asound"])
239        if str(env['libarchive']) == "1": env.Append( LIBS = ["archive"])
240        else: env.Append( LIBS = ["tar"])
241        if str(env['portaudio']) == "1": env.Append( LIBS = [ "portaudio" ] )
242        if str(env['portmidi']) == "1":
243                env.Append( LIBS = [ "portmidi" ] )
244                env.Append( LIBS = [ "porttime" ] )
245
246        if sys.platform == "darwin" and str(env['coreaudio']) == "1":
247                env.Append( LINKFLAGS = ['-framework','ApplicationServices'])
248                env.Append( LINKFLAGS = ['-framework','AudioUnit'])
249                env.Append( LINKFLAGS = ['-framework','Coreaudio'])
250
251
252
253        env.Append( LIBPATH = '3rdparty\libsndfile-1_0_17' )
254        env.Append( LIBPATH = 'build\pthreads\lib' )
255
256        app = env.Program(target = 'hydrogen', source = src )
257
258        env.Alias('programs', app)
259        env.Default('programs')
260
261        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/i18n"))
262        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/img"))
263        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/drumkits"))
264        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/demo_songs"))
265        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/hydrogen.default.conf"))
266        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/emptySample.wav"))
267        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/click.wav"))
268        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/doc"))
269        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/hydrogen/data', source="./data/DefaultSong.h2song"))
270        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/bin/', source="./hydrogen"))
271        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/applications', source="./hydrogen.desktop"))
272        env.Alias(target="install", source=env.Install(dir= env['DESTDIR'] + env['prefix'] + '/share/pixmaps', source="./data/img/gray/h2-icon.svg"))
273
274
275        return app
276
277def get_jack_api_flags(xenv, pkg_ver):
278    (major, minor, patch) = pkg_ver.rstrip().split('.')
279    major = int(major)
280    minor = int(minor)
281    patch = int(patch)
282    rv = ""
283    if (major == 0) and (minor < 102):
284        rv = "-DJACK_NO_BBT_OFFSET"
285    if (major == 0) and (minor == 102) and (patch < 4):
286        rv = "-DJACK_NO_BBT_OFFSET"
287    xenv.MergeFlags(rv)
288
289opts = Options('scache.conf')
290
291#platform independent settings
292opts.Add('debug', 'Set to 1 to build with debug informations', 0)
293opts.Add('libarchive', 'Set to 1 to enable libarchive instead of libtar', 0)
294opts.Add('prefix','Default: /usr/local',"/usr/local")
295opts.Add('DESTDIR','Default: none',"")
296
297#platform dependent settings
298if sys.platform == "darwin":
299        opts.Add('coreaudio', 'Set to 1 to enable Coreaudio',1)
300
301if sys.platform != "win32":
302        opts.Add('oss', 'Set to 1 to enable oss',1)
303
304        opts.Add('portmidi', 'Set to 1 to enable portmidi',0)
305       
306        opts.Add('portaudio', 'Set to 1 to enable portaudio',0)
307       
308        opts.Add('lash', 'Set to 1 to enable lash',0)
309       
310       
311        opts.Add('alsa', 'Set to 1 to enable alsa',1)
312       
313
314        opts.Add('jack', 'Set to 1 to enable jack',1)   
315       
316
317        opts.Add('lrdf', 'Set to 1 to enable lrdf',1)
318       
319
320        opts.Add('flac', 'Set to 1 to enable flac',1)
321else:
322        #alsa, lash,oss and jack are not available on windows
323        opts.Add('portmidi', 'Set to 1 to enable portmidi',1)
324       
325        opts.Add('portaudio', 'Set to 1 to enable portaudio',1)
326       
327        opts.Add('oss', 'Set to 1 to enable oss',0)
328
329        opts.Add('lash', 'Set to 1 to enable lash',0)
330       
331        opts.Add('alsa', 'Set to 1 to enable alsa',0)
332       
333        opts.Add('jack', 'Set to 1 to enable jack',0)
334       
335        opts.Add('lrdf', 'Set to 1 to enable lrdf',0)
336       
337        opts.Add('flac', 'Set to 1 to enable flac',0)
338
339
340
341#get includes ( important if you compile on non-standard envorionments)
342
343includes, a , b = get_platform_flags( opts )
344
345env = Environment(options = opts, CPPPATH = includes)
346
347
348Help(opts.GenerateHelpText(env))
349
350
351platform = sys.platform
352
353#just download 3rd party libs if we're *not* running linux.
354#We trust in our package managment system!
355if platform == "darwin" or platform == "win32":
356    download_3rdparty_libs()
357
358
359
360#Check if all required libraries are installed
361conf = Configure(env)
362if not conf.CheckCHeader('sndfile.h'):
363    print 'libsndfile must be installed!'
364    Exit(1)
365
366
367
368# it seems that conf.CheckCHeader  dislikes like the "++" in filenames
369#if not conf.CheckCHeader('FLAC++/all.h'):
370#   print 'FLAC++ must be installed!'
371#   Exit(1)
372
373
374# these libraries are optional (can be enabled/disabled, see 'scons -h')
375
376if str(env['portaudio']) == "1" and not conf.CheckCHeader('portaudio.h'):
377    print "portaudio must be installed!"
378    Exit(1)
379
380if str(env['portmidi']) == "1" and not conf.CheckCHeader('portmidi.h'):
381    print "portmidi must be installed!"
382    Exit(1)
383
384
385#alsa: (default: enabled)
386if str(env['alsa']) == "1" and not conf.CheckCHeader('alsa/asoundlib.h'):
387    print 'alsa must be installed!'
388    Exit(1)
389
390#jack: (default: enabled)
391if str(env['jack']) == "1" and not conf.CheckCHeader('jack/jack.h'):
392    print 'jack must be installed!'
393    Exit(1)
394
395#lash: (default: disabled)
396if str(env['lash']) == "1" and not os.path.isdir("/usr/include/lash-1.0"):
397    print 'liblash must be installed!'
398    Exit(1)
399
400#libarchive: (default: disabled)
401if str(env['libarchive']) == "1" and not conf.CheckCHeader("archive.h"):
402    print 'libarchive must be installed!'
403    Exit(1)
404#libtar: needed if not libarchive
405elif not str(env['libarchive']) == "1" and not conf.CheckCHeader("zlib.h"):
406   print 'zlib devel package must be installed!'
407   Exit(1)
408elif not str(env['libarchive']) == "1" and not conf.CheckCHeader("libtar.h"):
409   print 'libtar must be installed!'
410   Exit(1)
411
412#lrdf: categorizing of ladspa effects
413if str(env['lrdf']) == "1" and not conf.CheckCHeader('lrdf.h'):
414    print 'lrdf must be installed!'
415    Exit(1)
416
417#flac: support for flac samples
418if str(env['flac']) == "1" and not conf.CheckCHeader('FLAC/all.h'):
419    print 'FLAC must be installed!'
420    Exit(1)
421
422
423print ""
424print "================================================================="
425print " Hydrogen build script"
426print ""
427print " Revision: %s" % get_svn_revision()
428print " Platform: %s" % platform
429
430if str(env['debug']) == "1" :
431        print " Debug build"
432else:
433        print " Release build"
434
435print " Prefix: " + env['prefix']
436print " Destdir: " + env['DESTDIR']
437print "================================================================="
438print "Feature Overview:\n"
439
440
441print "      lash: " + printStatus( env["lash"] )
442print "      oss: " + printStatus( env["oss"] )
443print "      alsa: " + printStatus( env["alsa"] )
444print "      jack: " + printStatus( env["jack"] )
445print "libarchive: " + printStatus( env["libarchive"] ) + (' (using libtar instead)', '')[env['libarchive']]
446print " portaudio: " + printStatus( env["portaudio"] )
447print "  portmidi: " + printStatus( env["portmidi"] )
448if sys.platform == "darwin":
449        print " coreaudio: " + printStatus( env["coreaudio"] )
450
451print "\n================================================================="
452print ""
453
454# write the config.h file
455conf = open("config.h", "w")
456
457conf.write( "#ifndef HYD_CONFIG_H\n" )
458conf.write( "#define HYD_CONFIG_H\n" )
459conf.write( "#include <string>\n" )
460
461
462if str(env['debug']) == "1": conf.write( "#define CONFIG_DEBUG\n" )
463if str(env['lash']) == "1": conf.write( "#define LASH\n" )
464
465conf.write( "#ifndef QT_BEGIN_NAMESPACE\n" )
466conf.write( "#    define QT_BEGIN_NAMESPACE\n" )
467conf.write( "#endif\n" )
468conf.write( "#ifndef QT_END_NAMESPACE\n" )
469conf.write( "#    define QT_END_NAMESPACE\n" )
470conf.write( "#endif\n" )
471
472conf.write( "#define CONFIG_PREFIX \"%s\"\n" % env['prefix'] )
473conf.write( "#define DATA_PATH \"%s/share/hydrogen/data\"\n" % env['prefix'] )
474
475conf.write( "#endif\n" )
476
477conf.close()
478
479version = open("version.cpp", "w")
480version.write( "// autogenerated by Sconstruct script\n" )
481version.write( '#include "version.h"\n' )
482version.write( '#include "config.h"\n' )
483version.write( "static const std::string extra_version = \"svn%s\";\n" % get_svn_revision() )
484version.write( "static const std::string VERSION = \"0.9.4-\" + extra_version;\n" )
485version.write( "std::string get_version() { return VERSION;     }\n" )
486version.close()
487
488
489libhyd = get_hydrogen_lib( opts )
490app = get_hydrogen_gui( libhyd , opts )
491
492opts.Save("scache.conf",env)
Note: See TracBrowser for help on using the browser.