diff --git a/src/fs/FileInfo.cxx b/src/fs/FileInfo.cxx
new file mode 100644
index 000000000..f59e34deb
--- /dev/null
+++ b/src/fs/FileInfo.cxx
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright The Music Player Daemon Project
+
+#include "FileInfo.hxx"
+#include "lib/fmt/PathFormatter.hxx"
+#include "lib/fmt/SystemError.hxx"
+
+FileInfo::FileInfo(Path path, bool follow_symlinks)
+{
+	if (!GetFileInfo(path, *this, follow_symlinks)) {
+#ifdef _WIN32
+		throw FmtLastError("Failed to access {}", path);
+#else
+		throw FmtErrno("Failed to access {}", path);
+#endif
+	}
+}
diff --git a/src/fs/FileInfo.hxx b/src/fs/FileInfo.hxx
index 17a7b7e53..0ab7a0d70 100644
--- a/src/fs/FileInfo.hxx
+++ b/src/fs/FileInfo.hxx
@@ -4,8 +4,6 @@
 #pragma once
 
 #include "Path.hxx"
-#include "lib/fmt/PathFormatter.hxx"
-#include "lib/fmt/SystemError.hxx"
 
 #ifdef _WIN32
 #include "time/FileTime.hxx"
@@ -30,15 +28,7 @@ class FileInfo {
 public:
 	constexpr FileInfo() noexcept = default;
 
-	explicit FileInfo(Path path, bool follow_symlinks=true) {
-		if (!GetFileInfo(path, *this, follow_symlinks)) {
-#ifdef _WIN32
-			throw FmtLastError("Failed to access {}", path);
-#else
-			throw FmtErrno("Failed to access {}", path);
-#endif
-		}
-	}
+	explicit FileInfo(Path path, bool follow_symlinks=true);
 
 	constexpr bool IsRegular() const noexcept {
 #ifdef _WIN32
diff --git a/src/fs/meson.build b/src/fs/meson.build
index ef39b78cc..2660c2fd9 100644
--- a/src/fs/meson.build
+++ b/src/fs/meson.build
@@ -12,6 +12,7 @@ fs_sources = [
   'List.cxx',
   'LookupFile.cxx',
   'DirectoryReader.cxx',
+  'FileInfo.cxx',
 ]
 
 if is_windows