🔨 Automatically generate resources files with cmake (#4159)

Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
Fixes https://github.com/Chatterino/chatterino2/issues/3949
This commit is contained in:
Edgar 2022-11-19 12:29:12 +01:00 committed by GitHub
parent 2f4272cc2a
commit 9f5477c433
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 134 additions and 425 deletions

3
.gitignore vendored
View file

@ -115,3 +115,6 @@ vcpkg_installed/
# NatVis files
qt5.natvis
qt6.natvis
# Autogenerated resource file
resources/resources_autogenerated.qrc

View file

@ -132,6 +132,7 @@
- Dev: Batched checking live status for all channels after startup. (#3757, #3762, #3767)
- Dev: Moved most command context into the command controller. (#3824)
- Dev: Error NetworkResults now include the body data. (#3987)
- Dev: Automatically generate resources files with cmake. (#4159)
## 2.3.5

View file

@ -150,6 +150,9 @@ if (BUILD_TESTS OR BUILD_BENCHMARKS)
add_definitions(-DCHATTERINO_TEST)
endif ()
# Generate resource files
include(cmake/resources/generate_resources.cmake)
add_subdirectory(src)
if (BUILD_TESTS)

View file

@ -0,0 +1,13 @@
/****************************************************************************
** WARNING! This file is autogenerated by cmake
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include "ResourcesAutogen.hpp"
namespace chatterino {
Resources2::Resources2()
{
@RES_SOURCE_CONTENT@
}
} // namespace chatterino

View file

@ -0,0 +1,17 @@
/****************************************************************************
** WARNING! This file is autogenerated by cmake
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include <QPixmap>
#include "common/Singleton.hpp"
namespace chatterino {
class Resources2 : public Singleton
{
public:
Resources2();
@RES_HEADER_CONTENT@
};
} // namespace chatterino

View file

@ -0,0 +1,82 @@
set(RES_DIR "${CMAKE_SOURCE_DIR}/resources")
# Note: files in this ignorelist should be relative to ${RES_DIR}
set(
RES_IGNORED_FILES
.gitignore
qt.conf
resources.qrc
resources_autogenerated.qrc
windows.rc
)
file(GLOB_RECURSE RES_ALL_FILES RELATIVE "${RES_DIR}" LIST_DIRECTORIES false CONFIGURE_DEPENDS "${RES_DIR}/*")
file(GLOB_RECURSE RES_IMAGE_FILES RELATIVE "${RES_DIR}" LIST_DIRECTORIES false CONFIGURE_DEPENDS "${RES_DIR}/*.png")
list(REMOVE_ITEM RES_ALL_FILES ${RES_IGNORED_FILES})
###############################
# Generate resources_autogenerated.qrc
###############################
message(STATUS "Generating resources_autogenerated.qrc")
foreach (_file ${RES_ALL_FILES})
list(APPEND RES_RESOURCES_CONTENT " <file>${_file}</file>")
endforeach ()
list(JOIN RES_RESOURCES_CONTENT "\n" RES_RESOURCES_CONTENT)
configure_file(${CMAKE_CURRENT_LIST_DIR}/resources_autogenerated.qrc.in ${RES_DIR}/resources_autogenerated.qrc @ONLY)
###############################
# Generate ResourcesAutogen.cpp
###############################
message(STATUS "Generating ResourcesAutogen.cpp")
foreach (_file ${RES_IMAGE_FILES})
get_filename_component(_ext "${_file}" EXT)
string(REPLACE "${_ext}" "" _var_name ${_file})
string(REPLACE "/" "." _var_name ${_var_name})
list(APPEND RES_SOURCE_CONTENT " this->${_var_name} = QPixmap(\":/${_file}\")\;")
list(APPEND RES_VAR_NAMES "${_var_name}")
endforeach ()
list(JOIN RES_SOURCE_CONTENT "\n" RES_SOURCE_CONTENT)
configure_file(${CMAKE_CURRENT_LIST_DIR}/ResourcesAutogen.cpp.in ${CMAKE_BINARY_DIR}/autogen/ResourcesAutogen.cpp @ONLY)
###############################
# Generate ResourcesAutogen.hpp
###############################
message(STATUS "Generating ResourcesAutogen.hpp")
set(_struct_list "")
foreach (_file ${RES_IMAGE_FILES})
get_filename_component(_dir "${_file}" DIRECTORY)
get_filename_component(_name "${_file}" NAME_WE)
string(REPLACE "/" "_" _dir "${_dir}")
if (NOT _dir)
set(_dir "root")
endif ()
list(APPEND ${_dir} "${_name}")
list(APPEND _struct_list "${_dir}")
endforeach ()
list(REMOVE_DUPLICATES _struct_list)
foreach (_str_name ${_struct_list})
if (NOT "${_str_name}" STREQUAL "root")
list(APPEND RES_HEADER_CONTENT " struct {")
set(_indent " ")
else ()
set(_indent " ")
endif ()
foreach (_name ${${_str_name}})
list(APPEND RES_HEADER_CONTENT "${_indent}QPixmap ${_name}\;")
endforeach ()
if (NOT "${_str_name}" STREQUAL "root")
list(APPEND RES_HEADER_CONTENT " } ${_str_name}\;")
endif ()
endforeach ()
list(JOIN RES_HEADER_CONTENT "\n" RES_HEADER_CONTENT)
configure_file(${CMAKE_CURRENT_LIST_DIR}/ResourcesAutogen.hpp.in ${CMAKE_BINARY_DIR}/autogen/ResourcesAutogen.hpp @ONLY)
set(RES_AUTOGEN_FILES
"${CMAKE_SOURCE_DIR}/resources/resources_autogenerated.qrc"
"${CMAKE_BINARY_DIR}/autogen/ResourcesAutogen.cpp"
"${CMAKE_BINARY_DIR}/autogen/ResourcesAutogen.hpp"
)

View file

@ -0,0 +1,9 @@
<!--
WARNING! This file is autogenerated by cmake
WARNING! All changes made in this file will be lost!
-->
<RCC>
<qresource prefix="/">
@RES_RESOURCES_CONTENT@
</qresource>
</RCC>

View file

@ -1,39 +0,0 @@
resources_header = \
'''<RCC>
<qresource prefix="/">'''
resources_footer = \
''' </qresource>
</RCC>\n'''
header_header = \
'''#include <QPixmap>
#include "common/Singleton.hpp"
namespace chatterino {
class Resources2 : public Singleton
{
public:
Resources2();
'''
header_footer = \
'''};
} // namespace chatterino\n'''
source_header = \
'''#include "ResourcesAutogen.hpp"
namespace chatterino {
Resources2::Resources2()
{
'''
source_footer = \
'''}
} // namespace chatterino\n'''

View file

@ -1,70 +0,0 @@
#!/usr/bin/env python3
from pathlib import Path
from _generate_resources import *
ignored_files = ['qt.conf', 'resources.qrc', 'resources_autogenerated.qrc', 'windows.rc',
'generate_resources.py', '_generate_resources.py']
ignored_names = ['.gitignore', '.DS_Store']
# to ignore all files in a/b, add a/b to ignored_directories.
# this will ignore a/b/c/d.txt and a/b/xd.txt
ignored_directories = ['__pycache__', 'linuxinstall']
def isNotIgnored(file):
# check if file exists in an ignored direcory
for ignored_directory in ignored_directories:
if file.parent.as_posix().startswith(ignored_directory):
return False
return file.as_posix() not in ignored_files and file.name not in ignored_names
all_files = sorted(list(filter(isNotIgnored, \
filter(Path.is_file, Path('.').glob('**/*')))))
image_files = sorted(list(filter(isNotIgnored, \
filter(Path.is_file, Path('.').glob('**/*.png')))))
with open('./resources_autogenerated.qrc', 'w') as out:
out.write(resources_header + '\n')
for file in all_files:
out.write(f" <file>{file.as_posix()}</file>\n")
out.write(resources_footer)
with open('../src/autogenerated/ResourcesAutogen.cpp', 'w') as out:
out.write(source_header)
for file in sorted(image_files):
var_name = file.with_suffix("").as_posix().replace("/",".")
out.write(f' this->{var_name}')
out.write(f' = QPixmap(":/{file.as_posix()}");\n')
out.write(source_footer)
def writeHeader(out, name, element, indent):
if isinstance(element, dict):
if name != "":
out.write(f"{indent}struct {{\n")
for (key, value) in element.items():
writeHeader(out, key, value, indent + ' ')
if name != "":
out.write(f"{indent}}} {name};\n");
else:
out.write(f"{indent}QPixmap {element};\n")
with open('../src/autogenerated/ResourcesAutogen.hpp', 'w') as out:
out.write(header_header)
elements = {}
for file in sorted(image_files):
elements_ref = elements
directories = file.as_posix().split('/')[:-1]
filename = file.stem
for directory in directories:
if directory not in elements_ref:
elements_ref[directory] = {}
elements_ref = elements_ref[directory]
elements_ref[filename] = filename
writeHeader(out, "", elements, '')
out.write(header_footer)

View file

@ -1,133 +0,0 @@
<RCC>
<qresource prefix="/">
<file>avatars/_1xelerate.png</file>
<file>avatars/alazymeme.png</file>
<file>avatars/brian6932.png</file>
<file>avatars/explooosion_code.png</file>
<file>avatars/fourtf.png</file>
<file>avatars/hicupalot.png</file>
<file>avatars/iprodigy.png</file>
<file>avatars/jaxkey.png</file>
<file>avatars/kararty.png</file>
<file>avatars/karlpolice.png</file>
<file>avatars/matthewde.jpg</file>
<file>avatars/mm2pl.png</file>
<file>avatars/mohad12211.png</file>
<file>avatars/pajlada.png</file>
<file>avatars/revolter.jpg</file>
<file>avatars/slch.png</file>
<file>avatars/xheaveny.png</file>
<file>avatars/zneix.png</file>
<file>buttons/addSplit.png</file>
<file>buttons/addSplitDark.png</file>
<file>buttons/ban.png</file>
<file>buttons/banRed.png</file>
<file>buttons/cancel.svg</file>
<file>buttons/cancelDark.svg</file>
<file>buttons/clearSearch.png</file>
<file>buttons/copyDark.png</file>
<file>buttons/copyDark.svg</file>
<file>buttons/copyLight.png</file>
<file>buttons/copyLight.svg</file>
<file>buttons/emote.svg</file>
<file>buttons/emoteDark.svg</file>
<file>buttons/menuDark.png</file>
<file>buttons/menuLight.png</file>
<file>buttons/mod.png</file>
<file>buttons/modModeDisabled.png</file>
<file>buttons/modModeDisabled2.png</file>
<file>buttons/modModeEnabled.png</file>
<file>buttons/modModeEnabled2.png</file>
<file>buttons/pinDisabledDark.png</file>
<file>buttons/pinDisabledDark.svg</file>
<file>buttons/pinDisabledLight.png</file>
<file>buttons/pinDisabledLight.svg</file>
<file>buttons/pinEnabled.png</file>
<file>buttons/pinEnabled.svg</file>
<file>buttons/replyDark.png</file>
<file>buttons/replyDark.svg</file>
<file>buttons/replyThreadDark.png</file>
<file>buttons/replyThreadDark.svg</file>
<file>buttons/search.png</file>
<file>buttons/timeout.png</file>
<file>buttons/trashCan.png</file>
<file>buttons/trashcan.svg</file>
<file>buttons/unban.png</file>
<file>buttons/unmod.png</file>
<file>buttons/unvip.png</file>
<file>buttons/update.png</file>
<file>buttons/updateError.png</file>
<file>buttons/viewersDark.png</file>
<file>buttons/viewersLight.png</file>
<file>buttons/vip.png</file>
<file>chatterino.icns</file>
<file>com.chatterino.chatterino.appdata.xml</file>
<file>com.chatterino.chatterino.desktop</file>
<file>contributors.txt</file>
<file>emoji.json</file>
<file>error.png</file>
<file>examples/moving.gif</file>
<file>examples/splitting.gif</file>
<file>icon.ico</file>
<file>icon.png</file>
<file>licenses/boost_boost.txt</file>
<file>licenses/emoji-data-source.txt</file>
<file>licenses/libcommuni_BSD3.txt</file>
<file>licenses/lrucache.txt</file>
<file>licenses/magic_enum.txt</file>
<file>licenses/openssl.txt</file>
<file>licenses/pajlada_settings.txt</file>
<file>licenses/pajlada_signals.txt</file>
<file>licenses/qt_lgpl-3.0.txt</file>
<file>licenses/qtkeychain.txt</file>
<file>licenses/rapidjson.txt</file>
<file>licenses/websocketpp.txt</file>
<file>pajaDank.png</file>
<file>qss/settings.qss</file>
<file>scrolling/downScroll.png</file>
<file>scrolling/downScroll.svg</file>
<file>scrolling/neutralScroll.png</file>
<file>scrolling/neutralScroll.svg</file>
<file>scrolling/upScroll.png</file>
<file>scrolling/upScroll.svg</file>
<file>settings/about.svg</file>
<file>settings/aboutlogo.png</file>
<file>settings/accounts.svg</file>
<file>settings/advanced.svg</file>
<file>settings/behave.svg</file>
<file>settings/browser.svg</file>
<file>settings/commands.svg</file>
<file>settings/emote.svg</file>
<file>settings/externaltools.svg</file>
<file>settings/filters.svg</file>
<file>settings/ignore.svg</file>
<file>settings/keybinds.svg</file>
<file>settings/moderation.svg</file>
<file>settings/notification2.svg</file>
<file>settings/notifications.svg</file>
<file>settings/theme.svg</file>
<file>sounds/ping2.wav</file>
<file>split/down.png</file>
<file>split/left.png</file>
<file>split/move.png</file>
<file>split/right.png</file>
<file>split/up.png</file>
<file>streamerMode.png</file>
<file>switcher/plus.svg</file>
<file>switcher/popup.svg</file>
<file>switcher/switch.svg</file>
<file>tlds.txt</file>
<file>twitch/admin.png</file>
<file>twitch/automod.png</file>
<file>twitch/broadcaster.png</file>
<file>twitch/cheer1.png</file>
<file>twitch/globalmod.png</file>
<file>twitch/moderator.png</file>
<file>twitch/prime.png</file>
<file>twitch/staff.png</file>
<file>twitch/subscriber.png</file>
<file>twitch/turbo.png</file>
<file>twitch/verified.png</file>
<file>twitch/vip.png</file>
</qresource>
</RCC>

View file

@ -537,11 +537,7 @@ set(SOURCE_FILES
widgets/splits/SplitOverlay.cpp
widgets/splits/SplitOverlay.hpp
autogenerated/ResourcesAutogen.cpp
autogenerated/ResourcesAutogen.hpp
${CMAKE_SOURCE_DIR}/resources/resources.qrc
${CMAKE_SOURCE_DIR}/resources/resources_autogenerated.qrc
)
if (WIN32)
@ -559,6 +555,9 @@ endif ()
# Generate source groups for use in IDEs
source_group(TREE ${CMAKE_SOURCE_DIR} FILES ${SOURCE_FILES})
# Add autogenerated files
list(APPEND SOURCE_FILES ${RES_AUTOGEN_FILES})
add_library(${LIBRARY_PROJECT} OBJECT ${SOURCE_FILES})
if (CHATTERINO_GENERATE_COVERAGE)
@ -616,7 +615,7 @@ if (BUILD_APP)
endif()
add_sanitizers(${EXECUTABLE_PROJECT})
target_include_directories(${EXECUTABLE_PROJECT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${EXECUTABLE_PROJECT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/autogen/)
target_link_libraries(${EXECUTABLE_PROJECT} PUBLIC ${LIBRARY_PROJECT})
@ -740,7 +739,7 @@ if (APPLE AND BUILD_APP)
)
endif ()
target_include_directories(${LIBRARY_PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${LIBRARY_PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/autogen/)
if (WinToast_FOUND)
target_link_libraries(${LIBRARY_PROJECT}

View file

@ -1,80 +0,0 @@
#include "ResourcesAutogen.hpp"
namespace chatterino {
Resources2::Resources2()
{
this->avatars._1xelerate = QPixmap(":/avatars/_1xelerate.png");
this->avatars.alazymeme = QPixmap(":/avatars/alazymeme.png");
this->avatars.brian6932 = QPixmap(":/avatars/brian6932.png");
this->avatars.explooosion_code = QPixmap(":/avatars/explooosion_code.png");
this->avatars.fourtf = QPixmap(":/avatars/fourtf.png");
this->avatars.hicupalot = QPixmap(":/avatars/hicupalot.png");
this->avatars.iprodigy = QPixmap(":/avatars/iprodigy.png");
this->avatars.jaxkey = QPixmap(":/avatars/jaxkey.png");
this->avatars.kararty = QPixmap(":/avatars/kararty.png");
this->avatars.karlpolice = QPixmap(":/avatars/karlpolice.png");
this->avatars.mm2pl = QPixmap(":/avatars/mm2pl.png");
this->avatars.mohad12211 = QPixmap(":/avatars/mohad12211.png");
this->avatars.pajlada = QPixmap(":/avatars/pajlada.png");
this->avatars.slch = QPixmap(":/avatars/slch.png");
this->avatars.xheaveny = QPixmap(":/avatars/xheaveny.png");
this->avatars.zneix = QPixmap(":/avatars/zneix.png");
this->buttons.addSplit = QPixmap(":/buttons/addSplit.png");
this->buttons.addSplitDark = QPixmap(":/buttons/addSplitDark.png");
this->buttons.ban = QPixmap(":/buttons/ban.png");
this->buttons.banRed = QPixmap(":/buttons/banRed.png");
this->buttons.clearSearch = QPixmap(":/buttons/clearSearch.png");
this->buttons.copyDark = QPixmap(":/buttons/copyDark.png");
this->buttons.copyLight = QPixmap(":/buttons/copyLight.png");
this->buttons.menuDark = QPixmap(":/buttons/menuDark.png");
this->buttons.menuLight = QPixmap(":/buttons/menuLight.png");
this->buttons.mod = QPixmap(":/buttons/mod.png");
this->buttons.modModeDisabled = QPixmap(":/buttons/modModeDisabled.png");
this->buttons.modModeDisabled2 = QPixmap(":/buttons/modModeDisabled2.png");
this->buttons.modModeEnabled = QPixmap(":/buttons/modModeEnabled.png");
this->buttons.modModeEnabled2 = QPixmap(":/buttons/modModeEnabled2.png");
this->buttons.pinDisabledDark = QPixmap(":/buttons/pinDisabledDark.png");
this->buttons.pinDisabledLight = QPixmap(":/buttons/pinDisabledLight.png");
this->buttons.pinEnabled = QPixmap(":/buttons/pinEnabled.png");
this->buttons.replyDark = QPixmap(":/buttons/replyDark.png");
this->buttons.replyThreadDark = QPixmap(":/buttons/replyThreadDark.png");
this->buttons.search = QPixmap(":/buttons/search.png");
this->buttons.timeout = QPixmap(":/buttons/timeout.png");
this->buttons.trashCan = QPixmap(":/buttons/trashCan.png");
this->buttons.unban = QPixmap(":/buttons/unban.png");
this->buttons.unmod = QPixmap(":/buttons/unmod.png");
this->buttons.unvip = QPixmap(":/buttons/unvip.png");
this->buttons.update = QPixmap(":/buttons/update.png");
this->buttons.updateError = QPixmap(":/buttons/updateError.png");
this->buttons.viewersDark = QPixmap(":/buttons/viewersDark.png");
this->buttons.viewersLight = QPixmap(":/buttons/viewersLight.png");
this->buttons.vip = QPixmap(":/buttons/vip.png");
this->error = QPixmap(":/error.png");
this->icon = QPixmap(":/icon.png");
this->pajaDank = QPixmap(":/pajaDank.png");
this->scrolling.downScroll = QPixmap(":/scrolling/downScroll.png");
this->scrolling.neutralScroll = QPixmap(":/scrolling/neutralScroll.png");
this->scrolling.upScroll = QPixmap(":/scrolling/upScroll.png");
this->settings.aboutlogo = QPixmap(":/settings/aboutlogo.png");
this->split.down = QPixmap(":/split/down.png");
this->split.left = QPixmap(":/split/left.png");
this->split.move = QPixmap(":/split/move.png");
this->split.right = QPixmap(":/split/right.png");
this->split.up = QPixmap(":/split/up.png");
this->streamerMode = QPixmap(":/streamerMode.png");
this->twitch.admin = QPixmap(":/twitch/admin.png");
this->twitch.automod = QPixmap(":/twitch/automod.png");
this->twitch.broadcaster = QPixmap(":/twitch/broadcaster.png");
this->twitch.cheer1 = QPixmap(":/twitch/cheer1.png");
this->twitch.globalmod = QPixmap(":/twitch/globalmod.png");
this->twitch.moderator = QPixmap(":/twitch/moderator.png");
this->twitch.prime = QPixmap(":/twitch/prime.png");
this->twitch.staff = QPixmap(":/twitch/staff.png");
this->twitch.subscriber = QPixmap(":/twitch/subscriber.png");
this->twitch.turbo = QPixmap(":/twitch/turbo.png");
this->twitch.verified = QPixmap(":/twitch/verified.png");
this->twitch.vip = QPixmap(":/twitch/vip.png");
}
} // namespace chatterino

View file

@ -1,96 +0,0 @@
#include <QPixmap>
#include "common/Singleton.hpp"
namespace chatterino {
class Resources2 : public Singleton
{
public:
Resources2();
struct {
QPixmap _1xelerate;
QPixmap alazymeme;
QPixmap brian6932;
QPixmap explooosion_code;
QPixmap fourtf;
QPixmap hicupalot;
QPixmap iprodigy;
QPixmap jaxkey;
QPixmap kararty;
QPixmap karlpolice;
QPixmap mm2pl;
QPixmap mohad12211;
QPixmap pajlada;
QPixmap slch;
QPixmap xheaveny;
QPixmap zneix;
} avatars;
struct {
QPixmap addSplit;
QPixmap addSplitDark;
QPixmap ban;
QPixmap banRed;
QPixmap clearSearch;
QPixmap copyDark;
QPixmap copyLight;
QPixmap menuDark;
QPixmap menuLight;
QPixmap mod;
QPixmap modModeDisabled;
QPixmap modModeDisabled2;
QPixmap modModeEnabled;
QPixmap modModeEnabled2;
QPixmap pinDisabledDark;
QPixmap pinDisabledLight;
QPixmap pinEnabled;
QPixmap replyDark;
QPixmap replyThreadDark;
QPixmap search;
QPixmap timeout;
QPixmap trashCan;
QPixmap unban;
QPixmap unmod;
QPixmap unvip;
QPixmap update;
QPixmap updateError;
QPixmap viewersDark;
QPixmap viewersLight;
QPixmap vip;
} buttons;
QPixmap error;
QPixmap icon;
QPixmap pajaDank;
struct {
QPixmap downScroll;
QPixmap neutralScroll;
QPixmap upScroll;
} scrolling;
struct {
QPixmap aboutlogo;
} settings;
struct {
QPixmap down;
QPixmap left;
QPixmap move;
QPixmap right;
QPixmap up;
} split;
QPixmap streamerMode;
struct {
QPixmap admin;
QPixmap automod;
QPixmap broadcaster;
QPixmap cheer1;
QPixmap globalmod;
QPixmap moderator;
QPixmap prime;
QPixmap staff;
QPixmap subscriber;
QPixmap turbo;
QPixmap verified;
QPixmap vip;
} twitch;
};
} // namespace chatterino

View file

@ -1,6 +1,6 @@
#pragma once
#include "autogenerated/ResourcesAutogen.hpp"
#include "ResourcesAutogen.hpp"
namespace chatterino {