efl
277 строк · 7.2 Кб
1/*
2* Copyright 2019 by its authors. See AUTHORS.
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17#include <iostream>
18#include <fstream>
19
20#include <stdlib.h>
21#include <unistd.h>
22#include <getopt.h>
23#include <libgen.h>
24
25#include <string>
26#include <algorithm>
27#include <stdexcept>
28#include <iosfwd>
29
30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
34#include <Eina.hh>
35
36
37namespace efl_mono_msbuild_gen {
38
39/// Program options.
40struct options_type
41{
42std::string out_file;
43std::string out_assembly;
44std::string target_type;
45std::string platform;
46std::vector<std::string> cs_files;
47std::vector<std::string> defines;
48std::vector<std::string> references;
49std::vector<std::string> lib_paths;
50};
51
52efl::eina::log_domain domain("efl_mono_msbuild_gen");
53
54namespace {
55
56void
57_print_version()
58{
59std::cerr
60<< "EFL Mono MSBuild Generator (EFL "
61<< PACKAGE_VERSION << ")" << std::endl;
62}
63
64static void
65_usage(const char *progname)
66{
67std::cerr
68<< progname
69<< " [options] [files]" << std::endl
70<< "Options:" << std::endl
71<< " -o, --out-file <file> The output file name. [default: <classname>.eo.hh]" << std::endl
72<< " -v, --version Print the version." << std::endl
73<< " -h, --help Print this help." << std::endl;
74exit(EXIT_FAILURE);
75}
76
77static void
78_assert_not_dup(std::string option, std::string value)
79{
80if (value != "")
81{
82EINA_CXX_DOM_LOG_ERR(efl_mono_msbuild_gen::domain) <<
83"Option -" + option + " already set (" + value + ")";
84}
85}
86
87static bool
88opts_check(efl_mono_msbuild_gen::options_type const& opts)
89{
90if (opts.out_file.empty())
91{
92EINA_CXX_DOM_LOG_ERR(efl_mono_msbuild_gen::domain)
93<< "Nowhere to generate?" << std::endl;
94}
95else
96return true; // valid.
97return false;
98}
99
100static efl_mono_msbuild_gen::options_type
101opts_get(int argc, char **argv)
102{
103efl_mono_msbuild_gen::options_type opts;
104
105const struct option long_options[] =
106{
107{ "out-file", required_argument, 0, 'o' },
108{ "assembly", required_argument, 0, 'a' },
109{ "target-type", required_argument, 0, 't' },
110{ "platform", required_argument, 0, 'p' },
111{ "define", required_argument, 0, 'd' },
112{ "reference", required_argument, 0, 'r' },
113{ "lib-path", required_argument, 0, 'l' },
114{ "version", no_argument, 0, 'v' },
115{ "help", no_argument, 0, 'h' },
116{ 0, 0, 0, 0 }
117};
118const char* options = "o:a:t:p:d:r:l:vh";
119
120int c, idx;
121while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1)
122{
123if (c == 'o')
124{
125_assert_not_dup("o", opts.out_file);
126opts.out_file = optarg;
127}
128else if (c == 'a')
129{
130_assert_not_dup("a", opts.out_assembly);
131opts.out_assembly = optarg;
132}
133else if (c == 't')
134{
135_assert_not_dup("t", opts.target_type);
136opts.target_type = optarg;
137}
138else if (c == 'p')
139{
140_assert_not_dup("p", opts.platform);
141opts.platform = optarg;
142}
143else if (c == 'd')
144{
145opts.defines.push_back(optarg);
146}
147else if (c == 'r')
148{
149opts.references.push_back(optarg);
150}
151else if (c == 'l')
152{
153opts.lib_paths.push_back(optarg);
154}
155else if (c == 'h')
156{
157_usage(argv[0]);
158}
159else if (c == 'v')
160{
161_print_version();
162if (argc == 2) exit(EXIT_SUCCESS);
163}
164}
165
166for (int i = optind; i < argc; ++i)
167{
168opts.cs_files.push_back(argv[i]);
169}
170
171if (!efl_mono_msbuild_gen::opts_check(opts))
172{
173_usage(argv[0]);
174assert(false && "Wrong options passed in command-line");
175}
176
177return opts;
178}
179
180static void
181run(options_type const& opts)
182{
183std::ofstream os (opts.out_file.c_str());
184if(!os.is_open())
185{
186throw std::runtime_error(std::string{"Couldn't open output file "} + opts.out_file);
187}
188
189os << "<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n";
190
191os << " <PropertyGroup>\n";
192if (opts.target_type == "library")
193os << " <OutputType>Library</OutputType>\n";
194//os << " <Version>" << opts.version << "</Version>\n"; // TODO
195if (!opts.defines.empty())
196{
197os << " <DefineConstants>$(DefineConstants)";
198for (auto const& def : opts.defines)
199{
200os << ";" << def;
201}
202os << "</DefineConstants>\n";
203}
204os << " </PropertyGroup>\n";
205
206if (!opts.cs_files.empty())
207{
208os << " <ItemGroup>\n";
209for (auto fname : opts.cs_files)
210{
211std::replace(fname.begin(), fname.end(), '/', '\\');
212os << " <CSFile Include=\"" << fname << "\" />\n";
213}
214os << " </ItemGroup>\n";
215}
216
217if (!opts.references.empty())
218{
219os << " <ItemGroup>\n";
220for (auto libname : opts.references)
221{
222os << " <Reference Include=\"" << libname << "\" />\n";
223}
224os << " </ItemGroup>\n";
225}
226
227if (!opts.lib_paths.empty())
228{
229os << " <ItemGroup>\n";
230for (auto libpath : opts.lib_paths)
231{
232std::replace(libpath.begin(), libpath.end(), '/', '\\');
233os << " <LibPath Include=\"" << libpath << "\" />\n";
234}
235os << " </ItemGroup>\n";
236}
237
238os << " <Target Name=\"Build\">\n";
239os << " <CSC Sources=\"@(CSFile)\" References=\"@(Reference)\" AdditionalLibPaths=\"$(LibPath)\" DefineConstants=\"$(DefineConstants)\" ";
240{
241if (!opts.out_assembly.empty())
242{
243os << "OutputAssembly=\"" << opts.out_assembly << "\" ";
244}
245if (!opts.target_type.empty())
246{
247os << "TargetType=\"" << opts.target_type << "\" ";
248}
249if (!opts.platform.empty())
250{
251os << "Platform=\"" << opts.platform << "\" ";
252}
253}
254os << "/>\n";
255os << " </Target>\n";
256
257os << "</Project>\n";
258}
259
260} // anonymous namespace
261} // namespace efl_mono_msbuild_gen
262
263int main(int argc, char **argv)
264{
265try
266{
267efl::eina::eina_init eina_init;
268efl_mono_msbuild_gen::options_type opts = efl_mono_msbuild_gen::opts_get(argc, argv);
269efl_mono_msbuild_gen::run(opts);
270}
271catch(std::exception const& e)
272{
273EINA_CXX_DOM_LOG_ERR(efl_mono_msbuild_gen::domain) << "EFL Mono MSBuild generation for the following reason: " << e.what() << std::endl;
274return -1;
275}
276return 0;
277}
278