Skip to content

volk: prefer XDG config dir for volk_config, add tests & docs (#792)#810

Open
DhanashreePetare wants to merge 6 commits intognuradio:mainfrom
DhanashreePetare:feature/xdg-config-path
Open

volk: prefer XDG config dir for volk_config, add tests & docs (#792)#810
DhanashreePetare wants to merge 6 commits intognuradio:mainfrom
DhanashreePetare:feature/xdg-config-path

Conversation

@DhanashreePetare
Copy link
Copy Markdown

Summary:

  • Change volk to prefer XDG Base Directory for the user config file location (use $XDG_CONFIG_HOME/volk or $HOME/.config/volk) while preserving legacy fallback to $HOME/.volk and the system /etc/volk/volk_config. Add unit tests and documentation.

Motivation:

What I changed:

  • Code: Prefer XDG config dirs in volk_prefs.c — lookup order: VOLK_CONFIGPATH override → $XDG_CONFIG_HOME/volk$HOME/.config/volk → legacy $HOME/.volk/etc/volk/volk_config. When writing, create the chosen XDG/home .config/volk directory if missing.
  • CMake: Adjust default VOLK_CONFIGPATH used for profiling to prefer XDG config dir in CMakeLists.txt.
  • Tests: Add test_volk_paths.cc to exercise override, XDG presence, write-mode directory creation, and legacy fallback. Update CMakeLists.txt to FetchContent fmt and googletest if not available.
  • Docs: Append note in README.md explaining XDG behavior and backward compatibility.
  • Repo: Changes are on branch feature/xdg-config-path.

Testing done / expected:

  • Added unit tests covering new lookup and write behavior; CI will run the full build+test matrix across supported compilers/OS. Local build on Windows required toolchain upgrades; recommend CI verification or running in a modern toolchain/WSL matching CI.

Backward compatibility:

  • Legacy behavior preserved: VOLK_CONFIGPATH still overrides; if XDG and $HOME/.config/volk are not available, the code falls back to $HOME/.volk and /etc/volk/volk_config.

Notes for reviewers:

  • Focus review on volk_prefs.c (path selection + directory-creation logic), test_volk_paths.cc (coverage), and the small CMakeLists.txt change for profiling default. CI will validate formatting and cross-platform builds.
  • Commits include DCO sign-off and were formatted with project clang-format.

Closes: #792

Comment thread tests/CMakeLists.txt
Comment on lines +13 to +33
include(FetchContent)

find_package(fmt QUIET)
find_package(fmt QUIET)
find_package(GTest QUIET)
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.2.1
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(fmt)
endif()

if(NOT GTest_FOUND)
message(STATUS "GTest not found: fetching googletest via FetchContent")
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(googletest)
find_package(GTest REQUIRED)
endif()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

voice from the off: generally, I'd avoid random FetchContents in CMake appearing, because it makes packaging much harder.

However, here, FetchContent is only used when no system lib has been found, AND it fixes the version fetched, so I feel that's OK.

Copy link
Copy Markdown
Member

@marcusmueller marcusmueller left a comment

Choose a reason for hiding this comment

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

Please fix the syntax errors and make sure things build and test successfully on your machine :)

Comment thread tests/CMakeLists.txt Outdated
Comment on lines +15 to +22
find_package(fmt QUIET)
find_package(fmt QUIET)
find_package(GTest QUIET)
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.2.1
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(fmt)
endif()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

syntax error!

CMake Error at tests/CMakeLists.txt:18:
  Parse error.  Expected "(", got unquoted argument with text
  "https://github.com/fmtlib/fmt.git".

Have you tried to build this on your machine?

Copy link
Copy Markdown
Contributor

@jdemel jdemel left a comment

Choose a reason for hiding this comment

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

Thank you for your PR. Overall, it looks good. I feel like my comments should only be minor changes. The CI needs to pass again though.

Comment thread CMakeLists.txt Outdated
Comment on lines +372 to +373
elseif(DEFINED ENV{HOME})
set(VOLK_CONFIGPATH "$ENV{HOME}/.config/volk")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I feel like this is a good change but: Unfortunately this breaks the previous behavior. Right now, I'm undecided if this is an acceptable thing to do. Adding a new option with XDG_CONFIG_HOME is fine though.

Comment thread CMakeLists.txt Outdated
elseif(DEFINED ENV{HOME})
set(VOLK_CONFIGPATH "$ENV{HOME}/.config/volk")
elseif(DEFINED ENV{APPDATA})
# Windows fallback
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The comment is misleading because there's no other option for the Windows case.

Comment thread README.md
Comment thread tests/CMakeLists.txt
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why does anything in this file need to change? The intended behavior before was to skip over these tests of the required dependencies are missing.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

  • I made the CMakeLists.txt fetch fmt / googletest only as a fallback when the system packages are not found (it still prefers find_package(...) first). This keeps CI reproducible by pinning a known-good version while not forcing all contributors to install those libs system-wide.
  • I also used FetchContent_Populate + add_subdirectory for googletest to work around a CMake/FetchContent issue we hit on Windows/WSL mounts.
  • If you'd rather keep the prior behavior (skip tests when deps are missing) I'm happy to revert to that — or I can gate the FetchContent behind an option so packagers can opt out.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's OK to go with fetchContent after the check. One more thing though: We have similar stuff in other parts of our CMake structure. That'd need to be combined.

Comment thread tests/test_volk_paths.cc Outdated
Comment on lines +10 to +23
#if defined(_MSC_VER)
static void set_env(const char* name, const char* value)
{
_putenv_s(name, value ? value : "");
}
#else
static void set_env(const char* name, const char* value)
{
if (value)
setenv(name, value, 1);
else
unsetenv(name);
}
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since these are C++ tests, you can use const std::string_view, or (the older approach) const std::string&.

Comment thread tests/test_volk_paths.cc Outdated
Comment on lines +125 to +129
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This shouldn't be a part of the file. So far, the googletest default main suffices and I can't find a reason why this should change here.

DhanashreePetare pushed a commit to DhanashreePetare/GNUradio-volk that referenced this pull request Jan 17, 2026
DhanashreePetare added 5 commits January 17, 2026 15:35
…docs

Signed-off-by: DhanashreePetare <dhanashreepetare8125@gmail.com>
…viewers

Signed-off-by: DhanashreePetare <dhanashreepetare8125@gmail.com>
…viewers

Signed-off-by: DhanashreePetare <dhanashreepetare8125@gmail.com>
…aths tests; address reviewer suggestions (refs gnuradio#792 gnuradio#810)

Signed-off-by: DhanashreePetare <dhanashreepetare8125@gmail.com>
Signed-off-by: DhanashreePetare <dhanashreepetare8125@gmail.com>
@DhanashreePetare
Copy link
Copy Markdown
Author

Adds opt-in XDG config path support while preserving legacy fallbacks, ensures dirs are created on write, adds portable std::filesystem tests and fixes tests CMake; addresses reviewer feedback (use std::string_view, removed custom test main). DCO-signed and force-pushed — tested locally (WSL native build), all tests passed (253/253).

Comment thread lib/volk_prefs.c Outdated
Comment on lines +36 to +40
#if defined(_MSC_VER)
/* use _mkdir on MSVC */
#else
/* ensure sys/stat available */
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is this doing?

Comment thread lib/volk_prefs.c
Comment on lines +63 to +74
#if defined(_MSC_VER)
_mkdir(parent);
_mkdir(dir);
#else
struct stat st = { 0 };
if (stat(parent, &st) == -1) {
mkdir(parent, 0755);
}
if (stat(dir, &st) == -1) {
mkdir(dir, 0755);
}
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The old function behavior was to just check for possible folders and return the path. Why is it necessary to create folders now?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The original function returned a path string, but didn't guarantee that path could actually be used for writing. If a user called volk_get_config_path(path, false) (write-mode) and tried to write the config file, it would fail with a file I/O error if the parent directories didn't exist.

I agree this might be outside the function's scope. Would you prefer:
Option A: Keep current behavior (create dirs in write-mode) — simpler for callers
Option B: Return path only, let caller handle directory creation — better separation of concerns

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Go with option B. This function should just discover where to look for files =D

Comment thread lib/volk_prefs.c
const char* appdata = getenv("APPDATA");
if (appdata) {
snprintf(tmp, sizeof(tmp), "%s%s", appdata, legacy_suffix);
if (!read || access(tmp, F_OK) == 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The old behavior was access(tmp, F_OK) != -1, why does that need to change?

Comment thread lib/volk_prefs.c Outdated
Comment on lines +130 to +149
/* System-wide */
if (access("/etc/volk/volk_config", F_OK) == 0) {
strncpy(path, "/etc/volk/volk_config", 512);
return;
}
/* If nothing found, follow the XDG-first fallback behavior:
- if XDG_CONFIG_HOME is set, return XDG_CONFIG_HOME/volk/volk_config
- else if HOME is set, return HOME/.config/volk/volk_config
- otherwise return empty string
This ensures read-mode returns the new XDG location as fallback. */
if (xdg) {
snprintf(tmp, sizeof(tmp), "%s/volk/volk_config", xdg);
strncpy(path, tmp, 512);
return;
}
if (home) {
snprintf(tmp, sizeof(tmp), "%s/.config/volk/volk_config", home);
strncpy(path, tmp, 512);
return;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The old function implementation followed a regular pattern to check for possible config folders and reacted accordingly. Could you restore the old structure and add the XDG part accordingly?
Introducing a new variable for every option is fine and probably improves readability.
Could you clean-up the implementation in this function?

Comment thread tests/CMakeLists.txt Outdated
Comment on lines +16 to +26
find_package(fmt QUIET)
if(NOT fmt_FOUND)
message(STATUS "fmt not found: fetching fmt via FetchContent")
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.2.1
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(fmt)
endif()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

fmt is available at this point because we either do find_package or FetchContent in the top-level CMakeLists.txt. Since it is required now, for other reasons, no need to fetch it here.

Comment thread tests/CMakeLists.txt Outdated
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please go with the latest release version. That'd be 1.17 at the time of writing.

…tent, update googletest to v1.17.0

Signed-off-by: DhanashreePetare <dhanashreepetare8125@gmail.com>
@DhanashreePetare
Copy link
Copy Markdown
Author

Addressed reviewer feedback: simplified volk_prefs.c fallback logic (removed duplicate XDG/HOME checks at end), removed empty comment block scaffolding, standardized access() checks to == 0 for consistency. Removed fmt FetchContent from CMakeLists.txt (already provided by top-level). Updated googletest to v1.17.0. Tested locally in WSL (native build): all 253 tests pass, build clean with Ninja/GCC.

Comment thread lib/volk_prefs.c
Comment on lines +63 to +74
#if defined(_MSC_VER)
_mkdir(parent);
_mkdir(dir);
#else
struct stat st = { 0 };
if (stat(parent, &st) == -1) {
mkdir(parent, 0755);
}
if (stat(dir, &st) == -1) {
mkdir(dir, 0755);
}
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Go with option B. This function should just discover where to look for files =D

Comment thread tests/CMakeLists.txt
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's OK to go with fetchContent after the check. One more thing though: We have similar stuff in other parts of our CMake structure. That'd need to be combined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update Linux config file folder location to follow XDG base directory specification

3 participants