From f5b09df9c88d49c95fd0c0ef7b3670b40634ca5c Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Fri, 27 May 2022 09:50:35 +0200 Subject: WIP: automatic externals --- src/configure.cc | 86 ++++++++++++++++++++++++++++++++++++++- src/libctor.h | 14 ++++++- src/search.cc | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/search.h | 37 +++++++++++++++++ 4 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 src/search.cc create mode 100644 src/search.h (limited to 'src') diff --git a/src/configure.cc b/src/configure.cc index bc7d3e8..a7e47eb 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -14,6 +14,7 @@ #include "libctor.h" #include "tasks.h" #include "rebuild.h" +#include "search.h" #include "externals.h" std::filesystem::path configurationFile("configuration.cc"); @@ -146,6 +147,58 @@ public: } }; +int resolv(const Settings& settings, const std::string& name, + const ExternalAutomatic& ext, Flags& flags) +{ + using namespace std::string_literals; + + flags = ext.flags; + + for(const auto& header : ext.headers) + { + std::vector paths; + auto it = external_includedir.find(name); + if(it != external_includedir.end()) + { + paths.push_back(it->second); + } + + auto res = findHeader(settings, header, paths); + if(res.empty()) + { + std::cout << "Header " << header << " required by " << name << + " not found.\n"; + return 1; + } + auto flag = "-I"s + res.string(); + flags.cxxflags.push_back(flag); + } + + for(const auto& lib : ext.libs) + { + std::vector paths; + auto it = external_libdir.find(name); + if(it != external_libdir.end()) + { + paths.push_back(it->second); + } + + auto res = findLibrary(settings, lib, paths); + if(res.empty()) + { + std::cout << "Library " << lib << " required by " << name << + " not found.\n"; + return 1; + } + auto flag = "-L"s + res[0].parent_path().string(); + flags.ldflags.push_back(flag); + flag = "-l"s + lib; + flags.ldflags.push_back(flag); + } + + return 0; +} + // helper constant for the visitor template inline constexpr bool always_false_v = false; @@ -288,7 +341,11 @@ int regenerateCache(const Settings& default_settings, std::visit([&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) + { + add_path_args(ext.name); + } + else if constexpr (std::is_same_v) { add_path_args(ext.name); } @@ -298,6 +355,24 @@ int regenerateCache(const Settings& default_settings, } }, ext.external); + /* + if(std::holds_alternative(ext.external)) + { + opt.add(ext.name + "-includedir", required_argument, key++, + "Set path to " + ext.name + " header file.", + [&]() { + //X_includedir = optarg; + return 0; + }); + + opt.add(ext.name + "-libdir", required_argument, key++, + "Set path to " + ext.name + " libraries.", + [&]() { + //X_libdir = optarg; + return 0; + }); + } + */ } opt.add("help", no_argument, 'h', @@ -434,6 +509,15 @@ int regenerateCache(const Settings& default_settings, return ret; } } + else if(std::holds_alternative(ext.external)) + { + if(auto ret = resolv(settings, ext.name, + std::get(ext.external), + resolved_flags)) + { + return ret; + } + } else { std::cout << "Unknown external type\n"; diff --git a/src/libctor.h b/src/libctor.h index 14fdf1d..9775085 100644 --- a/src/libctor.h +++ b/src/libctor.h @@ -69,7 +69,8 @@ struct Settings std::string builddir{"build"}; std::size_t parallel_processes{1}; int verbose{0}; // -1: completely silent, 0: normal, 1: verbose, ... -}; + std::vector include_paths{"/usr/include", "/usr/local/include"}; + std::vector library_paths{"/lib", "/usr/lib", "/usr/local/lib"};}; struct BuildConfiguration; using GeneratorCb = std::function headers; + std::vector libs; + Flags flags; +}; struct ExternalConfiguration { std::string name; // Name for configuration - std::variant external; + std::variant external; }; using ExternalConfigurations = std::vector; diff --git a/src/search.cc b/src/search.cc new file mode 100644 index 0000000..e33fc04 --- /dev/null +++ b/src/search.cc @@ -0,0 +1,120 @@ +#include "search.h" + +#include + +#include "libctor.h" + +// https://stackoverflow.com/questions/17939930/finding-out-what-the-gcc-include-path-is + +// /usr/include/ +// /usr/local/include +std::filesystem::path findFile(const Settings& settings, + const std::string& needle, + const std::vector& haystack) +{ + if(settings.verbose > 0) + { + std::cout << "Looking for '" << needle << "'\n"; + } + for(const auto& path : haystack) + { + std::filesystem::path candidate = std::filesystem::path(path) / needle; + if(settings.verbose > 1) + { + std::cout << " in '" << candidate.string() << "' ... "; + } + if(std::filesystem::exists(candidate)) + { + if(settings.verbose > 1) + { + std::cout << "yes\n"; + } + return path; + } + else + { + if(settings.verbose > 1) + { + std::cout << "no\n"; + } + } + } + + if(settings.verbose > 0) + { + std::cout << "Not found.\n"; + } + + return ""; // not found +} + +std::filesystem::path findHeader(const Settings& settings, + const std::string& needle, + const std::vector& haystack) +{ + auto paths = haystack; + paths.insert(paths.end(), + settings.include_paths.begin(), + settings.include_paths.end()); + return findFile(settings, needle, paths); +} + +std::vector findBasename(const Settings& settings, + const std::string& needle, + const std::vector& haystack) +{ + std::vector matches; + if(settings.verbose > 0) + { + std::cout << "Looking for basename '" << needle << "'\n"; + } + + for(const auto& path : haystack) + { + if(settings.verbose > 1) + { + std::cout << "Looking in '" << path << "\n"; + } + + for(const auto& dir_entry : std::filesystem::directory_iterator{path}) + { + if(std::filesystem::is_regular_file(dir_entry)) + { + if(dir_entry.path().stem() == needle) + { + if(settings.verbose > 1) + { + std::cout << "Found " << path / dir_entry.path() << "\n"; + } + matches.push_back(path / dir_entry.path()); + } + } + } + } + + if(matches.empty() && settings.verbose > 0) + { + std::cout << "Not found.\n"; + } + + return matches; +} + +std::vector findLibrary(const Settings& settings, + const std::string& needle, + const std::vector& haystack) +{ + using namespace std::string_literals; + + std::string lib = needle; + if(!lib.starts_with("lib")) + { + lib = "lib"s + needle; + } + auto paths = haystack; + paths.insert(paths.end(), + settings.library_paths.begin(), + settings.library_paths.end()); + return findBasename(settings, lib, paths); +} + diff --git a/src/search.h b/src/search.h new file mode 100644 index 0000000..1841978 --- /dev/null +++ b/src/search.h @@ -0,0 +1,37 @@ +// -*- c++ -*- +// Distributed under the BSD 2-Clause License. +// See accompanying file LICENSE for details. +#pragma once + +#include +#include +#include + +struct Settings; + +//! Locate file (needle) in the provided search path list (haystack) +//! The provided settings is used to control verbosity during the search. +//! \returns a std::filesystem::path pointing to path in which file was found +//! - empty if not found. +std::filesystem::path findFile(const Settings& settings, + const std::string& needle, + const std::vector& haystack); + +//! Locate header (needle) in the provided search path list (haystack) +//! The provided settings is used to control verbosity during the search as well +//! as providing the search paths defaults for headers. +//! The argument provided haystack is prepended to the one supplied by settings. +//! \returns a std::filesystem::path pointing to path where the file was found +//! - empty if not found. +std::filesystem::path findHeader(const Settings& settings, + const std::string& needle, + const std::vector& haystack); + + +std::vector findBasename(const Settings& settings, + const std::string& needle, + const std::vector& haystack); + +std::vector findLibrary(const Settings& settings, + const std::string& needle, + const std::vector& haystack); -- cgit v1.2.3