[M6] brute-force probe + INTERFACE IMPORTED target codegen
This commit is contained in:
81
src/resolver/brute_scan.cpp
Normal file
81
src/resolver/brute_scan.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
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
|
||||
Reference in New Issue
Block a user