diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 8f58228..ce2d276 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -20,13 +20,13 @@ jobs: run: | mkdir build cd build - CXX=g++-8 cmake -DCMAKE_BUILD_TYPE="Release" .. + CXX=g++-8 cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_CXX_FLAGS="-Wall -Wextra" -DCMAKE_CXX_FLAGS_RELEASE="-O2" .. make -j$(nproc) - name: Bundle run: | - ./build/bundler -e ./build/bundler -e $(which chrpath) -e $(which strip) -d bundler - cp src/bundler bundler/bundler - tar -zcvf bundler_x86_64.tar.gz bundler + ./build/libtree -e ./build/libtree -e $(which chrpath) -e $(which strip) -d libtree + cp src/libtree libtree/libtree + tar -zcvf libtree_x86_64.tar.gz libtree - name: Create Release id: create_release uses: actions/create-release@v1 @@ -44,6 +44,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./bundler_x86_64.tar.gz - asset_name: bundler_x86_64.tar.gz + asset_path: ./libtree_x86_64.tar.gz + asset_name: libtree_x86_64.tar.gz asset_content_type: application/gzip diff --git a/.gitignore b/.gitignore index ee4a420..802294b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ main *.swp build/ +Dockerfile diff --git a/CMakeLists.txt b/CMakeLists.txt index 081e6f1..b1e6019 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required (VERSION 3.0) -project (bundler) +project (libtree) message(STATUS "Generating excludelist") execute_process( @@ -18,8 +18,8 @@ set(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/ld.cpp ) -add_executable(bundler ${SOURCE}) -target_link_libraries(bundler cxxopts termcolor cppglob ELFIO) -target_include_directories(bundler PRIVATE include deps/cppglob/include ${CMAKE_CURRENT_BINARY_DIR}) +add_executable(libtree ${SOURCE}) +target_link_libraries(libtree cxxopts termcolor cppglob ELFIO) +target_include_directories(libtree PRIVATE include deps/cppglob/include ${CMAKE_CURRENT_BINARY_DIR}) -set_property(TARGET bundler PROPERTY CXX_STANDARD 17) +set_property(TARGET libtree PROPERTY CXX_STANDARD 17) diff --git a/README.md b/README.md index 37ae7a4..7363a69 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -# bundler +# libtree A tool that: -- :deciduous_tree: turns `ldd` into a fancy tree -- :point_up: explains why `ldd` finds shared libraries and why not -- :package: optionally deploys relevant executables and dependencies into a single directory +- :deciduous_tree: turns `ldd` into a tree +- :point_up: explains why shared libraries are found and why not +- :package: optionally deploys executables and dependencies into a single directory ## Installation -Download the [**latest release**](https://github.com/haampie/bundler/releases) from Github: +Download the [**latest release**](https://github.com/haampie/libtree/releases) from Github: -``` -- wget https://github.com/haampie/bundler/releases/download/v0.1.5/bundler_x86_64.tar.gz -- tar -xzf bundler_x86_64.tar.gz -- ./bundler/bundler -e $(which man) +```bash +$ wget https://github.com/haampie/libtree/releases/download/v1.0.0/libtree_x86_64.tar.gz +$ tar -xzf libtree_x86_64.tar.gz +$ ./libtree/libtree $(which man) ``` ## Example 1: listing the dependencies of an executable @@ -20,27 +20,20 @@ Download the [**latest release**](https://github.com/haampie/bundler/releases) f ## Example 2: deploying binaries + dependencies into a folder: ```bash -$ bundler -e $(which bundler) -d bundler.bundle -Dependency tree -bundler -├── libcppglob.so.1 [runpath] -│ ├── libstdc++.so.6 (skipped) [ld.so.conf] -│ ├── libgcc_s.so.1 (skipped) [ld.so.conf] -│ └── libc.so.6 (skipped) [ld.so.conf] -├── libstdc++.so.6 (skipped) [ld.so.conf] -├── libgcc_s.so.1 (skipped) [ld.so.conf] -└── libc.so.6 (skipped) [ld.so.conf] +$ libtree $(which libtree) -d libtree.bundle --chrpath --strip +libtree +└── libcppglob.so.1 [runpath] -Deploying to "bundler.bundle/usr" -"/home/.../Documents/projects/bundler/build/bundler" => "bundler.bundle/usr/bin/bundler" -"/home/.../Documents/projects/bundler/build/lib/libcppglob.so.1.1.0" => "bundler.bundle/usr/lib/libcppglob.so.1.1.0" - creating symlink "bundler.bundle/usr/lib/libcppglob.so.1" +Deploying to "libtree.bundle/usr" +"/bundler/build/libtree" => "libtree.bundle/usr/bin/libtree" +"/bundler/build/lib/libcppglob.so.1.1.0" => "libtree.bundle/usr/lib/libcppglob.so.1.1.0" + creating symlink "libtree.bundle/usr/lib/libcppglob.so.1" -$ tree bundler.bundle/ -bundler.bundle/ +$ tree libtree.bundle/ +libtree.bundle/ └── usr ├── bin - │   └── bundler + │ └── libtree └── lib ├── libcppglob.so.1 -> libcppglob.so.1.1.0 └── libcppglob.so.1.1.0 @@ -48,23 +41,31 @@ bundler.bundle/ 3 directories, 3 files ``` +## Verbose output +By default certain standard depenendencies are not shown. For more verbose output use +- `libtree -v $(which man)` to show skipped libraries without their children +- `libtree -a $(which apt-get)` to show the full recursive list of libraries + +## Changing search paths +`libtree` follows the rules of `ld.so` to locate libraries, but does not use `ldconfig`'s +cache. Instead it parses `/etc/ld.so.conf` runtime. The location of the `ld.so` config +can be changed as well by setting `--ldconf mylibs.conf`. + +Search paths can be added at runtime as well via `LD_LIBRARY_PATH=path libtree ...`. + ## Build from source ```bash -git clone --recursive https://github.com/haampie/bundler.git -cd bundler +git clone --recursive https://github.com/haampie/libtree.git +cd libtree mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release .. make ``` -## Current functionality -- [x] Add executables with `-e` and libraries via `-l` -- [x] Walks the dependency tree like `ld.so` (handles `RPATH`, `RUNPATH` and `LD_LIBRARY_PATH` correctly). -- [x] Uses `/etc/ld.so.conf` or any custom conf file via `-ldconf /path/to/ld.so.conf` -- [x] Skips blacklisted dependencies (and their dependencies) such as libc.so and libstdc++.so. -- [x] Deploy binaries and rewrite their `RUNPATH`s\* -- [x] Ship `chrpath` and `strip` -- [ ] i386 (currently it's hardcoded to only deploy x86_64) - -\* Note: `patchelf` seems to be very broken software, so instead I'm using `chrpath`. The downside is `chrpath` will only patch rpaths _when they already exist in the binary_. Therefore you might still need to add the `yourapp/lib` folder to ld's search paths by running `echo /path/to/yourapp.bundle/lib > /etc/ld.so.conf/my_app.conf && ldconfig` or by setting `LD_LIBRARY_PATH=/path/to/yourapp.bundle/lib`. +## Known issues +- When deploying libs with `libtree app -d folder.bundle --chrpath`, the runpaths are only + changed when the binaries already have an an rpath or runpath. This is a limitation of + `chrpath`. Another option is to use `patchelf` instead, but this tool is known to break + binaries sometimes. +- There's no support yet for i386. diff --git a/doc/screenshot.png b/doc/screenshot.png index 482df64..b92b226 100644 Binary files a/doc/screenshot.png and b/doc/screenshot.png differ diff --git a/include/bundler/deploy.hpp b/include/libtree/deploy.hpp similarity index 93% rename from include/bundler/deploy.hpp rename to include/libtree/deploy.hpp index 4726e58..e95bf8d 100644 --- a/include/bundler/deploy.hpp +++ b/include/libtree/deploy.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/include/bundler/deps.hpp b/include/libtree/deps.hpp similarity index 57% rename from include/bundler/deps.hpp rename to include/libtree/deps.hpp index 2a9ce4e..a94a38a 100644 --- a/include/bundler/deps.hpp +++ b/include/libtree/deps.hpp @@ -1,22 +1,37 @@ #pragma once -#include +#include #include #include #include #include +template struct overloaded : Ts... { using Ts::operator()...; }; +template overloaded(Ts...) -> overloaded; + class deps { public: - deps(std::vector &&input, std::vector &&ld_so_conf, std::vector && ld_library_paths, bool verbose); + enum class verbosity_t {NONE, VERBOSE, VERY_VERBOSE}; + + deps( + std::vector &&input, + std::vector &&ld_so_conf, + std::vector &&ld_library_paths, + std::unordered_set &&skip, + verbosity_t verbose + ); std::vector const &get_deps() const; private: void explore(Elf const &elf, std::vector &rpaths, std::vector &done); void explore(Elf const &elf, std::vector &rpaths); + void print_error(fs::path const &lib, std::vector const &rpaths, std::vector const &runpaths, std::vector const &done) const; + + std::string get_indent(std::vector const &done) const; + std::string get_error_indent(std::vector const &done) const; std::optional locate(Elf const &parent, fs::path const &so, std::vector const &rpaths, std::vector const &runpaths); std::optional locate_directly(Elf const &parent, fs::path const &so); @@ -29,8 +44,9 @@ class deps { std::vector m_ld_so_conf; std::vector m_default_paths{"/lib", "/usr/lib"}; std::unordered_set m_visited; + std::unordered_set m_skip; std::vector m_all_binaries; - bool m_verbose; + verbosity_t m_verbosity; }; \ No newline at end of file diff --git a/include/bundler/elf.hpp b/include/libtree/elf.hpp similarity index 100% rename from include/bundler/elf.hpp rename to include/libtree/elf.hpp diff --git a/include/bundler/exec.hpp b/include/libtree/exec.hpp similarity index 100% rename from include/bundler/exec.hpp rename to include/libtree/exec.hpp diff --git a/include/bundler/ld.hpp b/include/libtree/ld.hpp similarity index 100% rename from include/bundler/ld.hpp rename to include/libtree/ld.hpp diff --git a/src/deploy.cpp b/src/deploy.cpp index 202c30e..04f6cc8 100644 --- a/src/deploy.cpp +++ b/src/deploy.cpp @@ -1,28 +1,30 @@ -#include -#include +#include +#include #include // Copy binaries over, change their rpath if they have it, and strip them void deploy(std::vector const &deps, fs::path const &bin, fs::path const &lib, fs::path const &chrpath_path, fs::path const &strip_path, bool chrpath, bool strip) { for (auto const &elf : deps) { - // Go through all symlinks. auto canonical = fs::canonical(elf.abs_path); - //Copy to the deploy folder + // Copy to the deploy folder auto deploy_folder = (elf.type == deploy_t::EXECUTABLE ? bin : lib); auto deploy_path = deploy_folder / canonical.filename(); fs::copy_file(canonical, deploy_path, fs::copy_options::overwrite_existing); std::cout << termcolor::green << canonical << termcolor::reset << " => " << termcolor::green << deploy_path << termcolor::reset << '\n'; + // Create all symlinks - for (auto link = elf.abs_path; fs::is_symlink(link); link = fs::read_symlink(link)) { - auto link_destination = deploy_folder / link.filename(); - fs::remove(link_destination); - fs::create_symlink(deploy_path.filename(), link_destination); - - std::cout << " " << termcolor::yellow << "creating symlink " << link_destination << '\n'; + if (elf.type == deploy_t::LIBRARY) { + for (auto link = elf.abs_path; fs::is_symlink(link); link = fs::read_symlink(link)) { + auto link_destination = deploy_folder / link.filename(); + fs::remove(link_destination); + fs::create_symlink(deploy_path.filename(), link_destination); + + std::cout << " " << termcolor::yellow << "creating symlink " << link_destination << termcolor::reset << '\n'; + } } auto rpath = (elf.type == deploy_t::EXECUTABLE ? "\\$ORIGIN/../lib" : "\\$ORIGIN"); diff --git a/src/deps.cpp b/src/deps.cpp index 84f34a5..c0c2bb0 100644 --- a/src/deps.cpp +++ b/src/deps.cpp @@ -1,10 +1,10 @@ -#include +#include #include #include #include -#include "excludelist.h" +#include std::string repeat(std::string_view input, size_t num) { @@ -13,11 +13,17 @@ std::string repeat(std::string_view input, size_t num) return os.str(); } -deps::deps(std::vector &&input, std::vector &&ld_so_conf, std::vector && ld_library_paths, bool verbose) +deps::deps( + std::vector &&input, + std::vector &&ld_so_conf, + std::vector &&ld_library_paths, + std::unordered_set &&skip, + deps::verbosity_t verbose) : m_top_level(std::move(input)), - m_ld_so_conf(std::move(ld_so_conf)), m_ld_library_paths(std::move(ld_library_paths)), - m_verbose(verbose) + m_ld_so_conf(std::move(ld_so_conf)), + m_skip(std::move(skip)), + m_verbosity(verbose) { std::vector rpaths; for (auto const &elf : m_top_level) @@ -33,38 +39,46 @@ void deps::explore(Elf const &elf, std::vector &rpaths) { explore(elf, rpaths, done); } -void deps::explore(Elf const &elf, std::vector &rpaths, std::vector &done) { +std::string deps::get_indent(std::vector const &done) const { + std::string indent; + + for (size_t idx = 0; idx + 1 < done.size(); ++idx) + indent += done[idx] ? " " : "│ "; + + if (done.size() != 0) + indent += done.back() ? "└── " : "├── "; + + return indent; +} + +std::string deps::get_error_indent(std::vector const &done) const { std::string indent; - for (size_t idx = 0; idx < done.size(); ++idx) { - if (done[idx]) { - if (idx + 1 == done.size()) - indent += "└── "; - else - indent += " "; - } else { - if (idx + 1 == done.size()) - indent += "├── "; - else - indent += "│ "; - } - } - auto cached = m_visited.count(elf.name) > 0; - auto search = std::find(generatedExcludelist.begin(), generatedExcludelist.end(), elf.name); - auto excluded = search != generatedExcludelist.end(); + for (size_t idx = 0; idx + 1 < done.size(); ++idx) + indent += done[idx] ? " " : "│ "; + + if (done.size() != 0) + indent += " "; + return indent; +} + +void deps::explore(Elf const &parent, std::vector &rpaths, std::vector &done) { + auto indent = get_indent(done); + auto cached = m_visited.count(parent.name) > 0; + auto excluded = m_skip.count(parent.name) > 0; - std::cout << indent << (excluded ? termcolor::magenta : cached ? termcolor::blue : termcolor::yellow); + std::cout << indent << (excluded ? termcolor::magenta : cached ? termcolor::blue : termcolor::cyan); if (!excluded && !cached) std::cout << termcolor::bold; - std::cout << elf.name + std::cout << parent.name << (excluded ? " (skipped)" : cached ? " (visited)" : "") << termcolor::reset; - std::cout << termcolor::magenta; - switch(elf.found_via) { - case found_t::NONE: break; + std::cout << (excluded ? termcolor::magenta : cached ? termcolor::blue : termcolor::yellow); + switch(parent.found_via) { + case found_t::NONE: break; case found_t::DIRECT: std::cout << " [direct]"; break; case found_t::RPATH: std::cout << " [rpath]"; break; case found_t::LD_LIBRARY_PATH: std::cout << " [LD_LIBRARY_PATH]"; break; @@ -76,50 +90,79 @@ void deps::explore(Elf const &elf, std::vector &rpaths, std::vector> children; + + // First detect all needed libs + for (auto const &lib : parent.needed) { + auto result = locate(parent, lib, total_rpaths, parent.runpaths); + + if (m_verbosity == verbosity_t::NONE && result && m_skip.count(result->name) > 0) + continue; + + if (result) + children.push_back(*result); + else + children.push_back(lib); + } // Recurse deeper done.push_back(false); - for (size_t idx = 0; idx < elf.needed.size(); ++idx) { + for (size_t idx = 0; idx < children.size(); ++idx) { // Set to true if this is the last child we're visiting. - if (idx + 1 == elf.needed.size()) + if (idx + 1 == children.size()) done[done.size() - 1] = true; - auto result = locate(elf, elf.needed[idx], total_rpaths, elf.runpaths); - - if (result) - explore(*result, total_rpaths, done); - else { - std::string whitespaces(indent.size(), ' '); - std::cout << indent << termcolor::red << termcolor::bold << "ERROR could not find " << elf.name << ". \n" << termcolor::reset - << whitespaces << termcolor::blue << "RPATH: " << termcolor::reset; - std::copy(total_rpaths.begin(), total_rpaths.end(), std::ostream_iterator(std::cout, ":")); - std::cout << '\n' - << whitespaces << termcolor::blue << "RUNPATH: " << termcolor::reset; - std::copy(elf.runpaths.begin(), elf.runpaths.end(), std::ostream_iterator(std::cout, ":")); - std::cout << '\n' - << whitespaces << termcolor::blue << "LD_LIBRARY_PATH: " << termcolor::reset; - std::copy(m_ld_library_paths.begin(), m_ld_library_paths.end(), std::ostream_iterator(std::cout, ":")); - std::cout << '\n' - << whitespaces << termcolor::blue << "/etc/ld.so.conf: " << termcolor::reset; - std::copy(m_ld_so_conf.begin(), m_ld_so_conf.end(), std::ostream_iterator(std::cout, ":")); - std::cout << '\n'; - } + std::visit(overloaded { + [&](Elf const &lib) { explore(lib, total_rpaths, done); }, + [&](fs::path const &lib) { print_error(lib, total_rpaths, parent.runpaths, done); } + }, children[idx]); } done.pop_back(); } +void deps::print_error(fs::path const &lib, std::vector const &rpaths, std::vector const &runpaths, std::vector const &done) const { + + auto indent = get_indent(done); + std::string whitespaces = get_error_indent(done); + std::cout << indent << termcolor::bold << termcolor::red << lib.string() << " not found: " << termcolor::reset + << termcolor::blue << "RPATH " << termcolor::reset; + if (rpaths.empty()) + std::cout << "(empty)"; + else + std::copy(rpaths.begin(), rpaths.end(), std::ostream_iterator(std::cout, ":")); + std::cout << ' ' << termcolor::blue << "LD_LIBRARY_PATH " << termcolor::reset; + if (m_ld_library_paths.empty()) + std::cout << "(empty)"; + else + std::copy(m_ld_library_paths.begin(), m_ld_library_paths.end(), std::ostream_iterator(std::cout, ":")); + std::cout << ' ' << termcolor::blue << "RUNPATH " << termcolor::reset; + if (runpaths.empty()) + std::cout << "(empty)"; + else + std::copy(runpaths.begin(), runpaths.end(), std::ostream_iterator(std::cout, ":")); + std::cout << ' ' << termcolor::blue << "/etc/ld.so.conf " << termcolor::reset; + if (m_ld_so_conf.empty()) + std::cout << "(empty)"; + else + std::copy(m_ld_so_conf.begin(), m_ld_so_conf.end(), std::ostream_iterator(std::cout, ":")); + std::cout << '\n'; +} + std::optional deps::locate(Elf const &parent, fs::path const &so, std::vector const &rpaths, std::vector const &runpaths) { // Empty, not sure if that even can happen... but it's a no-go. if (so.empty()) diff --git a/src/elf.cpp b/src/elf.cpp index 7eaeae0..b2568a5 100644 --- a/src/elf.cpp +++ b/src/elf.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/src/exec.cpp b/src/exec.cpp index 867d050..ec08b19 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/src/generate_exclude_list.sh b/src/generate_exclude_list.sh index a987cf9..f85adcb 100644 --- a/src/generate_exclude_list.sh +++ b/src/generate_exclude_list.sh @@ -48,9 +48,9 @@ cat > "$tempfile" <<\EOF */ #include -#include +#include -static std::vector generatedExcludelist = { +static std::unordered_set generatedExcludelist = { EOF # create array diff --git a/src/ld.cpp b/src/ld.cpp index 06c057b..3af0e44 100644 --- a/src/ld.cpp +++ b/src/ld.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/src/bundler b/src/libtree similarity index 85% rename from src/bundler rename to src/libtree index a6e43e4..0de1943 100755 --- a/src/bundler +++ b/src/libtree @@ -5,4 +5,4 @@ DIR=$(dirname $(readlink -f $0)) export LD_LIBRARY_PATH="$DIR/usr/lib:$LD_LIBRARY_PATH" export PATH="$DIR/usr/bin:$PATH" -$DIR/usr/bin/bundler $@ +$DIR/usr/bin/libtree $@ diff --git a/src/main.cpp b/src/main.cpp index 62e8d8d..d8dd5d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,63 +3,70 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include namespace fs = std::filesystem; +bool is_lib(fs::path const &p) { + if (!p.has_extension()) + return false; + + if (p.stem().string().find("lib") != 0) + return false; + + return p.extension().string().find("so") == 0; +} + int main(int argc, char ** argv) { - cxxopts::Options options("bundler", "Show the dependency tree of binaries and optionally bundle them into a single folder"); + cxxopts::Options options("libtree", "Show the dependency tree of binaries and optionally bundle them into a single folder"); // Use the strip and chrpath that we ship if we can detect them std::string strip = "strip"; std::string chrpath = "chrpath"; - options.add_options("(A) bundler as ldd replacement") - ("e,executable", "Deploy or inspect executable", cxxopts::value>()) - ("l,library", "Deploy or inspect shared library", cxxopts::value>()) - ("ldconf", "Path to custom ld.conf to test settings", cxxopts::value()->default_value("/etc/ld.so.conf")) - ("s,skip", "Skip library and its dependencies from being deployed or inspected", cxxopts::value>()); + options.positional_help("binary [more binaries...]"); + + options.add_options("A: Locating libs") + ("v,verbose", "Show the skipped libraries without their children", cxxopts::value()->default_value("false")) + ("a,all", "Show the skipped libraries and their children", cxxopts::value()->default_value("false")) + ("l,ldconf", "Path to custom ld.conf to test settings", cxxopts::value()->default_value("/etc/ld.so.conf")) + ("s,skip", "Skip library and its dependencies from being deployed or inspected", cxxopts::value>()) + ("b,binary", "Binary to inspect", cxxopts::value>()); - options.add_options("(B) bundler as bundler") + options.add_options("B: Copying libs") ("d,destination", "OPTIONAL: When a destination is set to a folder, all binaries and their dependencies are copied over", cxxopts::value()) - ("disable-strip", "Do not call strip on binaries when deploying", cxxopts::value()->default_value("false")) - ("disable-chrpath", "Do not call chrpath on binaries when deploying", cxxopts::value()->default_value("false")); + ("strip", "Call strip on binaries when deploying", cxxopts::value()->default_value("false")) + ("chrpath", "Call chrpath on binaries when deploying", cxxopts::value()->default_value("false")); options.add_options()("h,help", "Print usage"); + options.parse_positional("binary"); auto result = options.parse(argc, argv); std::vector pool; - if (result["executable"].count()) { - for (auto f : result["executable"].as>()) { - auto val = from_path(deploy_t::EXECUTABLE, found_t::NONE, f); + if (result["binary"].count()) { + for (auto const &f : result["binary"].as>()) { + auto type = is_lib(fs::canonical(f)) ? deploy_t::LIBRARY : deploy_t::EXECUTABLE; + auto val = from_path(type, found_t::NONE, f); if (val != std::nullopt) pool.push_back(*val); } } - if (result["library"].count()) { - for (auto const &f : result["library"].as>()) { - auto val = from_path(deploy_t::LIBRARY, found_t::NONE, f); - if (val != std::nullopt) - pool.push_back(*val); - } - } - - if (result.count("help") || pool.size() == 0) - { + if (result.count("help") || pool.size() == 0) { std::cout << options.help() << std::endl; return 0; } if (result["skip"].count()) { auto const &list = result["skip"].as>(); - std::copy(list.begin(), list.end(), std::back_inserter(generatedExcludelist)); + for (auto const &lib : list) + generatedExcludelist.insert(lib); } // Fill ld library path from the env variable @@ -70,13 +77,14 @@ int main(int argc, char ** argv) { ld_library_paths.push_back(path); // Default search paths is ldconfig + /lib + /usr/lib - auto search_directories = parse_ld_conf(result["ldconf"].as()); - search_directories.push_back("/lib"); - search_directories.push_back("/usr/lib"); + auto ld_conf = parse_ld_conf(result["ldconf"].as()); // Walk the dependency tree - std::cout << termcolor::bold << "Dependency tree" << termcolor::reset << '\n'; - deps tree{std::move(pool), std::move(search_directories), std::move(ld_library_paths), true}; + deps::verbosity_t verbosity = result.count("all") ? deps::verbosity_t::VERY_VERBOSE + : result.count("v") ? deps::verbosity_t::VERBOSE + : deps::verbosity_t::NONE; + + deps tree{std::move(pool), std::move(ld_conf), std::move(ld_library_paths), std::move(generatedExcludelist), verbosity}; std::cout << '\n'; @@ -91,6 +99,6 @@ int main(int argc, char ** argv) { fs::create_directories(bin_dir); fs::create_directories(lib_dir); - deploy(tree.get_deps(), bin_dir, lib_dir, chrpath, strip, !result["disable-chrpath"].as(), !result["disable-strip"].as()); + deploy(tree.get_deps(), bin_dir, lib_dir, chrpath, strip, result["chrpath"].as(), result["strip"].as()); } }