feat: Use pre-compiled headers

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers
2025-12-14 18:33:34 -07:00
parent bf0d0a1d5b
commit e53093c4b4
6 changed files with 346 additions and 11 deletions

View File

@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.22) # minimum version required by Qt cmake_minimum_required(VERSION 3.22) # minimum version required by Qt
project(Launcher) project(Launcher LANGUAGES C CXX)
if(APPLE)
enable_language(OBJC OBJCXX)
endif()
string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BUILD_DIR}" IS_IN_SOURCE_BUILD)
if(IS_IN_SOURCE_BUILD) if(IS_IN_SOURCE_BUILD)

View File

@@ -1300,6 +1300,16 @@ endif()
include(CompilerWarnings) include(CompilerWarnings)
######## Precompiled Headers ###########
set(PRECOMPILED_HEADERS
include/base.pch.hpp
include/qtcore.pch.hpp
include/qtgui.pch.hpp
)
####### Targets ########
# Add executable # Add executable
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
set_project_warnings(Launcher_logic set_project_warnings(Launcher_logic
@@ -1308,6 +1318,7 @@ set_project_warnings(Launcher_logic
"${Launcher_GCC_WARNINGS}") "${Launcher_GCC_WARNINGS}")
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
target_precompile_headers(Launcher_logic PRIVATE ${PRECOMPILED_HEADERS})
target_link_libraries(Launcher_logic target_link_libraries(Launcher_logic
systeminfo systeminfo
Launcher_murmur2 Launcher_murmur2
@@ -1389,6 +1400,7 @@ endif()
target_link_libraries(Launcher_logic) target_link_libraries(Launcher_logic)
add_executable(${Launcher_Name} MACOSX_BUNDLE WIN32 main.cpp ${LAUNCHER_RCS}) add_executable(${Launcher_Name} MACOSX_BUNDLE WIN32 main.cpp ${LAUNCHER_RCS})
target_precompile_headers(${Launcher_Name} REUSE_FROM Launcher_logic)
target_link_libraries(${Launcher_Name} Launcher_logic) target_link_libraries(${Launcher_Name} Launcher_logic)
if(DEFINED Launcher_APP_BINARY_NAME) if(DEFINED Launcher_APP_BINARY_NAME)
@@ -1420,6 +1432,7 @@ if(Launcher_BUILD_UPDATER)
# Updater # Updater
add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI})
target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_precompile_headers(prism_updater_logic PRIVATE ${PRECOMPILED_HEADERS})
target_link_libraries(prism_updater_logic target_link_libraries(prism_updater_logic
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
systeminfo systeminfo
@@ -1439,6 +1452,7 @@ if(Launcher_BUILD_UPDATER)
add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp) add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp)
target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest) target_sources("${Launcher_Name}_updater" PRIVATE updater/prismupdater/updater.exe.manifest)
target_link_libraries("${Launcher_Name}_updater" prism_updater_logic) target_link_libraries("${Launcher_Name}_updater" prism_updater_logic)
target_precompile_headers("${Launcher_Name}_updater" REUSE_FROM prism_updater_logic)
if(DEFINED Launcher_APP_BINARY_NAME) if(DEFINED Launcher_APP_BINARY_NAME)
set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater") set_target_properties("${Launcher_Name}_updater" PROPERTIES OUTPUT_NAME "${Launcher_APP_BINARY_NAME}_updater")
@@ -1469,6 +1483,8 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
"${Launcher_GCC_WARNINGS}") "${Launcher_GCC_WARNINGS}")
target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(filelink_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_precompile_headers(filelink_logic PRIVATE ${PRECOMPILED_HEADERS})
target_link_libraries(filelink_logic target_link_libraries(filelink_logic
systeminfo systeminfo
BuildConfig BuildConfig
@@ -1482,6 +1498,8 @@ if(WIN32 OR (DEFINED Launcher_BUILD_FILELINKER AND Launcher_BUILD_FILELINKER))
add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp) add_executable("${Launcher_Name}_filelink" WIN32 filelink/filelink_main.cpp)
target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest) target_sources("${Launcher_Name}_filelink" PRIVATE filelink/filelink.exe.manifest)
target_precompile_headers("${Launcher_Name}_filelink" REUSE_FROM filelink_logic)
# HACK: Fix manifest issues with Ninja in release mode (and only release mode) and MSVC # HACK: Fix manifest issues with Ninja in release mode (and only release mode) and MSVC
# I have no idea why this works or why it's needed. UPDATE THIS IF YOU EDIT THE MANIFEST!!! -@getchoo # I have no idea why this works or why it's needed. UPDATE THIS IF YOU EDIT THE MANIFEST!!! -@getchoo
# Thank you 2018 CMake mailing list thread https://cmake.cmake.narkive.com/LnotZXus/conflicting-msvc-manifests # Thank you 2018 CMake mailing list thread https://cmake.cmake.narkive.com/LnotZXus/conflicting-msvc-manifests

View File

@@ -0,0 +1,17 @@
#pragma once
#ifndef PRISM_PRECOMPILED_BASE_HEADERS_H
#define PRISM_PRECOMPILED_BASE_HEADERS_H
#include <algorithm>
#include <functional>
#include <memory>
#include <optional>
#include <utility>
#include <BuildConfig.h>
#include <FileSystem.h>
#include <Json.h>
#include <Version.h>
#include <sys.h>
#endif // PRISM_PRECOMPILED_BASE_HEADERS_H

View File

@@ -0,0 +1,59 @@
#pragma once
#ifndef PRISM_PRECOMPILED_QTCORE_HEADERS_H
#define PRISM_PRECOMPILED_QTCORE_HEADERS_H
#include <QEvent>
#include <QMetaType>
#include <QObject>
#include <QVariant>
#include <QDebug>
#include <QCoreApplication>
// collections
#include <QByteArray>
#include <QHash>
#include <QList>
#include <QMap>
#include <QPair>
#include <QSet>
#include <QString>
#include <QStringList>
#include <QDateTime>
#include <QAbstractListModel>
#include <QCryptographicHash>
#include <QFuture>
#include <QFutureWatcher>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QMimeData>
#include <QSaveFile>
#include <QStandardPaths>
#include <QMutex>
#include <QProcess>
#include <QRegularExpression>
#include <QSortFilterProxyModel>
#include <QTimer>
#include <QUrl>
#include <QUuid>
#include <QtMath>
#endif // PRISM_PRECOMPILED_QTCORE_HEADERS_H

View File

@@ -0,0 +1,47 @@
#pragma once
#ifndef PRISM_PRECOMPILED_QTGUI_HEADERS_H
#define PRISM_PRECOMPILED_QTGUI_HEADERS_H
#include <QApplication>
#include <QMainWindow>
#include <QClipboard>
#include <QWidget>
#include <QAction>
#include <QKeyEvent>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QMessageBox>
#include <QCheckBox>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QPushButton>
#include <QStyle>
#include <QStyledItemDelegate>
#include <QScrollBar>
#include <QTabBar>
#include <QToolButton>
#include <QHeaderView>
#include <QListView>
#include <QTreeView>
#include <QLayout>
#include <QVBoxLayout>
#include <QIcon>
#include <QPainter>
#include <QPixmap>
#include <QPixmapCache>
#endif // PRISM_PRECOMPILED_GUI_HEADERS_H

191
tools/ninjatracing.py Normal file
View File

@@ -0,0 +1,191 @@
#!/usr/bin/env python3
# Copyright 2018 Nico Weber
# Patched to work with v7 logs
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Converts one (or several) .ninja_log files into chrome's about:tracing format.
If clang -ftime-trace .json files are found adjacent to generated files they
are embedded.
Usage:
ninja -C $BUILDDIR
ninjatracing $BUILDDIR/.ninja_log > trace.json
"""
import json
import os
import optparse
import re
import sys
class Target:
"""Represents a single line read for a .ninja_log file. Start and end times
are milliseconds."""
def __init__(self, start, end):
self.start = int(start)
self.end = int(end)
self.targets = []
def read_targets(log, show_all):
"""Reads all targets from .ninja_log file |log_file|, sorted by start
time"""
header = log.readline()
m = re.search(r'^# ninja log v(\d+)\n$', header)
assert m, "unrecognized ninja log version %r" % header
version = int(m.group(1))
assert 5 <= version <= 7, "unsupported ninja log version %d" % version
if version >= 6:
# Skip header line
next(log)
targets = {}
last_end_seen = 0
for line in log:
if line.startswith('#'):
continue
start, end, _, name, cmdhash = line.strip().split('\t') # Ignore restat.
if not show_all and int(end) < last_end_seen:
# An earlier time stamp means that this step is the first in a new
# build, possibly an incremental build. Throw away the previous data
# so that this new build will be displayed independently.
targets = {}
last_end_seen = int(end)
targets.setdefault(cmdhash, Target(start, end)).targets.append(name)
return sorted(targets.values(), key=lambda job: job.end, reverse=True)
class Threads:
"""Tries to reconstruct the parallelism from a .ninja_log"""
def __init__(self):
self.workers = [] # Maps thread id to time that thread is occupied for.
def alloc(self, target):
"""Places target in an available thread, or adds a new thread."""
for worker in range(len(self.workers)):
if self.workers[worker] >= target.end:
self.workers[worker] = target.start
return worker
self.workers.append(target.start)
return len(self.workers) - 1
def read_events(trace, options):
"""Reads all events from time-trace json file |trace|."""
trace_data = json.load(trace)
def include_event(event, options):
"""Only include events if they are complete events, are longer than
granularity, and are not totals."""
return ((event['ph'] == 'X') and
(event['dur'] >= options['granularity']) and
(not event['name'].startswith('Total')))
return [x for x in trace_data['traceEvents'] if include_event(x, options)]
def trace_to_dicts(target, trace, options, pid, tid):
"""Read a file-like object |trace| containing -ftime-trace data and yields
about:tracing dict per eligible event in that log."""
ninja_time = (target.end - target.start) * 1000
for event in read_events(trace, options):
# Check if any event duration is greater than the duration from ninja.
if event['dur'] > ninja_time:
print("Inconsistent timing found (clang time > ninja time). Please"
" ensure that timings are from consistent builds.")
sys.exit(1)
# Set tid and pid from ninja log.
event['pid'] = pid
event['tid'] = tid
# Offset trace time stamp by ninja start time.
event['ts'] += (target.start * 1000)
yield event
def embed_time_trace(ninja_log_dir, target, pid, tid, options):
"""Produce time trace output for the specified ninja target. Expects
time-trace file to be in .json file named based on .o file."""
for t in target.targets:
o_path = os.path.join(ninja_log_dir, t)
json_trace_path = os.path.splitext(o_path)[0] + '.json'
try:
with open(json_trace_path, 'r') as trace:
for time_trace_event in trace_to_dicts(target, trace, options,
pid, tid):
yield time_trace_event
except IOError:
pass
def log_to_dicts(log, pid, options):
"""Reads a file-like object |log| containing a .ninja_log, and yields one
about:tracing dict per command found in the log."""
threads = Threads()
for target in read_targets(log, options['showall']):
tid = threads.alloc(target)
yield {
'name': '%0s' % ', '.join(target.targets), 'cat': 'targets',
'ph': 'X', 'ts': (target.start * 1000),
'dur': ((target.end - target.start) * 1000),
'pid': pid, 'tid': tid, 'args': {},
}
if options.get('embed_time_trace', False):
# Add time-trace information into the ninja trace.
try:
ninja_log_dir = os.path.dirname(log.name)
except AttributeError:
continue
for time_trace in embed_time_trace(ninja_log_dir, target, pid,
tid, options):
yield time_trace
def main(argv):
usage = __doc__
parser = optparse.OptionParser(usage)
parser.add_option('-a', '--showall', action='store_true', dest='showall',
default=False,
help='report on last build step for all outputs. Default '
'is to report just on the last (possibly incremental) '
'build')
parser.add_option('-g', '--granularity', type='int', default=50000,
dest='granularity',
help='minimum length time-trace event to embed in '
'microseconds. Default: %default')
parser.add_option('-e', '--embed-time-trace', action='store_true',
default=False, dest='embed_time_trace',
help='embed clang -ftime-trace json file found adjacent '
'to a target file')
(options, args) = parser.parse_args()
if len(args) == 0:
print('Must specify at least one .ninja_log file')
parser.print_help()
return 1
entries = []
for pid, log_file in enumerate(args):
with open(log_file, 'r') as log:
entries += list(log_to_dicts(log, pid, vars(options)))
json.dump(entries, sys.stdout)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))