| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file LICENSE.rst or https://cmake.org/licensing for details. */
- #include "cmFileSet.h"
- #include <sstream>
- #include <string>
- #include <unordered_map>
- #include <utility>
- #include <vector>
- #include <cm/optional>
- #include <cmext/algorithm>
- #include <cmext/string_view>
- #include "cmsys/RegularExpression.hxx"
- #include "cmGeneratorExpression.h"
- #include "cmList.h"
- #include "cmListFileCache.h"
- #include "cmLocalGenerator.h"
- #include "cmMakefile.h"
- #include "cmMessageType.h"
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- #include "cmake.h"
- cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
- {
- switch (vis) {
- case cmFileSetVisibility::Interface:
- return "INTERFACE"_s;
- case cmFileSetVisibility::Public:
- return "PUBLIC"_s;
- case cmFileSetVisibility::Private:
- return "PRIVATE"_s;
- }
- return ""_s;
- }
- cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
- cmMakefile* mf)
- {
- if (name == "INTERFACE"_s) {
- return cmFileSetVisibility::Interface;
- }
- if (name == "PUBLIC"_s) {
- return cmFileSetVisibility::Public;
- }
- if (name == "PRIVATE"_s) {
- return cmFileSetVisibility::Private;
- }
- auto msg = cmStrCat("File set visibility \"", name, "\" is not valid.");
- if (mf) {
- mf->IssueMessage(MessageType::FATAL_ERROR, msg);
- } else {
- cmSystemTools::Error(msg);
- }
- return cmFileSetVisibility::Private;
- }
- bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
- {
- switch (vis) {
- case cmFileSetVisibility::Interface:
- return false;
- case cmFileSetVisibility::Public:
- case cmFileSetVisibility::Private:
- return true;
- }
- return false;
- }
- bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
- {
- switch (vis) {
- case cmFileSetVisibility::Interface:
- case cmFileSetVisibility::Public:
- return true;
- case cmFileSetVisibility::Private:
- return false;
- }
- return false;
- }
- bool cmFileSetTypeCanBeIncluded(std::string const& type)
- {
- return type == "HEADERS"_s;
- }
- cmFileSet::cmFileSet(cmake& cmakeInstance, std::string name, std::string type,
- cmFileSetVisibility visibility)
- : CMakeInstance(cmakeInstance)
- , Name(std::move(name))
- , Type(std::move(type))
- , Visibility(visibility)
- {
- }
- void cmFileSet::CopyEntries(cmFileSet const* fs)
- {
- cm::append(this->DirectoryEntries, fs->DirectoryEntries);
- cm::append(this->FileEntries, fs->FileEntries);
- }
- void cmFileSet::ClearDirectoryEntries()
- {
- this->DirectoryEntries.clear();
- }
- void cmFileSet::AddDirectoryEntry(BT<std::string> directories)
- {
- this->DirectoryEntries.push_back(std::move(directories));
- }
- void cmFileSet::ClearFileEntries()
- {
- this->FileEntries.clear();
- }
- void cmFileSet::AddFileEntry(BT<std::string> files)
- {
- this->FileEntries.push_back(std::move(files));
- }
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
- cmFileSet::CompileFileEntries() const
- {
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
- for (auto const& entry : this->FileEntries) {
- for (auto const& ex : cmList{ entry.Value }) {
- cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace);
- auto cge = ge.Parse(ex);
- result.push_back(std::move(cge));
- }
- }
- return result;
- }
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>>
- cmFileSet::CompileDirectoryEntries() const
- {
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> result;
- for (auto const& entry : this->DirectoryEntries) {
- for (auto const& ex : cmList{ entry.Value }) {
- cmGeneratorExpression ge(this->CMakeInstance, entry.Backtrace);
- auto cge = ge.Parse(ex);
- result.push_back(std::move(cge));
- }
- }
- return result;
- }
- std::vector<std::string> cmFileSet::EvaluateDirectoryEntries(
- std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges,
- cmLocalGenerator const* lg, std::string const& config,
- cmGeneratorTarget const* target,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- {
- struct DirCacheEntry
- {
- std::string collapsedDir;
- cm::optional<cmSystemTools::FileId> fileId;
- };
- std::unordered_map<std::string, DirCacheEntry> dirCache;
- std::vector<std::string> result;
- for (auto const& cge : cges) {
- auto entry = cge->Evaluate(lg, config, target, dagChecker);
- cmList dirs{ entry };
- for (std::string dir : dirs) {
- if (!cmSystemTools::FileIsFullPath(dir)) {
- dir = cmStrCat(lg->GetCurrentSourceDirectory(), '/', dir);
- }
- auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry());
- auto& dirCacheEntry = dirCacheResult.first->second;
- auto const isNewCacheEntry = dirCacheResult.second;
- if (isNewCacheEntry) {
- cmSystemTools::FileId fileId;
- auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId);
- dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir);
- dirCacheEntry.fileId =
- isFileIdValid ? cm::optional<decltype(fileId)>(fileId) : cm::nullopt;
- }
- for (auto const& priorDir : result) {
- auto priorDirCacheEntry = dirCache.at(priorDir);
- bool sameFile = dirCacheEntry.fileId.has_value() &&
- priorDirCacheEntry.fileId.has_value() &&
- (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId);
- if (!sameFile &&
- (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir,
- priorDirCacheEntry.collapsedDir) ||
- cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir,
- dirCacheEntry.collapsedDir))) {
- lg->GetCMakeInstance()->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat(
- "Base directories in file set cannot be subdirectories of each "
- "other:\n ",
- priorDir, "\n ", dir),
- cge->GetBacktrace());
- return {};
- }
- }
- result.push_back(dir);
- }
- }
- return result;
- }
- void cmFileSet::EvaluateFileEntry(
- std::vector<std::string> const& dirs,
- std::map<std::string, std::vector<std::string>>& filesPerDir,
- std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
- cmLocalGenerator const* lg, std::string const& config,
- cmGeneratorTarget const* target,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- {
- auto files = cge->Evaluate(lg, config, target, dagChecker);
- for (std::string file : cmList{ files }) {
- if (!cmSystemTools::FileIsFullPath(file)) {
- file = cmStrCat(lg->GetCurrentSourceDirectory(), '/', file);
- }
- auto collapsedFile = cmSystemTools::CollapseFullPath(file);
- bool found = false;
- std::string relDir;
- for (auto const& dir : dirs) {
- auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
- if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
- found = true;
- relDir = cmSystemTools::GetParentDirectory(
- cmSystemTools::RelativePath(collapsedDir, collapsedFile));
- break;
- }
- }
- if (!found) {
- std::ostringstream e;
- e << "File:\n " << file
- << "\nmust be in one of the file set's base directories:";
- for (auto const& dir : dirs) {
- e << "\n " << dir;
- }
- lg->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str(),
- cge->GetBacktrace());
- return;
- }
- filesPerDir[relDir].push_back(file);
- }
- }
- bool cmFileSet::IsValidName(std::string const& name)
- {
- static cmsys::RegularExpression const regex("^[a-z0-9][a-zA-Z0-9_]*$");
- cmsys::RegularExpressionMatch match;
- return regex.find(name.c_str(), match);
- }
|