root/simulator/trunk/vendor/cmake/Source/cmPreCompiledHeaderCommand.cpp

Revision 1468, 17.5 kB (checked in by sehenley, 6 months ago)

Update to Ogre 1.7.0 - removed CEGUI (no mingw support).

Line 
1 //    OSRail -- a network enabled railroad operations simulator and utilities
2 //    Copyright (C) 2007,2008 Samuel E. Henley sehenley@comcast.net
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 // cmakefilter.cpp
19
20 #include <iostream>
21 #include <fstream>
22 #include <string>
23 #include <cstring>
24 #include <vector>
25 #include <cstdlib>
26 #include <algorithm>
27 #include <cctype>
28
29 //#include <signal.h
30 #include "cmake.h"
31 #include "cmMakefile.h"
32 #include "cmSourceFile.h"
33 #include "cmTest.h"
34
35 #include "cmPreCompiledHeaderCommand.h"
36
37 using namespace std;
38
39 /// \addtogroup utilities "Utilities"
40 /// @{
41 ///   \addtogroup utilitiescmake "Utilities CMake Custom Command PURGECONFIGURE"
42 ///   @{
43
44
45 /// \file
46 /// Special CMake command to filter and unwined the output
47 /// of xxx-config and pkg-config programes.
48 ///
49 /// from cmCacheManager.h in cmake source
50
51
52
53 namespace precompiledheader
54 {
55     //FILE* log_file = 0;
56     //const char* log_file_name = "/home/samuel/working/simulator/branches/dashboard-682/MAKE/bin/precompiledheader/log.txt";
57
58
59     static const char version[] = "$Id:";
60
61     //extern "C" void TrapsForSignals( int sig )
62     //{
63     //      fprintf(stderr, "PurgeConfigure crashed with signal: %d.\n", sig);
64     //}
65
66     const char* generator_table[] =
67     {
68          "Borland Makefiles",
69          "MSYS Makefiles",
70          "MinGW Makefiles",
71          "NMake Makefiles",
72          "Unix Makefiles",
73          "Visual Studio 6",
74          "Visual Studio 7",
75          "Visual Studio 7 .NET 2003",
76          "Visual Studio 8 2005",
77          "Visual Studio 8 2005 Win64",
78          "Visual Studio 9 2008",
79          "Visual Studio 9 2008 Win64",
80          "Watcom WMake",
81          "CodeBlocks - MinGW Makefiles",
82          "CodeBlocks - Unix Makefiles",
83          "Eclipse CDT4 - MinGW Makefiles",
84          "Eclipse CDT4 - NMake Makefiles",
85          "Eclipse CDT4 - Unix Makefiles",
86          "CodeBlocks",
87     };
88
89     const size_t generator_table_size = sizeof( generator_table )/sizeof( const char* );
90
91     /// Convert a cmake string to a set of strings - can't use cmSystemTools
92     void list2set( const std::string sz, std::set< std::string >& vector, bool clear=true )
93     {
94         if( clear )vector.clear();
95
96         size_t start = sz.find_first_not_of(" ;", 0 );
97         while( start != std::string::npos )
98         {
99             std::string name;
100             size_t stop = sz.find_first_of(" ;", start );
101
102             if( stop != std::string::npos )
103             {
104                 vector.insert( sz.substr( start, stop - start ));
105                 start = sz.find_first_not_of(" ;", stop );
106             }
107             else
108             {
109                 vector.insert( sz.substr( start, sz.size() ));
110                 start = std::string::npos;
111             }
112         }
113     }
114
115
116
117
118
119
120
121 } //namespace precompiledheader
122
123     bool operator==( const std::string& a, const char* b )
124     {
125         return a.compare( b ) == 0;
126     }
127
128     bool cmPreCompiledHeaderCommand::InitialPass( std::vector<std::string> const& args, cmExecutionStatus &status )
129     {
130         //log_file = fopen( log_file_name, "ab" );
131         //fprintf( log_file, "initialPass %s\n", argv[0] );
132         //fclose( log_file );
133
134         //signal( SIGSEGV, TrapsForSignals );
135         //signal( SIGBUS,  TrapsForSignals );
136         //signal( SIGILL,  TrapsForSignals );
137
138         size_t argc = args.size();
139
140         if( argc < 2 )
141         {
142             std::string error;
143             error = "Error Must have at lest a generator and target";
144             SetError( error.c_str() );
145             return false;
146         }
147
148         Data& data = arguments[args[1]];
149         data.target = args[1];
150         data.generator = args[0];
151
152         std::string sz;
153
154         try
155         {
156             const char* p = Makefile->GetDefinition( "CMAKE_GENERATOR" );
157             if( data.generator.compare( p ) != 0 ) return 1; //not this time
158
159             size_t index = 0;
160             for( ; index < precompiledheader::generator_table_size; index++ ) if( data.generator == precompiledheader::generator_table[index] ) break;
161             if( index == precompiledheader::generator_table_size )
162             {
163                 std::string error;
164                 error = "Compiler/IDE type not supported - ";
165                 error += data.generator;
166                 SetError( error.c_str() );
167                 return false;
168             }
169
170             switch( index )
171             {
172                 case 0  : break;
173                 case 1  : //MSYS Makefiles
174                 case 2  : //MinGW Makefiles
175                 case 4  : //Unix Makefiles
176                 case 13 : //CodeBlocks - MinGW Makefiles
177                 case 14 : //CodeBlocks - Unix Makefiles
178                     if( argc == 4 )
179                     {
180                         data.header_file = args[2];
181                         data.directory = args[3];
182                         Makefile->AddIncludeDirectory( data.directory.c_str() );
183                     }
184                     else
185                     {
186                         std::string error;
187                         error = "Error gcc requires generator, target, header and directory";
188                         SetError( error.c_str() );
189                         return false;
190                     }
191                     break;
192                 case 3  : break; //NMake Makefiles
193                 case 5  : break;
194                 case 6  : break;
195                 case 7  : //Visual Studio 7 .NET 2003
196                 case 8  : //Visual Studio 8 2005
197                 case 10 : //Visual Studio 9 2008
198                     if( argc == 5 )
199                     {
200                         data.header_file = args[2];
201                         data.dummy_file = args[3];
202                     }
203                     else
204                     {
205                         std::string error;
206                         error = "Error MSVC requires generator, target, directory, header and dummy cpp";
207                         SetError( error.c_str() );
208                         return false;
209                     }
210                     break;
211                 case 9  : break;
212                 case 11 : break;
213                 case 12 : break;
214
215                 case 15 : break;
216                 case 16 : break;
217                 case 17 : break;
218                 case 18 : //CodeBlocks
219                     if( argc == 4 )
220                     {
221                         data.header_file = args[2];
222                         data.pch_mode = args[3];
223                     }
224                     else
225                     {
226                         std::string error;
227                         error = "Error CodeBlocks requires generator, target and pch mode of 1, 2, or 3";
228                         SetError( error.c_str() );
229                         return false;
230                     }
231                     break;
232             }
233
234
235         }
236         catch( ... )
237         {
238             std::string error;
239             error = "Error reading string:";
240             error += sz;
241             SetError( error.c_str() );
242             return false;
243         }
244
245
246         //signal( SIGSEGV, 0 );
247         //signal( SIGBUS,  0 );
248         //signal( SIGILL,  0 );
249
250         return true;
251
252     }
253
254     //IF( UNIX )
255     //
256     //    ADD_CUSTOM_COMMAND( OUTPUT ${Simulator_SOURCE_DIR}/${PCH_HEADER}.gch
257     //          COMMAND ${CMAKE_CXX_COMPILER}
258     //                          ARGS ${CMAKE_CXX_FLAGS}
259     //                          -x c++-header
260     //                          -o ${Simulator_SOURCE_DIR}/${PCH_HEADER}.gch
261     //                          -I ${SIMULATOR_WORKING_DIRECTORY}/src/include
262     //                -I ${SIMULATOR_OGRE_INCLUDE_DIRECTORY}
263     //                -I ${SIMULATOR_WORKING_BINARY_DIRECTORY}/include
264     //                -I ${SIMULATOR_ANGELSCRIPT_INCLUDE_DIRECTORY}
265     //                -I ${SIMULATOR_WORKING_DIRECTORY}/src/utilities
266     //                -I ${Console_SOURCE_DIR}
267     //                -I ${SIMULATOR_OIS_INCLUDE_DIRECTORY}
268     //                -I ${SIMULATOR_LIBCURL_INCLUDE_PATH}
269     //                          ${Simulator_SOURCE_DIR}/${PCH_HEADER}
270     //        MAIN_DEPENDENCY ${PCH_HEADER}
271     //  )
272     //
273     //ENDIF( UNIX )
274
275     void cmPreCompiledHeaderCommand::gccPreCompiledHeader( cmTarget* target, std::string& header_file, std::string& directory )
276     {
277         std::vector< std::string >depends;
278         depends.clear();
279
280         cmCustomCommandLine command;
281         std::string compiler;
282         const char* p = Makefile->GetDefinition( "CMAKE_CXX_COMPILER" );
283         if( p )compiler = p;
284         else compiler = "g++";
285
286         std::set< std::string > flags;
287
288         std::string symbol = "CMAKE_CXX_FLAGS";
289         p = Makefile->GetDefinition( symbol.c_str() );
290         if( p )
291         {
292             std::string sz = p;
293             precompiledheader::list2set( sz, flags, true );
294         }
295
296         std::string build_type;
297         p = Makefile->GetDefinition( "CMAKE_BUILD_TYPE" );
298         if( p )build_type = p;
299         else build_type = "RelWithDebInfo";
300         symbol += '_';
301         symbol += cmSystemTools::UpperCase( build_type );
302
303         p = Makefile->GetDefinition( symbol.c_str() );
304         if( p )
305         {
306             std::string sz = p;
307             precompiledheader::list2set( sz, flags, false );
308         }
309
310
311         if( target->GetType() == cmTarget::SHARED_LIBRARY )
312         {
313             symbol = "CMAKE_SHARED_LIBRARY_CXX_FLAGS";
314             p = Makefile->GetDefinition( symbol.c_str() );
315             if( p )
316             {
317                 std::string sz = p;
318                 precompiledheader::list2set( sz, flags, false );
319             }
320         }
321         else if( target->GetType() == cmTarget::MODULE_LIBRARY )
322         {
323             symbol = "CMAKE_MODULE_LIBRARY_CXX_FLAGS";
324             p = Makefile->GetDefinition( symbol.c_str() );
325             if( p )
326             {
327                 std::string sz = p;
328                 precompiledheader::list2set( sz, flags, false );
329             }
330         }
331
332         p = Makefile->GetDefineFlags();
333
334         if( p && strlen(p) > 0 )
335         {
336             std::string sz = p;
337             precompiledheader::list2set( sz, flags, false );
338         }
339
340         symbol = "COMPILE_DEFINITIONS";
341         std::set< std::string > no_d;
342         p = Makefile->GetProperty( symbol.c_str() );
343         if( p )
344         {
345             std::string sz = p;
346             precompiledheader::list2set( sz, no_d, true );
347             std::set< std::string >::iterator it = no_d.begin();
348             while( it != no_d.end() )
349             {
350                 std::string sz = "-D";
351                 sz += *it++;
352                 flags.insert( sz );
353             }
354
355         }
356
357         p = target->GetProperty( symbol.c_str() );
358         if( p )
359         {
360             std::string sz = p;
361             precompiledheader::list2set( sz, no_d, true );
362             std::set< std::string >::iterator it = no_d.begin();
363             while( it != no_d.end() )
364             {
365                 std::string sz = "-D";
366                 sz += *it++;
367                 flags.insert( sz );
368             }
369
370         }
371
372
373         symbol += '_';
374         symbol += cmSystemTools::UpperCase( build_type );
375         p = Makefile->GetProperty( symbol.c_str() );
376         if( p )
377         {
378             std::string sz = p;
379             precompiledheader::list2set( sz, no_d, true );
380             std::set< std::string >::iterator it = no_d.begin();
381             while( it != no_d.end() )
382             {
383                 std::string sz = "-D";
384                 sz += *it++;
385                 flags.insert( sz );
386             }
387
388         }
389
390         p = target->GetProperty( symbol.c_str() );
391         if( p )
392         {
393             std::string sz = p;
394             precompiledheader::list2set( sz, no_d, true );
395             std::set< std::string >::iterator it = no_d.begin();
396             while( it != no_d.end() )
397             {
398                 std::string sz = "-D";
399                 sz += *it++;
400                 flags.insert( sz );
401             }
402
403         }
404         command.push_back( compiler );
405         std::set< std::string >::iterator it = flags.begin();
406         while( it != flags.end() )
407         {
408             //remove linker flags
409             if( (*it).find( "-Wl") == std::string::npos )command.push_back( *it++ );
410             else it++;
411         }
412         command.push_back( "-x" );
413         command.push_back( "c++-header" );
414         command.push_back( "-o" );
415         std::string output = directory;
416         output += '/';
417         output += header_file;
418         output += ".gch";
419         command.push_back( output );
420
421         const std::vector< std::string >& includes = Makefile->GetIncludeDirectories();
422         for( size_t i=0; i<includes.size(); i++ )
423         {
424             std::string sz = "-I";
425             sz += includes[i];
426             command.push_back( sz );
427         }
428
429         std::string source = Makefile->GetStartDirectory();
430         source += '/';
431         source += header_file;
432         command.push_back( source );
433
434         //for( size_t j=0; j<command.size(); j++ ) std::cerr << command[j] << std::endl;
435
436
437
438         cmCustomCommandLines commands;
439         commands.push_back( command );
440
441
442         Makefile->AddCustomCommandToOutput( output.c_str(),
443                                             depends,
444                                             header_file.c_str(),
445                                             commands,
446                                             0,                 //comment
447                                             0  );              //working directory
448
449
450
451
452         cmSourceFile* gch = Makefile->GetOrCreateSource( output.c_str(), true ); //a generated file
453         gch->SetProperty( "GENERATED", "TRUE" );
454
455     }
456
457     //IF( MSVC )
458     //
459     //    SET_TARGET_PROPERTIES( Simulator
460     //                           PROPERTIES COMPILE_FLAGS "/Yu${PCH_HEADER} /Fp${PCH_FILE}"
461     //    )
462     //
463     //    SET_SOURCE_FILES_PROPERTIES( ${PCH_DUMMY}
464     //                                 PROPERTIES COMPILE_FLAGS "/Yc${PCH_HEADER} /Fp${PCH_FILE}"
465     //    )
466     //
467     //
468     //ENDIF( MSVC )
469
470     void cmPreCompiledHeaderCommand::vcPreCompiledHeader( std::string& header_file, std::string& dummy_file )
471     {
472
473     }
474
475
476     //# \note Project property CODEBLOCKS_PCH_MODE={ 0, 1, 2 } - Generate in a directory alongside header,
477     //    ##  in object directory, or default to alongside header. Generator will add the directory for option
478     //    ##  1 to the top of the compiler include list.
479     //
480     //    SET_PROPERTY( TARGET Simulator
481     //                         PROPERTY CODEBLOCKS_PCH_MODE 1
482     //    )
483
484     void cmPreCompiledHeaderCommand::cbPreCompiledHeader( cmTarget* target, std::string& header_file, std::string& pch_mode )
485     {
486          target->SetProperty( "CODEBLOCKS_PCH_MODE", pch_mode.c_str() );
487          cmSourceFile* source = Makefile->GetOrCreateSource( header_file.c_str(), false ); //not a generated file
488          source->SetProperty( "CODEBLOCKS_SOURCE_WEIGHT", "0" );
489     }
490
491
492     void cmPreCompiledHeaderCommand::FinalPass()
493     {
494         //log_file = fopen( log_file_name, "ab" );
495         //fprintf( log_file, "finalPass\n" );
496         //fclose( log_file );
497
498         std::map< std::string, Data >::iterator targets = arguments.begin();
499
500         while( targets != arguments.end() )
501         {
502             Data& data = (*targets++).second;
503             cmTarget* target = Makefile->FindTarget( data.target.c_str() );
504
505             const char* p = Makefile->GetDefinition( "CMAKE_GENERATOR" );
506             if( data.generator.compare( p ) != 0 )
507             {
508                 continue;
509             }
510
511             size_t index = 0;
512             for( ; index<precompiledheader::generator_table_size; index++ ) if( data.generator == precompiledheader::generator_table[index] ) break;
513             if( index == precompiledheader::generator_table_size )
514             {
515                 std::string error;
516                 error = "Compiler/IDE type not supported - ";
517                 error += data.generator;
518                 SetError( error.c_str() );
519                 return;
520             }
521
522             switch( index )
523             {
524                 case 0  : break;
525                 case 1  : //MSYS Makefiles
526                 case 2  : //MinGW Makefiles
527                 case 4  : //Unix Makefiles
528                 case 13 : //CodeBlocks - MinGW Makefiles
529                 case 14 : //CodeBlocks - Unix Makefiles
530                     gccPreCompiledHeader( target, data.header_file, data.directory );
531                     break;
532                 case 3  : break; //NMake Makefiles
533                 case 5  : break;
534                 case 6  : break;
535                 case 7  : //Visual Studio 7 .NET 2003
536                 case 8  : //Visual Studio 8 2005
537                 case 10 : //Visual Studio 9 2008
538                     vcPreCompiledHeader( data.header_file, data.dummy_file );
539                     break;
540                 case 9  : break;
541                 case 11 : break;
542                 case 12 : break;
543
544                 case 15 : break;
545                 case 16 : break;
546                 case 17 : break;
547                 case 18 : //CodeBlocks
548                     cbPreCompiledHeader( target, data.header_file, data.pch_mode );
549                     break;
550             }
551
552
553         }
554
555
556     }
557
558
559 ///   @}   group utilitiescmake
560 /// @}   group utilities
Note: See TracBrowser for help on using the browser.