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
""
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

View File

@ -385,7 +385,8 @@ struct LIBPKG_EXPORT Package : public ReflectiveRapidJSON::JsonSerializable<Pack
PackageNameData decomposeName() const;
void addInfoFromPkgInfoFile(const std::string &info);
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);
std::vector<std::string> processDllsReferencedByImportLibs(std::set<std::string> &&dllsReferencedByImportLibs);
bool addDepsAndProvidesFromOtherPackage(const Package &otherPackage, bool force = false);

View File

@ -1,3 +1,5 @@
#define CPP_UTILITIES_PATHHELPER_STRING_VIEW
#include "./binary.h"
#include <c++utilities/conversion/stringbuilder.h>
@ -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);
}
}

View File

@ -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;

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 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<std::string> &dllsReferencedByImportLibs)
void Package::addDepsAndProvidesFromContainedFile(
const std::string &directoryPath, const ArchiveFile &file, std::set<std::string> &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> Package::fromPkgFile(const string &path)
}
return;
}
tmpPackageForLibraryDeps.addDepsAndProvidesFromContainedFile(file, dllsReferencedByImportLibs);
tmpPackageForLibraryDeps.addDepsAndProvidesFromContainedFile(directoryPath, file, dllsReferencedByImportLibs);
},
[&tmpPackageForLibraryDeps](std::string &&directoryPath) {
if (directoryPath.empty()) {

View File

@ -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);

View File

@ -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<string> 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<string> 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<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",