PhoenixGenerator  2.0.4
Set of tools to generate code
Loading...
Searching...
No Matches
project_generator_load.cpp
Go to the documentation of this file.
1/***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : CeCILL-C
5****************************************/
6
7#include "phoenix_color.h"
8#include "parser_toml.h"
10
12
16bool project_generator_split_dependencies(ProjectConfig & config, std::vector<PString> & vecDependencies){
17 for(const PString & depStr : vecDependencies){
18 PString name(""), min_version(""), max_version("");
19 std::istringstream iss(depStr);
20 std::vector<PString> depValues;
21 PString token;
22 while (iss >> token){depValues.push_back(token);}
23 if(!depValues.empty()){
24 name = depValues[0];
25 for(size_t i=1; i<depValues.size(); ++i){
26 if(depValues[i].isSameBegining("==")) {
27 // User specifies the exact version
28 min_version = depValues[i];
29 max_version = "";
30 break;
31 }
32 if(depValues[i].isSameBegining(">=") || depValues[i].isSameBegining(">")) {
33 min_version = depValues[i];
34 if(!min_version.empty() && min_version.back() == ',') min_version.pop_back();
35 }
36 if(depValues[i].isSameBegining("<=") || depValues[i].isSameBegining("<")) {
37 max_version = depValues[i];
38 if(!max_version.empty() && max_version.back() == ',') max_version.pop_back();
39 }
40 }
41 }else{
42 name = depStr;
43 }
44 // Fill the matching attributes
45 config.mapDependencies[name].setName(name);
46 config.mapDependencies[name].setMinVersion(min_version);
47 config.mapDependencies[name].setMaxVersion(max_version);
48 }
49 return true;
50}
51
53
57bool parseProjectMembers(ProjectMembersMap & memberMap, const DicoValue * memberDico){
58 if(memberDico == NULL || !memberDico->hasVec()){
59 return false;
60 }
61 const std::vector<DicoValue> & vecMember = memberDico->getVecChild();
62 for(size_t iMember = 0; iMember < vecMember.size(); iMember++){
63 const DicoValue & memberData = vecMember[iMember];
64 if(memberData.hasMap()){
65 PProjectMembers member;
66 member.setLastName(phoenix_get_string(memberData, "lastName", ""));
67 member.setFirstName(phoenix_get_string(memberData, "firstName", ""));
68 member.setAffiliation(phoenix_get_string(memberData, "affiliation", ""));
69 member.setEmail(phoenix_get_string(memberData, "mail", ""));
70
71 // Use lastName + firstName as key to handle duplicate lastNames
72 PString key = member.getLastName() + "_" + member.getFirstName();
73 memberMap[key] = member;
74 }
75 }
76 return true;
77}
78
80
84bool project_generator_loadConfig(ProjectConfig & config, const PPath & descriptionFile){
85 DicoValue dico;
86 if(!parser_toml(dico, descriptionFile)){
87 std::cerr << termRed() << "project_generator_loadConfig : cannot parse config file '"<<descriptionFile<<"'" << termDefault() << std::endl;
88 return false;
89 }
90 DicoValue * mapProject = dico.getMap("project");
91 if(mapProject == NULL){
92 std::cerr << termRed() << "project_generator_loadConfig : Missing [project] in config file '"<<descriptionFile<<"'" << termDefault() << std::endl;
93 return false;
94 }
95 //TODO : It should be better to tell if there are missing values, but it's late ...
96 config.name = phoenix_get_string(*mapProject, "name", "MyAwesomeProject");
97 config.url = phoenix_get_string(*mapProject, "url", "need and url");
98 config.version = phoenix_get_string(*mapProject, "version", "0.1.0");
99 config.description = phoenix_get_string(*mapProject, "description", "A very important project");
100 config.mainBranch = phoenix_get_string(*mapProject, "main_branch", "main");
101 config.runnerTag = phoenix_get_string(*mapProject, "runner_tag", ""); //Could be MUST_big_runner
102 config.ciToolkitVersion = phoenix_get_string(*mapProject, "ci_toolkit_version", "3.0.4"); //Default version if not specified
103 config.ciToolkitUrl = phoenix_get_string(*mapProject, "ci_toolkit_url", "https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/citoolkit/phoenixcitoolkitcpp/phoenix-workflow-cpp");
104
105 //Keywords
106 if(mapProject->isKeyExist("keywords")){
107 const DicoValue * keywordDico = mapProject->getMap("keywords");
108 if(keywordDico != NULL && keywordDico->hasVec()){
109 const std::vector<DicoValue> & vecKeyword = keywordDico->getVecChild();
110 for(size_t iKeyword = 0; iKeyword < vecKeyword.size(); iKeyword++){
111 config.keywordList.push_back(vecKeyword[iKeyword].getString());;
112 }
113 }
114 }
115 //Authors
116 if(mapProject->isKeyExist("authors")){
117 const DicoValue * authorDico = mapProject->getMap("authors");
118 parseProjectMembers(config.authorMap, authorDico);
119 }
120 //Maintainers
121 if(mapProject->isKeyExist("maintainers")){
122 const DicoValue * maintainerDico = mapProject->getMap("maintainers");
123 parseProjectMembers(config.maintainerMap, maintainerDico);
124 }
125 //Contributors
126 if(mapProject->isKeyExist("contributors")){
127 const DicoValue * contributorDico = mapProject->getMap("contributors");
128 parseProjectMembers(config.contributorMap, contributorDico);
129 }
130 //Dependencies
131 if(mapProject->isKeyExist("dependencies")){
132 const DicoValue * depDico = mapProject->getMap("dependencies");
133 if(depDico != NULL && depDico->hasVec()){
134 const std::vector<DicoValue> & vecDep = depDico->getVecChild();
135 std::vector<PString> depList;
136 for(size_t iDep = 0; iDep < vecDep.size(); iDep++){
137 depList.push_back(vecDep[iDep].getString());
138 }
139 if(!project_generator_split_dependencies(config, depList)){
140 std::cerr << termRed() << "project_generator_loadConfig : cannot parse dependencies in config file '"<<descriptionFile<<"'" << termDefault() << std::endl;
141 return false;
142 }
143 }
144 }
145 return true;
146}
147
148
150
155bool generate_empty_config(PPath & outFileName, const PString & name, PString& minVersion, PString& maxVersion){
156 PString body;
157 body += "# To fill the package info use the description below, then remove the commented lines.\n";
158 body += "[[Package]]\n";
159 body += "# This is the name of your package (eg on your git repository)\n";
160 body += "name = \"" + name + "\"\n";
161 body += "# # This is the name of your package for the pixi.toml. You can find the name of the pixi package by searching it on prefix.dev \n";
162 body += "pixi_name = \"\"\n";
163 body += "# If your package provides a CMake configuration file (find File), this should be the value used in find_package().\n";
164 body += "cmake_find = \"\"\n";
165 body += "# If your package provides a CMake configuration library, this should be the name of the main library target provided by the package.\n";
166 body += "cmake_lib = \"\"\n";
167 body += "#This is the URL of your package repository if you want to use the pull_extra_module feature of PhoenixCMake (only for Phoenix packages)\n";
168 body += "url = \"\"\n\n";
169 return outFileName.saveFileContent(body);
170}
171
173
179bool check_package_file(const PPath & fileName, const PString & name, const PPath & packageDir, PPackageAttribute & pkgAttr){
180 bool found = false;
181 if(fileName.getExtension() != "toml"){
182 return found;
183 }
184 DicoValue dico;
185 PPath tomlFile = packageDir / fileName;
186 if(!parser_toml(dico, tomlFile)){
187 return found;
188 }
189 const DicoValue* mapPkg = dico.getMap("Package");
190 const std::vector<DicoValue> & vecChild = mapPkg->getVecChild();
191 for(size_t iChild = 0; iChild < vecChild.size() && !found; ++iChild){
192 const DicoValue & pkgBlock = vecChild[iChild];
193 PString tomlName = phoenix_get_string(pkgBlock, "name", "");
194 if(tomlName == name){
195 pkgAttr.setUrl(phoenix_get_string(pkgBlock, "url", ""));
196 pkgAttr.setPixiName(phoenix_get_string(pkgBlock, "pixi_name", ""));
197 pkgAttr.setCmakeFind(phoenix_get_string(pkgBlock, "cmake_find", ""));
198 pkgAttr.setCmakeLib(phoenix_get_string(pkgBlock, "cmake_lib", ""));
199 if(pkgAttr.getUrl() != "" || pkgAttr.getPixiName() != "" || pkgAttr.getCmakeFind() != "" || pkgAttr.getCmakeLib() != ""){
200 found = true;
201 }else{
202 std::cerr << termRed() << "check_package_file : incomplete package file '"<<tomlFile<<"'" << termDefault() << std::endl;
203 }
204 }
205 }
206 return found;
207}
208
210
216bool is_package_in_dir(std::vector<PPath> & packageFileNames, const PString & name, const PPath & packageDir, PPackageAttribute & pkgAttr){
217 for(size_t iFile = 0; iFile < packageFileNames.size(); ++iFile){
218 if(check_package_file(packageFileNames[iFile], name, packageDir, pkgAttr)){
219 std::cout << termGreen() << "Found package '" << name << "' in file '" << packageFileNames[iFile] << "'." << termDefault() << std::endl;
220 return true;
221 }
222 }
223 return false;
224}
225
227
231void is_generate_empty_config_ok(PPath & tomlFile, const PString & name, PPackageAttribute & pkgAttr){
232 if(!generate_empty_config(tomlFile, name, pkgAttr.getMinVersion(), pkgAttr.getMaxVersion())){
233 std::cerr << termRed() << "project_generator_loadPackageInfo : cannot generate empty config file for package '"<<name<<"'" << termDefault() << std::endl;
234 }
235 else{
236 std::cerr << termYellow() << "Package '" << name << "' does not exist in the configuration. A skeleton file has been created at '" << tomlFile << "'. Please complete it manually." << termDefault() << std::endl;
237 }
238}
239
241
245 // 1. Get all files in "share/PhoenixGenerator/Packages"
246 PPath packageDir = PPath(SYSTEM_INSTALL_DIR) / PPath("share") / PPath("PhoenixGenerator") / PPath("Packages");
247 std::cout << "Loading package info from directory '" << packageDir << "'." << std::endl;
248 PVecPath packageFileNames = packageDir.getAllFileInDir();
249 size_t packageNotFound = 0;
250
251 // 2. Search in toml files in PackageDir for each package, and fill other attributes if found
252 for(PackageMap::iterator it = config.mapDependencies.begin(); it != config.mapDependencies.end(); ++it){
253 const PString & name = it->first;
254 PPackageAttribute & pkgAttr = it->second;
255
256 if(!is_package_in_dir(packageFileNames, name, packageDir, pkgAttr)){
257 PPath localPackageDir = PPath::getCurrentDirectory() / PPath("Packages");
258 std::cout << "saving file in local dir: " << localPackageDir << std::endl;
259 PPath tomlFile = localPackageDir / PPath(name + ".toml");
260 if(localPackageDir.isDirectoryExist()){
261 PVecPath localPackageFileNames = localPackageDir.getAllFileInDir();
262 if(!is_package_in_dir(localPackageFileNames, name, localPackageDir, pkgAttr)){
263 is_generate_empty_config_ok(tomlFile, name, pkgAttr);
264 packageNotFound++;
265 }
266 }
267 //If the folder does not exists it means that the package we are looking for is unknown, so we create an empty config file inside the new created Packages/ directory
268 else{
269 localPackageDir.createDirectory();
270 is_generate_empty_config_ok(tomlFile, name, pkgAttr);
271 packageNotFound++;
272 }
273 }
274 }
275 if(packageNotFound != 0){
276 std::cout << termRed() << packageNotFound << " package(s) not found in the package directory." << termDefault() << std::endl;
277 }
278 return packageNotFound == 0;
279}
280
281
Describes a package attributes.
void setCmakeLib(const PString &cmakeLib)
Sets the cmakeLib of the PPackageAttribute.
void setPixiName(const PString &pixiName)
Sets the pixiName of the PPackageAttribute.
const PString & getMaxVersion() const
Gets the maxVersion of the PPackageAttribute.
const PString & getUrl() const
Gets the url of the PPackageAttribute.
const PString & getCmakeFind() const
Gets the cmakeFind of the PPackageAttribute.
const PString & getCmakeLib() const
Gets the cmakeLib of the PPackageAttribute.
void setUrl(const PString &url)
Sets the url of the PPackageAttribute.
void setCmakeFind(const PString &cmakeFind)
Sets the cmakeFind of the PPackageAttribute.
const PString & getMinVersion() const
Gets the minVersion of the PPackageAttribute.
const PString & getPixiName() const
Gets the pixiName of the PPackageAttribute.
Describes a package attributes.
void setAffiliation(const PString &affiliation)
Sets the affiliation of the PProjectMembers.
const PString & getFirstName() const
Gets the firstName of the PProjectMembers.
void setFirstName(const PString &firstName)
Sets the firstName of the PProjectMembers.
void setEmail(const PString &email)
Sets the email of the PProjectMembers.
const PString & getLastName() const
Gets the lastName of the PProjectMembers.
void setLastName(const PString &lastName)
Sets the lastName of the PProjectMembers.
bool is_package_in_dir(std::vector< PPath > &packageFileNames, const PString &name, const PPath &packageDir, PPackageAttribute &pkgAttr)
Search the package in the package directory.
void is_generate_empty_config_ok(PPath &tomlFile, const PString &name, PPackageAttribute &pkgAttr)
Generate an empty package info file skeleton and notify the user.
bool project_generator_loadPackageInfo(ProjectConfig &config)
This function should load the package info file from share/PhoenixGenerator/Packages and retrieve the...
bool check_package_file(const PPath &fileName, const PString &name, const PPath &packageDir, PPackageAttribute &pkgAttr)
Check the package file.
bool generate_empty_config(PPath &outFileName, const PString &name, PString &minVersion, PString &maxVersion)
Generate an empty package info file skeleton.
bool project_generator_split_dependencies(ProjectConfig &config, std::vector< PString > &vecDependencies)
Split dependencies strings into name, min_version, max_version and fill the map of dependencies.
bool parseProjectMembers(ProjectMembersMap &memberMap, const DicoValue *memberDico)
Parse project members (authors, maintainers, contributors) from TOML data.
bool project_generator_loadConfig(ProjectConfig &config, const PPath &descriptionFile)
Load the project configuration.
std::map< PString, PProjectMembers > ProjectMembersMap
Configuration of the project.
PString description
Description of the project.
ProjectMembersMap contributorMap
Map of the contributors of the project.
PString name
Name of the project.
PackageMap mapDependencies
Map of all dependencies of the project with structure PPackageAttribute values.
ProjectMembersMap authorMap
Map of authors of the project.
PString runnerTag
Specific runner tag if needed (could be MUST_big_runner)
PString ciToolkitUrl
CI toolkit url.
PString ciToolkitVersion
Version of the Phoenix CI toolkit component (optional, defaults to 3.0.4)
PString url
Project url.
PString mainBranch
Main branch of hte project.
PString version
Project version.
ProjectMembersMap maintainerMap
Map of maintainers of the project.
std::vector< PString > keywordList
List of keywords linked to the project.