/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmIncludeDirectoryCommand.h" #include #include #include "cmGeneratorExpression.h" #include "cmMakefile.h" #include "cmSystemTools.h" class cmExecutionStatus; // cmIncludeDirectoryCommand bool cmIncludeDirectoryCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { if (args.empty()) { return true; } std::vector::const_iterator i = args.begin(); bool before = this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_BEFORE"); bool system = false; if ((*i) == "BEFORE") { before = true; ++i; } else if ((*i) == "AFTER") { before = false; ++i; } std::vector beforeIncludes; std::vector afterIncludes; std::set systemIncludes; for (; i != args.end(); ++i) { if (*i == "SYSTEM") { system = true; continue; } if (i->empty()) { this->SetError("given empty-string as include directory."); return false; } std::vector includes; this->GetIncludes(*i, includes); if (before) { beforeIncludes.insert(beforeIncludes.end(), includes.begin(), includes.end()); } else { afterIncludes.insert(afterIncludes.end(), includes.begin(), includes.end()); } if (system) { systemIncludes.insert(includes.begin(), includes.end()); } } std::reverse(beforeIncludes.begin(), beforeIncludes.end()); this->Makefile->AddIncludeDirectories(afterIncludes); this->Makefile->AddIncludeDirectories(beforeIncludes, before); this->Makefile->AddSystemIncludeDirectories(systemIncludes); return true; } // do a lot of cleanup on the arguments because this is one place where folks // sometimes take the output of a program and pass it directly into this // command not thinking that a single argument could be filled with spaces // and newlines etc like below: // // " /foo/bar // /boo/hoo /dingle/berry " // // ideally that should be three separate arguments but when sucking the // output from a program and passing it into a command the cleanup doesn't // always happen // void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg, std::vector& incs) { // break apart any line feed arguments std::string::size_type pos = 0; std::string::size_type lastPos = 0; while ((pos = arg.find('\n', lastPos)) != std::string::npos) { if (pos) { std::string inc = arg.substr(lastPos, pos); this->NormalizeInclude(inc); if (!inc.empty()) { incs.push_back(std::move(inc)); } } lastPos = pos + 1; } std::string inc = arg.substr(lastPos); this->NormalizeInclude(inc); if (!inc.empty()) { incs.push_back(std::move(inc)); } } void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc) { std::string::size_type b = inc.find_first_not_of(" \r"); std::string::size_type e = inc.find_last_not_of(" \r"); if ((b != std::string::npos) && (e != std::string::npos)) { inc.assign(inc, b, 1 + e - b); // copy the remaining substring } else { inc.clear(); return; } if (!cmSystemTools::IsOff(inc)) { cmSystemTools::ConvertToUnixSlashes(inc); if (!cmSystemTools::FileIsFullPath(inc)) { if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) { std::string tmp = this->Makefile->GetCurrentSourceDirectory(); tmp += "/"; tmp += inc; inc = tmp; } } } }