root/simulator/trunk/vendor/cmake/Source/cmGlobalCodeBlocksGenerator.cxx

Revision 1306, 19.1 kB (checked in by sehenley, 10 months ago)

Update vendor cmake to 2.8.0-rc3

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 //
19 //----------------------------------------------------------------------
20 /// \file
21 /// Implementation file for CodeBlocks Global (Workspace Files) Generator for CMake
22 #if defined(_WIN32) && !defined(__CYGWIN__)
23     #include "windows.h"
24 #endif
25 #include "cmGlobalCodeBlocksGenerator.h"
26 #include "cmLocalCodeBlocksGenerator.h"
27 #include "cmLocalGenerator.h"
28 #include "cmake.h"
29 #include "cmMakefile.h"
30 #include "cmTest.h"
31
32 using namespace codeblocksgenerator;
33
34 // ///////////// cmGlobalGenerator interface ////////////
35 /// Initial Global Generator
36 cmGlobalCodeBlocksGenerator::cmGlobalCodeBlocksGenerator()
37 {
38         FindMakeProgramFile = "CMakeCodeBlocksFindMake.cmake";
39 }
40
41 /// Destroy all Generators
42 cmGlobalCodeBlocksGenerator::~cmGlobalCodeBlocksGenerator()
43 {
44 }
45
46 /// \note Called from cmGlobalGenerator::Configure()
47 cmLocalGenerator* cmGlobalCodeBlocksGenerator::CreateLocalGenerator()
48 {
49     cmLocalCodeBlocksGenerator* local = new cmLocalCodeBlocksGenerator; //Will be destroyed in base class
50     local->SetGlobalGenerator( this );  //cmLocalGenerator.h
51     return local;
52 }
53
54 void cmGlobalCodeBlocksGenerator::GetDocumentation( cmDocumentationEntry& entry )const
55 {
56         entry.Name = GetName();
57     entry.Brief = "Generates project files for CodeBlocks to be used with gcc.";
58     entry.Full = "Generates workspace and project files for CodeBlocks\n"
59                  "Support gcc under Linux and Windows.";
60 }
61
62
63 /// \note Called initial pass
64 void cmGlobalCodeBlocksGenerator::Configure()
65 {
66     cmGlobalGenerator::Configure();
67
68 }
69
70
71 /// \note Called when the configure/generate button is pressed,
72 /// same instance as last configure pass
73 void cmGlobalCodeBlocksGenerator::Generate()
74 {
75     cmGlobalGenerator::Generate();
76     writeWorkspaceFile();
77 }
78
79 void cmGlobalCodeBlocksGenerator::EnableLanguage(std::vector<std::string>const& languages, cmMakefile* makefile, bool optional)
80 {
81
82     makefile->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
83     makefile->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
84
85     // Create list of configurations requested by user's cache, if any.
86     cmGlobalGenerator::EnableLanguage( languages, makefile, optional );
87
88
89
90
91     std::string configurations;
92         const char* p = this->CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES");
93         if( !p )
94         {
95             makefile->AddCacheDefinition(       "CMAKE_CONFIGURATION_TYPES",
96                                                                     "RelWithDebInfo;Debug;Release;MinSizeRel",
97                                                                     "Semicolon separated list of supported configuration types.",
98                                                                     cmCacheManager::STRING );
99         }
100         else configurations = p;
101
102     /// \note found on the command line of ctest - must be set early
103     makefile->AddCacheDefinition( "CMAKE_CFG_INTDIR", "$(TARGET_NAME)",
104                                                           "Build time configuration directory.",
105                                                           cmCacheManager::STRING );
106
107 }
108
109 std::string cmGlobalCodeBlocksGenerator::GenerateBuildCommand( const char* makeProgram,
110                                                                                                                            const char* workspaceName,
111                                                                                                                            const char* additionalOptions,
112                                                                const char* targetName,
113                                                                                                                            const char* config,
114                                                                                                                            bool ignoreErrors, bool fast )
115 {
116
117     static std::string result;
118         std::string extenstion = ".workspace";;
119         bool workspace = true;
120
121         result = makeProgram;
122
123         std::string project = workspaceName;
124
125         std::string flags;
126         std::string target;
127
128         if( config )
129         {
130                 target = " --target=";
131                 target += config;
132         }
133         else
134         {
135             target = " --target=RelWithDebInfo";
136         }
137         result += " --rebuild ";
138
139         result += target;
140         result += ' ';
141         result += project;
142         result += extenstion;
143
144         return result;
145 }
146
147 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
148
149
150
151
152 //////////////////////////////////////// CodeBlocks Workspace //////////////////////////////////////////////
153 //Write the workspace header
154 //<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
155 //<CodeBlocks_workspace_file>
156 //    <Workspace title="Workspace">
157 std::string writeWorkspaceHeader( Buffer& workspace, const std::string& directory, const std::string& name )
158 {
159     workspace.clear();
160     workspace << less << "?xml version=" << quote << "1.0" << quote << " encoding="
161               << quote << "UTF-8" << quote << " standalone=" << quote << "yes" << quote << '?' << greater << endl;
162     workspace << less << "CodeBlocks_workspace_file" << greater << endl;
163     workspace << advance << less << "Workspace title=" << quote << name << quote << greater << endl << retreat;
164     workspace << advance << less << '/' << "Workspace" << greater << endl << retreat;
165     workspace << less << '/' << "CodeBlocks_workspace_file" << greater << endl;
166
167
168     std::string workspace_file = directory;
169     workspace_file += '/';
170     workspace_file += name;
171     workspace_file += ".workspace";
172     workspace.writeBuffer( workspace_file );
173
174     return workspace_file;
175
176 }
177
178 /// write a project and its dependencies into the workspace file
179 void insertProjectWorkspace( Buffer& workspace, const std::string& project_file, const std::string& workspace_file,
180                              const std::set< std::string >& depends, bool active = false )
181 {
182     workspace.clear();
183
184     workspace << advance << advance << "<Project filename=\"" << project_file << "\" ";
185     if( active ) workspace << "active=\"1\" ";
186     if( depends.empty() ) workspace << "/>" << endl;
187     else
188     {
189         workspace << '>' << endl;
190         //<Depends filename="TestLib/TestLib.cbp" />
191         std::set< std::string >::iterator i = depends.begin();
192         while( i != depends.end() )
193         {
194             workspace << advance << "<Depends filename=\"" << *i++ << "\" />" << endl << retreat;
195         }
196         workspace << "</Project>" <<endl << retreat << retreat;
197     }
198
199     if( !workspace.insertBuffer( "\t</Workspace>\n", workspace_file ) ) throw program_error_insert_project_workspace();
200
201 }
202
203
204 void cmGlobalCodeBlocksGenerator::gatherWorkspaceTargets( cmMakefile* makefile )
205 {
206     //accumalate targets used for workspace depends
207     cmTargets& targets = makefile->GetTargets();
208     cmTargets::iterator it = targets.begin();
209     while( it != targets.end() )
210     {
211         cmTarget& target = it->second;
212         if( convertTargetType( target.GetType() ) & (Static_library|Shared_library|Module_library) )
213         {
214             Dependent record;
215             std::string name = target.GetName();
216             record.target = &target;
217             record.project_file = makefile->GetCurrentOutputDirectory();
218             record.project_file += '/';
219             record.project_file += name;
220             record.project_file += ".cbp";
221             workspace_target_list[name] = record;
222         }
223
224         it++;
225     }
226 }
227
228
229
230
231 void cmGlobalCodeBlocksGenerator::writeWorkspaceFile()
232 {
233     if( LocalGenerators.empty() )return; //how did we get here
234
235     codeblocksgenerator::Buffer workspace;
236
237     try
238     {
239         std::string workspace_binary_directory = LocalGenerators[0]->GetMakefile()->GetHomeOutputDirectory();
240         cmSystemTools::MakeDirectory( workspace_binary_directory.c_str() );
241         std::string project_name = LocalGenerators[0]->GetMakefile()->GetProjectName();
242         std::string workspace_file = writeWorkspaceHeader( workspace, workspace_binary_directory, project_name );
243
244         std::set< std::string > run_tests_projects;
245
246         for( size_t generator_index=0; generator_index<LocalGenerators.size(); generator_index++ )
247         {
248             cmMakefile* makefile = LocalGenerators[generator_index]->GetMakefile();
249
250             //Each target gets its own project file
251             cmTargets& targets = makefile->GetTargets();
252             cmTargets::iterator target_index = targets.begin();
253             std::string project_directory = makefile->GetStartOutputDirectory();
254
255             while( target_index != targets.end() )
256             {
257                 cmTarget& target = target_index->second;
258                 std::string target_name = target.GetName();
259
260                 /// \note CodeBlocksGenerator CMake Target Property CODEBLOCKS_WORKSPACE_EXCLUDE_TARGET will
261                 /// remove the project files for a target from the workspace file.
262                 bool exclude_target = cmSystemTools::IsOn( const_cast<cmTarget&>(target).GetProperty( "CODEBLOCKS_WORKSPACE_EXCLUDE_TARGET", cmProperty::TARGET ));
263
264
265                 /// \note CodeBlocksGenerator CMake Directory File Property CODEBLOCKS_WORKSPACE_EXCLUDE_GROUP will
266                 /// remove the project files for a group ( Executable, Static_library, Shared_library
267                 /// Module_library, Utility, Global_target, Install_files, Install_programs, Install_directory )
268                 /// from the workspace file.
269                 bool exclude_group_from_workspace = false;
270
271                 const std::string name = target.TargetTypeNames[ target.GetType() ];
272
273                 const char* p  = makefile->GetProperty( "CODEBLOCKS_WORKSPACE_EXCLUDE_GROUP", cmProperty::DIRECTORY );
274
275                 if( p )
276                 {
277                     const std::string sz = p;
278                     std::string groups = cmSystemTools::UpperCase( sz );
279                     if( groups.find( name ) != std::string::npos )exclude_group_from_workspace = true;
280                 }
281
282
283                 /// \note CodeBlocksGenerator CMake traget Property CODEBLOCKS_CREATE_WORKSPACE will
284                 /// generate a workspace for a single target in the top binary directory.
285                 bool create_workspace =
286                        cmSystemTools::IsOn( const_cast<cmTarget&>(target).GetProperty( "CODEBLOCKS_CREATE_WORKSPACE", cmProperty::TARGET ));
287
288
289
290
291                 /// \note CodeBlocksGenerator CMake Source File Property CODEBLOCKS_PROJECT_EXCLUDE_GROUP will
292                 /// prevent project files being created for a group ( Executable, Static_library, Shared_library
293                 /// Module_library, Utility, Global_target, Install_files, Install_programs, Install_directory ).
294
295                 bool exclude_group_project_file = false;
296                 p = makefile->GetProperty( "CODEBLOCKS_PROJECT_EXCLUDE_GROUP", cmProperty::DIRECTORY );
297
298                 if( p )
299                 {
300                     const std::string sz;
301                     std::string groups = cmSystemTools::UpperCase( sz );
302
303                     if( groups.find( name ) != std::string::npos )
304                     {
305                         exclude_group_from_workspace = true;
306                         create_workspace = true;
307                         exclude_group_project_file = true;
308                     }
309                 }
310
311                 std::string project_file;
312
313                 // write a project file
314                 if( !exclude_group_project_file )
315                 {
316
317                     if( target_name == "RUN_TESTS" )
318                     {
319                         std::map<cmStdString, cmTest*>& tests = makefile->GetTests();
320                         std::map<cmStdString, cmTest*>::iterator i = tests.begin();
321                         while( i != tests.end() )
322                         {
323                             std::vector<std::string> const& command = i->second->GetCommand();
324                             if( !command.empty() )
325                             {
326                                 std::string test_path = project_directory;
327                                 std::string test_name = command[0];
328                                 size_t ix = test_name.rfind( '/' );
329                                 if( ix != std::string::npos )
330                                 {
331                                     test_name.erase( 0, ix );
332                                 }
333                                 else test_path += '/';
334
335                                 test_path += test_name;
336                                 test_path += ".cbp";
337                                 run_tests_projects.insert( test_path );
338                              }
339                              i++;
340                         }
341                         target_index++;
342                         continue; //only one test at the top
343                     }
344
345                     std::string project_file = project_directory;
346                     project_file += '/';
347                     project_file += target_name;
348                     project_file += ".cbp";
349
350                     //project_file = writeProjectHeader( project_directory, target_name );
351
352                     // The rules are not build yet - this statement creates them under the source file (project.rule) custom command????
353                     target.TraceDependencies( 0 );
354
355
356                     std::set< std::string >depends;
357                     std::set< const cmTarget* >depends_targets;
358                     if( convertTargetType( target.GetType() ) & (Executable|Static_library|Shared_library|Module_library) )
359                     {
360                         // Get the libraries
361                         target.FinishConfigure();
362                         const cmTarget::LinkLibraryVectorType& libraries = target.GetLinkLibraries();
363                         for( size_t generator_index=0; generator_index<libraries.size(); generator_index++ )
364                         {
365
366                             const cmTarget::LibraryID id = libraries[generator_index];
367                             // if this library is in workspace_target_list then target_index is a dependency from codeblocks workspace point of view
368                             if( workspace_target_list.count( id.first ) != 0 )
369                             {
370                                 std::string name = workspace_target_list[id.first].project_file;
371
372                                 depends.insert( name );
373                                 depends_targets.insert( workspace_target_list[id.first].target );
374
375                                 //log_file = fopen( log_file_name, "ab" );
376                                 //fprintf( log_file, "Target: %s Library %s cbp of %s\n", target.GetName(), id.first.c_str(), workspace_target_list[ id.first].c_str() );
377                                 //fclose( log_file );
378                             }
379                         }
380                     }
381
382
383                     if( !exclude_target && !exclude_group_from_workspace )
384                     {
385                         target.FinishConfigure();
386
387                         /// \note CodeBlocksGenerator CMake traget Property CODEBLOCKS_ACTIVE_PROJECT will
388                         /// signal the active codeblocks project in a workspace.
389                         bool active_target = cmSystemTools::IsOn( const_cast<cmTarget&>(target).GetProperty( "CODEBLOCKS_ACTIVE_PROJECT", cmProperty::TARGET ));
390
391                         // Add this target to the global workspace
392                         insertProjectWorkspace( workspace, project_file, workspace_file, depends, active_target );
393
394
395                         //log_file = fopen( log_file_name, "ab" );
396                         //fprintf( log_file, "Inserted Project File: %s in Workspacefile %s\n", project_file.c_str(), workspace_file.c_str() );
397                         //fclose( log_file );
398
399                     }
400
401                     // This target requires its own local workspace
402                     if( create_workspace )
403                     {
404                         std::string sub_workspace_file = writeWorkspaceHeader( workspace, workspace_binary_directory, target.GetName() ); //All workspaces in top directory
405                         insertProjectWorkspace( workspace, project_file, sub_workspace_file, depends, true ); //Is the active target
406
407
408                         //log_file = fopen( log_file_name, "ab" );
409                         //fprintf( log_file, "Inserted Project File: %s in Workspacefile %s\n", project_file.c_str(), sub_workspace_file.c_str() );
410                         //fclose( log_file );
411
412
413                     }
414
415
416
417
418                     if( convertTargetType( target.GetType() ) & ( Utility | Global_target ) )
419                     {
420                          static_cast<cmLocalCodeBlocksGenerator*>(LocalGenerators[generator_index])->writeUtilityProject( makefile, target, project_directory, project_file );
421                     }
422                     else if( convertTargetType( target.GetType() ) & (Executable|Static_library|Shared_library|Module_library) )
423                     {
424                        static_cast<cmLocalCodeBlocksGenerator*>(LocalGenerators[generator_index])->writeProject( makefile, target, project_directory, project_file, depends_targets );
425                     }
426
427
428                 }
429
430
431
432                 target_index++; //next target
433
434            }
435
436         }
437
438
439         if( !run_tests_projects.empty() )
440         {
441             std::string project_file = workspace_binary_directory;
442             project_file += '/';
443             project_file += "RUN_TESTS";
444             project_file += ".cbp";
445
446             std::string command = GetCMakeInstance()->GetCTestCommand();
447             command += " -C $(TARGET_NAME) --force-new-ctest-process";
448
449             std::string title = "RUN_TESTS";
450
451             static_cast<cmLocalCodeBlocksGenerator*>(LocalGenerators[0])->writeCommandProject( LocalGenerators[0]->GetMakefile(), command, title, project_file );
452
453             std::string sub_workspace_file = writeWorkspaceHeader( workspace, workspace_binary_directory, "RUN_TESTS" );
454             insertProjectWorkspace( workspace, project_file, sub_workspace_file, run_tests_projects, true ); //Is the active target
455
456         }
457
458         std::string project_file = workspace_binary_directory;
459         project_file += '/';
460         project_file += "INSTALL";
461         project_file += ".cbp";
462
463
464         std::string command;
465         const char* p = LocalGenerators[0]->GetMakefile()->GetDefinition( "CMAKE_COMMAND" );
466         if( p )command = p;
467         else command = "cmake"; //hope it's in the path
468
469         std::string prefix;
470         p = LocalGenerators[0]->GetMakefile()->GetDefinition( "CMAKE_INSTALL_PREFIX" );
471         if( p )
472         {
473             prefix =  " -DCMAKE_INSTALL_PREFIX=";
474             prefix += p;
475         }
476
477         command += prefix;
478         command += " -DCMAKE_INSTALL_CONFIG_NAME=$(TARGET_NAME) -P cmake_install.cmake";
479
480         std::string title = "INSTALL";
481
482         static_cast<cmLocalCodeBlocksGenerator*>(LocalGenerators[0])->writeCommandProject( LocalGenerators[0]->GetMakefile(), command, title, project_file );
483
484         run_tests_projects.clear(); //dummy
485         std::string sub_workspace_file = writeWorkspaceHeader( workspace, workspace_binary_directory, "INSTALL" );
486         insertProjectWorkspace( workspace, project_file, sub_workspace_file, run_tests_projects, true ); //Is the active target
487
488     }
489     catch( ... )
490     {
491     }
492 }
Note: See TracBrowser for help on using the browser.