PhoenixGenerator  0.2.0
Set of tools to generate code
Loading...
Searching...
No Matches
wrapper_generator.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
9#include "wrapper_test.h"
10#include "wrapper_generator.h"
11
13
17 ProjectConfig wrapper(projectConfig);
18 wrapper.name = "Py"+projectConfig.name;
19 wrapper.url = wrapper.url.replace(projectConfig.name, wrapper.name);
20
21 return wrapper;
22}
23
25
29bool project_wrapper_generator_readme(const PPath & fileName, const ProjectConfig & projectConfig){
30 PString body;
31 body += "![PLIBS_9 logo](doc/logo.png)\n\n";
32
33 body += "# Remarks\n\n";
34 body += "This project was generated automatically by [phoenix_filegenerator](https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/PhoenixFileGenerator)\n";
35 body += "using [phoenix_generator](https://gitlab.in2p3.fr/CTA-LAPP/PHOENIX_LIBS2/PhoenixGenerator) library\n\n";
36
37 body += "# Code\n\n";
38 body += "Version : " + projectConfig.version + "\n\n";
39 body += projectConfig.url + "\n\n";
40 body += "# Description\n\n";
41 body += "Python wrapper version.\n";
42 body += projectConfig.description + "\n\n";
43
44 return fileName.saveFileContent(body);
45}
46
48
55bool project_wrapper_generator_setuppy(const PPath & fileName, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
56 PString body, moduleName = "py" + projectConfig.name.toLower();
57 body += "\n";
58 body += getCMakeListsHeader();
59 body += "from setuptools import setup\n";
60 body += "from setuptools import Extension\n";
61 body += "import sys\n";
62 body += "import numpy as np\n";
63 body += "import subprocess\n";
64 body += "\n";
65 body += "dataStreamIncludeDir = subprocess.run(['phoenixdatastream-config', '--include'], capture_output = True, text = True).stdout.strip(\"\\n\")\n";
66 body += "dataStreamLibDir = subprocess.run(['phoenixdatastream-config', '--lib'], capture_output = True, text = True).stdout.strip(\"\\n\")\n";
67 body += "\n";
68 body += "ext_modules = [\n";
69 body += "\tExtension(\""+moduleName+"\", sources=([\n";
70 body += "\t\t\""+moduleName+"/"+baseImplInclude+"_wrapper.cpp\",\n";
71 body += "\t\t\""+moduleName+"/"+projectConfig.name.toLower()+"_module.cpp\"\n";
72 body += "\t]),\n";
73 body += "\textra_compile_args = [\"-O3\", \"-Werror\", \"-g\"],\n";
74
75 body += "\tinclude_dirs = [np.get_include(), dataStreamIncludeDir, \"./\", \""+moduleName+"/\"],\n";
76 body += "\tlibraries=[\"phoenix_data_stream\"],\n";
77 body += "\tlibrary_dirs=[dataStreamLibDir],\n";
78 body += "\t)\n";
79 body += "]\n\n";
80
81 body += "try:\n";
82 body += "\tsetup(\n";
83 body += "\t\tname=\""+moduleName+"\",\n";
84 body += "\t\tversion=\""+projectConfig.version+"\",\n";
85 body += "\t\text_modules=ext_modules,\n";
86 body += "\t)\n";
87 body += "except Exception as e:\n";
88 body += "\tprint(str(e))\n";
89 body += "\tsys.exit(-1)\n";
90 body += "\n";
91 return fileName.saveFileContent(body);
92}
93
95
102bool project_wrapper_generator_pyprojectToml(const PPath & fileName, const ProjectConfig & projectConfig, const PString & baseImplInclude, const std::vector<PClassConfig> & vecClassConfig, const PVecPath & vecInclude){
103 PString body;
104 body += "\n";
105 body += getCMakeListsHeader();
106 body += "[project]\n";
107 body += "name = \"py"+projectConfig.name.toLower()+"\"\n";
108 body += "version = \""+projectConfig.version+"\"\n";
109 body += "description = \""+projectConfig.description.replace("\n", " ")+"\"\n";
110 body += "readme = \"README.md\"\n";
111 body += "license = \"CeCILL-C\"\n";
112 body += "dependencies = [\n";
113 body += "\t\"numpy\"\n";
114 body += "]\n";
115 body += "\n";
116 body += "[build-system]\n";
117 body += "requires = [\n";
118 body += "\t\"numpy\",\n";
119 body += "\t\"setuptools >= 74.1\",\n";
120 body += "\t\"cython\"\n";
121 body += "]\n";
122 body += "build-backend = \"setuptools.build_meta\"\n";
123 body += "\n";
124// body += "[tool.setuptools]\n";
125// body += "ext-modules = [\n";
126// body += "\t{\n";
127// body += "\t\tname = \""+projectConfig.name.toLower()+"\",\n";
128// body += "\t\tsources = [\n";
129// body += "\t\t\t\""+projectConfig.name.toLower()+"/"+baseImplInclude+"_wrapper.cpp\",\n";
130// body += "\t\t\t\""+projectConfig.name.toLower()+"/"+projectConfig.name+"_module.cpp\"\n";
131// body += "\t\t],\n";
132// body += "\t\textra_compile_args = [\"-O3\", \"-Werror\", \"-g\"]\n";
133// body += "\t}\n";
134// body += "\n";
135// body += "]\n";
136 body += "\n";
137 return fileName.saveFileContent(body);
138}
139
141
143void updateVecClassConfig(std::vector<PClassConfig> & vecClassConfig){
144 std::map<std::string, std::string> mapEnum;
145 for(std::vector<PClassConfig>::iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
146 if(it->getIsEnum()){
147 mapEnum[it->getName() + "::" + it->getName()] = it->getName();
148 size_t i(0lu);
149 std::vector<PClassAttribute> & vecAttr = it->getListAttribute();
150 for(std::vector<PClassAttribute>::iterator itAttr(vecAttr.begin()); itAttr != vecAttr.end(); ++itAttr){
151 if(itAttr->getDefaultValue() == ""){
152 itAttr->setDefaultValue(PString::toString(i));
153 }
154 ++i;
155 }
156 }
157 }
158 for(std::vector<PClassConfig>::iterator itClass(vecClassConfig.begin()); itClass != vecClassConfig.end(); ++itClass){
159 std::vector<PClassAttribute> & vecAttr = itClass->getListAttribute();
160 for(std::vector<PClassAttribute>::iterator itAttr(vecAttr.begin()); itAttr != vecAttr.end(); ++itAttr){
161 std::map<std::string, std::string>::iterator it(mapEnum.find(itAttr->getType()));
162 if(it != mapEnum.end()){
163 itAttr->setType(it->second);
164 itAttr->setIsEnum(true);
165 }
166 if(itAttr->getType() == "PPath" || itAttr->getType() == "PString"){
167 itAttr->setType("std::string");
168 }
169 }
170 }
171}
172
174
178bool project_wrapper_generator(const ProjectConfig & projectConfig, const PPath & configFile){
179 ProjectConfig wrapperConfig(project_createWrapperConfig(projectConfig));
180 PVecPath vecInclude;
181 std::vector<PClassConfig> vecClassConfig;
182 if(!parserClassConfig(vecClassConfig, vecInclude, configFile)){
183 std::cerr << "project_wrapper_generator : can't load file '" << configFile << "'" << std::endl;
184 return false;
185 }
186 //TODO : pass through vecClassConfig and replace PPath and PString by std::string to ensure PhoenixDataStream will work well on them for the wrapper
187 updateVecClassConfig(vecClassConfig);
188
189 //Then, let's create the hierarchy
190 PPath mainProjectDir(wrapperConfig.name);
191 if(!mainProjectDir.createDirectory()){
192 std::cerr << "project_wrapper_generator : cannot create main directory of project '"<<mainProjectDir<<"'" << std::endl;
193 return false;
194 }
195 //And module dir
196 PPath mainProjectModule(mainProjectDir / PPath(wrapperConfig.name.toLower()));
197 if(!mainProjectModule.createDirectory()){
198 std::cerr << "project_generator : cannot create module directory of project '"<<mainProjectModule<<"'" << std::endl;
199 return false;
200 }
201 //The readme
202 PPath readmeFile(mainProjectDir / PPath("README.md"));
203 if(!project_wrapper_generator_readme(readmeFile, projectConfig)){return false;}
204
205 PString baseImplInclude = configFile.getFileName().eraseExtension();
206 //The readme
207 PPath setupFile(mainProjectDir / PPath("setup.py"));
208 if(!project_wrapper_generator_setuppy(setupFile, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
209
210 PPath pyprojectFile(mainProjectDir / PPath("pyproject.toml"));
211 if(!project_wrapper_generator_pyprojectToml(pyprojectFile, projectConfig, baseImplInclude, vecClassConfig, vecInclude)){return false;}
212 //The unit tests
213 if(!project_wrapper_moduleGeneratorTest(mainProjectDir, projectConfig, "py"+projectConfig.name.toLower(), vecClassConfig, vecInclude)){return false;}
214 //The full module
215 return project_wrapper_moduleGenerator(mainProjectModule, projectConfig, baseImplInclude, vecClassConfig, vecInclude);
216}
217
218
219
PString getCMakeListsHeader()
Get the CMakeLists.txt header.
bool parserClassConfig(std::vector< PClassConfig > &listClassConfig, PVecPath &listInclude, const PPath &fileName)
Parser list class config.
Configuration of the project.
PString description
Description of the project.
PString name
Name of the project.
PString url
Project url.
PString version
Project version.
bool project_wrapper_generator_setuppy(const PPath &fileName, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the readme of the project directory.
bool project_wrapper_generator_readme(const PPath &fileName, const ProjectConfig &projectConfig)
Create the readme of the project directory.
bool project_wrapper_generator_pyprojectToml(const PPath &fileName, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the readme of the project directory.
ProjectConfig project_createWrapperConfig(const ProjectConfig &projectConfig)
Create the config of the wrapper.
void updateVecClassConfig(std::vector< PClassConfig > &vecClassConfig)
Update the vector of class configuration.
bool project_wrapper_generator(const ProjectConfig &projectConfig, const PPath &configFile)
Generate a full python wrapper project with PhoenixDataStream and PhoenixTypeStream.
bool project_wrapper_moduleGenerator(const PPath &modulePath, const ProjectConfig &projectConfig, const PString &baseImplInclude, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Create the wrapper module.
bool project_wrapper_moduleGeneratorTest(const PPath &projectPath, const ProjectConfig &projectConfig, const PString &moduleName, const std::vector< PClassConfig > &vecClassConfig, const PVecPath &vecInclude)
Generate the unit tests of the project.