Distinguish Android libs from GNU/Linux libs

This commit is contained in:
Martchus 2022-03-04 21:48:28 +01:00
parent 3d3ba1457a
commit 1f3abd5596
7 changed files with 37 additions and 24 deletions

View File

@ -50,7 +50,7 @@ set(META_VERSION_PATCH 1)
set(CONFIGURATION_PACKAGE_SUFFIX set(CONFIGURATION_PACKAGE_SUFFIX
"" ""
CACHE STRING "sets the suffix for find_package() calls to packages configured via c++utilities") 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_cpp_utilities(VISIBILITY PUBLIC)
# use std::filesystem # use std::filesystem

View File

@ -385,7 +385,8 @@ struct LIBPKG_EXPORT Package : public ReflectiveRapidJSON::JsonSerializable<Pack
PackageNameData decomposeName() const; PackageNameData decomposeName() const;
void addInfoFromPkgInfoFile(const std::string &info); void addInfoFromPkgInfoFile(const std::string &info);
void addDepsAndProvidesFromContainedDirectory(const std::string &directoryPath); void addDepsAndProvidesFromContainedDirectory(const std::string &directoryPath);
void addDepsAndProvidesFromContainedFile(const ArchiveFile &file, std::set<std::string> &dllsReferencedByImportLibs); void addDepsAndProvidesFromContainedFile(
const std::string &directoryPath, const ArchiveFile &file, std::set<std::string> &dllsReferencedByImportLibs);
void addDepsAndProvidesFromContents(const FileMap &contents); void addDepsAndProvidesFromContents(const FileMap &contents);
std::vector<std::string> processDllsReferencedByImportLibs(std::set<std::string> &&dllsReferencedByImportLibs); std::vector<std::string> processDllsReferencedByImportLibs(std::set<std::string> &&dllsReferencedByImportLibs);
bool addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force = false); bool addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force = false);

View File

@ -1,3 +1,5 @@
#define CPP_UTILITIES_PATHHELPER_STRING_VIEW
#include "./binary.h" #include "./binary.h"
#include <c++utilities/conversion/stringbuilder.h> #include <c++utilities/conversion/stringbuilder.h>
@ -176,19 +178,20 @@ ostream &operator<<(ostream &o, const BinaryClass &mode)
return o; return o;
} }
void Binary::load(const char *filePath) void Binary::load(std::string_view filePath)
{ {
ifstream file; ifstream file;
file.exceptions(ios_base::failbit | ios_base::badbit); 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); parse(file);
switch (type) { switch (type) {
case BinaryType::Pe: case BinaryType::Pe:
// use name of library file as there's no soname filed in PEs
name = fileName(filePath); name = fileName(filePath);
break; break;
case BinaryType::Elf: case BinaryType::Elf:
if (auto ec = std::error_code(); // use name of regular file as library name if no soname could be determined
name.empty() && std::string_view(filePath).ends_with(".so") && std::filesystem::is_regular_file(filePath, ec) && !ec) { if (auto ec = std::error_code(); name.empty() && filePath.ends_with(".so") && std::filesystem::is_regular_file(filePath, ec) && !ec) {
name = fileName(filePath); name = fileName(filePath);
} }
break; 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); stringstream fileStream(ios_base::in | ios_base::out | ios_base::binary);
fileStream.exceptions(ios_base::failbit | ios_base::badbit); 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); parse(fileStream, &fileContent);
switch (type) { switch (type) {
case BinaryType::Pe: case BinaryType::Pe:
// use name of library file as there's no soname filed in PEs
name = fileName; name = fileName;
break; break;
case BinaryType::Elf: 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")) { if (name.empty() && isRegularFile && fileName.ends_with(".so")) {
name = fileName; 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; break;
default:; default:;
} }
@ -232,17 +243,17 @@ std::string Binary::addPrefix(const std::string &dependencyName) const
{ {
switch (type) { switch (type) {
case BinaryType::Elf: case BinaryType::Elf:
return argsToString("elf-", architecture, ':', ':', dependencyName); return argsToString(extraPrefix, "elf-", architecture, ':', ':', dependencyName);
case BinaryType::Pe: case BinaryType::Pe:
return argsToString("pe-", architecture, ':', ':', toLower(dependencyName)); return argsToString(extraPrefix, "pe-", architecture, ':', ':', toLower(dependencyName));
case BinaryType::Ar: case BinaryType::Ar:
switch (subType) { switch (subType) {
case BinarySubType::WindowsImportLibrary: case BinarySubType::WindowsImportLibrary:
return argsToString("pe-", architecture, ':', ':', toLower(dependencyName)); return argsToString(extraPrefix, "pe-", architecture, ':', ':', toLower(dependencyName));
default:; default:;
} }
default: default:
return "unknown::" + dependencyName; return argsToString(extraPrefix, "unknown::", dependencyName);
} }
} }

View File

@ -82,13 +82,14 @@ inline VirtualAddressMapping::VirtualAddressMapping()
} }
struct LIBPKG_EXPORT Binary { struct LIBPKG_EXPORT Binary {
void load(const char *filePath); void load(std::string_view filePath);
void load(const std::string &fileContent, const std::string &fileName, bool isRegularFile = false); 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; std::string addPrefix(const std::string &dependencyName) const;
BinaryType type = BinaryType::Invalid; BinaryType type = BinaryType::Invalid;
BinarySubType subType = BinarySubType::None; BinarySubType subType = BinarySubType::None;
std::string name; std::string name;
std::string_view extraPrefix;
BinaryClass binaryClass = BinaryClass::Invalid; BinaryClass binaryClass = BinaryClass::Invalid;
bool isBigEndian = false; bool isBigEndian = false;
std::string architecture; std::string architecture;

View File

@ -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 pythonVersionRegex("usr/lib/python(2|3)\\.([0-9]*)(\\..*)?/site-packages");
static const regex perlVersionRegex("usr/lib/perl5/5\\.([0-9]*)(\\..*)?/vendor_perl"); 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 // check for Python modules
thread_local smatch match; thread_local smatch match;
@ -774,11 +774,12 @@ void Package::addDepsAndProvidesFromContainedDirectory(const string &directoryPa
} }
} }
void Package::addDepsAndProvidesFromContainedFile(const ArchiveFile &file, std::set<std::string> &dllsReferencedByImportLibs) void Package::addDepsAndProvidesFromContainedFile(
const std::string &directoryPath, const ArchiveFile &file, std::set<std::string> &dllsReferencedByImportLibs)
{ {
try { try {
Binary binary; 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.name.empty()) {
if (binary.type == BinaryType::Ar && binary.subType == BinarySubType::WindowsImportLibrary) { if (binary.type == BinaryType::Ar && binary.subType == BinarySubType::WindowsImportLibrary) {
dllsReferencedByImportLibs.emplace(binary.addPrefix(binary.name)); dllsReferencedByImportLibs.emplace(binary.addPrefix(binary.name));
@ -826,7 +827,7 @@ void Package::addDepsAndProvidesFromContents(const FileMap &contents)
for (const auto &[directoryPath, files] : contents) { for (const auto &[directoryPath, files] : contents) {
addDepsAndProvidesFromContainedDirectory(directoryPath); addDepsAndProvidesFromContainedDirectory(directoryPath);
for (const auto &file : files) { for (const auto &file : files) {
addDepsAndProvidesFromContainedFile(file, dllsReferencedByImportLibs); addDepsAndProvidesFromContainedFile(directoryPath, file, dllsReferencedByImportLibs);
} }
} }
processDllsReferencedByImportLibs(std::move(dllsReferencedByImportLibs)); processDllsReferencedByImportLibs(std::move(dllsReferencedByImportLibs));
@ -850,7 +851,7 @@ std::shared_ptr<Package> Package::fromPkgFile(const string &path)
} }
return; return;
} }
tmpPackageForLibraryDeps.addDepsAndProvidesFromContainedFile(file, dllsReferencedByImportLibs); tmpPackageForLibraryDeps.addDepsAndProvidesFromContainedFile(directoryPath, file, dllsReferencedByImportLibs);
}, },
[&tmpPackageForLibraryDeps](std::string &&directoryPath) { [&tmpPackageForLibraryDeps](std::string &&directoryPath) {
if (directoryPath.empty()) { if (directoryPath.empty()) {

View File

@ -58,7 +58,7 @@ void BinaryParserTests::tearDown()
void BinaryParserTests::testParsingElf() void BinaryParserTests::testParsingElf()
{ {
Binary bin; 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("type", BinaryType::Elf, bin.type);
CPPUNIT_ASSERT_EQUAL_MESSAGE("class", BinaryClass::Class64Bit, bin.binaryClass); CPPUNIT_ASSERT_EQUAL_MESSAGE("class", BinaryClass::Class64Bit, bin.binaryClass);
CPPUNIT_ASSERT_EQUAL_MESSAGE("sub type", BinarySubType::SharedObject, bin.subType); CPPUNIT_ASSERT_EQUAL_MESSAGE("sub type", BinarySubType::SharedObject, bin.subType);
@ -72,7 +72,7 @@ void BinaryParserTests::testParsingElf()
void BinaryParserTests::testParsingPe() void BinaryParserTests::testParsingPe()
{ {
Binary bin; 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("type", BinaryType::Pe, bin.type);
CPPUNIT_ASSERT_EQUAL_MESSAGE("arch", "x86_64"s, bin.architecture); CPPUNIT_ASSERT_EQUAL_MESSAGE("arch", "x86_64"s, bin.architecture);
CPPUNIT_ASSERT_EQUAL_MESSAGE("name", "c++utilities.dll"s, bin.name); CPPUNIT_ASSERT_EQUAL_MESSAGE("name", "c++utilities.dll"s, bin.name);
@ -84,7 +84,7 @@ void BinaryParserTests::testParsingPe()
void BinaryParserTests::testParsingAr() void BinaryParserTests::testParsingAr()
{ {
Binary bin; 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("type", BinaryType::Ar, bin.type);
CPPUNIT_ASSERT_EQUAL_MESSAGE("arch", "x86_64"s, bin.architecture); CPPUNIT_ASSERT_EQUAL_MESSAGE("arch", "x86_64"s, bin.architecture);
CPPUNIT_ASSERT_EQUAL_MESSAGE("name", "KERNEL32.dll"s, bin.name); CPPUNIT_ASSERT_EQUAL_MESSAGE("name", "KERNEL32.dll"s, bin.name);

View File

@ -105,9 +105,8 @@ void checkSyncthingTrayPackageSoDependencies(const Package &package)
{ {
CPPUNIT_ASSERT_EQUAL_MESSAGE("origin", PackageOrigin::PackageContents, package.origin); 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); CPPUNIT_ASSERT_EQUAL_MESSAGE("file name"s, "syncthingtray-0.6.2-1-x86_64.pkg.tar.xz"s, package.packageInfo->fileName);
const set<string> sonames( const set<string> sonames({ "elf-x86_64::libsyncthingwidgets.so.0.6.2", "elf-x86_64::libsyncthingmodel.so.0.6.2",
{ "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::libsyncthingconnector.so.0.6.2", "elf-x86_64::libsyncthingfileitemaction.so" });
"elf-x86_64::libsyncthingfileitemaction.so" });
CPPUNIT_ASSERT_EQUAL_MESSAGE("library provides from sonames"s, sonames, package.libprovides); CPPUNIT_ASSERT_EQUAL_MESSAGE("library provides from sonames"s, sonames, package.libprovides);
const set<string> required({ "elf-x86_64::libqtutilities.so.5", "elf-x86_64::libsyncthingmodel.so.0.6.2", "elf-x86_64::libKF5KIOWidgets.so.5", const set<string> 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", "elf-x86_64::libsyncthingconnector.so.0.6.2", "elf-x86_64::libsyncthingwidgets.so.0.6.2", "elf-x86_64::libKF5KIOCore.so.5",