Add IREE_BUILD_TRACY CMake option. (#7382)

* Off by default for now, and I only expect that this works on Linux.
* If `-DIREE_BUILD_TRACY=ON` then `ninja tracy/all` will build both the headless capture tool and the full GUI (if sufficient deps are installed).
* My intent is, in a next step, to enable a traced runtime Python wheel as an alternative to the normal IREE runtime, and in that, I will include the headless capture tool.
* Add scripts to install deps on manylinux2014 to build Tracy.
* Add console scripts to iree.runtime Python package to bundle iree-tracy-capture and iree-run-module (because why not while here).
* Add an instrumented runtime package variant to the release pipeline.

diff --git a/.github/workflows/build_package.yml b/.github/workflows/build_package.yml
index 1d4998e..56bcd4a 100644
--- a/.github/workflows/build_package.yml
+++ b/.github/workflows/build_package.yml
@@ -42,6 +42,9 @@
             build_package: py-runtime-pkg
             experimental: false
           - os: ubuntu-18.04
+            build_package: instrumented-py-runtime-pkg
+            experimental: true
+          - os: ubuntu-18.04
             build_package: py-xla-compiler-tools-pkg
             experimental: false
           - os: ubuntu-18.04
@@ -122,7 +125,8 @@
         run: |
           python -m pip install cibuildwheel==1.7.2
 
-      - name: Write version info
+      - name: Write version info (release)
+        if: "!startsWith(matrix.build_package, 'instrumented-')"
         shell: bash
         run: |
           cat << EOF > ./main_checkout/version_info.json
@@ -134,6 +138,19 @@
           EOF
           cat ./main_checkout/version_info.json
 
+      - name: Write version info (instrumented)
+        if: "startsWith(matrix.build_package, 'instrumented-')"
+        shell: bash
+        run: |
+          cat << EOF > ./main_checkout/version_info.json
+          {
+            "package-suffix": "-instrumented${{ github.event.inputs.package_suffix }}",
+            "package-version": "${{ github.event.inputs.package_version }}",
+            "iree-revision": "$(cd ./main_checkout && git rev-parse HEAD)"
+          }
+          EOF
+          cat ./main_checkout/version_info.json
+
       # The main distribution consists of the project being built, installed
       # and archived. We have to split it per operating system, and Linux
       # is special because we build under a manylinux container which gives
@@ -167,6 +184,18 @@
           mkdir -p $package_dir && touch $package_dir/setup.py
           python -m cibuildwheel --output-dir bindist $package_dir
 
+      - name: Build runtime wheels (instrumented)
+        if: "matrix.build_package == 'instrumented-py-runtime-pkg'"
+        shell: bash
+        run: |
+          package_dir="./iree-install/python_packages/iree_runtime"
+          export CIBW_BEFORE_ALL_LINUX="./main_checkout/build_tools/github_actions/install_tracy_cli_deps_manylinux2014.sh"
+          export CIBW_BEFORE_BUILD="python ./main_checkout/build_tools/github_actions/build_dist.py py-runtime-pkg"
+          # TODO: cibuildwheel sanity checks this, but our setup.py is the
+          # *output* of the build :( Make source packages.
+          mkdir -p $package_dir && touch $package_dir/setup.py
+          python -m cibuildwheel --output-dir bindist $package_dir
+
       # Experimental iree.compiler package.
       - name: Build compiler wheels
         if: "matrix.build_package == 'py-compiler-pkg'"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6205283..77fd81d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,7 @@
 option(IREE_BUILD_BENCHMARKS "Builds IREE benchmark suites." OFF)
 option(IREE_BUILD_DOCS "Builds IREE docs." OFF)
 option(IREE_BUILD_SAMPLES "Builds IREE sample projects." ON)
+option(IREE_BUILD_TRACY "Builds tracy server tools." OFF)
 
 option(IREE_BUILD_TENSORFLOW_ALL "Builds all TensorFlow compiler frontends." OFF)
 option(IREE_BUILD_TENSORFLOW_COMPILER "Builds TensorFlow compiler frontend." OFF)
@@ -516,8 +517,18 @@
 
 add_subdirectory(iree/tools)
 
+if(IREE_BUILD_TRACY)
+  if(NOT LINUX)
+    message(WARNING "Building Tracy (IREE_BUILD_TRACY) on non-Linux is unsupported and may fail below.")
+  endif()
+  add_subdirectory(build_tools/third_party/tracy ${CMAKE_CURRENT_BINARY_DIR}/tracy)
+  if(NOT TARGET IREETracyCaptureServer)
+    message(SEND_ERROR "Could not build Tracy. Either unset IREE_BUILD_TRACY or look for missing dependencies above and install them.")
+  endif()
+endif()
+
 # Order constraint: The python bindings install tools targets from iree/tools
-# and must come after it.
+# and tracy, and must come after it.
 if(${IREE_BUILD_PYTHON_BINDINGS})
   add_subdirectory(bindings/python)
 endif()
diff --git a/bindings/python/iree/runtime/CMakeLists.txt b/bindings/python/iree/runtime/CMakeLists.txt
index dccdf00..1e1a11e 100644
--- a/bindings/python/iree/runtime/CMakeLists.txt
+++ b/bindings/python/iree/runtime/CMakeLists.txt
@@ -4,6 +4,17 @@
 # See https://llvm.org/LICENSE.txt for license information.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
+set(_python_extra_srcs)
+set(_extra_install_tool_targets)
+set(_tracy_enabled OFF)
+
+if(TARGET IREETracyCaptureServer)
+  message(STATUS "Bundline Tracy CLI tools with Python API")
+  set(_tracy_enabled ON)
+  list(APPEND _python_extra_srcs "scripts/iree-tracy-capture")
+  list(APPEND _extra_install_tool_targets "IREETracyCaptureServer")
+endif()
+
 ################################################################################
 # Package
 ################################################################################
@@ -43,6 +54,8 @@
     "tracing.py"
     "scripts/iree_benchmark_trace/__main__.py"
     "scripts/iree_run_trace/__main__.py"
+    "scripts/iree_run_module/__main__.py"
+    ${_python_extra_srcs}
   PYEXT_DEPS
     ::PyExtRt
 )
@@ -59,6 +72,20 @@
   TO_EXE_NAME iree-run-trace
 )
 
+iree_symlink_tool(
+  TARGET runtime
+  FROM_TOOL_TARGET iree_tools_iree-run-module
+  TO_EXE_NAME iree-run-module
+)
+
+if(_tracy_enabled)
+  iree_symlink_tool(
+    TARGET runtime
+    FROM_TOOL_TARGET IREETracyCaptureServer
+    TO_EXE_NAME iree-tracy-capture
+  )
+endif()
+
 ################################################################################
 # Tests
 ################################################################################
@@ -102,7 +129,9 @@
   DEPS
     bindings_python_iree_runtime_PyExtRt
     iree_tools_iree-benchmark-trace
+    iree_tools_iree-run-module
     iree_tools_iree-run-trace
+    ${_extra_install_tool_targets}
   ADDL_PACKAGE_FILES
     ${CMAKE_CURRENT_SOURCE_DIR}/README.md
 )
@@ -116,7 +145,9 @@
 install(
   TARGETS
     iree_tools_iree-benchmark-trace
+    iree_tools_iree-run-module
     iree_tools_iree-run-trace
+    ${_extra_install_tool_targets}
   DESTINATION "${PY_INSTALL_MODULE_DIR}"
   COMPONENT "${PY_INSTALL_COMPONENT}"
 )
diff --git a/bindings/python/iree/runtime/scripts/iree_run_module/__main__.py b/bindings/python/iree/runtime/scripts/iree_run_module/__main__.py
new file mode 100644
index 0000000..a5509a3
--- /dev/null
+++ b/bindings/python/iree/runtime/scripts/iree_run_module/__main__.py
@@ -0,0 +1,20 @@
+# Copyright 2021 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import os
+import subprocess
+import sys
+
+
+def main(args=None):
+  if args is None:
+    args = sys.argv[1:]
+  exe = os.path.join(os.path.dirname(__file__), "..", "..", "iree-run-module")
+  return subprocess.call(args=[exe] + args)
+
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/bindings/python/iree/runtime/scripts/iree_tracy_capture/__main__.py b/bindings/python/iree/runtime/scripts/iree_tracy_capture/__main__.py
new file mode 100644
index 0000000..58f2118
--- /dev/null
+++ b/bindings/python/iree/runtime/scripts/iree_tracy_capture/__main__.py
@@ -0,0 +1,21 @@
+# Copyright 2021 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import os
+import subprocess
+import sys
+
+
+def main(args=None):
+  if args is None:
+    args = sys.argv[1:]
+  exe = os.path.join(os.path.dirname(__file__), "..", "..",
+                     "iree-tracy-capture")
+  return subprocess.call(args=[exe] + args)
+
+
+if __name__ == "__main__":
+  sys.exit(main())
diff --git a/bindings/python/iree/runtime/setup.py.in b/bindings/python/iree/runtime/setup.py.in
index dc25a35..2d0cfac 100644
--- a/bindings/python/iree/runtime/setup.py.in
+++ b/bindings/python/iree/runtime/setup.py.in
@@ -41,14 +41,18 @@
     package_data={
         "": [
             f"*{sysconfig.get_config_var('EXT_SUFFIX')}",
+            "iree-run-module*",
             "iree-run-trace*",
             "iree-benchmark-trace*",
+            "iree-tracy-capture*",
         ],
     },
     entry_points={
         "console_scripts": [
+            "iree-run-module = iree.runtime.scripts.iree_run_module.__main__:main",
             "iree-run-trace = iree.runtime.scripts.iree_run_trace.__main__:main",
             "iree-benchmark-trace = iree.runtime.scripts.iree_benchmark_trace.__main__:main",
+            "iree-tracy-capture = iree.runtime.scripts.iree_tracy_capture.__main__:main",
         ],
     },
     zip_safe=False,
diff --git a/build_tools/github_actions/build_dist.py b/build_tools/github_actions/build_dist.py
index 00fb326..f9e9545 100644
--- a/build_tools/github_actions/build_dist.py
+++ b/build_tools/github_actions/build_dist.py
@@ -210,17 +210,30 @@
                  check=True)
 
 
-def build_py_runtime_pkg():
+def build_py_runtime_pkg(instrumented: bool = False):
   """Builds the iree-install/python_packages/iree_runtime package.
 
   This includes native, python-version dependent code and is designed to
   be built multiple times.
+
+  Note that an instrumented build may require additional dependencies.
+  See: install_tracy_cli_deps_manylinux2014.sh for how to set up on that
+  container.
   """
   install_python_requirements()
 
   # Clean up install and build trees.
   shutil.rmtree(INSTALL_DIR, ignore_errors=True)
   remove_cmake_cache()
+  extra_cmake_flags = []
+
+  # Extra options for instrumentation.
+  if instrumented:
+    print("*** Enabling options for instrumented build ***")
+    extra_cmake_flags.extend([
+        f"-DIREE_ENABLE_RUNTIME_TRACING=ON",
+        f"-DIREE_BUILD_TRACY=ON",
+    ])
 
   # CMake configure.
   print("*** Configuring ***")
@@ -234,7 +247,7 @@
       f"-DIREE_BUILD_PYTHON_BINDINGS=ON",
       f"-DIREE_BUILD_SAMPLES=OFF",
       f"-DIREE_BUILD_TESTS=OFF",
-  ],
+  ] + extra_cmake_flags,
                  check=True)
 
   print("*** Building ***")
@@ -405,6 +418,8 @@
   build_main_dist()
 elif command == "py-runtime-pkg":
   build_py_runtime_pkg()
+elif command == "instrumented-py-runtime-pkg":
+  build_py_runtime_pkg(instrumented=True)
 elif command == "py-pure-pkgs":
   build_py_pure_pkgs()
 elif command == "py-xla-compiler-tools-pkg":
diff --git a/build_tools/github_actions/install_tbb_manylinux2014.sh b/build_tools/github_actions/install_tbb_manylinux2014.sh
new file mode 100755
index 0000000..7c8e9b1
--- /dev/null
+++ b/build_tools/github_actions/install_tbb_manylinux2014.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# Copyright 2021 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# The version of tbb installed on manylinux2014 is too old to support the
+# parallel STL libraries on the installed GCC9-based toolchain. Further,
+# Intel *broke* compatibility starting in 2021 for GCC<=10.
+# To make matters worse, the prior 2020 versions did not have cmake or
+# install support.
+# Shame on you Intel.
+# See: https://community.intel.com/t5/Intel-oneAPI-Threading-Building/tbb-task-has-not-been-declared/m-p/1254418
+# Since this is unlikely to be helpful outside of the old centos systems
+# that manylinux2014 is based on (newer ones are based on Debian),
+# we just tailor this specifically for docker images of that distro.
+
+# You can test this with either an official manylinux2014 docker image or
+# our special one (which is really only special in that it includes bazel):
+# docker run --rm -it -v $(pwd):/work stellaraccident/manylinux2014_x86_64-bazel-3.7.2:latest /bin/bash
+
+set -e
+
+mkdir -p /tmp/libtbb_build
+cd /tmp/libtbb_build
+curl -o tbbsrc.tgz -L https://github.com/oneapi-src/oneTBB/archive/refs/tags/v2020.3.tar.gz
+tar xzf tbbsrc.tgz
+cd oneTBB-*/
+
+echo "****** BUILDING TBB ******"
+make -j$(nproc)
+cp -R include/* /usr/include
+cp build/*_release/* /usr/lib64
+echo "prefix=/usr
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib64
+includedir=${prefix}/include
+
+Name: Threading Building Blocks
+Description: Intel's parallelism library for C++
+URL: http://www.threadingbuildingblocks.org/
+Version:
+Libs: -ltbb
+Cflags:
+" > /usr/lib64/pkgconfig/tbb.pc
+
+echo "****** DONE BUILDING TBB ******"
+
+cd /
+rm -Rf /tmp/libtbb_build
diff --git a/build_tools/github_actions/install_tracy_cli_deps_manylinux2014.sh b/build_tools/github_actions/install_tracy_cli_deps_manylinux2014.sh
new file mode 100755
index 0000000..2eda736
--- /dev/null
+++ b/build_tools/github_actions/install_tracy_cli_deps_manylinux2014.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 2021 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+# Installs deps on a manylinux2014 CentOS docker container needed for
+# building Tracy CLI capture tool.
+
+set -e
+
+td="$(cd $(dirname $0) && pwd)"
+yum -y install capstone-devel libzstd-devel
+$td/install_tbb_manylinux2014.sh
diff --git a/build_tools/third_party/tracy/CMakeLists.txt b/build_tools/third_party/tracy/CMakeLists.txt
new file mode 100644
index 0000000..7c1e43d
--- /dev/null
+++ b/build_tools/third_party/tracy/CMakeLists.txt
@@ -0,0 +1,183 @@
+# Copyright 2021 The IREE Authors
+#
+# Licensed under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 3.16.3)
+
+project(IREETracyServer C CXX)
+
+set(TRACY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../third_party/tracy")
+
+find_package(Threads REQUIRED)
+
+#-------------------------------------------------------------------------------
+# Detect package manager
+#-------------------------------------------------------------------------------
+
+message(STATUS "Checking for Tracy dependencies...")
+find_program(PKGCONFIG pkg-config)
+if(NOT PKGCONFIG)
+  message(STATUS "Could not find pkg-config (on Ubuntu/Debian, 'apt install pkg-config')")
+else()
+  include(FindPkgConfig)
+  pkg_check_modules(TRACY_DEPS
+    capstone
+    tbb
+    libzstd
+  )
+  pkg_check_modules(TRACY_GTK_DEPS
+    freetype2
+    glfw3
+    gtk+-3.0
+  )
+endif()
+
+if(NOT TRACY_DEPS_FOUND)
+  message(STATUS "Could not find Tracy dependencies (Tracy server will not be built).")
+  message(STATUS "To build Tracy, install packages capstone, and tbb (on Ubuntu/Debian, 'apt install libcapstone-dev libtbb-dev libzstd-dev')")
+  return()
+endif()
+
+if(NOT TRACY_GTK_DEPS_FOUND)
+  message(STATUS
+    "Could not find deps required to build graphical programs: "
+    "Tracy graphical profiler will not be built (on Ubuntu/Debian, 'apt install libglfw3-dev libfreetype-dev libgtk-3-dev')")
+endif()
+
+#-------------------------------------------------------------------------------
+# Configuration
+#-------------------------------------------------------------------------------
+
+function(setup_cxx_options name)
+  set_target_properties(${name}
+    PROPERTIES
+      CXX_STANDARD 17
+  )
+  target_compile_options(${name}
+    PRIVATE
+      $<$<CXX_COMPILER_ID:GNU,Clang>:-Wno-unused-result>
+  )
+  target_include_directories(${name}
+    PUBLIC
+      ${TRACY_SOURCE_DIR}/imgui
+      ${TRACY_DEPS_INCLUDE_DIRS}
+  )
+  target_link_libraries(${name}
+    PRIVATE
+      ${TRACY_DEPS_LIBRARIES}
+      ${CMAKE_DL_LIBS}
+      ${CMAKE_THREAD_LIBS_INIT}
+  )
+endfunction()
+
+function(setup_graphics_deps name)
+  target_compile_definitions(${name}
+  PRIVATE
+    DISPLAY_SERVER_X11
+  )
+  target_include_directories(${name}
+  PUBLIC
+    ${TRACY_GTK_DEPS_INCLUDE_DIRS}
+  )
+  target_link_libraries(${name}
+  PRIVATE
+    ${TRACY_GTK_DEPS_LIBRARIES}
+  )
+endfunction()
+
+#-------------------------------------------------------------------------------
+# Common library
+#-------------------------------------------------------------------------------
+
+file(GLOB COMMON_SRCS ${TRACY_SOURCE_DIR}/common/*.cpp)
+add_library(IREETracyCommon
+  ${COMMON_SRCS}
+)
+setup_cxx_options(IREETracyCommon)
+
+#-------------------------------------------------------------------------------
+# Server library
+#-------------------------------------------------------------------------------
+
+file(GLOB SERVER_SRCS ${TRACY_SOURCE_DIR}/server/*.cpp)
+add_library(IREETracyServer
+  ${SERVER_SRCS}
+)
+setup_cxx_options(IREETracyServer)
+target_link_libraries(IREETracyServer
+  PRIVATE
+    IREETracyCommon
+)
+
+#-------------------------------------------------------------------------------
+# IMGUI library
+#-------------------------------------------------------------------------------
+
+file(GLOB IMGUI_SOURCES ${TRACY_SOURCE_DIR}/imgui/*.cpp)
+add_library(IREETracyIMGUI
+  ${IMGUI_SOURCES}
+)
+setup_cxx_options(IREETracyServer)
+
+#-------------------------------------------------------------------------------
+# Standalone capture server
+#-------------------------------------------------------------------------------
+
+add_executable(IREETracyCaptureServer
+  ${TRACY_SOURCE_DIR}/capture/src/capture.cpp
+)
+set_target_properties(IREETracyCaptureServer
+  PROPERTIES
+    OUTPUT_NAME "iree-tracy-capture"
+)
+setup_cxx_options(IREETracyCaptureServer)
+target_link_libraries(IREETracyCaptureServer
+  PRIVATE
+    IREETracyCommon
+    IREETracyServer
+)
+
+#-------------------------------------------------------------------------------
+# Graphical frontends
+#-------------------------------------------------------------------------------
+
+if(TRACY_GTK_DEPS_FOUND)
+  #-----------------------------------------------------------------------------
+  # NFD library
+  #-----------------------------------------------------------------------------
+
+  set(NFD_SOURCES
+    ${TRACY_SOURCE_DIR}/nfd/nfd_common.c
+    ${TRACY_SOURCE_DIR}/nfd/nfd_gtk.c
+  )
+  add_library(IREETracyNFD
+    ${NFD_SOURCES}
+  )
+  setup_cxx_options(IREETracyNFD)
+  setup_graphics_deps(IREETracyNFD)
+
+  #-----------------------------------------------------------------------------
+  # Profiler
+  #-----------------------------------------------------------------------------
+
+  file(GLOB PROFILER_SRCS ${TRACY_SOURCE_DIR}/profiler/src/*.cpp)
+  add_executable(IREETracyProfiler
+    ${PROFILER_SRCS}
+  )
+  set_target_properties(IREETracyProfiler
+    PROPERTIES
+      OUTPUT_NAME "iree-tracy-profiler"
+  )
+  setup_cxx_options(IREETracyProfiler)
+  setup_graphics_deps(IREETracyProfiler)
+  target_link_libraries(IREETracyProfiler
+    PRIVATE
+      IREETracyIMGUI
+      IREETracyCommon
+      IREETracyNFD
+      IREETracyServer
+      ${CMAKE_THREAD_LIBS_INIT}
+  )
+endif()