| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmBinUtilsWindowsPELinker.h"
- #include <algorithm>
- #include <iterator>
- #include <sstream>
- #include <utility>
- #include <vector>
- #include <cm/memory>
- #include "cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.h"
- #include "cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.h"
- #include "cmRuntimeDependencyArchive.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- #ifdef _WIN32
- # include <windows.h>
- # include "cmsys/Encoding.hxx"
- #endif
- #ifdef _WIN32
- namespace {
- void ReplaceWithActualNameCasing(std::string& path)
- {
- WIN32_FIND_DATAW findData;
- HANDLE hFind = ::FindFirstFileW(
- cmsys::Encoding::ToWindowsExtendedPath(path).c_str(), &findData);
- if (hFind != INVALID_HANDLE_VALUE) {
- auto onDiskName = cmsys::Encoding::ToNarrow(findData.cFileName);
- ::FindClose(hFind);
- path.replace(path.end() - onDiskName.size(), path.end(), onDiskName);
- }
- }
- }
- #endif
- cmBinUtilsWindowsPELinker::cmBinUtilsWindowsPELinker(
- cmRuntimeDependencyArchive* archive)
- : cmBinUtilsLinker(archive)
- {
- }
- bool cmBinUtilsWindowsPELinker::Prepare()
- {
- std::string tool = this->Archive->GetGetRuntimeDependenciesTool();
- if (tool.empty()) {
- std::vector<std::string> command;
- if (this->Archive->GetGetRuntimeDependenciesCommand("dumpbin", command)) {
- tool = "dumpbin";
- } else {
- tool = "objdump";
- }
- }
- if (tool == "dumpbin") {
- this->Tool =
- cm::make_unique<cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool>(
- this->Archive);
- } else if (tool == "objdump") {
- this->Tool =
- cm::make_unique<cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool>(
- this->Archive);
- } else {
- std::ostringstream e;
- e << "Invalid value for CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL: " << tool;
- this->SetError(e.str());
- return false;
- }
- return true;
- }
- bool cmBinUtilsWindowsPELinker::ScanDependencies(
- std::string const& file, cmStateEnums::TargetType /* unused */)
- {
- std::vector<std::string> needed;
- if (!this->Tool->GetFileInfo(file, needed)) {
- return false;
- }
- struct WinPEDependency
- {
- WinPEDependency(std::string o)
- : Original(std::move(o))
- , LowerCase(cmSystemTools::LowerCase(Original))
- {
- }
- std::string const Original;
- std::string const LowerCase;
- };
- std::vector<WinPEDependency> depends;
- depends.reserve(needed.size());
- std::move(needed.begin(), needed.end(), std::back_inserter(depends));
- std::string origin = cmSystemTools::GetFilenamePath(file);
- for (auto const& lib : depends) {
- if (!this->Archive->IsPreExcluded(lib.LowerCase)) {
- std::string path;
- bool resolved = false;
- if (!this->ResolveDependency(lib.LowerCase, origin, path, resolved)) {
- return false;
- }
- if (resolved) {
- if (!this->Archive->IsPostExcluded(path)) {
- #ifdef _WIN32
- ReplaceWithActualNameCasing(path);
- #else
- path.replace(path.end() - lib.Original.size(), path.end(),
- lib.Original);
- #endif
- bool unique;
- this->Archive->AddResolvedPath(lib.Original, path, unique);
- if (unique &&
- !this->ScanDependencies(path, cmStateEnums::SHARED_LIBRARY)) {
- return false;
- }
- }
- } else {
- this->Archive->AddUnresolvedPath(lib.Original);
- }
- }
- }
- return true;
- }
- bool cmBinUtilsWindowsPELinker::ResolveDependency(std::string const& name,
- std::string const& origin,
- std::string& path,
- bool& resolved)
- {
- auto dirs = this->Archive->GetSearchDirectories();
- #ifdef _WIN32
- char buf[MAX_PATH];
- unsigned int len;
- if ((len = GetWindowsDirectoryA(buf, MAX_PATH)) > 0) {
- dirs.insert(dirs.begin(), std::string(buf, len));
- }
- if ((len = GetSystemDirectoryA(buf, MAX_PATH)) > 0) {
- dirs.insert(dirs.begin(), std::string(buf, len));
- }
- #endif
- dirs.insert(dirs.begin(), origin);
- for (auto const& searchPath : dirs) {
- path = cmStrCat(searchPath, '/', name);
- if (cmSystemTools::PathExists(path)) {
- resolved = true;
- return true;
- }
- }
- resolved = false;
- return true;
- }
|