Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimized CMake Build Process #5657

Open
wants to merge 44 commits into
base: master
Choose a base branch
from
Open

Optimized CMake Build Process #5657

wants to merge 44 commits into from

Conversation

AverageNerdz
Copy link
Contributor

Brief Description of What This PR Does

This PR refines the CMake configuration for our GDExtension, optimizing build performance across platforms. It addresses specific compilation issues on Windows, bringing improvements in speed and reliability it should mantain robust performances on Linux.

Related Issues

Progress Checklist

Note: before starting this checklist the PR should be marked as non-draft.

  • PR author has checked that this PR works as intended and doesn't
    break existing features:
    https://wiki.revolutionarygamesstudio.com/wiki/Testing_Checklist
    (this is important as to not waste the time of Thrive team
    members reviewing this PR)
  • Initial code review passed (this and further items should not be checked by the PR author)
  • Functionality is confirmed working by another person (see above checklist link)
  • Final code review is passed and code conforms to the
    styleguide.

Before merging all CI jobs should finish on this PR without errors, if
there are automatically detected style issues they should be fixed by
the PR author. Merging must follow our
styleguide.

@AverageNerdz AverageNerdz changed the title Optimize CMake Build Process Optimized CMake Build Process Nov 5, 2024
@hhyyrylainen hhyyrylainen added this to the Release 0.8.0 milestone Nov 5, 2024
add_library(thrive_extension SHARED)

# Collect all source files recursively
file(GLOB_RECURSE EXTENSION_SOURCES
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I really dislike GLOB because it doesn't automatically re-run cmake when new files are added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you have another way to do it recursively i'm all ears pal, i added GLOB because it seemed the easier to implement and the one that was pretty easy on the CPUs plus it allows anyone to add anything they want in the folder and just start working on it without editing addittional code other than the interops

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only good way is to manually list each file. That way cmake is forced to re-run when a new file is defined and everything works fine. With GLOB you have to manually re-run cmake whenever you add a file so it is a major pain and you cannot easily see what all gets compiled in. So I'm totally against the use of GLOB at all for defining cmake files to compile.

set(DOUBLE_PRECISION ON)

if(THRIVE_AVX)
set(USE_AVX ON)
set(USE_AVX2 ON)
set(USE_AVX ON)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you re-indent all the files using the existing formatting rules (two spaces per indentation level)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done :]

@@ -0,0 +1,219 @@
# Windows-specific godot-cpp configuration (temporary fix)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to not accept a temporary fix into the main repo as it'll then just be here forever...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should have probably dvelved into more an yeah that temporary fix is a stretch but i found out that the main culprit is the cmakelist from the godot-cpp folder, and i don't know if they may release a better cmake which is also suitable for windows uses in the future that is why i put this in the comment

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be really annoying to maintain as each specific godot-cpp update might break our build, and then I wouldn't notice it until someone tries using MSVC the next time and finds it broken.

If at all possible it would be better to try to modify any variables this script uses or modify the resulting targets it exports, so that any forceful customizations could still be kept outside this file (so that we can use the upstream file as-is so that we don't have to forever maintain our separate version).

Though one more alternative would be to open an issue / talk to the godot-cpp repo people and ask if they would accept changes to their file that make it MSVC compatible.

CMakeLists.txt Outdated
endfunction()

# Source files print function
function(print_source_files target)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this like debugging code? I'd remove this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this helps printing the files that are being compiled in the unity instead of just having the unity being compiled it is really important for the compile imho

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long helper code like this should be moved to a separate file (probably fine to have in the scripts folder like Scripts/CMakeHelperMethods.cmake) for cleaning things up in the main files.

cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.13)

set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;Distribution" CACHE STRING "" FORCE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should copy the comment from where you moved this code (the reason why the non-standard distribution type is here).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, i added something to it too :]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't see the comment text about Jolt requiring the Distribution type...

CMakeLists.txt Outdated
cmake_minimum_required(VERSION 3.13)

set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;Distribution" CACHE STRING "" FORCE)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be just removed as this is default behaviour and I think it is unnecessarily complication to be at the top of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done :]

CMakeLists.txt Outdated
# Options
# Building either the faster variant with AVX or without for older CPU support

# CPU core optimization
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this stuff is super long, so I think it should be put into a separate file like Scripts/CMakeTargetConfiguration.cmake and included here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean keeping all the compile as is for Linux and just use .cmakes for windows in the implementation you suggested?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I mean putting all of the long code you plan to keep into a separate file so that reading the main cmake file doesn't require you to read through a ton of specific details before getting to the options etc. actually important parts of the file.

CMakeLists.txt Outdated
# Windows detection function
function(configure_windows_target target)
if(NOT WIN32 OR NOT MSVC)
return()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should really be an error if this is called on a different platform.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you tested it? if you mean the cpu part i would be really glad to know how it is done in Linux i tried to make something that works on both sides and doesn't impact the compile speed but as i don't have those platforms in hand it is difficult to make something without any feedback

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is literally just an early return that seems to not do anything. So if someone accidentally calls this method, then they silently don't get any feedback that nothing happened. That's very unintuitive which is why error conditions should print error messages.

CMakeLists.txt Outdated
/wd4273 # Inconsistent dll linkage
/wd4141 # 'inline' used more than once
# Other warning disables
/wd4068 # Unknown pragma
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the thrive code doesn't trigger any of these warnings it would be, much much better to not include these. In general you have made a ton of changes here, whereas I'd prefer to only have the things that are truly, truly needed and not just list everything just in case at it makes it super hard to see what actually is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the problem isn't in the thrive code pal, the problem is in the thousands of files from the godot library which tended to give a lot of warnings and sometimes errors making the compile task quite tedious

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then make it so that the godot library gets added these as public compile flags, that's the modern way to handle this in cmake. I see quite a lot of cmake usage where the old way to do things is used instead of the modern and more clean cmake way.

CMakeLists.txt Outdated
-Wextra
-Wpedantic
-Wno-unknown-pragmas
-fPIC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed because we use the POSITION_INDEPENDENT_CODE from Cmake which ensures it is correctly set for all compilers cmake supports.

CMakeLists.txt Outdated
configure_linux_target(${target})
endif()

target_compile_definitions(${target} PRIVATE
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JPH stuff should all be configured in the third party cmakelists folder where that target is imported from, keeps stuff much cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean like putting all this code just in the third party?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in the third party cmakelists, I've already gathered quite a lot of JPH config there so having it all in one place just makes way too much sense (and when the next time JPH build breaks I'll be able to find all of the stuff related to it easily instead of having to hunt around for it).

CMakeLists.txt Outdated
set(THRIVE_ARCH "x64")
else()
set(THRIVE_OS "linux")
execute_process(COMMAND uname -m OUTPUT_VARIABLE THRIVE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you add support for compiling as 32-bit? If you didn't I think this line is totally useless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i did pal

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you review the constants that need tweaking for 32-bit? I'm pretty sure I put in TODOs in the precompiled header / defines file that some struct sizes have to be different for 32-bit (and there's that pointer stuffing but I guess that should also work thanks to the alignment). Also I'm not fully sure but I think the C# also needs changes as the struct sizes are different in 32-bit mode. So I think there's at least some bugs with the 32-bit mode.


function(configure_linux_target target)
if(WIN32)
return()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing an error

set_target_properties(${target} PROPERTIES
POSITION_INDEPENDENT_CODE ON
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does inlines have to be forced hidden? This is a non-default option, right? So this might surprise me in the future and cause me to have to debug linker errors for hours if I forget that this flag was snuck in here.

endif()
endfunction()

# Function to configure godot-cpp target without modifying its CMakeLists
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stuff is just needed for the third party stuff (right?) so I would totally like to see this only be in the third_party folder cmakelists file.

target_compile_options(thrive_extension PRIVATE /WX)
endif()
# Print files and configure build
print_source_files(thrive_extension)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think it should be a special option to print the source files and not do it by default.


# TODO debug symbols in release for MSVC (and Distribution mode)
# Common compile definitions for both OS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any comments etc. referring to Thrive being just for TWO OSes is not going to be good because in the not too distant future all of this stuff also needs to be on mac. For this reason, because I think I have to do it, I don't want this huge set of cmake changes that aren't what I'm used to.

THRIVE_NATIVE_BUILD
_HAS_EXCEPTIONS=1
JPH_PROFILE_ENABLED=0
JPH_DEBUG_RENDERER=0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this here? When compiling in debug mode this has to be defined to one or everything will break (well at least for the thrive native library, but it would be super weird to not have consistent options).

set(USE_LZCNT OFF)
set(USE_TZCNT OFF)
set(DOUBLE_PRECISION OFF)
message(WARNING "32-bit build detected, using single precision")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested that Jolt doesn't allow double precision in 32-bit mode? This seems like an unnecessary difference to me.

AverageNerdz and others added 10 commits November 7, 2024 13:42
Co-authored-by: Henri Hyyryläinen <[email protected]>
- Removed hardcoded version that wouldn't be updated
- Reorganized options to top for better visibility
- Fixed installation path structure
- Proper minimum CMake version handling
- Platform plain configuration
- Improved debug/release configuration
- Added proper dependency handling
- Removed the typo in the project function
- Centralized external library handling
- Fixed precision settings
- Made proper runtime configuration
- Build performance optimization
- Platform specific handling
- Installation organization
- Far better warning management
- Platform independent configurations
- Fixed linking issues
- Debug/Release mode handling
- Proper build outputs
- Installation organization
- Dependency management
- Cross-platform support
- Proper error messages
- Clear configuration structure
- Build performance optimization
- Debug support improvement
- Maintainable organization
- Future platform support
- Old CPU support maintenance
- Platform specific optimizations
- Proper error handling
- Installation organization
- Build output management
- Performance configurations
- Debug symbol handling
@AverageNerdz
Copy link
Contributor Author

I tried to work from the advices you gave me and reworked the environment a little bit, any feedback is appreciated pal :]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

2 participants