97d5c3534c7554ce1c5445cc52d420b4bb055dd1
[senf.git] / senfscons / SENFSCons.py
1 import os.path, glob
2 import SCons.Options, SCons.Environment, SCons.Script.SConscript, SCons.Node.FS
3 import SCons.Defaults, SCons.Action
4 from SCons.Script import *
5
6 def GlobSources(env, exclude=[], subdirs=[]):
7     testSources = glob.glob("*.test.cc")
8     sources = [ x for x in glob.glob("*.cc") if x not in testSources and x not in exclude ]
9     for subdir in subdirs:
10         testSources += glob.glob(os.path.join(subdir,"*.test.cc"))
11         sources += [ x for x in glob.glob(os.path.join(subdir,"*.cc"))
12                      if x not in testSources and x not in exclude ]
13     return (sources, testSources)
14
15 def GlobIncludes(env, exclude=[], subdirs=[]):
16     includes = []
17     for d in [ '.' ] + subdirs:
18         for f in os.listdir(d):
19             ext = '.' + f.split('.',1)[-1]
20             p = os.path.join(d,f)
21             if ext in env['CPP_INCLUDE_EXTENSIONS'] \
22                and ext not in env['CPP_EXCLUDE_EXTENSIONS'] \
23                and p not in exclude:
24                 includes.append(p)
25     return includes
26
27 def Glob(env, exclude=[], subdirs=[]):
28     return ( GlobSources(env, exclude, subdirs),
29              GlobIncludes(env, exclude, subdirs) )
30
31 def LibPath(lib): return '${LOCALLIBDIR}/${LIBPREFIX}%s${LIBADDSUFFIX}${LIBSUFFIX}' % lib
32
33 def Test(env, sources):
34     test = env.BoostUnitTests( target = 'test', 
35                                source = sources, 
36                                TEST_EXTRA_LIBS = [ '$LIBSENF$LIBADDSUFFIX' 
37                                                    ] + env['TEST_EXTRA_LIBS'])
38         
39     compileTestSources = [ src for src in sources
40                            if 'COMPILE_CHECK' in file(src).read() ]
41     if compileTestSources:
42         env.Depends(test, env.CompileCheck(source = compileTestSources))
43
44     env.Alias('all_tests', test)
45
46     return test
47     
48
49 def Objects(env, sources, testSources = None):
50     if type(sources) == type(()):
51         testSources = sources[1]
52         sources = sources[0]
53     if type(sources) is not type([]):
54         sources = [ sources ]
55
56     objects = env.Object(sources)
57
58     if testSources:
59         Test(env, testSources)
60
61     return objects
62
63 def Doxygen(env, doxyfile = "Doxyfile", extra_sources = []):
64     # There is one small problem we need to solve with this builder: The Doxygen builder reads
65     # the Doxyfile and thus depends on the environment variables set by doclib/doxygen.sh. We
66     # thus have to provide all necessary definitions here manually via DOXYENV !
67
68     if type(doxyfile) is type(""):
69         doxyfile = env.File(doxyfile)
70
71     # Module name is derived from the doxyfile path
72     # Utils/Console/Doxyfile -> Utils_Console
73     module = doxyfile.dir.abspath[len(env.Dir('#').abspath)+1:].replace('/','_')
74     if not module : module = "Main"
75
76     # Rule to generate tagfile
77     # (need to exclude the 'clean' case, otherwise we'll have duplicate nodes)
78     if not env.GetOption('clean'):
79         tagfile = env.Doxygen(doxyfile,
80                               DOXYOPTS = [ '--tagfile-name', '"${MODULE}.tag"',
81                                            '--tagfile' ],
82                               DOXYENV  = { 'TOPDIR'          : env.Dir('#').abspath,
83                                            'output_dir'      : 'doc',
84                                            'html_dir'        : 'html',
85                                            'html'            : 'NO',
86                                            'generate_tagfile': 'doc/${MODULE}.tag' },
87                               MODULE   = module )
88         env.Append(ALL_TAGFILES = tagfile[0].abspath)
89         env.Depends(tagfile, env.File('#/doclib/doxygen.sh'))
90
91     # Rule to generate HTML documentation
92     doc = env.Doxygen(doxyfile,
93                       DOXYOPTS = [ '--tagfiles', '"$ALL_TAGFILES"',
94                                    '--tagfile-name', '"${MODULE}.tag"',
95                                    '--html' ],
96                       MODULE   = module,
97                       DOXYENV  = { 'TOPDIR'          : env.Dir('#').abspath,
98                                    'tagfiles'        : '${ALL_TAGFILES}',
99                                    'output_dir'      : 'doc',
100                                    'html_dir'        : 'html',
101                                    'html'            : 'YES' } )
102     env.Depends(doc, env.File('#/doclib/doxygen.sh'))
103
104     # Copy the extra_sources (the images) into the documentation directory
105     # (need to exclude the 'clean' case otherwise there are multiple ways to clean the copies)
106     if not env.GetOption('clean'):
107         if extra_sources:
108             env.Depends(doc,
109                         [ env.CopyToDir( source=source, target=doc[0].dir )
110                           for source in extra_sources ])
111
112     # Install documentation into DOCINSTALLDIR
113     l = len(env.Dir('#').abspath)
114     env.Alias('install_all',
115               env.Command('$DOCINSTALLDIR' + doc[0].dir.abspath[l:], doc[0].dir,
116                           [ SCons.Defaults.Copy('$TARGET','$SOURCE') ]))
117
118     # Useful aliases
119     env.Alias('all_docs', doc)
120     env.Clean('all_docs', doc)
121     env.Clean('all', doc)
122
123     return doc
124
125 def Lib(env, sources, testSources = None, OBJECTS = []):
126     objects = Objects(env,sources,testSources)
127     env.Append(ALLOBJECTS = objects)
128     return objects
129
130 def Object(env, target, sources, testSources = None, OBJECTS = []):
131     objects = Objects(env,sources,testSources)
132     ob = env.Command(target+"${OBJADDSUFFIX}${OBJSUFFIX}", objects+OBJECTS, 
133                      [ "ld -r -o $TARGET $SOURCES" ])
134     env.Default(ob)
135     env.Alias('default', ob)
136     env.Alias('install_all', env.Install("$OBJINSTALLDIR", ob))
137     return ob
138
139 def Binary(env, binary, sources, testSources = None, OBJECTS = []):
140     objects = Objects(env, sources, testSources)
141     program = env.Program(target = binary, 
142                           source = objects+OBJECTS,
143                           LIBS   = [ '$LIBSENF$LIBADDSUFFIX' ] + env['LIBS'])
144     env.Default(program)
145     env.Alias('default', program)
146     env.Alias('install_all', env.Install('$BININSTALLDIR', program))
147     return program
148
149 def AllIncludesHH(env, headers):
150     headers.sort()
151     target = env.File("all_includes.hh")
152     file(target.abspath,"w").write("".join([ '#include "%s"\n' % f
153                                              for f in headers ]))
154     env.Clean('all', target)
155
156 def PhonyTarget(env, target, action, sources=[]):
157     env.AlwaysBuild(env.Alias(target, sources, env.Action(action)))