82 lines
2.4 KiB
C++
82 lines
2.4 KiB
C++
module cargoxx.resolver;
|
|
|
|
import std;
|
|
import cargoxx.util;
|
|
|
|
namespace cargoxx::resolver {
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
namespace {
|
|
|
|
auto is_lib_filename(const fs::path& p) -> bool {
|
|
auto name = p.filename().string();
|
|
if (!name.starts_with("lib")) {
|
|
return false;
|
|
}
|
|
auto ext = p.extension().string();
|
|
if (ext == ".a") {
|
|
return true;
|
|
}
|
|
if (ext == ".so" || ext == ".dylib") {
|
|
return true;
|
|
}
|
|
// .so.<N>, .so.<N>.<M>, ... — common shared-lib versioning. Use a
|
|
// looser check: if the name contains ".so." or ".dylib." anywhere
|
|
// after the lib prefix, accept it.
|
|
return name.find(".so.") != std::string::npos ||
|
|
name.find(".dylib.") != std::string::npos;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
auto brute_scan(const fs::path& store_path, const std::string& package_name)
|
|
-> util::Result<BruteCandidate> {
|
|
if (package_name.empty()) {
|
|
return std::unexpected(util::Error{
|
|
util::ErrorCode::ResolutionUnknownPackage,
|
|
"brute_scan: package name is empty",
|
|
"", std::nullopt, std::nullopt,
|
|
});
|
|
}
|
|
const auto lib_dir = store_path / "lib";
|
|
const auto include_dir = store_path / "include";
|
|
|
|
BruteCandidate out;
|
|
std::error_code ec;
|
|
|
|
if (fs::exists(lib_dir, ec) && !ec) {
|
|
for (const auto& entry : fs::directory_iterator{
|
|
lib_dir, fs::directory_options::skip_permission_denied, ec}) {
|
|
if (!entry.is_regular_file() && !entry.is_symlink()) {
|
|
continue;
|
|
}
|
|
if (!is_lib_filename(entry.path())) {
|
|
continue;
|
|
}
|
|
out.lib_files.push_back(entry.path().string());
|
|
}
|
|
std::ranges::sort(out.lib_files);
|
|
}
|
|
|
|
if (fs::exists(include_dir, ec) && !ec) {
|
|
// For include/, expose the top-level directory itself (e.g.
|
|
// `<store>/include`) — that's what `#include <pkg/foo.h>`
|
|
// expects. Adding every subdir would also work, but is noisier
|
|
// and provokes name collisions across deps.
|
|
out.include_dirs.push_back(include_dir.string());
|
|
}
|
|
|
|
if (out.lib_files.empty() && out.include_dirs.empty()) {
|
|
return std::unexpected(util::Error{
|
|
util::ErrorCode::ResolutionUnknownPackage,
|
|
std::format("no libs or headers under '{}'", store_path.string()),
|
|
"", store_path, std::nullopt,
|
|
});
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
} // namespace cargoxx::resolver
|