Skip to content
Merged

Dev #373

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 76 additions & 50 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"installDir": "${sourceDir}/install/${presetName}"
"installDir": "${sourceDir}/install/${presetName}",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_CXX_FLAGS": "-Wall -Wno-unused-private-field -ftemplate-backtrace-limit=0 -fvisibility=hidden -fvisibility-inlines-hidden"
}
},
{
"name": "linux-debug",
"inherits": "base",
"displayName": "Linux Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-Wall -ftemplate-backtrace-limit=0 -Og"
"CMAKE_CXX_FLAGS_DEBUG": "-ggdb3 -O0 -fno-omit-frame-pointer -fno-inline -fno-optimize-sibling-calls"
},
"condition": {
"type": "equals",
Expand All @@ -28,7 +32,9 @@
"displayName": "Linux Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_FLAGS": "-Wall -ftemplate-backtrace-limit=0 -O3 -DNDEBUG"
"CMAKE_CXX_FLAGS_RELEASE": "-O3 -DNDEBUG",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON",
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "-Wl,--exclude-libs,ALL -Wl,--strip-all"
},
"condition": {
"type": "equals",
Expand All @@ -42,7 +48,7 @@
"displayName": "macOS Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-Wall -Wno-unused-private-field -ftemplate-backtrace-limit=0 -Og"
"CMAKE_CXX_FLAGS_DEBUG": "-g3 -Og -fno-omit-frame-pointer -fno-inline -gsplit-dwarf"
},
"condition": {
"type": "equals",
Expand All @@ -56,7 +62,9 @@
"displayName": "macOS Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_FLAGS": "-Wall -Wno-unused-private-field -ftemplate-backtrace-limit=0 -O3 -DNDEBUG"
"CMAKE_CXX_FLAGS_RELEASE": "-O3 -DNDEBUG",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON",
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "-Wl,-dead_strip -Wl,-x"
},
"condition": {
"type": "equals",
Expand All @@ -65,99 +73,117 @@
}
},
{
"name": "windows",
"hidden": true,
"name": "mingw-debug",
"inherits": "base",
"displayName": "Mingw x64 Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER": "g++.exe",
"CMAKE_CXX_FLAGS": "-Wall -Wno-unused-private-field -ftemplate-backtrace-limit=0 -Wa,-mbig-obj -fvisibility=hidden -fvisibility-inlines-hidden",
"CMAKE_CXX_FLAGS_DEBUG": "-g3 -Og -fno-omit-frame-pointer -fno-inline -gsplit-dwarf"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "mingw-release",
"inherits": "base",
"displayName": "Mingw x64 Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_COMPILER": "g++.exe",
"CMAKE_CXX_FLAGS": "-Wall -Wno-unused-private-field -ftemplate-backtrace-limit=0 -Wa,-mbig-obj -fvisibility=hidden -fvisibility-inlines-hidden",
"CMAKE_CXX_FLAGS_RELEASE": "-O3 -DNDEBUG",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON",
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "-Wl,--exclude-all-symbols"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "windows-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"installDir": "${sourceDir}/install/${presetName}",
"toolchainFile": "$env{VCPKG_ROOT}\\scripts\\buildsystems\\vcpkg.cmake",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE"
},
"toolchainFile": "$env{VCPKG_ROOT}\\scripts\\buildsystems\\vcpkg.cmake"
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "msvc-debug",
"inherits": "windows",
"inherits": "windows-base",
"displayName": "MSVC x64 Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE",
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "EditAndContinue"
"CMAKE_CXX_FLAGS_DEBUG": "/Od",
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "ProgramDatabase"
}
},
{
"name": "msvc-release",
"inherits": "windows",
"inherits": "windows-base",
"displayName": "MSVC x64 Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /O2 /DNDEBUG /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE",
"CMAKE_CXX_FLAGS_RELEASE": "/O2 /DNDEBUG",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON",
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "ProgramDatabase"
}
},

{
"name": "clang-windows-debug",
"inherits": "windows",
"inherits": "windows-base",
"displayName": "Clang Windows Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER": "clang-cl.exe",
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /clang:-Wno-unused-private-field"
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /clang:-Wno-unused-private-field",
"CMAKE_CXX_FLAGS_DEBUG": "/Od /Zi"
}
},
{
"name": "clang-windows-release",
"inherits": "windows",
"inherits": "windows-base",
"displayName": "Clang Windows Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_COMPILER": "clang-cl.exe",
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /O2 /DNDEBUG /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /clang:-Wno-unused-private-field"
}
},
{
"name": "mingw-debug",
"inherits": "base",
"displayName": "Mingw x64 Debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER": "g++.exe",
"CMAKE_CXX_FLAGS": "-Wall -ftemplate-backtrace-limit=0 -Wa,-mbig-obj -Og"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "mingw-release",
"inherits": "base",
"displayName": "Mingw x64 Release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_CXX_COMPILER": "g++.exe",
"CMAKE_CXX_FLAGS": "-Wall -ftemplate-backtrace-limit=0 -Wa,-mbig-obj -O3 -DNDEBUG"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
"CMAKE_CXX_FLAGS": "/EHs /W4 /bigobj /utf-8 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /clang:-Wno-unused-private-field",
"CMAKE_CXX_FLAGS_RELEASE": "/O2 /DNDEBUG",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON"
}
}
],

"buildPresets": [
{
"name": "linux-debug",
"displayName": "Build Linux Debug",
"configurePreset": "linux-debug"
"configurePreset": "linux-debug",
"jobs": 6
},
{
"name": "linux-release",
"displayName": "Build Linux Release",
"configurePreset": "linux-release"
"configurePreset": "linux-release",
"jobs": 6
},
{
"name": "macos-debug",
Expand Down Expand Up @@ -200,4 +226,4 @@
"configurePreset": "mingw-release"
}
]
}
}
50 changes: 50 additions & 0 deletions docs/packaging/build_settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,53 @@ This instructs the linker to ignore all unresolved symbols during linking. The s
### Windows

On Windows, no special linker flags are required. The extension links directly against the Ruby library (e.g., `x64-vcruntime140-ruby320.lib`), which provides the necessary symbols at link time.

## Link Time Optimization (LTO)

Link Time Optimization is **highly recommended** for Rice extensions, especially for release builds. Rice makes extensive use of C++ templates, which can result in significant code duplication across translation units. LTO allows the linker to deduplicate template instantiations and perform whole-program optimizations.

### Why LTO Matters for Rice

Rice's template-heavy design means that each `.cpp` file that uses Rice generates its own copies of template instantiations. Without LTO, these duplicate instantiations remain in the final binary, dramatically increasing its size. LTO enables the linker to:

- Deduplicate identical template instantiations across object files
- Inline functions across translation unit boundaries
- Remove dead code more effectively

### Build Size Comparison

The following table shows the impact of LTO on a real-world Rice extension (opencv-ruby bindings):

| Platform | Debug | Release (with LTO) | Size Reduction |
|----------|--------|--------------------|----------------|
| MSVC | 140 MB | 70 MB | 50% |
| macOS | 324 MB | 164 MB | 50% |
| MinGW | 1.4 GB | 200 MB | 86% |

As shown, LTO provides substantial size reductions across all platforms, with MinGW benefiting the most dramatically.

Rice's `CMakePreset.json` automatically enables LTO by setting `CMAKE_INTERPROCEDURAL_OPTIMIZATION` to `ON`.

If you are using `extconf.rb (Mkmf)` then:

```ruby
$CXXFLAGS << " -flto"
$LDFLAGS << " -flto"
```

For MSVC:

```ruby
$CXXFLAGS << " /GL"
$LDFLAGS << " /LTCG"
```

### Debug Symbol Splitting (GCC/Clang)

For debug builds with GCC or Clang, consider using `-gsplit-dwarf` to separate debug information into `.dwo` files. This keeps the main binary smaller while preserving full debug capability:

```cmake
set(CMAKE_CXX_FLAGS_DEBUG "-g -gsplit-dwarf")
```

This is particularly useful for g++ where debug builds can exceed 1 GB without it.