Skip to content

Conversation

@DhanashreePetare
Copy link

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 on lines 13 to 45
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
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
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 on lines 15 to 26
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
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
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.

CMakeLists.txt Outdated
Comment on lines 372 to 373
elseif(DEFINED ENV{HOME})
set(VOLK_CONFIGPATH "$ENV{HOME}/.config/volk")
Copy link
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.

CMakeLists.txt Outdated
elseif(DEFINED ENV{HOME})
set(VOLK_CONFIGPATH "$ENV{HOME}/.config/volk")
elseif(DEFINED ENV{APPDATA})
# Windows fallback
Copy link
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.

Copy link
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
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
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 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
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 on lines 125 to 129
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Copy link
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
Copy link
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).

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
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 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
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
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
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

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
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?

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
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 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
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.

FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
Copy link
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 <[email protected]>
@DhanashreePetare
Copy link
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 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
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

Copy link
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