* Bring back rbuild build to be used until bug 6372 is fixed.
[reactos.git] / tools / rbuild / backend / msvc / vcxprojmaker.cpp
1 /*
2 * Copyright (C) 2002 Patrik Stridvall
3 * Copyright (C) 2005 Royce Mitchell III
4 * Copyright (C) 2006 Hervé Poussineau
5 * Copyright (C) 2006 Christoph von Wittich
6 * Copyright (C) 2009 Ged Murphy
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #ifdef _MSC_VER
24 #pragma warning ( disable : 4786 )
25 #endif//_MSC_VER
26
27 #include <string>
28 #include <vector>
29 #include <set>
30 #include <algorithm>
31 #include <fstream>
32 #include <iostream>
33
34 #include <stdio.h>
35
36 #include "msvc.h"
37
38 using std::string;
39 using std::vector;
40 using std::set;
41
42 typedef set<string> StringSet;
43
44 #ifdef OUT
45 #undef OUT
46 #endif//OUT
47
48
49 VCXProjMaker::VCXProjMaker ( )
50 {
51 vcproj_file = "";
52 }
53
54 VCXProjMaker::VCXProjMaker ( Configuration& buildConfig,
55 const std::vector<MSVCConfiguration*>& msvc_configs,
56 std::string filename,
57 const Module& module)
58 {
59 configuration = buildConfig;
60 m_configurations = msvc_configs;
61 vcproj_file = filename;
62
63 OUT = fopen ( vcproj_file.c_str(), "wb" );
64
65 if ( !OUT )
66 {
67 printf ( "Could not create file '%s'.\n", vcproj_file.c_str() );
68 }
69
70 // Set the binary type
71 string module_type = GetExtension(*module.output);
72
73 if ((module.type == ObjectLibrary) || (module.type == RpcClient) ||(module.type == RpcServer) || (module_type == ".lib") || (module_type == ".a"))
74 binaryType = Lib;
75 else if ((module_type == ".dll") || (module_type == ".cpl"))
76 binaryType = Dll;
77 else if ((module_type == ".exe") || (module_type == ".scr"))
78 binaryType = Exe;
79 else if (module_type == ".sys")
80 binaryType = Sys;
81 else
82 binaryType = BinUnknown;
83 }
84
85 VCXProjMaker::~VCXProjMaker()
86 {
87 fclose ( OUT );
88 }
89
90 void
91 VCXProjMaker::_generate_item_group (std::vector<std::string> files)
92 {
93 size_t i;
94
95 for( i = 0; i<files.size(); i++)
96 {
97 std::string extension = ToLower(GetExtension(files[i]));
98
99 if( extension == ".c" || extension == ".cpp")
100 fprintf ( OUT, "\t\t<ClCompile Include=\"%s\" />\r\n", files[i].c_str());
101 else if( extension == ".s")
102 fprintf ( OUT, "\t\t<s_as_mscpp Include=\"%s\" />\r\n", files[i].c_str());
103 else if( extension == ".spec")
104 fprintf ( OUT, "\t\t<spec Include=\"%s\" />\r\n", files[i].c_str());
105 else if( extension == ".pspec")
106 fprintf ( OUT, "\t\t<pspec Include=\"%s\" />\r\n", files[i].c_str());
107 else if( extension == ".rc")
108 fprintf ( OUT, "\t\t<ResourceCompile Include=\"%s\" />\r\n", files[i].c_str());
109 else if( extension == ".h")
110 fprintf ( OUT, "\t\t<ClInclude Include=\"%s\" />\r\n", files[i].c_str());
111 else
112 fprintf ( OUT, "\t\t<None Include=\"%s\" />\r\n", files[i].c_str());
113 }
114 }
115
116 string
117 VCXProjMaker::_get_configuration_type ()
118 {
119 switch (binaryType)
120 {
121 case Exe:
122 return "Application";
123 case Dll:
124 case Sys:
125 return "DynamicLibrary";
126 case Lib:
127 return "StaticLibrary";
128 default:
129 return "";
130 }
131 }
132
133 void
134 VCXProjMaker::_generate_proj_file ( const Module& module )
135 {
136 string path_basedir = module.GetPathToBaseDir ();
137 size_t i;
138 string vcdir;
139
140 if ( configuration.UseVSVersionInPath )
141 {
142 vcdir = DEF_SSEP + _get_vc_dir();
143 }
144
145 printf ( "Creating MSVC project: '%s'\n", vcproj_file.c_str() );
146
147 _collect_files(module);
148
149 fprintf ( OUT, "<?xml version=\"1.0\" encoding = \"utf-8\"?>\r\n" );
150 fprintf ( OUT, "<Project " );
151 fprintf ( OUT, "DefaultTargets=\"Build\" " ); //FIXME: what's Build??
152 fprintf ( OUT, "ToolsVersion=\"4.0\" " ); //version 4 is the one bundled with .net framework 4
153 fprintf ( OUT, "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n" );
154
155 if (configuration.VSProjectVersion.empty())
156 configuration.VSProjectVersion = "10.00";
157
158 // Write out the configurations
159 fprintf ( OUT, "\t<ItemGroup Label=\"ProjectConfigurations\">\r\n" );
160 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
161 {
162 const MSVCConfiguration& cfg = *m_configurations[icfg];
163
164 if ( cfg.optimization == RosBuild )
165 _generate_makefile_configuration( module, cfg );
166 else
167 _generate_standard_configuration( module, cfg, binaryType );
168 }
169 fprintf ( OUT, "\t</ItemGroup>\r\n\r\n" );
170
171 // Write out the global info
172 fprintf ( OUT, "\t<PropertyGroup Label=\"Globals\">\r\n" );
173 fprintf ( OUT, "\t\t<ProjectGuid>{%s}</ProjectGuid>\r\n", module.guid.c_str() );
174 fprintf ( OUT, "\t\t<Keyword>%s</Keyword>\r\n", "Win32Proj" ); //FIXME: Win32Proj???
175 fprintf ( OUT, "\t\t<RootNamespace>%s</RootNamespace>\r\n", module.name.c_str() ); //FIXME: shouldn't this be the soltion name?
176 fprintf ( OUT, "\t</PropertyGroup>\r\n" );
177 fprintf ( OUT, "\r\n" );
178
179 fprintf ( OUT, "\t<PropertyGroup Label=\"Configuration\">\r\n");
180 if( binaryType != BinUnknown)
181 fprintf ( OUT, "\t\t<ConfigurationType>%s</ConfigurationType>\r\n" , _get_configuration_type().c_str());
182 fprintf ( OUT, "\t\t<CharacterSet>%s</CharacterSet>\r\n", module.isUnicode ? "Unicode" : "MultiByte");
183 fprintf ( OUT, "\t</PropertyGroup>\r\n");
184
185 fprintf ( OUT, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\r\n" );
186 fprintf ( OUT, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\r\n" );
187 fprintf ( OUT, "\t<ImportGroup Label=\"PropertySheets\">\r\n");
188 fprintf ( OUT, "\t\t<Import Project=\"%s\\reactos.props\" />\r\n", path_basedir.c_str());
189 fprintf ( OUT, "\t\t<Import Project=\"%s\\tools\\rbuild\\backend\\msvc\\rules\\reactos.defaults.props\" />\r\n", path_basedir.c_str());
190 fprintf ( OUT, "\t</ImportGroup>\r\n");
191
192 fprintf ( OUT, "\t<PropertyGroup>\r\n");
193 fprintf ( OUT, "\t\t<OutDir>$(RootOutDir)\\%s%s\\$(Configuration)\\</OutDir>\r\n", module.output->relative_path.c_str (), vcdir.c_str ());
194 fprintf ( OUT, "\t\t<IntDir>$(RootIntDir)\\%s%s\\$(Configuration)\\</IntDir>\r\n", module.output->relative_path.c_str (), vcdir.c_str ());
195
196 if( includes.size() != 0)
197 {
198 fprintf( OUT, "\t\t<ProjectIncludes>");
199 for ( i = 0; i < includes.size(); i++ )
200 fprintf ( OUT, "%s;", includes[i].c_str() );
201 fprintf( OUT, "</ProjectIncludes>\r\n");
202 }
203
204 if(defines.size() != 0)
205 {
206 fprintf( OUT, "\t\t<ProjectDefines>");
207 for ( i = 0; i < defines.size(); i++ )
208 fprintf ( OUT, "%s;", defines[i].c_str() );
209 fprintf( OUT, "</ProjectDefines>\r\n");
210 }
211
212 fprintf ( OUT, "\t</PropertyGroup>\r\n\r\n");
213
214 fprintf ( OUT, "\t<ItemDefinitionGroup>\r\n");
215 fprintf ( OUT, "\t\t<ClCompile>\r\n");
216 if ( module.cplusplus )
217 fprintf ( OUT, "\t\t\t<CompileAs>CompileAsCpp</CompileAs>\r\n");
218 fprintf ( OUT, "\t\t</ClCompile>\r\n");
219
220 fprintf ( OUT, "\t\t<Link>\r\n");
221 if(libraries.size() != 0)
222 {
223 fprintf ( OUT, "\t\t\t<AdditionalDependencies>");
224 for ( i = 0; i < libraries.size(); i++ )
225 {
226 string libpath = libraries[i].c_str();
227 libpath = libpath.erase (0, libpath.find_last_of ("\\") + 1 );
228 fprintf ( OUT, "%s;", libpath.c_str() );
229 }
230 fprintf ( OUT, "%%(AdditionalDependencies)</AdditionalDependencies>\r\n");
231
232 fprintf ( OUT, "\t\t\t<AdditionalLibraryDirectories>");
233 for ( i = 0; i < libraries.size(); i++ )
234 {
235 string libpath = libraries[i].c_str();
236 libpath = libpath.substr (0, libpath.find_last_of ("\\") );
237 fprintf ( OUT, "%s;", libpath.c_str() );
238 }
239 fprintf ( OUT, "%%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\r\n");
240 }
241
242 if( module.CRT != "msvcrt")
243 fprintf ( OUT, "\t\t\t<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>\r\n");
244
245 fprintf ( OUT, "\t\t</Link>\r\n");
246 fprintf ( OUT, "\t</ItemDefinitionGroup>\r\n");
247
248 fprintf ( OUT, "\t<ItemGroup>\r\n");
249 _generate_item_group(header_files);
250 _generate_item_group(source_files);
251 _generate_item_group(resource_files);
252 _generate_item_group(generated_files);
253 fprintf ( OUT, "\t</ItemGroup>\r\n\r\n");
254
255 fprintf ( OUT, "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\r\n");
256 fprintf ( OUT, "\t<Import Project=\"%s\\tools\\rbuild\\backend\\msvc\\rules\\reactos.targets\" />\r\n", path_basedir.c_str());
257
258 fprintf ( OUT, "</Project>\r\n");
259 }
260
261 void
262 VCXProjMaker::_generate_user_configuration ()
263 {
264 // Call base implementation
265 ProjMaker::_generate_user_configuration ();
266 }
267
268 void
269 VCXProjMaker::_generate_standard_configuration( const Module& module, const MSVCConfiguration& cfg, BinaryType binaryType )
270 {
271 fprintf ( OUT, "\t\t<ProjectConfiguration Include=\"%s|Win32\">\r\n", cfg.name.c_str() );
272 fprintf ( OUT, "\t\t<Configuration>%s</Configuration>\r\n", cfg.name.c_str() );
273 fprintf ( OUT, "\t\t<Platform>Win32</Platform>\r\n" );
274 fprintf ( OUT, "\t</ProjectConfiguration>\r\n" );
275 }
276
277 void
278 VCXProjMaker::_generate_makefile_configuration( const Module& module, const MSVCConfiguration& cfg )
279 {
280 // TODO: Implement me
281 ProjMaker::_generate_makefile_configuration ( module, cfg );
282 }