sim: implement getdents/getdents64 in user mode
[gem5.git] / src / SConscript
index 88fedbfdcbacfe22f672a3fbafaadfc6bd56715a..85bebc3ca031bb497672bfb199ba95cd075b58ca 100755 (executable)
@@ -63,6 +63,8 @@ from m5.util import code_formatter, compareVersions
 # false).  Current filters are:
 #     main -- specifies the gem5 main() function
 #     skip_lib -- do not put this file into the gem5 library
+#     skip_no_python -- do not put this file into a no_python library
+#       as it embeds compiled Python
 #     <unittest> -- unit tests use filters based on the unit test name
 #
 # A parent can now be specified for a source file and default filter
@@ -229,7 +231,7 @@ class SwigSource(SourceFile):
 
     def __init__(self, package, source, **guards):
         '''Specify the python package, the source file, and any guards'''
-        super(SwigSource, self).__init__(source, **guards)
+        super(SwigSource, self).__init__(source, skip_no_python=True, **guards)
 
         modname,ext = self.extname
         assert ext == 'i'
@@ -238,8 +240,8 @@ class SwigSource(SourceFile):
         cc_file = joinpath(self.dirname, modname + '_wrap.cc')
         py_file = joinpath(self.dirname, modname + '.py')
 
-        self.cc_source = Source(cc_file, swig=True, parent=self)
-        self.py_source = PySource(package, py_file, parent=self)
+        self.cc_source = Source(cc_file, swig=True, parent=self, **guards)
+        self.py_source = PySource(package, py_file, parent=self, **guards)
 
 class ProtoBuf(SourceFile):
     '''Add a Protocol Buffer to build'''
@@ -377,8 +379,20 @@ def makeTheISA(source, target, env):
 
 ''')
 
+    # create defines for the preprocessing and compile-time determination
     for i,isa in enumerate(isas):
         code('#define $0 $1', define(isa), i + 1)
+    code()
+
+    # create an enum for any run-time determination of the ISA, we
+    # reuse the same name as the namespaces
+    code('enum class Arch {')
+    for i,isa in enumerate(isas):
+        if i + 1 == len(isas):
+            code('  $0 = $1', namespace(isa), define(isa))
+        else:
+            code('  $0 = $1,', namespace(isa), define(isa))
+    code('};')
 
     code('''
 
@@ -577,6 +591,18 @@ def createSimObjectParamStruct(target, source, env):
     obj.cxx_param_decl(code)
     code.write(target[0].abspath)
 
+def createSimObjectCxxConfig(is_header):
+    def body(target, source, env):
+        assert len(target) == 1 and len(source) == 1
+
+        name = str(source[0].get_contents())
+        obj = sim_objects[name]
+
+        code = code_formatter()
+        obj.cxx_config_param_file(code, is_header)
+        code.write(target[0].abspath)
+    return body
+
 def createParamSwigWrapper(target, source, env):
     assert len(target) == 1 and len(source) == 1
 
@@ -625,6 +651,10 @@ def createSimObjectSwigWrapper(target, source, env):
     obj.swig_decl(code)
     code.write(target[0].abspath)
 
+# dummy target for generated code
+# we start out with all the Source files so they get copied to build/*/ also.
+SWIG = env.Dummy('swig', [s.tnode for s in Source.get()])
+
 # Generate all of the SimObject param C++ struct header files
 params_hh_files = []
 for name,simobj in sorted(sim_objects.iteritems()):
@@ -636,6 +666,62 @@ for name,simobj in sorted(sim_objects.iteritems()):
     env.Command(hh_file, Value(name),
                 MakeAction(createSimObjectParamStruct, Transform("SO PARAM")))
     env.Depends(hh_file, depends + extra_deps)
+    env.Depends(SWIG, hh_file)
+
+# C++ parameter description files
+if GetOption('with_cxx_config'):
+    for name,simobj in sorted(sim_objects.iteritems()):
+        py_source = PySource.modules[simobj.__module__]
+        extra_deps = [ py_source.tnode ]
+
+        cxx_config_hh_file = File('cxx_config/%s.hh' % name)
+        cxx_config_cc_file = File('cxx_config/%s.cc' % name)
+        env.Command(cxx_config_hh_file, Value(name),
+                    MakeAction(createSimObjectCxxConfig(True),
+                    Transform("CXXCPRHH")))
+        env.Command(cxx_config_cc_file, Value(name),
+                    MakeAction(createSimObjectCxxConfig(False),
+                    Transform("CXXCPRCC")))
+        env.Depends(cxx_config_hh_file, depends + extra_deps +
+                    [File('params/%s.hh' % name), File('sim/cxx_config.hh')])
+        env.Depends(cxx_config_cc_file, depends + extra_deps +
+                    [cxx_config_hh_file])
+        Source(cxx_config_cc_file)
+
+    cxx_config_init_cc_file = File('cxx_config/init.cc')
+
+    def createCxxConfigInitCC(target, source, env):
+        assert len(target) == 1 and len(source) == 1
+
+        code = code_formatter()
+
+        for name,simobj in sorted(sim_objects.iteritems()):
+            if not hasattr(simobj, 'abstract') or not simobj.abstract:
+                code('#include "cxx_config/${name}.hh"')
+        code()
+        code('void cxxConfigInit()')
+        code('{')
+        code.indent()
+        for name,simobj in sorted(sim_objects.iteritems()):
+            not_abstract = not hasattr(simobj, 'abstract') or \
+                not simobj.abstract
+            if not_abstract and 'type' in simobj.__dict__:
+                code('cxx_config_directory["${name}"] = '
+                     '${name}CxxConfigParams::makeDirectoryEntry();')
+        code.dedent()
+        code('}')
+        code.write(target[0].abspath)
+
+    py_source = PySource.modules[simobj.__module__]
+    extra_deps = [ py_source.tnode ]
+    env.Command(cxx_config_init_cc_file, Value(name),
+        MakeAction(createCxxConfigInitCC, Transform("CXXCINIT")))
+    cxx_param_hh_files = ["cxx_config/%s.hh" % simobj
+        for simobj in sorted(sim_objects.itervalues())
+        if not hasattr(simobj, 'abstract') or not simobj.abstract]
+    Depends(cxx_config_init_cc_file, cxx_param_hh_files +
+            [File('sim/cxx_config.hh')])
+    Source(cxx_config_init_cc_file)
 
 # Generate any needed param SWIG wrapper files
 params_i_files = []
@@ -645,6 +731,7 @@ for name,param in params_to_swig.iteritems():
     env.Command(i_file, Value(name),
                 MakeAction(createParamSwigWrapper, Transform("SW PARAM")))
     env.Depends(i_file, depends)
+    env.Depends(SWIG, i_file)
     SwigSource('m5.internal', i_file)
 
 # Generate all enum header files
@@ -656,17 +743,20 @@ for name,enum in sorted(all_enums.iteritems()):
     env.Command(cc_file, Value(name),
                 MakeAction(createEnumStrings, Transform("ENUM STR")))
     env.Depends(cc_file, depends + extra_deps)
+    env.Depends(SWIG, cc_file)
     Source(cc_file)
 
     hh_file = File('enums/%s.hh' % name)
     env.Command(hh_file, Value(name),
                 MakeAction(createEnumDecls, Transform("ENUMDECL")))
     env.Depends(hh_file, depends + extra_deps)
+    env.Depends(SWIG, hh_file)
 
     i_file = File('python/m5/internal/enum_%s.i' % name)
     env.Command(i_file, Value(name),
                 MakeAction(createEnumSwigWrapper, Transform("ENUMSWIG")))
     env.Depends(i_file, depends + extra_deps)
+    env.Depends(SWIG, i_file)
     SwigSource('m5.internal', i_file)
 
 # Generate SimObject SWIG wrapper files
@@ -704,6 +794,7 @@ for swig in SwigSource.all:
     init_file = '%s/%s_init.cc' % (dirname(cc_file), basename(cc_file))
     env.Command(init_file, Value(swig.module),
                 MakeAction(makeEmbeddedSwigInit, Transform("EMBED SW")))
+    env.Depends(SWIG, init_file)
     Source(init_file, **swig.guards)
 
 # Build all protocol buffers if we have got protoc and protobuf available
@@ -718,6 +809,7 @@ if env['HAVE_PROTOBUF']:
                                '--proto_path ${SOURCE.dir} $SOURCE',
                                Transform("PROTOC")))
 
+        env.Depends(SWIG, [proto.cc_file, proto.hh_file])
         # Add the C++ source file
         Source(proto.cc_file, **proto.guards)
 elif ProtoBuf.all:
@@ -730,40 +822,42 @@ elif ProtoBuf.all:
 def makeDebugFlagCC(target, source, env):
     assert(len(target) == 1 and len(source) == 1)
 
-    val = eval(source[0].get_contents())
-    name, compound, desc = val
-    compound = list(sorted(compound))
-
     code = code_formatter()
 
+    # delay definition of CompoundFlags until after all the definition
+    # of all constituent SimpleFlags
+    comp_code = code_formatter()
+
     # file header
     code('''
 /*
- * DO NOT EDIT THIS FILE! Automatically generated
+ * DO NOT EDIT THIS FILE! Automatically generated by SCons.
  */
 
 #include "base/debug.hh"
-''')
 
-    for flag in compound:
-        code('#include "debug/$flag.hh"')
-    code()
-    code('namespace Debug {')
-    code()
+namespace Debug {
 
-    if not compound:
-        code('SimpleFlag $name("$name", "$desc");')
-    else:
-        code('CompoundFlag $name("$name", "$desc",')
-        code.indent()
-        last = len(compound) - 1
-        for i,flag in enumerate(compound):
-            if i != last:
-                code('$flag,')
-            else:
-                code('$flag);')
-        code.dedent()
+''')
+
+    for name, flag in sorted(source[0].read().iteritems()):
+        n, compound, desc = flag
+        assert n == name
 
+        if not compound:
+            code('SimpleFlag $name("$name", "$desc");')
+        else:
+            comp_code('CompoundFlag $name("$name", "$desc",')
+            comp_code.indent()
+            last = len(compound) - 1
+            for i,flag in enumerate(compound):
+                if i != last:
+                    comp_code('$flag,')
+                else:
+                    comp_code('$flag);')
+            comp_code.dedent()
+
+    code.append(comp_code)
     code()
     code('} // namespace Debug')
 
@@ -780,9 +874,7 @@ def makeDebugFlagHH(target, source, env):
     # file header boilerplate
     code('''\
 /*
- * DO NOT EDIT THIS FILE!
- *
- * Automatically generated by SCons
+ * DO NOT EDIT THIS FILE! Automatically generated by SCons.
  */
 
 #ifndef __DEBUG_${name}_HH__
@@ -814,11 +906,15 @@ for name,flag in sorted(debug_flags.iteritems()):
     n, compound, desc = flag
     assert n == name
 
-    env.Command('debug/%s.hh' % name, Value(flag),
+    hh_file = 'debug/%s.hh' % name
+    env.Command(hh_file, Value(flag),
                 MakeAction(makeDebugFlagHH, Transform("TRACING", 0)))
-    env.Command('debug/%s.cc' % name, Value(flag),
-                MakeAction(makeDebugFlagCC, Transform("TRACING", 0)))
-    Source('debug/%s.cc' % name)
+    env.Depends(SWIG, hh_file)
+
+env.Command('debug/flags.cc', Value(debug_flags),
+            MakeAction(makeDebugFlagCC, Transform("TRACING", 0)))
+env.Depends(SWIG, 'debug/flags.cc')
+Source('debug/flags.cc')
 
 # Embed python files.  All .py files that have been indicated by a
 # PySource() call in a SConscript need to be embedded into the M5
@@ -874,9 +970,10 @@ EmbeddedPython embedded_${sym}(
     code.write(str(target[0]))
 
 for source in PySource.all:
-    env.Command(source.cpp, source.tnode, 
+    env.Command(source.cpp, source.tnode,
                 MakeAction(embedPyFile, Transform("EMBED PY")))
-    Source(source.cpp)
+    env.Depends(SWIG, source.cpp)
+    Source(source.cpp, skip_no_python=True)
 
 ########################################################################
 #
@@ -935,6 +1032,15 @@ def makeEnv(env, label, objsfx, strip = False, **kwargs):
         if compareVersions(env['GCC_VERSION'], '4.7') >= 0:
             new_env.Append(CXXFLAGS='-Wdelete-non-virtual-dtor')
             swig_env.Append(CCFLAGS='-Wno-maybe-uninitialized')
+
+        # Only gcc >= 4.9 supports UBSan, so check both the version
+        # and the command-line option before adding the compiler and
+        # linker flags.
+        if GetOption('with_ubsan') and \
+                compareVersions(env['GCC_VERSION'], '4.9') >= 0:
+            new_env.Append(CCFLAGS='-fsanitize=undefined')
+            new_env.Append(LINKFLAGS='-fsanitize=undefined')
+
     if env['CLANG']:
         # Always enable the warning for deletion of derived classes
         # with non-virtual destructors
@@ -948,6 +1054,12 @@ def makeEnv(env, label, objsfx, strip = False, **kwargs):
                 '-Wno-deprecated-register',
                 ])
 
+        # All supported clang versions have support for UBSan, so if
+        # asked to use it, append the compiler and linker flags.
+        if GetOption('with_ubsan'):
+            new_env.Append(CCFLAGS='-fsanitize=undefined')
+            new_env.Append(LINKFLAGS='-fsanitize=undefined')
+
     werror_env = new_env.Clone()
     werror_env.Append(CCFLAGS='-Werror')
 
@@ -973,14 +1085,19 @@ def makeEnv(env, label, objsfx, strip = False, **kwargs):
 
         return obj
 
-    static_objs = \
-        [ make_obj(s, True) for s in Source.get(main=False, skip_lib=False) ]
-    shared_objs = \
-        [ make_obj(s, False) for s in Source.get(main=False, skip_lib=False) ]
+    lib_guards = {'main': False, 'skip_lib': False}
+
+    # Without Python, leave out all SWIG and Python content from the
+    # library builds.  The option doesn't affect gem5 built as a program
+    if GetOption('without_python'):
+        lib_guards['skip_no_python'] = False
+
+    static_objs = [ make_obj(s, True) for s in Source.get(**lib_guards) ]
+    shared_objs = [ make_obj(s, False) for s in Source.get(**lib_guards) ]
 
     static_date = make_obj(date_source, static=True, extra_deps=static_objs)
     static_objs.append(static_date)
-    
+
     shared_date = make_obj(date_source, static=False, extra_deps=shared_objs)
     shared_objs.append(shared_date)