diff --git a/libpkg/CMakeLists.txt b/libpkg/CMakeLists.txt index 83259d6..4ec0682 100644 --- a/libpkg/CMakeLists.txt +++ b/libpkg/CMakeLists.txt @@ -50,7 +50,7 @@ set(META_VERSION_PATCH 1) set(CONFIGURATION_PACKAGE_SUFFIX "" CACHE STRING "sets the suffix for find_package() calls to packages configured via c++utilities") -find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.12.0 REQUIRED) +find_package(c++utilities${CONFIGURATION_PACKAGE_SUFFIX} 5.14.0 REQUIRED) use_cpp_utilities(VISIBILITY PUBLIC) # use std::filesystem diff --git a/libpkg/data/package.h b/libpkg/data/package.h index b7f1b25..97ff9cd 100644 --- a/libpkg/data/package.h +++ b/libpkg/data/package.h @@ -385,7 +385,8 @@ struct LIBPKG_EXPORT Package : public ReflectiveRapidJSON::JsonSerializable &dllsReferencedByImportLibs); + void addDepsAndProvidesFromContainedFile( + const std::string &directoryPath, const ArchiveFile &file, std::set &dllsReferencedByImportLibs); void addDepsAndProvidesFromContents(const FileMap &contents); std::vector processDllsReferencedByImportLibs(std::set &&dllsReferencedByImportLibs); bool addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force = false); diff --git a/libpkg/parser/binary.cpp b/libpkg/parser/binary.cpp index 27dae6a..678dbb1 100644 --- a/libpkg/parser/binary.cpp +++ b/libpkg/parser/binary.cpp @@ -1,3 +1,5 @@ +#define CPP_UTILITIES_PATHHELPER_STRING_VIEW + #include "./binary.h" #include @@ -176,19 +178,20 @@ ostream &operator<<(ostream &o, const BinaryClass &mode) return o; } -void Binary::load(const char *filePath) +void Binary::load(std::string_view filePath) { ifstream file; file.exceptions(ios_base::failbit | ios_base::badbit); - file.open(filePath, ios_base::in | ios_base::binary); + file.open(filePath.data(), ios_base::in | ios_base::binary); parse(file); switch (type) { case BinaryType::Pe: + // use name of library file as there's no soname filed in PEs name = fileName(filePath); break; case BinaryType::Elf: - if (auto ec = std::error_code(); - name.empty() && std::string_view(filePath).ends_with(".so") && std::filesystem::is_regular_file(filePath, ec) && !ec) { + // use name of regular file as library name if no soname could be determined + if (auto ec = std::error_code(); name.empty() && filePath.ends_with(".so") && std::filesystem::is_regular_file(filePath, ec) && !ec) { name = fileName(filePath); } break; @@ -196,7 +199,7 @@ void Binary::load(const char *filePath) } } -void Binary::load(const string &fileContent, const string &fileName, bool isRegularFile) +void Binary::load(const string &fileContent, const string &fileName, const string &directoryPath, bool isRegularFile) { stringstream fileStream(ios_base::in | ios_base::out | ios_base::binary); fileStream.exceptions(ios_base::failbit | ios_base::badbit); @@ -204,12 +207,20 @@ void Binary::load(const string &fileContent, const string &fileName, bool isRegu parse(fileStream, &fileContent); switch (type) { case BinaryType::Pe: + // use name of library file as there's no soname filed in PEs name = fileName; break; case BinaryType::Elf: + // use name of regular file as library name if no soname could be determined if (name.empty() && isRegularFile && fileName.ends_with(".so")) { name = fileName; } + // add prefix to Android libs to avoid confusion with normal GNU/Linux ELFs + // note: Relying on the path is not nice. Have Android libs any special header to be distinguishable? + if (directoryPath.starts_with("opt/android-libs") + || (directoryPath.starts_with("opt/android-ndk") && directoryPath.find("/sysroot/") != std::string::npos)) { + extraPrefix = "android-"; + } break; default:; } @@ -232,17 +243,17 @@ std::string Binary::addPrefix(const std::string &dependencyName) const { switch (type) { case BinaryType::Elf: - return argsToString("elf-", architecture, ':', ':', dependencyName); + return argsToString(extraPrefix, "elf-", architecture, ':', ':', dependencyName); case BinaryType::Pe: - return argsToString("pe-", architecture, ':', ':', toLower(dependencyName)); + return argsToString(extraPrefix, "pe-", architecture, ':', ':', toLower(dependencyName)); case BinaryType::Ar: switch (subType) { case BinarySubType::WindowsImportLibrary: - return argsToString("pe-", architecture, ':', ':', toLower(dependencyName)); + return argsToString(extraPrefix, "pe-", architecture, ':', ':', toLower(dependencyName)); default:; } default: - return "unknown::" + dependencyName; + return argsToString(extraPrefix, "unknown::", dependencyName); } } diff --git a/libpkg/parser/binary.h b/libpkg/parser/binary.h index 14174e0..5564c9e 100644 --- a/libpkg/parser/binary.h +++ b/libpkg/parser/binary.h @@ -82,13 +82,14 @@ inline VirtualAddressMapping::VirtualAddressMapping() } struct LIBPKG_EXPORT Binary { - void load(const char *filePath); - void load(const std::string &fileContent, const std::string &fileName, bool isRegularFile = false); + void load(std::string_view filePath); + void load(const std::string &fileContent, const std::string &fileName, const std::string &directoryPath, bool isRegularFile = false); std::string addPrefix(const std::string &dependencyName) const; BinaryType type = BinaryType::Invalid; BinarySubType subType = BinarySubType::None; std::string name; + std::string_view extraPrefix; BinaryClass binaryClass = BinaryClass::Invalid; bool isBigEndian = false; std::string architecture; diff --git a/libpkg/parser/package.cpp b/libpkg/parser/package.cpp index 7772a9a..d39edee 100644 --- a/libpkg/parser/package.cpp +++ b/libpkg/parser/package.cpp @@ -750,7 +750,7 @@ void Package::addInfoFromPkgInfoFile(const string &info) static const regex pythonVersionRegex("usr/lib/python(2|3)\\.([0-9]*)(\\..*)?/site-packages"); static const regex perlVersionRegex("usr/lib/perl5/5\\.([0-9]*)(\\..*)?/vendor_perl"); -void Package::addDepsAndProvidesFromContainedDirectory(const string &directoryPath) +void Package::addDepsAndProvidesFromContainedDirectory(const std::string &directoryPath) { // check for Python modules thread_local smatch match; @@ -774,11 +774,12 @@ void Package::addDepsAndProvidesFromContainedDirectory(const string &directoryPa } } -void Package::addDepsAndProvidesFromContainedFile(const ArchiveFile &file, std::set &dllsReferencedByImportLibs) +void Package::addDepsAndProvidesFromContainedFile( + const std::string &directoryPath, const ArchiveFile &file, std::set &dllsReferencedByImportLibs) { try { Binary binary; - binary.load(file.content, file.name, file.type == ArchiveFileType::Regular); + binary.load(file.content, file.name, directoryPath, file.type == ArchiveFileType::Regular); if (!binary.name.empty()) { if (binary.type == BinaryType::Ar && binary.subType == BinarySubType::WindowsImportLibrary) { dllsReferencedByImportLibs.emplace(binary.addPrefix(binary.name)); @@ -826,7 +827,7 @@ void Package::addDepsAndProvidesFromContents(const FileMap &contents) for (const auto &[directoryPath, files] : contents) { addDepsAndProvidesFromContainedDirectory(directoryPath); for (const auto &file : files) { - addDepsAndProvidesFromContainedFile(file, dllsReferencedByImportLibs); + addDepsAndProvidesFromContainedFile(directoryPath, file, dllsReferencedByImportLibs); } } processDllsReferencedByImportLibs(std::move(dllsReferencedByImportLibs)); @@ -850,7 +851,7 @@ std::shared_ptr Package::fromPkgFile(const string &path) } return; } - tmpPackageForLibraryDeps.addDepsAndProvidesFromContainedFile(file, dllsReferencedByImportLibs); + tmpPackageForLibraryDeps.addDepsAndProvidesFromContainedFile(directoryPath, file, dllsReferencedByImportLibs); }, [&tmpPackageForLibraryDeps](std::string &&directoryPath) { if (directoryPath.empty()) { diff --git a/libpkg/tests/parser_binary.cpp b/libpkg/tests/parser_binary.cpp index 01eeb7a..0276d01 100644 --- a/libpkg/tests/parser_binary.cpp +++ b/libpkg/tests/parser_binary.cpp @@ -58,7 +58,7 @@ void BinaryParserTests::tearDown() void BinaryParserTests::testParsingElf() { Binary bin; - bin.load(testFilePath("c++utilities/libc++utilities.so.4.5.0").data()); + bin.load(testFilePath("c++utilities/libc++utilities.so.4.5.0")); CPPUNIT_ASSERT_EQUAL_MESSAGE("type", BinaryType::Elf, bin.type); CPPUNIT_ASSERT_EQUAL_MESSAGE("class", BinaryClass::Class64Bit, bin.binaryClass); CPPUNIT_ASSERT_EQUAL_MESSAGE("sub type", BinarySubType::SharedObject, bin.subType); @@ -72,7 +72,7 @@ void BinaryParserTests::testParsingElf() void BinaryParserTests::testParsingPe() { Binary bin; - bin.load(testFilePath("c++utilities/c++utilities.dll").data()); + bin.load(testFilePath("c++utilities/c++utilities.dll")); CPPUNIT_ASSERT_EQUAL_MESSAGE("type", BinaryType::Pe, bin.type); CPPUNIT_ASSERT_EQUAL_MESSAGE("arch", "x86_64"s, bin.architecture); CPPUNIT_ASSERT_EQUAL_MESSAGE("name", "c++utilities.dll"s, bin.name); @@ -84,7 +84,7 @@ void BinaryParserTests::testParsingPe() void BinaryParserTests::testParsingAr() { Binary bin; - bin.load(testFilePath("mingw-w64-crt/libkernel32.a").data()); + bin.load(testFilePath("mingw-w64-crt/libkernel32.a")); CPPUNIT_ASSERT_EQUAL_MESSAGE("type", BinaryType::Ar, bin.type); CPPUNIT_ASSERT_EQUAL_MESSAGE("arch", "x86_64"s, bin.architecture); CPPUNIT_ASSERT_EQUAL_MESSAGE("name", "KERNEL32.dll"s, bin.name); diff --git a/libpkg/tests/parser_helper.cpp b/libpkg/tests/parser_helper.cpp index ca4cf44..be6b6a6 100644 --- a/libpkg/tests/parser_helper.cpp +++ b/libpkg/tests/parser_helper.cpp @@ -105,9 +105,8 @@ void checkSyncthingTrayPackageSoDependencies(const Package &package) { CPPUNIT_ASSERT_EQUAL_MESSAGE("origin", PackageOrigin::PackageContents, package.origin); CPPUNIT_ASSERT_EQUAL_MESSAGE("file name"s, "syncthingtray-0.6.2-1-x86_64.pkg.tar.xz"s, package.packageInfo->fileName); - const set sonames( - { "elf-x86_64::libsyncthingwidgets.so.0.6.2", "elf-x86_64::libsyncthingmodel.so.0.6.2", "elf-x86_64::libsyncthingconnector.so.0.6.2", - "elf-x86_64::libsyncthingfileitemaction.so" }); + const set sonames({ "elf-x86_64::libsyncthingwidgets.so.0.6.2", "elf-x86_64::libsyncthingmodel.so.0.6.2", + "elf-x86_64::libsyncthingconnector.so.0.6.2", "elf-x86_64::libsyncthingfileitemaction.so" }); CPPUNIT_ASSERT_EQUAL_MESSAGE("library provides from sonames"s, sonames, package.libprovides); const set required({ "elf-x86_64::libqtutilities.so.5", "elf-x86_64::libsyncthingmodel.so.0.6.2", "elf-x86_64::libKF5KIOWidgets.so.5", "elf-x86_64::libsyncthingconnector.so.0.6.2", "elf-x86_64::libsyncthingwidgets.so.0.6.2", "elf-x86_64::libKF5KIOCore.so.5",