Browse Source

CMake: gc-sections + no-rtti/exceptions options

Turns out gc-sections helps significantly even with LTO (-84 KiB for the
MinSizeRel rg99 build).

Also adds options for disabling RTTI and exceptions.
pull/4769/head
Gleb Mazovetskiy 4 years ago
parent
commit
39afeaf8b1
  1. 33
      CMakeLists.txt
  2. 45
      test/animationinfo_test.cpp

33
CMakeLists.txt

@ -64,6 +64,9 @@ option(DEVILUTIONX_RESAMPLER_SDL "Build with SDL resampler" ON)
option(DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT "Whether to use a lookup table for transparency blending with black. This improves performance of blending transparent black overlays, such as quest dialog background, at the cost of 128 KiB of RAM." ON) option(DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT "Whether to use a lookup table for transparency blending with black. This improves performance of blending transparent black overlays, such as quest dialog background, at the cost of 128 KiB of RAM." ON)
cmake_dependent_option(DEVILUTIONX_DISABLE_RTTI "Disable RTTI" ON "NONET" OFF)
cmake_dependent_option(DEVILUTIONX_DISABLE_EXCEPTIONS "Disable exceptions" ON "NONET" OFF)
if(TSAN) if(TSAN)
set(ASAN OFF) set(ASAN OFF)
endif() endif()
@ -156,6 +159,8 @@ endif()
if(NONET) if(NONET)
set(DISABLE_TCP ON) set(DISABLE_TCP ON)
set(DISABLE_ZERO_TIER ON) set(DISABLE_ZERO_TIER ON)
set(DISABLE_RTTI ON)
set(DISABLE_EXCEPTIONS ON)
set(PACKET_ENCRYPTION OFF) set(PACKET_ENCRYPTION OFF)
endif() endif()
@ -177,6 +182,34 @@ if(CCACHE_PROGRAM)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif() endif()
if(DEVILUTIONX_DISABLE_RTTI)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
elseif(MSVC)
string(REGEX REPLACE "/GR" "/GR-" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
endif()
if(DEVILUTIONX_DISABLE_EXCEPTIONS)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
elseif(MSVC)
string(REGEX REPLACE "/EHsc" "/EHs-c-" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endif()
endif()
# Remove unused symbols in non-debug mode.
# This is useful even with LTO (-84 KiB with MinSizeRel).
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# For some reason, adding to CMAKE_CXX_FLAGS results in a slightly smaller
# binary than using `add_compile/link_options`
set(_extra_flags "-ffunction-sections -fdata-sections -Wl,--gc-sections")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${_extra_flags}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${_extra_flags}")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${_extra_flags}")
endif()
# Not a genexp because CMake doesn't support it # Not a genexp because CMake doesn't support it
# https://gitlab.kitware.com/cmake/cmake/-/issues/20546 # https://gitlab.kitware.com/cmake/cmake/-/issues/20546
if(NOT DISABLE_LTO) if(NOT DISABLE_LTO)

45
test/animationinfo_test.cpp

@ -5,17 +5,24 @@
using namespace devilution; using namespace devilution;
enum class TestDataType {
SetNewAnimation,
GameTick,
Rendering
};
/** /**
* @brief Represents a Action in the game_logic or rendering. * @brief Represents a Action in the game_logic or rendering.
*/ */
struct TestData { struct TestData {
virtual ~TestData() = default; virtual ~TestData() = default;
virtual TestDataType type() const = 0;
}; };
/** /**
* @brief Represents a call to SetNewAnimation * @brief Represents a call to SetNewAnimation
*/ */
struct SetNewAnimationData : TestData { struct SetNewAnimationData : public TestData {
SetNewAnimationData(int numberOfFrames, int delayLen, AnimationDistributionFlags params = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0) SetNewAnimationData(int numberOfFrames, int delayLen, AnimationDistributionFlags params = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0)
{ {
_NumberOfFrames = numberOfFrames; _NumberOfFrames = numberOfFrames;
@ -24,6 +31,12 @@ struct SetNewAnimationData : TestData {
_NumSkippedFrames = numSkippedFrames; _NumSkippedFrames = numSkippedFrames;
_DistributeFramesBeforeFrame = distributeFramesBeforeFrame; _DistributeFramesBeforeFrame = distributeFramesBeforeFrame;
} }
TestDataType type() const override
{
return TestDataType::SetNewAnimation;
}
int _NumberOfFrames; int _NumberOfFrames;
int _DelayLen; int _DelayLen;
AnimationDistributionFlags _Params; AnimationDistributionFlags _Params;
@ -42,6 +55,11 @@ struct GameTickData : TestData {
_ExpectedAnimationFrame = expectedAnimationFrame; _ExpectedAnimationFrame = expectedAnimationFrame;
_ExpectedAnimationCnt = expectedAnimationCnt; _ExpectedAnimationCnt = expectedAnimationCnt;
} }
TestDataType type() const override
{
return TestDataType::GameTick;
}
}; };
/** /**
@ -59,6 +77,11 @@ struct RenderingData : TestData {
this->_fProgressToNextGameTick = fProgressToNextGameTick; this->_fProgressToNextGameTick = fProgressToNextGameTick;
this->_ExpectedRenderingFrame = expectedRenderingFrame; this->_ExpectedRenderingFrame = expectedRenderingFrame;
} }
TestDataType type() const override
{
return TestDataType::Rendering;
}
}; };
/** /**
@ -73,21 +96,20 @@ void RunAnimationTest(const std::vector<TestData *> &vecTestData)
int currentGameTick = 0; int currentGameTick = 0;
for (TestData *x : vecTestData) { for (TestData *x : vecTestData) {
auto setNewAnimationData = dynamic_cast<SetNewAnimationData *>(x); switch (x->type()) {
if (setNewAnimationData != nullptr) { case TestDataType::SetNewAnimation: {
auto setNewAnimationData = static_cast<SetNewAnimationData *>(x);
animInfo.SetNewAnimation(std::nullopt, setNewAnimationData->_NumberOfFrames, setNewAnimationData->_DelayLen, setNewAnimationData->_Params, setNewAnimationData->_NumSkippedFrames, setNewAnimationData->_DistributeFramesBeforeFrame); animInfo.SetNewAnimation(std::nullopt, setNewAnimationData->_NumberOfFrames, setNewAnimationData->_DelayLen, setNewAnimationData->_Params, setNewAnimationData->_NumSkippedFrames, setNewAnimationData->_DistributeFramesBeforeFrame);
} } break;
case TestDataType::GameTick: {
auto gameTickData = dynamic_cast<GameTickData *>(x); auto gameTickData = static_cast<GameTickData *>(x);
if (gameTickData != nullptr) {
currentGameTick += 1; currentGameTick += 1;
animInfo.ProcessAnimation(); animInfo.ProcessAnimation();
EXPECT_EQ(animInfo.CurrentFrame, gameTickData->_ExpectedAnimationFrame); EXPECT_EQ(animInfo.CurrentFrame, gameTickData->_ExpectedAnimationFrame);
EXPECT_EQ(animInfo.TickCounterOfCurrentFrame, gameTickData->_ExpectedAnimationCnt); EXPECT_EQ(animInfo.TickCounterOfCurrentFrame, gameTickData->_ExpectedAnimationCnt);
} } break;
case TestDataType::Rendering: {
auto renderingData = dynamic_cast<RenderingData *>(x); auto renderingData = static_cast<RenderingData *>(x);
if (renderingData != nullptr) {
gfProgressToNextGameTick = renderingData->_fProgressToNextGameTick; gfProgressToNextGameTick = renderingData->_fProgressToNextGameTick;
EXPECT_EQ(animInfo.GetFrameToUseForRendering(), renderingData->_ExpectedRenderingFrame) EXPECT_EQ(animInfo.GetFrameToUseForRendering(), renderingData->_ExpectedRenderingFrame)
<< std::fixed << std::setprecision(2) << std::fixed << std::setprecision(2)
@ -95,6 +117,7 @@ void RunAnimationTest(const std::vector<TestData *> &vecTestData)
<< " CurrentFrame: " << animInfo.CurrentFrame << " CurrentFrame: " << animInfo.CurrentFrame
<< " DelayCounter: " << animInfo.TickCounterOfCurrentFrame << " DelayCounter: " << animInfo.TickCounterOfCurrentFrame
<< " GameTick: " << currentGameTick; << " GameTick: " << currentGameTick;
} break;
} }
} }
for (TestData *x : vecTestData) { for (TestData *x : vecTestData) {

Loading…
Cancel
Save