diff --git a/docs/devel/tracing.txt b/docs/devel/tracing.txt
index 6144d9921b..c84d4c00ac 100644
--- a/docs/devel/tracing.txt
+++ b/docs/devel/tracing.txt
@@ -318,7 +318,8 @@ probes:
                          --target-type system \
                          --target-name x86_64 \
                          --group=all \
-                         trace-events-all >qemu.stp
+                         trace-events-all \
+                         qemu.stp
 
 To facilitate simple usage of systemtap where there merely needs to be printf
 logging of certain probes, a helper script "qemu-trace-stap" is provided.
diff --git a/meson.build b/meson.build
index f0fe5f8799..fadeb0c268 100644
--- a/meson.build
+++ b/meson.build
@@ -1037,7 +1037,6 @@ foreach target : target_dirs
         custom_target(exe_name + stp['ext'],
                       input: trace_events_all,
                       output: exe_name + stp['ext'],
-                      capture: true,
                       install: stp['install'],
                       install_dir: config_host['qemu_datadir'] / '../systemtap/tapset',
                       command: [
@@ -1046,7 +1045,7 @@ foreach target : target_dirs
                         '--target-name=' + target_name,
                         '--target-type=' + target_type,
                         '--probe-prefix=qemu.' + target_type + '.' + target_name,
-                        '@INPUT@',
+                        '@INPUT@', '@OUTPUT@'
                       ])
       endforeach
     endif
diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 31146242b7..ab7653a5ce 100644
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -16,7 +16,7 @@ __email__      = "stefanha@redhat.com"
 import sys
 import getopt
 
-from tracetool import error_write, out
+from tracetool import error_write, out, out_open
 import tracetool.backend
 import tracetool.format
 
@@ -32,7 +32,7 @@ def error_opt(msg = None):
     format_descr = "\n".join([ "    %-15s %s" % (n, d)
                                for n,d in tracetool.format.get_list() ])
     error_write("""\
-Usage: %(script)s --format=<format> --backends=<backends> [<options>]
+Usage: %(script)s --format=<format> --backends=<backends> [<options>] <trace-events> ... <output>
 
 Backends:
 %(backends)s
@@ -135,13 +135,15 @@ def main(args):
         if probe_prefix is None:
             probe_prefix = ".".join(["qemu", target_type, target_name])
 
-    if len(args) < 1:
-        error_opt("missing trace-events filepath")
+    if len(args) < 2:
+        error_opt("missing trace-events and output filepaths")
     events = []
-    for arg in args:
+    for arg in args[:-1]:
         with open(arg, "r") as fh:
             events.extend(tracetool.read_events(fh, arg))
 
+    out_open(args[-1])
+
     try:
         tracetool.generate(events, arg_group, arg_format, arg_backends,
                            binary=binary, probe_prefix=probe_prefix)
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index 3ccfa1e116..98104fa50e 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -31,14 +31,28 @@ def error(*lines):
     sys.exit(1)
 
 
+out_filename = '<none>'
+out_fobj = sys.stdout
+
+def out_open(filename):
+    global out_filename, out_fobj
+    out_filename = filename
+    out_fobj = open(filename, 'wt')
+
 def out(*lines, **kwargs):
     """Write a set of output lines.
 
     You can use kwargs as a shorthand for mapping variables when formating all
     the strings in lines.
+
+    The 'out_filename' kwarg is automatically added with the output filename.
     """
-    lines = [ l % kwargs for l in lines ]
-    sys.stdout.writelines("\n".join(lines) + "\n")
+    output = []
+    for l in lines:
+        kwargs['out_filename'] = out_filename
+        output.append(l % kwargs)
+
+    out_fobj.writelines("\n".join(output) + "\n")
 
 # We only want to allow standard C types or fixed sized
 # integer types. We don't want QEMU specific types
diff --git a/trace/meson.build b/trace/meson.build
index 56e870848e..16eccc0c22 100644
--- a/trace/meson.build
+++ b/trace/meson.build
@@ -11,20 +11,17 @@ foreach dir : [ '.' ] + trace_events_subdirs
   trace_h = custom_target(fmt.format('trace', 'h'),
                           output: fmt.format('trace', 'h'),
                           input: trace_events_file,
-                          command: [ tracetool, group, '--format=h', '@INPUT@' ],
-                          capture: true)
+                          command: [ tracetool, group, '--format=h', '@INPUT@', '@OUTPUT@' ])
   genh += trace_h
   trace_c = custom_target(fmt.format('trace', 'c'),
                           output: fmt.format('trace', 'c'),
                           input: trace_events_file,
-                          command: [ tracetool, group, '--format=c', '@INPUT@' ],
-                          capture: true)
+                          command: [ tracetool, group, '--format=c', '@INPUT@', '@OUTPUT@' ])
   if 'CONFIG_TRACE_UST' in config_host
     trace_ust_h = custom_target(fmt.format('trace-ust', 'h'),
                                 output: fmt.format('trace-ust', 'h'),
                                 input: trace_events_file,
-                                command: [ tracetool, group, '--format=ust-events-h', '@INPUT@' ],
-                                capture: true)
+                                command: [ tracetool, group, '--format=ust-events-h', '@INPUT@', '@OUTPUT@' ])
     trace_ss.add(trace_ust_h, lttng, urcubp)
     genh += trace_ust_h
   endif
@@ -33,8 +30,7 @@ foreach dir : [ '.' ] + trace_events_subdirs
     trace_dtrace = custom_target(fmt.format('trace-dtrace', 'dtrace'),
                                  output: fmt.format('trace-dtrace', 'dtrace'),
                                  input: trace_events_file,
-                                 command: [ tracetool, group, '--format=d', '@INPUT@' ],
-                                 capture: true)
+                                 command: [ tracetool, group, '--format=d', '@INPUT@', '@OUTPUT@' ])
     trace_dtrace_h = custom_target(fmt.format('trace-dtrace', 'h'),
                                    output: fmt.format('trace-dtrace', 'h'),
                                    input: trace_dtrace,
@@ -66,9 +62,8 @@ foreach d : [
   gen = custom_target(d[0],
                 output: d[0],
                 input: meson.source_root() / 'trace-events',
-                command: [ tracetool, '--group=root', '--format=@0@'.format(d[1]), '@INPUT@' ],
-                build_by_default: true, # to be removed when added to a target
-                capture: true)
+                command: [ tracetool, '--group=root', '--format=@0@'.format(d[1]), '@INPUT@', '@OUTPUT@' ],
+                build_by_default: true) # to be removed when added to a target
   specific_ss.add(gen)
 endforeach
 
@@ -76,13 +71,11 @@ if 'CONFIG_TRACE_UST' in config_host
   trace_ust_all_h = custom_target('trace-ust-all.h',
                                   output: 'trace-ust-all.h',
                                   input: trace_events_files,
-                                  command: [ tracetool, '--group=all', '--format=ust-events-h', '@INPUT@' ],
-                                  capture: true)
+                                  command: [ tracetool, '--group=all', '--format=ust-events-h', '@INPUT@', '@OUTPUT@' ])
   trace_ust_all_c = custom_target('trace-ust-all.c',
                                   output: 'trace-ust-all.c',
                                   input: trace_events_files,
-                                  command: [ tracetool, '--group=all', '--format=ust-events-c', '@INPUT@' ],
-                                  capture: true)
+                                  command: [ tracetool, '--group=all', '--format=ust-events-c', '@INPUT@', '@OUTPUT@' ])
   trace_ss.add(trace_ust_all_h, trace_ust_all_c)
   genh += trace_ust_all_h
 endif
