* Bring back rbuild build to be used until bug 6372 is fixed.
[reactos.git] / tools / rbuild / backend / mingw / rule.cpp
1 /*
2 * Copyright (C) 2008 Hervé Poussineau
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "../../rbuild.h"
20 #include "modulehandler.h"
21 #include "rule.h"
22
23 using std::string;
24
25 static void
26 ReplaceVariable( string& str,
27 const string& name,
28 const string& value )
29 {
30 size_t i = str.find ( name );
31 while ( i != string::npos )
32 {
33 str.replace ( i, name.length (), value );
34 i = str.find ( name );
35 }
36 }
37
38 static std::string
39 FixString ( const string& str, Backend *backend, const Module& module, const FileLocation *source,
40 const std::string& additional_dependencies, const std::string& compiler_flags,
41 const std::map<std::string, std::string>& custom_variables )
42 {
43 string ret = str;
44
45 for ( std::map<std::string, std::string>::const_iterator p = custom_variables.begin(); p != custom_variables.end(); ++ p )
46 {
47 ReplaceVariable ( ret, "$(" + p->first + ")", p->second );
48 }
49
50 string dep = additional_dependencies;
51
52 dep += " " + module.xmlbuildFile;
53
54 if ( source )
55 {
56 ReplaceVariable ( ret, "$(source_noext)", ReplaceExtension ( backend->GetFullName ( *source ), "" ) );
57 ReplaceVariable ( ret, "$(source)", backend->GetFullName ( *source ) );
58 ReplaceVariable ( ret, "$(source_dir)", source->relative_path );
59 ReplaceVariable ( ret, "$(source_name)", source->name );
60 ReplaceVariable ( ret, "$(source_name_noext)", ReplaceExtension ( source->name , "" ) );
61 ReplaceVariable ( ret, "$(source_path)", backend->GetFullPath ( *source ) );
62 ReplaceVariable ( ret, "$(intermediate_dir)", backend->GetFullPath ( FileLocation ( IntermediateDirectory, source->relative_path, "" ) ) );
63 ReplaceVariable ( ret, "$(intermediate_path_noext)", ReplaceExtension ( backend->GetFullName ( FileLocation ( IntermediateDirectory, source->relative_path, source->name ) ), "" ) );
64 ReplaceVariable ( ret, "$(intermediate_path_unique)", ReplaceExtension ( backend->GetFullName ( FileLocation ( IntermediateDirectory, source->relative_path, source->name ) ), "" ) + "_" + module.name );
65 }
66 ReplaceVariable ( ret, "$(dependencies)", dep );
67 ReplaceVariable ( ret, "$(bare_dependencies)", additional_dependencies );
68 ReplaceVariable ( ret, "$(module_name)", module.name );
69 ReplaceVariable ( ret, "$(module_dllname)", module.GetDllName() );
70 ReplaceVariable ( ret, "$(module_output)", GetTargetMacro ( module, true ) );
71 ReplaceVariable ( ret, "$(SEP)", sSep );
72
73 ReplaceVariable ( ret, "$(compiler_flags)", compiler_flags );
74
75 return ret;
76 }
77
78 Rule::Rule( const std::string& command, const char *generatedFile1, ... )
79 : command ( command )
80 {
81 va_list ap;
82 const char *s;
83
84 s = generatedFile1;
85 va_start ( ap, generatedFile1 );
86 while ( s )
87 {
88 generatedFiles.push_back ( s );
89 s = va_arg ( ap, const char* );
90 }
91 va_end ( ap );
92 }
93
94
95 void Rule::Execute ( FILE *outputFile,
96 MingwBackend *backend,
97 const Module& module,
98 const FileLocation *source,
99 string_list& clean_files,
100 const std::string& additional_dependencies,
101 const std::string& compiler_flags,
102 const std::map<std::string, std::string>& custom_variables ) const
103 {
104 string cmd = FixString ( command, backend, module, source, additional_dependencies, compiler_flags, custom_variables );
105
106 fprintf ( outputFile, "%s", cmd.c_str () );
107
108 for ( size_t i = 0; i < generatedFiles.size (); i++ )
109 {
110 string file = FixString ( generatedFiles[i], backend, module, source, "", "", custom_variables );
111 if ( file[file.length () - 1] != cSep )
112 {
113 clean_files.push_back ( file );
114 continue;
115 }
116
117 if ( file[0] != '$' )
118 throw InvalidOperationException ( __FILE__,
119 __LINE__,
120 "Invalid directory %s.",
121 file.c_str () );
122
123 size_t pos = file.find_first_of ( cSep );
124 string relative_path = file.substr ( pos + 1, file.length () - pos - 2 );
125 string dir = file.substr ( 0, pos );
126 if ( dir == "$(INTERMEDIATE)" )
127 backend->AddDirectoryTarget ( relative_path, backend->intermediateDirectory );
128 else if ( dir == "$(OUTPUT)" )
129 backend->AddDirectoryTarget ( relative_path, backend->outputDirectory );
130 else if ( dir == "$(INSTALL)" )
131 backend->AddDirectoryTarget ( relative_path, backend->installDirectory );
132 else
133 throw InvalidOperationException ( __FILE__,
134 __LINE__,
135 "Invalid directory %s.",
136 dir.c_str () );
137 }
138 }
139
140
141 void Rule::Execute ( FILE *outputFile,
142 MingwBackend *backend,
143 const Module& module,
144 const FileLocation *source,
145 string_list& clean_files,
146 const std::string& additional_dependencies,
147 const std::string& compiler_flags ) const
148 {
149 this->Execute ( outputFile,
150 backend,
151 module,
152 source,
153 clean_files,
154 additional_dependencies,
155 compiler_flags,
156 std::map<std::string, std::string>() );
157 }