From 6d33c0ea03e804fb0034b9ecd0121bc301a18910 Mon Sep 17 00:00:00 2001 From: nullsystem <15316579+nullsystem@users.noreply.github.com> Date: Wed, 5 Aug 2026 18:04:47 +0100 Subject: [PATCH 1/3] Add toggles for cmake unity build One for client/server and one for vgui2/tier1/mathlib as may want to turn it off only for working on just client/server library side. Also fixup compile/linker errors since the changes and add NEO_UNITY defines to fixup for those ifdef changes. Add info in README. --- README.md | 6 ++++++ src/CMakeLists.txt | 14 ++++++++++++++ src/game/client/CMakeLists.txt | 3 ++- src/game/client/neo/c_neo_killer_damage_infos.cpp | 2 ++ src/game/client/neo/ui/neo_hud_killer_info.cpp | 1 + src/game/client/viewpostprocess.cpp | 2 +- src/game/server/CMakeLists.txt | 3 ++- .../NextBot/Player/NextBotPlayerLocomotion.cpp | 1 + .../neo/bot/behavior/neo_bot_command_follow.cpp | 1 + .../server/neo/bot/behavior/neo_bot_ctg_enemy.h | 1 + src/mathlib/CMakeLists.txt | 5 +++-- src/tier1/CMakeLists.txt | 8 ++++++-- src/vgui2/vgui_controls/CMakeLists.txt | 7 ++++++- src/vgui2/vgui_controls/FileOpenDialog.cpp | 10 +++++----- src/vgui2/vgui_controls/KeyBindingHelpDialog.cpp | 4 ++-- src/vgui2/vgui_controls/KeyBoardEditorDialog.cpp | 6 +++--- src/vgui2/vgui_controls/ListPanel.cpp | 4 ++-- src/vgui2/vgui_controls/ListViewPanel.cpp | 4 ++-- src/vgui2/vgui_controls/Panel.cpp | 4 ++-- src/vgui2/vgui_controls/PerforceFileList.cpp | 6 +++--- src/vgui2/vgui_controls/PropertyDialog.cpp | 2 +- src/vgui2/vgui_controls/ToolWindow.cpp | 2 +- src/vgui2/vgui_controls/TreeView.cpp | 4 ++-- 23 files changed, 69 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 8a201afe1..ac7d87a14 100644 --- a/README.md +++ b/README.md @@ -320,6 +320,12 @@ shaders\fxc\sdk_screenspaceeffect_vs20.vcs 10.41 ``` +## Unity build + +By default, this project uses Unity Build to speed up compilation times. However, if you need to disable it for development +reasons, set the CMake options `NEO_UNITY_BUILD_CLIENT_SERVER` or `NEO_UNITY_BUILD_OTHERS` to `OFF`. This will disable +Unity Build for client/server libraries and vgui2/tier1/mathlib libraries, respectively. + ## Credits * [NeotokyoRevamp/neo](https://github.com/NeotokyoRevamp/neo) - Original fork source * [ValveSoftware/source-sdk-2013](https://github.com/ValveSoftware/source-sdk-2013) - Source SDK 2013 (2025 TF2 SDK Update) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd36b5686..5bda91539 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,8 @@ option(NEO_ENABLE_CPACK "Enable CPack" OFF) option(NEO_USE_MEM_DEBUG "Enable USE_MEM_DEBUG defines" OFF) option(NEO_GENERATE_GAMEDATA "Generate SourceMod gamedata" ${NEO_DEDICATED}) option(NEO_BUILD_LAUNCHER "Build the Steam mod launcher" ON) +option(NEO_UNITY_BUILD_CLIENT_SERVER "Enable unity build for client/server libraries" ON) +option(NEO_UNITY_BUILD_OTHERS "Enable unity build for vgui2, tier1, and mathlib libraries" ON) set(NEO_MOD_APPID "3172910" CACHE STRING "Steam appid for the mod launcher's steam_appid.txt") message(STATUS "Treat compile warnings as errors: ${CMAKE_COMPILE_WARNING_AS_ERROR}") @@ -80,8 +82,20 @@ message(STATUS "Use separate build info on Linux: ${NEO_USE_SEPARATE_BUILD_INFO} message(STATUS "Enable CPack: ${NEO_ENABLE_CPACK}") message(STATUS "Build the Steam mod launcher: ${NEO_BUILD_LAUNCHER}") message(STATUS "Mod launcher appid override: ${NEO_MOD_APPID}") +message(STATUS "Enable unity build for client/server libraries (NEO_UNITY_BUILD_CLIENT_SERVER): ${NEO_UNITY_BUILD_CLIENT_SERVER}") +message(STATUS "Enable unity build for vgui2, tier1, and mathlib libraries (NEO_UNITY_BUILD_OTHERS): ${NEO_UNITY_BUILD_OTHERS}") message("") +set(UNITY_BUILD_DEF_OTHERS) +if (NEO_UNITY_BUILD_OTHERS) + set(UNITY_BUILD_DEF_OTHERS NEO_UNITY) +endif () + +set(UNITY_BUILD_DEF_CLIENT_SERVER) +if (NEO_UNITY_BUILD_CLIENT_SERVER) + set(UNITY_BUILD_DEF_CLIENT_SERVER NEO_UNITY) +endif () + if(NEO_COPY_LIBRARIES) file(MAKE_DIRECTORY "${NEO_OUTPUT_LIBRARY_PATH}") endif() diff --git a/src/game/client/CMakeLists.txt b/src/game/client/CMakeLists.txt index 9273ef749..7fbb698e4 100644 --- a/src/game/client/CMakeLists.txt +++ b/src/game/client/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(client SHARED) set_target_properties(client PROPERTIES PREFIX "" - UNITY_BUILD ON + UNITY_BUILD ${NEO_UNITY_BUILD_CLIENT_SERVER} UNITY_BUILD_MODE GROUP ) @@ -49,6 +49,7 @@ target_compile_definitions(client VECTOR VERSION_SAFE_STEAM_API_INTERFACES NEXT_BOT + ${UNITY_BUILD_DEF_CLIENT_SERVER} ) target_link_libraries(client diff --git a/src/game/client/neo/c_neo_killer_damage_infos.cpp b/src/game/client/neo/c_neo_killer_damage_infos.cpp index a8c183ce8..a60b5c26b 100644 --- a/src/game/client/neo/c_neo_killer_damage_infos.cpp +++ b/src/game/client/neo/c_neo_killer_damage_infos.cpp @@ -2,6 +2,8 @@ #include #include "strtools.h" +#include "vgui/ILocalize.h" +#include "tier3/tier3.h" #include "c_neo_player.h" #include "neo_gamerules.h" diff --git a/src/game/client/neo/ui/neo_hud_killer_info.cpp b/src/game/client/neo/ui/neo_hud_killer_info.cpp index 1da827597..953e1032c 100644 --- a/src/game/client/neo/ui/neo_hud_killer_info.cpp +++ b/src/game/client/neo/ui/neo_hud_killer_info.cpp @@ -7,6 +7,7 @@ #include "c_neo_player.h" #include "neo_gamerules.h" #include "vgui/ILocalize.h" +#include "ui/neo_theme.h" #include "inputsystem/iinputsystem.h" #include "IGameUIFuncs.h" #include "igamesystem.h" diff --git a/src/game/client/viewpostprocess.cpp b/src/game/client/viewpostprocess.cpp index c6bcb2713..d0793cabd 100644 --- a/src/game/client/viewpostprocess.cpp +++ b/src/game/client/viewpostprocess.cpp @@ -87,7 +87,7 @@ ConVar mat_tonemap_algorithm( "mat_tonemap_algorithm", "1", FCVAR_CHEAT, "0 = Or ConVar mat_tonemap_percent_target( "mat_tonemap_percent_target", "60.0", FCVAR_CHEAT ); ConVar mat_tonemap_percent_bright_pixels( "mat_tonemap_percent_bright_pixels", "2.0", FCVAR_CHEAT ); ConVar mat_tonemap_min_avglum( "mat_tonemap_min_avglum", "3.0", FCVAR_CHEAT ); -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build extern ConVar mat_fullbright; #else ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); diff --git a/src/game/server/CMakeLists.txt b/src/game/server/CMakeLists.txt index da026598c..eb9a89088 100644 --- a/src/game/server/CMakeLists.txt +++ b/src/game/server/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(server SHARED) set_target_properties(server PROPERTIES PREFIX "" - UNITY_BUILD ON + UNITY_BUILD ${NEO_UNITY_BUILD_CLIENT_SERVER} UNITY_BUILD_MODE GROUP ) @@ -65,6 +65,7 @@ target_compile_definitions(server sprintf=use_Q_snprintf_instead_of_sprintf strncpy=use_Q_strncpy_instead NEXT_BOT + ${UNITY_BUILD_DEF_CLIENT_SERVER} ) target_link_libraries(server diff --git a/src/game/server/NextBot/Player/NextBotPlayerLocomotion.cpp b/src/game/server/NextBot/Player/NextBotPlayerLocomotion.cpp index d3f71e934..012a7afdb 100644 --- a/src/game/server/NextBot/Player/NextBotPlayerLocomotion.cpp +++ b/src/game/server/NextBot/Player/NextBotPlayerLocomotion.cpp @@ -10,6 +10,7 @@ #include "NextBotUtil.h" #include "NextBotPlayer.h" #include "NextBotPlayerLocomotion.h" +#include "bot/neo_bot.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" diff --git a/src/game/server/neo/bot/behavior/neo_bot_command_follow.cpp b/src/game/server/neo/bot/behavior/neo_bot_command_follow.cpp index 02bdd2a77..77ff22516 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_command_follow.cpp +++ b/src/game/server/neo/bot/behavior/neo_bot_command_follow.cpp @@ -3,6 +3,7 @@ #include "bot/neo_bot.h" #include "bot/behavior/neo_bot_command_follow.h" #include "bot/behavior/neo_bot_throw_weapon_at_player.h" +#include "bot/behavior/neo_bot_attack.h" #include "nav_mesh.h" // memdbgon must be the last include file in a .cpp file!!! diff --git a/src/game/server/neo/bot/behavior/neo_bot_ctg_enemy.h b/src/game/server/neo/bot/behavior/neo_bot_ctg_enemy.h index 152cad945..8ae07df41 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_ctg_enemy.h +++ b/src/game/server/neo/bot/behavior/neo_bot_ctg_enemy.h @@ -2,6 +2,7 @@ #define NEO_BOT_CTG_ENEMY_H #include "bot/neo_bot.h" +#include "Path/NextBotChasePath.h" //-------------------------------------------------------------------------------------------------------- class CNEOBotCtgEnemy : public Action< CNEOBot > diff --git a/src/mathlib/CMakeLists.txt b/src/mathlib/CMakeLists.txt index 4856db472..2ef34cea7 100644 --- a/src/mathlib/CMakeLists.txt +++ b/src/mathlib/CMakeLists.txt @@ -4,7 +4,7 @@ add_library(mathlib::mathlib ALIAS mathlib) set_target_properties(mathlib PROPERTIES PREFIX "" - UNITY_BUILD ON + UNITY_BUILD ${NEO_UNITY_BUILD_OTHERS} UNITY_BUILD_MODE GROUP ) @@ -18,7 +18,8 @@ target_include_directories(mathlib target_compile_definitions(mathlib PRIVATE - MATHLIB_LIB + MATHLIB_LIB + ${UNITY_BUILD_DEF_OTHERS} ) target_link_libraries(mathlib diff --git a/src/tier1/CMakeLists.txt b/src/tier1/CMakeLists.txt index 395eb3598..66a80d16e 100644 --- a/src/tier1/CMakeLists.txt +++ b/src/tier1/CMakeLists.txt @@ -2,14 +2,18 @@ add_library(tier1 STATIC) add_library(tier1::tier1 ALIAS tier1) -target_compile_definitions(tier1 PRIVATE TIER1_STATIC_LIB) +target_compile_definitions(tier1 + PRIVATE + TIER1_STATIC_LIB + ${UNITY_BUILD_DEF_OTHERS} +) set(unity_before [[ #include "tier0/memdbgoff.h" ]]) set_target_properties(tier1 PROPERTIES - UNITY_BUILD ON + UNITY_BUILD ${NEO_UNITY_BUILD_OTHERS} UNITY_BUILD_MODE GROUP UNITY_BUILD_CODE_BEFORE_INCLUDE "${unity_before}" ) diff --git a/src/vgui2/vgui_controls/CMakeLists.txt b/src/vgui2/vgui_controls/CMakeLists.txt index 94be59dce..bc59ab0c6 100644 --- a/src/vgui2/vgui_controls/CMakeLists.txt +++ b/src/vgui2/vgui_controls/CMakeLists.txt @@ -4,10 +4,15 @@ add_library(vgui_controls::vgui_controls ALIAS vgui_controls) set_target_properties(vgui_controls PROPERTIES PREFIX "" - UNITY_BUILD ON + UNITY_BUILD ${NEO_UNITY_BUILD_OTHERS} UNITY_BUILD_MODE GROUP ) +target_compile_definitions(vgui_controls + PRIVATE + ${UNITY_BUILD_DEF_OTHERS} +) + target_include_directories(vgui_controls PRIVATE ${CMAKE_SOURCE_DIR}/common diff --git a/src/vgui2/vgui_controls/FileOpenDialog.cpp b/src/vgui2/vgui_controls/FileOpenDialog.cpp index a7c36310a..4a5d89e05 100644 --- a/src/vgui2/vgui_controls/FileOpenDialog.cpp +++ b/src/vgui2/vgui_controls/FileOpenDialog.cpp @@ -47,7 +47,7 @@ #include #include #include -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -63,7 +63,7 @@ using namespace vgui; static int s_nLastSortColumn = 0; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static int ListFileNameSortFunc([[maybe_unused]] ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) { bool dir1 = item1.kv->GetInt("directory") == 1; @@ -180,7 +180,7 @@ static int ListBaseInteger64SortFunc(ListPanel *pPanel, const ListPanelItem &ite return ( i1 < i2 ) ? -1 : 1; } -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static int ListFileSizeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) { return ListBaseIntegerSortFunc( pPanel, item1, item2, "filesizeint" ); @@ -197,7 +197,7 @@ static int ListFileCreatedSortFunc(ListPanel *pPanel, const ListPanelItem &item1 // NOTE: Backward order to get most recent files first return ListBaseInteger64SortFunc( pPanel, item2, item1, "createdint_low", "createdint_high" ); } -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static int ListFileAttributesSortFunc(ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) { return ListBaseStringSortFunc( pPanel, item1, item2, "attributes" ); @@ -469,7 +469,7 @@ void FileCompletionEdit::OnMenuItemHighlight( int itemID ) //----------------------------------------------------------------------------- static CUtlDict< CUtlString, unsigned short > s_StartDirContexts; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build struct ColumnInfo_t { char const *columnName; diff --git a/src/vgui2/vgui_controls/KeyBindingHelpDialog.cpp b/src/vgui2/vgui_controls/KeyBindingHelpDialog.cpp index 993354121..76f8cef70 100644 --- a/src/vgui2/vgui_controls/KeyBindingHelpDialog.cpp +++ b/src/vgui2/vgui_controls/KeyBindingHelpDialog.cpp @@ -15,7 +15,7 @@ #include "vgui/Cursor.h" #include "tier1/utldict.h" #include "vgui_controls/KeyBoardEditorDialog.h" -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -28,7 +28,7 @@ using namespace vgui; // If the user holds the key bound to help down for this long, then the dialog will stay on automatically #define KB_HELP_CONTINUE_SHOWING_TIME 1.0 -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static bool BindingLessFunc( KeyValues * const & lhs, KeyValues * const &rhs ) { KeyValues *p1, *p2; diff --git a/src/vgui2/vgui_controls/KeyBoardEditorDialog.cpp b/src/vgui2/vgui_controls/KeyBoardEditorDialog.cpp index c4d0f4516..6c6974c8a 100644 --- a/src/vgui2/vgui_controls/KeyBoardEditorDialog.cpp +++ b/src/vgui2/vgui_controls/KeyBoardEditorDialog.cpp @@ -15,7 +15,7 @@ #include "KeyValues.h" #include "vgui/Cursor.h" #include "tier1/utldict.h" -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -25,7 +25,7 @@ using namespace vgui; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static char *CopyString( const char *in ) { if ( !in ) @@ -554,7 +554,7 @@ void CKeyBoardEditorPage::GetMappingList( Panel *panel, CUtlVector< PanelKeyBind } } -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static bool BindingLessFunc( KeyValues * const & lhs, KeyValues * const &rhs ) { KeyValues *p1, *p2; diff --git a/src/vgui2/vgui_controls/ListPanel.cpp b/src/vgui2/vgui_controls/ListPanel.cpp index c281ece62..f8e16bbf7 100644 --- a/src/vgui2/vgui_controls/ListPanel.cpp +++ b/src/vgui2/vgui_controls/ListPanel.cpp @@ -31,7 +31,7 @@ #include #include #include -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -39,7 +39,7 @@ #include "tier0/memdbgon.h" using namespace vgui; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build enum { WINDOW_BORDER_WIDTH=2 // the width of the window's border diff --git a/src/vgui2/vgui_controls/ListViewPanel.cpp b/src/vgui2/vgui_controls/ListViewPanel.cpp index 51ae830df..05ba0347d 100644 --- a/src/vgui2/vgui_controls/ListViewPanel.cpp +++ b/src/vgui2/vgui_controls/ListViewPanel.cpp @@ -24,7 +24,7 @@ #include #include #include -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -32,7 +32,7 @@ #include using namespace vgui; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build enum { WINDOW_BORDER_WIDTH=2 // the width of the window's border diff --git a/src/vgui2/vgui_controls/Panel.cpp b/src/vgui2/vgui_controls/Panel.cpp index 354e0ce0d..7fd3a2030 100644 --- a/src/vgui2/vgui_controls/Panel.cpp +++ b/src/vgui2/vgui_controls/Panel.cpp @@ -44,7 +44,7 @@ #include "tier0/vprof.h" -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -72,7 +72,7 @@ COMPILE_TIME_ASSERT( Panel::PIN_LAST == ARRAYSIZE( g_PinCornerStrings ) ); extern int GetBuildModeDialogCount(); -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static char *CopyString( const char *in ) { if ( !in ) diff --git a/src/vgui2/vgui_controls/PerforceFileList.cpp b/src/vgui2/vgui_controls/PerforceFileList.cpp index 09cf2d65f..67a8a97ac 100644 --- a/src/vgui2/vgui_controls/PerforceFileList.cpp +++ b/src/vgui2/vgui_controls/PerforceFileList.cpp @@ -14,7 +14,7 @@ #include "filesystem.h" #include "p4lib/ip4.h" #include "tier2/tier2.h" -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -25,7 +25,7 @@ using namespace vgui; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build static int ListFileNameSortFunc([[maybe_unused]] ListPanel *pPanel, const ListPanelItem &item1, const ListPanelItem &item2 ) { bool dir1 = item1.kv->GetInt("directory") == 1; @@ -133,7 +133,7 @@ static int ListFileTypeSortFunc(ListPanel *pPanel, const ListPanelItem &item1, c //----------------------------------------------------------------------------- // Dictionary of start dir contexts //----------------------------------------------------------------------------- -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build struct ColumnInfo_t { char const *columnName; diff --git a/src/vgui2/vgui_controls/PropertyDialog.cpp b/src/vgui2/vgui_controls/PropertyDialog.cpp index eb11c9897..381ab191e 100644 --- a/src/vgui2/vgui_controls/PropertyDialog.cpp +++ b/src/vgui2/vgui_controls/PropertyDialog.cpp @@ -60,7 +60,7 @@ PropertyDialog::~PropertyDialog() // Purpose: Returns a pointer to the PropertySheet this dialog encapsulates // Output : PropertySheet * //----------------------------------------------------------------------------- -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build vgui::PropertySheet *PropertyDialog::GetPropertySheet() #else PropertySheet *PropertyDialog::GetPropertySheet() diff --git a/src/vgui2/vgui_controls/ToolWindow.cpp b/src/vgui2/vgui_controls/ToolWindow.cpp index 092c0c40f..c584f54ba 100644 --- a/src/vgui2/vgui_controls/ToolWindow.cpp +++ b/src/vgui2/vgui_controls/ToolWindow.cpp @@ -108,7 +108,7 @@ bool ToolWindow::IsDraggableTabContainer() const // Purpose: Returns a pointer to the PropertySheet this dialog encapsulates // Output : PropertySheet * //----------------------------------------------------------------------------- -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build vgui::PropertySheet *ToolWindow::GetPropertySheet() #else PropertySheet *ToolWindow::GetPropertySheet() diff --git a/src/vgui2/vgui_controls/TreeView.cpp b/src/vgui2/vgui_controls/TreeView.cpp index 937c4cd9d..0185d7b59 100644 --- a/src/vgui2/vgui_controls/TreeView.cpp +++ b/src/vgui2/vgui_controls/TreeView.cpp @@ -28,7 +28,7 @@ #include #include #include -#ifdef NEO // Unity build +#ifdef NEO_UNITY // Unity build #include "Common.h" #endif @@ -42,7 +42,7 @@ #endif using namespace vgui; -#ifndef NEO // Unity build +#ifndef NEO_UNITY // Unity build enum { WINDOW_BORDER_WIDTH=2 // the width of the window's border From 61836885e9766089628774f1ef4da951eb455b5d Mon Sep 17 00:00:00 2001 From: sunmachine Date: Sat, 25 Jul 2026 22:05:17 +0000 Subject: [PATCH 2/3] Remove Source SDK build-script leftovers src/.vscode/tasks.json ran ./buildallprojects, and .gitattributes pinned line endings for the same file. Neither exists: the script came from the source-sdk-2013 import and never survived the move to CMake presets, so the task could only ever fail on invocation. --- .gitattributes | 1 - src/.vscode/tasks.json | 23 ----------------------- 2 files changed, 24 deletions(-) delete mode 100644 src/.vscode/tasks.json diff --git a/.gitattributes b/.gitattributes index 437f140a1..1d7eadd4b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,3 @@ -buildallprojects text vpc binary *.sh text diff --git a/src/.vscode/tasks.json b/src/.vscode/tasks.json deleted file mode 100644 index 87e569e8d..000000000 --- a/src/.vscode/tasks.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Build All Projects", - "type": "shell", - "command": "./buildallprojects", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": { - "base": "$gcc", - "fileLocation": ["relative", "${workspaceFolder}"] - }, - "presentation": { - "reveal": "always", - "panel": "shared" - } - } - ] -} - From 6ce4137ff2e9e64948f483c1e1a385ad89ebeb9c Mon Sep 17 00:00:00 2001 From: sunmachine Date: Thu, 6 Aug 2026 22:01:46 -0400 Subject: [PATCH 3/3] Add tools/ntre-dev-setup.sh to bootstrap C++ IntelliSense Run tools/ntre-dev-setup.sh, reload your editor, and go-to-definition works across src/game. It changes nothing about how NT;RE is built. A unity build's compile_commands.json lists only the generated unity_*.cxx blobs, so roughly 1300 translation units carry no compile flags an indexer can use. Navigation and completion are dead across most of src/game. What the script does: 1. Adds a "Linux Debug (IntelliSense index only)" preset to the git-ignored src/CMakeUserPresets.json, with NEO_UNITY_BUILD_CLIENT_SERVER and NEO_UNITY_BUILD_OTHERS set to OFF. 2. Configures that directory for its compile database alone. Nothing is built from it, and your real build directory keeps whatever unity settings you gave it. 3. Symlinks compile_commands.json at the repo root, where nearly every C++ tool probes for it. 4. Writes a .clangd that drops the GCC-only flags clang rejects. 5. Installs a pinned, checksummed clangd under .ide/. The sniper image ships clangd 13, which is too early for the repo's C++20. The script runs from the dev container (the CI image plus a non-root account matched to the local UID, so bind-mount files stay user-owned under rootful docker), from the tracked VS Code tasks, or directly from a shell. The output is a plain compile database, so any editor that speaks clangd works, not only VS Code. Everything generated is git-ignored. *.sh gains eol=lf so a Windows checkout cannot produce a script that fails to run. --- .devcontainer/Dockerfile | 14 ++ .devcontainer/devcontainer.json | 72 ++++++ .gitattributes | 3 +- .gitignore | 22 +- .vscode/tasks.json | 32 +++ README.md | 25 ++ tools/ntre-dev-setup.sh | 397 ++++++++++++++++++++++++++++++++ 7 files changed, 559 insertions(+), 6 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .vscode/tasks.json create mode 100755 tools/ntre-dev-setup.sh diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..d8dd6c078 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,14 @@ +# The CI image (.github/workflows/cibuild.yml) plus a non-root account, which +# the sniper SDK does not ship. Without one, a rootful-docker container writes +# root-owned files into the bind mount. devcontainer.json passes the host +# username, and updateRemoteUserUID rewrites the UID/GID to match at build time. +FROM registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest + +ARG USERNAME=dev +ARG USER_UID=1000 +ARG USER_GID=1000 + +RUN groupadd --gid "${USER_GID}" "${USERNAME}" \ + && useradd --uid "${USER_UID}" --gid "${USER_GID}" -m -s /bin/bash "${USERNAME}" \ + && echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/${USERNAME}" \ + && chmod 0440 "/etc/sudoers.d/${USERNAME}" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..8314e5468 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,72 @@ +{ + "name": "NT;RE - Steam Runtime 3 (sniper) SDK", + // The CI image (.github/workflows/cibuild.yml) plus a non-root account; see + // the Dockerfile. + "build": { + "dockerfile": "Dockerfile", + "args": { + // Account name only; file ownership comes from updateRemoteUserUID below. + "USERNAME": "${localEnv:USER:dev}" + } + }, + // SELinux hosts: without this the bind mount reads as Permission denied. + // Not :Z - that relabels the repo and breaks access from outside. + "runArgs": [ + "--security-opt", + "label=disable" + ], + // Must match the USERNAME build arg. updateRemoteUserUID rebuilds the image + // with the local UID/GID so bind-mount files stay owned by the host user. + "remoteUser": "${localEnv:USER:dev}", + "updateRemoteUserUID": true, + "postCreateCommand": "bash tools/ntre-dev-setup.sh --editor none", + "remoteEnv": { + "PATH": "${containerWorkspaceFolder}/.ide/bin:${containerEnv:PATH}" + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cmake-tools", + "llvm-vs-code-extensions.vscode-clangd" + ], + // Mirrors what tools/ntre-dev-setup.sh writes for non-container users; + // keep in sync. ${workspaceFolder} is VS Code's, not devcontainer.json's. + "settings": { + "cmake.sourceDirectory": "${workspaceFolder}/src", + "cmake.useCMakePresets": "always", + "cmake.configureOnOpen": false, + // Stops the extension downloading its own clangd. + "clangd.path": "${workspaceFolder}/.ide/bin/clangd", + "clangd.checkUpdates": false, + "clangd.onConfigChanged": "restart", + "clangd.arguments": [ + // Command-line-only option: reads include paths and predefined + // macros from the compiler that actually builds this tree. + "--query-driver=/usr/bin/g++*,/usr/bin/gcc*,/usr/bin/clang*,/usr/lib/llvm-*/bin/clang*", + "--header-insertion=never", + "--background-index", + "--completion-style=detailed", + "--pch-storage=memory" + ], + // clangd provides IntelliSense; stop cpptools double-indexing. + "C_Cpp.intelliSenseEngine": "disabled", + "files.associations": { + "*.h": "cpp", + "*.inc": "cpp" + }, + "[cpp]": { + "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + }, + "files.watcherExclude": { + "**/src/build/**": true, + "**/.cache/**": true, + "**/.ide/**": true + }, + "search.exclude": { + "**/src/build/**": true, + "**/.ide/**": true + } + } + } + } +} diff --git a/.gitattributes b/.gitattributes index 1d7eadd4b..4effc43a1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,7 @@ vpc binary -*.sh text +# eol=lf: a shell script checked out with CRLF fails to run at all. +*.sh text eol=lf *.bat text *.txt text *.c text diff --git a/.gitignore b/.gitignore index 2ac93e819..0de5b1b13 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,16 @@ out /src/CMakeSettings.json +/src/CMakeUserPresets.json + +# Generated by tools/ntre-dev-setup.sh +/.ide/ +/.clangd +/compile_commands.json +/.zed/ + +# Personal devcontainer variants, offered alongside the tracked one +/.devcontainer/local/ # ctest /src/Testing @@ -662,11 +672,6 @@ MigrationBackup/ FodyWeavers.xsd # VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json *.code-workspace # Local History for Visual Studio Code @@ -699,3 +704,10 @@ FodyWeavers.xsd # Selected Background /game/neo/scripts/[Cc]hapter[Bb]ackgrounds.txt + +# Share the ntre-dev-setup.sh task entry point; the rest of .vscode stays local. +# Three patterns because *.vscode/ above excludes the directory itself, and git +# cannot re-include a file whose parent directory is excluded. +!/.vscode/ +/.vscode/* +!/.vscode/tasks.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..66edf617d --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,32 @@ +{ + // The only tracked file under .vscode/ (see the re-include at the end of + // .gitignore); the setup task writes the per-developer settings.json and + // extensions.json. + "version": "2.0.0", + "tasks": [ + { + "label": "ntre-dev-setup: Set up VS Code", + "detail": "Installs the pinned clangd, generates the compile database and writes .vscode/settings.json + extensions.json. Linux or macOS shell (WSL on Windows).", + "type": "shell", + "command": "${workspaceFolder}/tools/ntre-dev-setup.sh", + "args": ["--editor", "vscode"], + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "ntre-dev-setup: Refresh compile database", + "detail": "Run after adding, removing or renaming sources, or after pulling changes to a CMakeLists.txt.", + "type": "shell", + "command": "${workspaceFolder}/tools/ntre-dev-setup.sh", + "args": ["--reconfigure"], + "problemMatcher": [], + "presentation": { + "reveal": "silent", + "panel": "shared" + } + } + ] +} diff --git a/README.md b/README.md index ac7d87a14..6cc54f251 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,31 @@ $ cmake --build --preset PRESET_NAME Available PRESET_NAME values: `windows-debug`, `windows-release`, `linux-debug`, `linux-release`. +## Development using Linux + +Optional tooling for working on the code, rather than for building it: a dev container definition and a setup script that give you a working C++ IntelliSense index. None of it changes how NT;RE is built. The [Qt Creator](#qt-creator-linux) and [CLI](#cli-with-ninja-windows--linux) workflows above are untouched, and every file the script generates is git-ignored. + +### Getting set up + +Either entry point is enough: + +* **Dev container** - open the repo in an editor that supports [dev containers](https://containers.dev/) (VS Code, the `devcontainer` CLI, JetBrains Gateway) and reopen in the container. It uses the same sniper SDK image as the CI runners and the manual container steps above, and runs the setup script for you on create. +* **Run it yourself** - from inside your own sniper container, or on a native toolchain new enough for C++20: + + ```bash + $ ./tools/ntre-dev-setup.sh + ``` + + Add `--editor vscode` to also write `.vscode/settings.json` and `extensions.json`; in VS Code, the *"ntre-dev-setup: Set up VS Code"* task does the same. `--editor zed` writes the equivalent `.zed/settings.json`. Run from an editor's own terminal, the default `--editor auto` picks whichever it detects. `--help` lists the rest. + +### What it sets up + +* A pinned `clangd` under `.ide/`, since distro packages are frequently too old for this tree's C++20. Use `--system-clangd` to keep your own instead, or `source .ide/env.sh` to put the pinned one on `PATH` for editors launched from a shell. +* `compile_commands.json`, symlinked at the repo root where clangd, CLion, Qt Creator and Sublime look for it, alongside a `.clangd` carrying the compile flags that need adjusting for the SteamRT toolchain. +* A `linux-debug-ide` preset in your `src/CMakeUserPresets.json` (per-developer, git-ignored) that generates the database with the [unity build](#unity-build) options off - the header of `tools/ntre-dev-setup.sh` explains why. **Do not build from it** - build with `linux-debug` as documented above. + +Re-run `./tools/ntre-dev-setup.sh --reconfigure` after adding, removing or renaming source files, or use the *"ntre-dev-setup: Refresh compile database"* task in VS Code. + ## Steam mod setup To make it appear in Steam, the install files have to appear under the sourcemods directory or be directed to it. diff --git a/tools/ntre-dev-setup.sh b/tools/ntre-dev-setup.sh new file mode 100755 index 000000000..752bc0b4a --- /dev/null +++ b/tools/ntre-dev-setup.sh @@ -0,0 +1,397 @@ +#!/usr/bin/env bash +# +# Bootstraps C++ IntelliSense: a compile_commands.json symlinked at the repo root +# and a .clangd beside it - the two interfaces every C++ indexer understands. +# +# Why a separate CMake directory: a unity build's database lists only generated +# unity_*.cxx blobs, so ~1300 translation units get no flags at all. This preset +# turns NEO_UNITY_BUILD_CLIENT_SERVER and NEO_UNITY_BUILD_OTHERS off for the +# database alone, leaving your real build directory configured however you like; +# nothing is compiled from it. +# +# Safe to re-run; it skips what is already in place. See --help. + +set -euo pipefail + +CLANGD_VERSION="22.1.6" +CLANGD_SHA256_LINUX_X86_64="a9c77443af2e447ed467e84771848d3a6ac1c56f84bcfcde717e66318de77cfa" +# clangd older than this mishandles the C++20 this tree is built with. +CLANGD_MIN_MAJOR=17 + +PRESET="linux-debug-ide" +BASE_PRESET="linux-debug" +# Globbed for the GCC 10 and Clang 19 in CONTRIBUTING.md, which install as +# gcc-10, clang-19, /usr/lib/llvm-19/bin/clang++. A driver clangd cannot query +# leaves it guessing the standard library paths. +QUERY_DRIVER='/usr/bin/g++*,/usr/bin/gcc*,/usr/bin/clang*,/usr/lib/llvm-*/bin/clang*' +EDITOR_TARGET="auto" +USE_SYSTEM_CLANGD=0 +RECONFIGURE=0 +FORCE=0 +CLANGD_VERSION_OVERRIDDEN=0 +CLANGD_SHA256_OVERRIDE="" + +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +IDE_DIR="${REPO_ROOT}/.ide" +SRC_DIR="${REPO_ROOT}/src" +BUILD_DIR="${SRC_DIR}/build/${PRESET}" + +usage() { + cat <<'EOF' +Usage: tools/ntre-dev-setup.sh [options] + + --editor + Write editor-specific config too. "auto" (default) + picks VS Code or Zed when run from that editor's + terminal or task. Every editor works without this; + it just saves pointing your client at + .ide/bin/clangd by hand. + --system-clangd Use clangd from PATH instead of downloading a + pinned one (must be >= major 17). + --clangd-version Override the pinned clangd release. Downloads + unverified unless --clangd-sha256 is also given. + --clangd-sha256 SHA-256 of the linux-x86_64 zip for an overridden + --clangd-version. + --preset IntelliSense preset name (default linux-debug-ide). + --base-preset Preset it inherits build flags from (default linux-debug). + --reconfigure Regenerate the compile database even if it exists. + Do this after adding/removing/renaming sources. + --force Overwrite generated config files (.clangd etc). + -h, --help This text. +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --editor) EDITOR_TARGET="$2"; shift 2 ;; + --system-clangd) USE_SYSTEM_CLANGD=1; shift ;; + --clangd-version) CLANGD_VERSION="$2"; CLANGD_VERSION_OVERRIDDEN=1; shift 2 ;; + --clangd-sha256) CLANGD_SHA256_OVERRIDE="$2"; shift 2 ;; + --preset) PRESET="$2"; BUILD_DIR="${SRC_DIR}/build/${PRESET}"; shift 2 ;; + --base-preset) BASE_PRESET="$2"; shift 2 ;; + --reconfigure) RECONFIGURE=1; shift ;; + --force) FORCE=1; shift ;; + -h|--help) usage; exit 0 ;; + *) echo "unknown option: $1" >&2; usage >&2; exit 2 ;; + esac +done + +# The pinned hash only vouches for the pinned version; an override replaces both. +if [[ $CLANGD_VERSION_OVERRIDDEN -eq 1 ]]; then + CLANGD_SHA256_LINUX_X86_64="$CLANGD_SHA256_OVERRIDE" +fi + +say() { printf '\033[1m==>\033[0m %s\n' "$*"; } +warn() { printf '\033[33mwarning:\033[0m %s\n' "$*" >&2; } +die() { printf '\033[31merror:\033[0m %s\n' "$*" >&2; exit 1; } + +# Writes stdin to $1 unless it exists (or --force). Returns 1 when skipped. +write_if_absent() { + local path="$1" + if [[ -e "$path" && $FORCE -eq 0 ]]; then + cat > /dev/null + return 1 + fi + mkdir -p "$(dirname "$path")" + cat > "$path" + return 0 +} + +# ---------------------------------------------------------------- prerequisites +for tool in cmake ninja; do + command -v "$tool" >/dev/null || die "$tool not found in PATH" +done +command -v g++ >/dev/null || warn "g++ not in PATH; the compile database will name a compiler this machine cannot query" +[[ -f "${SRC_DIR}/CMakePresets.json" ]] || die "no src/CMakePresets.json - run this from inside the repo" + +# ------------------------------------------------------------------- 1. clangd +CLANGD_BIN="${IDE_DIR}/bin/clangd" + +clangd_major() { "$1" --version 2>/dev/null | sed -n 's/.*clangd version \([0-9]*\).*/\1/p' | head -1; } + +install_clangd() { + local os arch asset major + os="$(uname -s)"; arch="$(uname -m)" + + case "${os}/${arch}" in + Linux/x86_64) asset="clangd-linux-${CLANGD_VERSION}.zip" ;; + *) + # No pinned release for this platform - notably linux/aarch64, and + # macOS, where this tree does not build anyway. + local sys; sys="$(command -v clangd || true)" + [[ -n "$sys" ]] || die "no clangd release for ${os}/${arch}; install clangd >= ${CLANGD_MIN_MAJOR} and re-run" + major="$(clangd_major "$sys")" + [[ -n "$major" && "$major" -ge $CLANGD_MIN_MAJOR ]] \ + || die "clangd ${major:-?} at ${sys} is too old for this tree's C++20; need >= ${CLANGD_MIN_MAJOR}" + warn "no clangd release for ${os}/${arch}; falling back to ${sys}" + mkdir -p "${IDE_DIR}/bin"; ln -sfn "$sys" "$CLANGD_BIN" + return + ;; + esac + + local dest="${IDE_DIR}/toolchain/clangd_${CLANGD_VERSION}" + if [[ ! -x "${dest}/bin/clangd" ]]; then + command -v curl >/dev/null || die "curl not found; needed to fetch clangd" + command -v unzip >/dev/null || die "unzip not found; needed to unpack clangd" + say "downloading clangd ${CLANGD_VERSION} (${asset})" + local tmp; tmp="$(mktemp -d)" + trap 'rm -rf "$tmp"' RETURN + curl -fsSL -o "${tmp}/clangd.zip" \ + "https://github.com/clangd/clangd/releases/download/${CLANGD_VERSION}/${asset}" + if [[ -n "$CLANGD_SHA256_LINUX_X86_64" ]]; then + echo "${CLANGD_SHA256_LINUX_X86_64} ${tmp}/clangd.zip" | sha256sum -c - >/dev/null \ + || die "clangd download failed checksum verification" + else + warn "no checksum for clangd ${CLANGD_VERSION}; skipping verification (pass --clangd-sha256 to pin one)" + fi + mkdir -p "${IDE_DIR}/toolchain" + rm -rf "$dest" + unzip -q "${tmp}/clangd.zip" -d "${IDE_DIR}/toolchain" + fi + mkdir -p "${IDE_DIR}/bin" + ln -sfn "../toolchain/clangd_${CLANGD_VERSION}/bin/clangd" "$CLANGD_BIN" +} + +if [[ $USE_SYSTEM_CLANGD -eq 1 ]]; then + sys="$(command -v clangd || true)" + [[ -n "$sys" ]] || die "--system-clangd given but no clangd in PATH" + major="$(clangd_major "$sys")" + [[ -n "$major" && "$major" -ge $CLANGD_MIN_MAJOR ]] \ + || die "clangd $major is too old for this tree's C++20; need >= ${CLANGD_MIN_MAJOR}" + mkdir -p "${IDE_DIR}/bin"; ln -sfn "$sys" "$CLANGD_BIN" +else + install_clangd +fi +say "clangd: $("$CLANGD_BIN" --version | head -1)" + +# ------------------------------------------------------- 2. CMakeUserPresets.json +# Per-developer by design and git-ignored, so writing here never dirties the tree. +# CMake Tools, CLion and `cmake --preset` all read it. +PRESETS_FILE="${SRC_DIR}/CMakeUserPresets.json" +if [[ -f "$PRESETS_FILE" ]] && grep -q "\"${PRESET}\"" "$PRESETS_FILE"; then + say "preset ${PRESET} already present in src/CMakeUserPresets.json" +elif [[ -f "$PRESETS_FILE" ]]; then + command -v python3 >/dev/null || die "src/CMakeUserPresets.json exists without a '${PRESET}' preset; install python3 so it can be merged, or add the preset by hand" + say "adding ${PRESET} to existing src/CMakeUserPresets.json" + PRESET="$PRESET" BASE_PRESET="$BASE_PRESET" python3 - "$PRESETS_FILE" <<'EOF' +import json, os, sys +path = sys.argv[1] +doc = json.load(open(path)) +doc.setdefault("version", 3) +doc.setdefault("configurePresets", []).append({ + "name": os.environ["PRESET"], + "displayName": "Linux Debug (IntelliSense index only)", + "description": "Configure-only, unity off, for the IntelliSense database. Do not build from it.", + "inherits": os.environ["BASE_PRESET"], + "cacheVariables": { + "NEO_UNITY_BUILD_CLIENT_SERVER": "OFF", + "NEO_UNITY_BUILD_OTHERS": "OFF", + "NEO_EXTRA_ASSETS": "OFF", + "NEO_COPY_LIBRARIES": "OFF", + "NEO_USE_CCACHE": "OFF", + }, +}) +json.dump(doc, open(path, "w"), indent=2) +open(path, "a").write("\n") +EOF +else + say "writing src/CMakeUserPresets.json" + cat > "$PRESETS_FILE" </dev/null || die "cmake configure failed; re-run without >/dev/null to see why" +else + say "compile database already present (--reconfigure to regenerate)" +fi + +entries=$(python3 -c "import json,sys; print(len(json.load(open(sys.argv[1]))))" "${BUILD_DIR}/compile_commands.json" 2>/dev/null || echo '?') +unity=$(grep -c 'Unity/unity_' "${BUILD_DIR}/compile_commands.json" 2>/dev/null || true) +say "compile database: ${entries} entries, ${unity:-0} unity blobs" +[[ "${unity:-0}" == "0" ]] || warn "unity entries present - something is overriding this preset's NEO_UNITY_BUILD_* = OFF" + +# Root symlink: the location nearly every C++ tool probes by default. +ln -sfn "src/build/${PRESET}/compile_commands.json" "${REPO_ROOT}/compile_commands.json" +say "symlinked compile_commands.json at the repo root" + +# ------------------------------------------------------------------ 5. env.sh +# For shell-launched editors (nvim, helix, emacs): source it and clangd is on PATH. +cat > "${IDE_DIR}/env.sh" <