1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #pragma once
4 
5 #include "cmConfigure.h" // IWYU pragma: keep
6 
7 #include <cstddef>
8 #include <functional>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include <cm/string_view>
15 
16 #include <cm3p/kwiml/int.h>
17 
18 #include "cmFindCommon.h"
19 #include "cmPolicies.h"
20 
21 // IWYU insists we should forward-declare instead of including <functional>,
22 // but we cannot forward-declare reliably because some C++ standard libraries
23 // put the template in an inline namespace.
24 #ifdef CMAKE_IWYU_FORWARD_STD_HASH
25 /* clang-format off */
26 namespace std {
27   template <class T> struct hash;
28 }
29 /* clang-format on */
30 #endif
31 
32 class cmExecutionStatus;
33 class cmSearchPath;
34 
35 /** \class cmFindPackageCommand
36  * \brief Load settings from an external project.
37  *
38  * cmFindPackageCommand
39  */
40 class cmFindPackageCommand : public cmFindCommon
41 {
42 public:
43   /*! A sorting order strategy to be applied to recovered package folders (see
44    * FIND_PACKAGE_SORT_ORDER)*/
45   enum /*class*/ SortOrderType
46   {
47     None,
48     Name_order,
49     Natural
50   };
51   /*! A sorting direction to be applied to recovered package folders (see
52    * FIND_PACKAGE_SORT_DIRECTION)*/
53   enum /*class*/ SortDirectionType
54   {
55     Asc,
56     Dec
57   };
58 
59   /*! sorts a given list of string based on the input sort parameters */
60   static void Sort(std::vector<std::string>::iterator begin,
61                    std::vector<std::string>::iterator end, SortOrderType order,
62                    SortDirectionType dir);
63 
64   cmFindPackageCommand(cmExecutionStatus& status);
65 
66   bool InitialPass(std::vector<std::string> const& args);
67 
68 private:
69   class PathLabel : public cmFindCommon::PathLabel
70   {
71   protected:
72     PathLabel();
73 
74   public:
PathLabel(const std::string & label)75     PathLabel(const std::string& label)
76       : cmFindCommon::PathLabel(label)
77     {
78     }
79     static PathLabel UserRegistry;
80     static PathLabel Builds;
81     static PathLabel SystemRegistry;
82   };
83 
84   bool FindPackageUsingModuleMode();
85   bool FindPackageUsingConfigMode();
86 
87   // Add additional search path labels and groups not present in the
88   // parent class
89   void AppendSearchPathGroups();
90 
91   void AppendSuccessInformation();
92   void AppendToFoundProperty(bool found);
93   void SetVersionVariables(
94     const std::function<void(const std::string&, cm::string_view)>&
95       addDefinition,
96     const std::string& prefix, const std::string& version, unsigned int count,
97     unsigned int major, unsigned int minor, unsigned int patch,
98     unsigned int tweak);
99   void SetModuleVariables(const std::string& components);
100   bool FindModule(bool& found);
101   void AddFindDefinition(const std::string& var, cm::string_view value);
102   void RestoreFindDefinitions();
103 
104   enum /*class*/ HandlePackageModeType
105   {
106     Module,
107     Config
108   };
109   bool HandlePackageMode(HandlePackageModeType type);
110 
111   bool FindConfig();
112   bool FindPrefixedConfig();
113   bool FindFrameworkConfig();
114   bool FindAppBundleConfig();
115   enum PolicyScopeRule
116   {
117     NoPolicyScope,
118     DoPolicyScope
119   };
120   bool ReadListFile(const std::string& f, PolicyScopeRule psr);
121   void StoreVersionFound();
122 
123   void ComputePrefixes();
124   void FillPrefixesPackageRoot();
125   void FillPrefixesCMakeEnvironment();
126   void FillPrefixesCMakeVariable();
127   void FillPrefixesSystemEnvironment();
128   void FillPrefixesUserRegistry();
129   void FillPrefixesSystemRegistry();
130   void FillPrefixesCMakeSystemVariable();
131   void FillPrefixesUserGuess();
132   void FillPrefixesUserHints();
133   void LoadPackageRegistryDir(std::string const& dir, cmSearchPath& outPaths);
134   void LoadPackageRegistryWinUser();
135   void LoadPackageRegistryWinSystem();
136   void LoadPackageRegistryWin(bool user, unsigned int view,
137                               cmSearchPath& outPaths);
138   bool CheckPackageRegistryEntry(const std::string& fname,
139                                  cmSearchPath& outPaths);
140   bool SearchDirectory(std::string const& dir);
141   bool CheckDirectory(std::string const& dir);
142   bool FindConfigFile(std::string const& dir, std::string& file);
143   bool CheckVersion(std::string const& config_file);
144   bool CheckVersionFile(std::string const& version_file,
145                         std::string& result_version);
146   bool SearchPrefix(std::string const& prefix);
147   bool SearchFrameworkPrefix(std::string const& prefix_in);
148   bool SearchAppBundlePrefix(std::string const& prefix_in);
149 
150   friend class cmFindPackageFileList;
151 
152   struct OriginalDef
153   {
154     bool exists;
155     std::string value;
156   };
157   std::map<std::string, OriginalDef> OriginalDefs;
158 
159   std::map<std::string, cmPolicies::PolicyID> DeprecatedFindModules;
160 
161   static const cm::string_view VERSION_ENDPOINT_INCLUDED;
162   static const cm::string_view VERSION_ENDPOINT_EXCLUDED;
163 
164   std::string Name;
165   std::string Variable;
166   std::string VersionComplete;
167   std::string VersionRange;
168   cm::string_view VersionRangeMin;
169   cm::string_view VersionRangeMax;
170   std::string Version;
171   unsigned int VersionMajor = 0;
172   unsigned int VersionMinor = 0;
173   unsigned int VersionPatch = 0;
174   unsigned int VersionTweak = 0;
175   unsigned int VersionCount = 0;
176   std::string VersionMax;
177   unsigned int VersionMaxMajor = 0;
178   unsigned int VersionMaxMinor = 0;
179   unsigned int VersionMaxPatch = 0;
180   unsigned int VersionMaxTweak = 0;
181   unsigned int VersionMaxCount = 0;
182   bool VersionExact = false;
183   std::string FileFound;
184   std::string VersionFound;
185   unsigned int VersionFoundMajor = 0;
186   unsigned int VersionFoundMinor = 0;
187   unsigned int VersionFoundPatch = 0;
188   unsigned int VersionFoundTweak = 0;
189   unsigned int VersionFoundCount = 0;
190   KWIML_INT_uint64_t RequiredCMakeVersion = 0;
191   bool Quiet = false;
192   bool Required = false;
193   bool UseConfigFiles = true;
194   bool UseFindModules = true;
195   bool NoUserRegistry = false;
196   bool NoSystemRegistry = false;
197   bool UseLib32Paths = false;
198   bool UseLib64Paths = false;
199   bool UseLibx32Paths = false;
200   bool UseRealPath = false;
201   bool PolicyScope = true;
202   std::string LibraryArchitecture;
203   std::vector<std::string> Names;
204   std::vector<std::string> Configs;
205   std::set<std::string> IgnoredPaths;
206   std::string DebugBuffer;
207 
208   /*! the selected sortOrder (None by default)*/
209   SortOrderType SortOrder = None;
210   /*! the selected sortDirection (Asc by default)*/
211   SortDirectionType SortDirection = Asc;
212 
213   struct ConfigFileInfo
214   {
215     std::string filename;
216     std::string version;
217 
218     bool operator<(ConfigFileInfo const& rhs) const
219     {
220       return this->filename < rhs.filename;
221     }
222 
223     bool operator==(ConfigFileInfo const& rhs) const
224     {
225       return this->filename == rhs.filename;
226     }
227 
228     bool operator!=(ConfigFileInfo const& rhs) const
229     {
230       return !(*this == rhs);
231     }
232   };
233   std::vector<ConfigFileInfo> ConsideredConfigs;
234 
235   friend struct std::hash<ConfigFileInfo>;
236 };
237 
238 namespace std {
239 
240 template <>
241 struct hash<cmFindPackageCommand::ConfigFileInfo>
242 {
243   using argument_type = cmFindPackageCommand::ConfigFileInfo;
244   using result_type = size_t;
245 
246   result_type operator()(argument_type const& s) const noexcept
247   {
248     result_type const h(std::hash<std::string>{}(s.filename));
249     return h;
250   }
251 };
252 }
253 
254 bool cmFindPackage(std::vector<std::string> const& args,
255                    cmExecutionStatus& status);
256