Class: Bake::ToCxx

Inherits:
Object
  • Object
show all
Defined in:
lib/tocxx.rb

Constant Summary collapse

@@linkBlock =
0
@@include_deps =
{}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeToCxx

Returns a new instance of ToCxx.



63
64
65
# File 'lib/tocxx.rb', line 63

def initialize
  @configTcMap = {}
end

Class Method Details

.include_depsObject



55
56
57
# File 'lib/tocxx.rb', line 55

def self.include_deps
  @@include_deps
end

.linkBlockObject



51
52
53
# File 'lib/tocxx.rb', line 51

def self.linkBlock
  @@linkBlock = 1
end

.reset_include_depsObject



59
60
61
# File 'lib/tocxx.rb', line 59

def self.reset_include_deps
  @@include_deps = {}
end

Instance Method Details

#addDependencies(block, config) ⇒ Object



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/tocxx.rb', line 162

def addDependencies(block, config)
  Blocks::ALL_BLOCKS.each do |bname, b|
    b.visited = false
  end
  block.visited = true

  block.bes = []
  block.besDirect = []
  block.config.depInc.each do |dep|
    if (Metamodel::Dependency === dep)
      @referencedConfigs[dep.name].each do |configRef|
        if configRef.name == dep.config
          qname = configRef.qname
          blockRef = Blocks::ALL_BLOCKS[qname]
  
          if configRef.private && configRef.parent.name != config.parent.name
            Bake.formatter.printError("#{config.parent.name} (#{config.name}) depends on #{configRef.parent.name} (#{configRef.name}) which is private.", configRef)
            ExitHelper.exit(1)
          end
  
          block.dependencies << qname if not Bake.options.project# and not Bake.options.filename
          if !blockRef.visited
            blockRef.visited = true
            subDeps = addSubDependencies(block, configRef)
            block.bes += subDeps
          end
          block.bes << dep
          block.besDirect << dep
          break
        end
      end
    else
      block.bes << dep
    end
  end
  
end

#addIncludes(block, config) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
# File 'lib/tocxx.rb', line 150

def addIncludes(block, config)
  return if !config.respond_to?("includeDir")
  config.includeDir.each do |inc|
    if inc.inject == "front" || inc.infix == "front"
      
    elsif inc.inject == "back" || inc.infix == "back"
    
    end
  end

end

#addLib(block, configSteps) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/tocxx.rb', line 96

def addLib(block, configSteps)
  Array(configSteps.step).each do |step|
    if Bake::Metamodel::Makefile === step
      block.lib_elements << LibElement.new(LibElement::LIB_WITH_PATH, step.lib) if step.lib != ""
    end
  end if configSteps
end

#addSteps(block, blockSteps, configSteps) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/tocxx.rb', line 104

def addSteps(block, blockSteps, configSteps)
  Array(configSteps.step).each do |step|
    if Bake::Metamodel::Makefile === step
      blockSteps << Blocks::Makefile.new(step, @referencedConfigs, block)
    elsif Bake::Metamodel::CommandLine === step
      blockSteps << Blocks::CommandLine.new(step)
    elsif Bake::Metamodel::Sleep === step
      blockSteps << Blocks::Sleep.new(step)
    elsif Bake::Metamodel::Move === step
      blockSteps << Blocks::FileUtil.new(step, :move, block.projectDir)
    elsif Bake::Metamodel::Copy === step
      blockSteps << Blocks::FileUtil.new(step, :copy, block.projectDir)
    elsif Bake::Metamodel::Remove === step
      blockSteps << Blocks::FileUtil.new(step, :remove, block.projectDir)
    elsif Bake::Metamodel::MakeDir === step
      blockSteps << Blocks::FileUtil.new(step, :makedir, block.projectDir)
    elsif Bake::Metamodel::Touch === step
      blockSteps << Blocks::FileUtil.new(step, :touch, block.projectDir)
    end
  end if configSteps
end

#addSubDependencies(block, config) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/tocxx.rb', line 126

def addSubDependencies(block, config)
  subDeps = []
  config.depInc.each do |dep|
    if (Metamodel::Dependency === dep)
      @referencedConfigs[dep.name].each do |configRef|
        if configRef.name == dep.config
          blockRef = Blocks::ALL_BLOCKS[configRef.qname]
          break if blockRef.visited
          blockRef.visited = true

          subDeps += addSubDependencies(block, configRef)
          subDeps << dep
          break
        end
      end
    else
      subDeps << dep if dep.inherit
    end
      
  end
  @correctOrder << Blocks::ALL_BLOCKS[config.qname] if @corOrderActive
  return subDeps
end

#calcPrebuildBlocksObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/tocxx.rb', line 200

def calcPrebuildBlocks
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|
      if config.prebuild
        @prebuild ||= {}
        config.prebuild.except.each do |except|
          pName = projName
          if not except.name.empty?
            if not @referencedConfigs.keys.include? except.name
              Bake.formatter.printInfo("Info: prebuild project #{except.name} not found")
              next
            end
            pName = except.name
          end
          if except.config != "" && !@referencedConfigs[pName].any? {|config| config.name == except.config}
            Bake.formatter.printWarning("Warning: prebuild config #{except.config} of project #{pName} not found")
            next
          end

          if not @prebuild.include?pName
            @prebuild[pName] = [except.config]
          else
            @prebuild[pName] << except.config
          end
        end
      end
    end
  end
end

#calcStartBlocksObject



577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
# File 'lib/tocxx.rb', line 577

def calcStartBlocks
  startProjectName = nil
  startConfigName = nil
  if Bake.options.project
    splitted = Bake.options.project.split(',')
    startProjectName = splitted[0]
    startConfigName = splitted[1] if splitted.length == 2
  end

  if startConfigName
    blockName = startProjectName+","+startConfigName
    if not Blocks::ALL_BLOCKS.include?(startProjectName+","+startConfigName)
      Bake.formatter.printError("Error: project #{startProjectName} with config #{startConfigName} not found")
      ExitHelper.exit(1)
    end
    startBlocks = [Blocks::ALL_BLOCKS[startProjectName+","+startConfigName]]
    Blocks::Block.set_num_projects(startBlocks)
  elsif startProjectName
    startBlocks = []
    Blocks::ALL_BLOCKS.each do |blockName, block|
      if blockName.start_with?(startProjectName + ",")
        startBlocks << block
      end
    end
    if startBlocks.length == 0
      Bake.formatter.printError("Error: project #{startProjectName} not found")
      ExitHelper.exit(1)
    end
    startBlocks.reverse! # most probably the order of dependencies if any
    Blocks::Block.set_num_projects(startBlocks)
  else
    startBlocks = [Blocks::ALL_BLOCKS[Bake.options.main_project_name+","+Bake.options.build_config]]
    Blocks::Block.set_num_projects(Blocks::ALL_BLOCKS.values)
  end
 return startBlocks
end

#callBlock(block, method) ⇒ Object



545
546
547
548
549
550
551
552
553
554
555
556
557
# File 'lib/tocxx.rb', line 545

def callBlock(block, method)
  begin
    return block.send(method)
  rescue AbortException
    raise
  rescue Exception => ex
    if Bake.options.debug
      puts ex.message
      puts ex.backtrace
    end
    return false
  end
end

#callBlocks(startBlocks, method, ignoreStopOnFirstError = false) ⇒ Object



559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
# File 'lib/tocxx.rb', line 559

def callBlocks(startBlocks, method, ignoreStopOnFirstError = false)
  Blocks::ALL_BLOCKS.each {|name,block| block.visited = false; block.result = true;  block.inDeps = false }
  Blocks::Block.reset_block_counter
  result = true
  startBlocks.each do |block|
    begin
      result = callBlock(block, method) && result
    ensure
      Blocks::Block::waitForAllThreads()
      result &&= Blocks::Block.delayed_result
    end
    if not ignoreStopOnFirstError
      return false if not result and Bake.options.stopOnFirstError
    end
  end
  return result
end

#connectObject



947
948
949
950
951
# File 'lib/tocxx.rb', line 947

def connect()
  if Bake.options.socket != 0
    Bake::IDEInterface.instance.connect(Bake.options.socket)
  end
end

#convert2bbObject



494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# File 'lib/tocxx.rb', line 494

def convert2bb
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|
      block = Blocks::ALL_BLOCKS[config.qname]

      addSteps(block, block.startupSteps,  config.startupSteps)
      addSteps(block, block.exitSteps,  config.exitSteps)

      if not Bake.options.prepro and not Bake.options.conversion_info and not Bake.options.docu and not Bake.options.filename and not Bake.options.analyze
        if block.prebuild
          addLib(block, config.preSteps)
          addLib(block, config.postSteps)
          addLib(block, config.cleanSteps)
        else
          addSteps(block, block.preSteps,   config.preSteps)
          addSteps(block, block.postSteps,  config.postSteps)
          addSteps(block, block.cleanSteps, config.cleanSteps)
        end
      end

      if Bake.options.docu
        block.mainSteps << Blocks::Docu.new(config, @configTcMap[config]) unless block.prebuild
      elsif Metamodel::CustomConfig === config
        if not Bake.options.prepro and not Bake.options.conversion_info and not Bake.options.docu and not Bake.options.filename and not Bake.options.analyze
          if block.prebuild
            addLib(block, config)
          else
            addSteps(block, block.mainSteps, config) if config.step
          end
        end
      elsif Bake.options.conversion_info
        block.mainSteps << Blocks::Convert.new(block, config, @referencedConfigs) unless block.prebuild
      else
        if not block.prebuild
          compile = Blocks::Compile.new(block, config, @referencedConfigs)
          (Blocks::ALL_COMPILE_BLOCKS[projName] ||= []) << compile
          block.mainSteps << compile
        end
        if not Bake.options.filename and not Bake.options.analyze
          if Metamodel::ExecutableConfig === config || (Bake.options.dev_features.include?("enforce-executable-config") && config == @mainConfig)
            block.mainSteps << Blocks::Executable.new(block, config, @referencedConfigs, compile) unless block.prebuild
          else
            block.mainSteps << Blocks::Library.new(block, config, @referencedConfigs, compile)
          end
        end
      end

    end
  end
end

#createBaseTcsForConfigObject



67
68
69
70
71
72
73
74
# File 'lib/tocxx.rb', line 67

def createBaseTcsForConfig
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|
      tcs = Utils.deep_copy(@defaultToolchain)
      @configTcMap[config] = tcs
    end
  end
end

#createTcsForConfigObject



76
77
78
79
80
81
82
# File 'lib/tocxx.rb', line 76

def createTcsForConfig
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|
      integrateToolchain(@configTcMap[config], config.toolchain)
    end
  end
end

#disconnectObject



953
954
955
956
957
# File 'lib/tocxx.rb', line 953

def disconnect()
  if Bake.options.socket != 0
    Bake::IDEInterface.instance.disconnect()
  end
end

#doitObject



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
# File 'lib/tocxx.rb', line 614

def doit()

  stdoutSuppression = nil
  orgStdout = nil
  if Bake.options.show_includes || Bake.options.show_includes_and_defines
    stdoutSuppression = StringIO.new
    orgStdout = Thread.current[:stdout]
    Thread.current[:stdout] = stdoutSuppression unless orgStdout
  end

  begin

    taskType = "Building"
    if Bake.options.conversion_info
      taskType = "Showing conversion infos"
    elsif Bake.options.docu
      taskType = "Generating documentation"
    elsif Bake.options.prepro
      taskType = "Preprocessing"
    elsif Bake.options.linkOnly
        taskType = "Linking"
    elsif Bake.options.rebuild
      taskType = "Rebuilding"
    elsif Bake.options.clean
      taskType = "Cleaning"
    end

    begin

      if Bake.options.showConfigs
        al = AdaptConfig.new
        adaptConfigs = al.load()
        Config.new.printConfigs(adaptConfigs)
      else
        cache = CacheAccess.new()
        @referencedConfigs = cache.load_cache unless Bake.options.nocache

        if @referencedConfigs.nil?
          al = AdaptConfig.new
          adaptConfigs = al.load()

          loadedConfig = Config.new
          @referencedConfigs = loadedConfig.load(adaptConfigs)

          cache.write_cache(@referencedConfigs, adaptConfigs)
        end
      end

      taskType = "Analyzing" if Bake.options.analyze

      @mainConfig = @referencedConfigs[Bake.options.main_project_name].select { |c| c.name == Bake.options.build_config }.first

      basedOn =  @mainConfig.defaultToolchain.basedOn
      basedOnToolchain = Bake::Toolchain::Provider[basedOn]
      if basedOnToolchain.nil?
        Bake.formatter.printError("DefaultToolchain based on unknown compiler '#{basedOn}'", @mainConfig.defaultToolchain)
        ExitHelper.exit(1)
      end

      # The flag "-FS" must only be set for VS2013 and above
      ENV["MSVC_FORCE_SYNC_PDB_WRITES"] = ""
      if basedOn == "MSVC"
        begin
          res = `cl.exe 2>&1`
          raise Exception.new unless $?.success?
          scan_res = res.scan(/ersion (\d+).(\d+).(\d+)/)
          if scan_res.length > 0
            ENV["MSVC_FORCE_SYNC_PDB_WRITES"] = "-FS" if scan_res[0][0].to_i >= 18 # 18 is the compiler major version in VS2013
          else
            Bake.formatter.printError("Could not read MSVC version")
            ExitHelper.exit(1)
          end
        rescue SystemExit
          raise
        rescue Exception => e
          Bake.formatter.printError("Could not detect MSVC compiler")
          ExitHelper.exit(1)
        end
      end

      @defaultToolchain = Utils.deep_copy(basedOnToolchain)
      @defaultToolchain = fill_compiler_env(@defaultToolchain)

      integrateToolchain(@defaultToolchain, @mainConfig.defaultToolchain)

      # todo: cleanup this hack
      Bake.options.analyze = @defaultToolchain[:COMPILER][:CPP][:COMPILE_FLAGS].include?"analyze"
      Bake.options.eclipseOrder = @mainConfig.defaultToolchain.eclipseOrder

      puts "Profiling #{Time.now - $timeStart}: create base toolchains..." if Bake.options.profiling
      createBaseTcsForConfig
      puts "Profiling #{Time.now - $timeStart}: substitute variables..." if Bake.options.profiling
      substVars
      puts "Profiling #{Time.now - $timeStart}: toolchains..." if Bake.options.profiling
      createTcsForConfig
      @@linkBlock = 0
      @prebuild = nil
      if Bake.options.prebuild
        puts "Profiling #{Time.now - $timeStart}: create prebuild blocks..." if Bake.options.profiling
        calcPrebuildBlocks
      end
      puts "Profiling #{Time.now - $timeStart}: make blocks..." if Bake.options.profiling
      makeBlocks
      puts "Profiling #{Time.now - $timeStart}: make graph..." if Bake.options.profiling
      makeGraph
      puts "Profiling #{Time.now - $timeStart}: make includes..." if Bake.options.profiling
      makeIncs
      puts "Profiling #{Time.now - $timeStart}: make dep overview..." if Bake.options.profiling
      makeDepOverview
      puts "Profiling #{Time.now - $timeStart}: make uniq..." if Bake.options.profiling
      makeUniq
      puts "Profiling #{Time.now - $timeStart}: convert to building blocks..." if Bake.options.profiling
      convert2bb
      if Bake.options.dot
        puts "Profiling #{Time.now - $timeStart}: make dot..." if Bake.options.profiling
        makeDot
      end

      if !Bake.options.cc2j_filename
        if !@mainConfig.cdb.nil?
          Bake.options.cc2j_filename = @mainConfig.cdb.name
          if !File.is_absolute?(Bake.options.cc2j_filename)
            Bake.options.cc2j_filename = File.join(
              File.rel_from_to_project(Dir.pwd, @mainConfig.parent.get_project_dir, false),
              Bake.options.cc2j_filename)
          end
        end
      end

       = Bake.options.dev_features.detect { |x| x.start_with?("metadata=") }
      if 
         = [9..-1]
        mainBlock = Blocks::ALL_BLOCKS[@mainConfig.parent.name + "," + @mainConfig.name]
        if Metamodel::ExecutableConfig === mainBlock.config || Metamodel::LibraryConfig === mainBlock.config
          Subst.substToolchain(@defaultToolchain)
          File.open(, "w") do |f|
            f.puts "{"
            f.puts "  \"module_path\":  \"#{mainBlock.projectDir}\","
            f.puts "  \"config_name\":  \"#{@mainConfig.name}\","
            Dir.chdir(mainBlock.projectDir) do
              if Blocks::Library === mainBlock.mainSteps.last || Blocks::Executable === mainBlock.mainSteps.last
                aName = File.expand_path(mainBlock.mainSteps.last.calcArtifactName)
              else
                aName = ""
              end
              f.puts "  \"artifact\":     \"#{aName}\","
            end
            f.puts "  \"compiler_c\":   \"#{@defaultToolchain[:COMPILER][:C][:COMMAND]}\","
            f.puts "  \"compiler_cxx\": \"#{@defaultToolchain[:COMPILER][:CPP][:COMMAND]}\","
            f.puts "  \"flags_c\":      \"#{@defaultToolchain[:COMPILER][:C][:FLAGS]}\","
            f.puts "  \"flags_cxx\":    \"#{@defaultToolchain[:COMPILER][:CPP][:FLAGS]}\","
            f.puts "  \"toolchain\":    \"#{@mainConfig.defaultToolchain.basedOn}\""
            f.puts "}"
          end
          puts "File #{} written."
          ExitHelper.exit(0)
        else
          Bake.formatter.printError("Error: dev-feature metadata is only for LibraryConfig or ExecutableConfig.")
          ExitHelper.exit(1)
        end
      end

    ensure
      if Bake.options.show_includes || Bake.options.show_includes_and_defines
        Thread.current[:stdout] = orgStdout
        puts stdoutSuppression.string # this ensures to print a error message is needed even in case of an exception
      end
    end

    if Bake.options.show_includes
      Blocks::Show.includes
    end

    if Bake.options.show_includes_and_defines
      Blocks::Show.includesAndDefines(@mainConfig, @configTcMap[@mainConfig])
    end

    startBlocks = calcStartBlocks

    Bake::IDEInterface.instance.set_build_info(@mainConfig.parent.name, @mainConfig.name, Blocks::ALL_BLOCKS.length)

    ideAbort = false
    Blocks::Block.reset_delayed_result

    puts "Profiling #{Time.now - $timeStart}: start build..." if Bake.options.profiling

    begin
      Blocks::Block.init_threads()
      result = callBlocks(startBlocks, :startup, true)
      if Bake.options.clean or Bake.options.rebuild
        if not Bake.options.stopOnFirstError or result
          result = callBlocks(startBlocks, :clean) && result
        end
      end
      if Bake.options.rebuild or not Bake.options.clean
        if not Bake.options.stopOnFirstError or result
          result = callBlocks(startBlocks, :execute) && result
        end
      end
    rescue AbortException
      ideAbort = true
    end
    result = callBlocks(startBlocks, :exits, true) && result

    if ideAbort || Bake::IDEInterface.instance.get_abort
      Bake.formatter.printError("\n#{taskType} aborted.")
      ExitHelper.set_exit_code(1)
      return
    end

    if Bake.options.cc2j_filename
      require "json"
      begin 
        Bake.formatter.printInfo("Info: writing compilation database #{Bake.options.cc2j_filename}") if Bake.options.verbose >= 1
        File.write(Bake.options.cc2j_filename, JSON.pretty_generate(Blocks::CC2J))
      rescue Exception => ex
        Bake.formatter.printError("Error: could not write compilation database: #{ex.message}")
        puts ex.backtrace if Bake.options.debug
        result = false
      end
    end

    if Bake.options.filelist && !Bake.options.dry
      mainBlock = Blocks::ALL_BLOCKS[Bake.options.main_project_name+","+Bake.options.build_config]
      Dir.chdir(mainBlock.projectDir) do
        Utils.gitIgnore(mainBlock.output_dir)
        File.open(mainBlock.output_dir + "/" + "global-file-list.txt", 'wb') do |f|
          Bake.options.filelist.sort.each do |entry|
            f.puts(entry)
          end
        end
      end
    end

    if result == false
      Bake.formatter.printError("\n#{taskType} failed.")
      ExitHelper.set_exit_code(1)
      return
    else
      if Bake.options.linkOnly and @@linkBlock == 0
        Bake.formatter.printSuccess("\nNothing to link.")
      else
        # CompilationCheck
        if !Bake.options.project &&
           !Bake.options.filename &&
           !Bake.options.linkOnly &&
           !Bake.options.prepro &&
           !Bake.options.compileOnly &&
           !Bake.options.dry &&
           !Bake.options.clean

          ccChecks = []
          ccIncludes = Set.new
          ccExcludes = Set.new
          ccIgnores = Set.new
          @referencedConfigs.each do |projName, configs|
            configs.compilationCheck.each do |cc|
              ccChecks << cc
            end
          end
          ccChecks.each do |cc|
            Dir.chdir(cc.parent.parent.get_project_dir) do
              Dir.glob(cc.include).select {|f| File.file?(f)}.each {|f| ccIncludes << File.expand_path(f)}
              Dir.glob(cc.exclude).select {|f| File.file?(f)}.each {|f| ccExcludes << File.expand_path(f)}
              Dir.glob(cc.ignore). select {|f| File.file?(f)}.each {|f| ccIgnores  << File.expand_path(f)}
            end
          end
          ccIncludes -= ccIgnores
          ccExcludes -= ccIgnores
          ccIncludes -= ccExcludes

          if !ccIncludes.empty? || !ccExcludes.empty?
            inCompilation = Set.new
            Blocks::ALL_BLOCKS.each do |name,block|
              block.mainSteps.each do |b|
                if Blocks::Compile === b && !b.source_files_compiled.nil?
                  b.source_files_compiled.each do |s|
                    inCompilation << File.expand_path(s, b.projectDir)
                    type = b.get_source_type(s)
                    if type != :ASM && b.object_files && b.object_files.has_key?(s)
                      o = b.object_files[s]
                      dep_filename = b.calcDepFile(o, type)
                      dep_filename_conv = b.calcDepFileConv(dep_filename)
                      fname = File.expand_path(dep_filename_conv, b.projectDir)
                      if File.exist?(fname)
                        File.readlines(fname).map{|line| line.strip}.each do |dep|
                          header = File.expand_path(dep, b.projectDir)
                          if File.exist?(header)
                            inCompilation << header
                          end
                        end
                      end
                    end
                  end
                end
              end
            end

            pnPwd = Pathname.new(Dir.pwd)
            ccNotIncluded = (ccIncludes - inCompilation).to_a
            ccNotExcluded = inCompilation.select {|i| ccExcludes.include?(i) }
            ccNotIncluded.each do |cc|
              cc = Pathname.new(cc).relative_path_from(pnPwd)
              Bake.formatter.printWarning("Warning: file not included in build: #{cc}")
            end
            ccNotExcluded.each do |cc|
              cc = Pathname.new(cc).relative_path_from(pnPwd)
              Bake.formatter.printWarning("Warning: file not excluded from build: #{cc}")
            end

            if Bake.options.verbose >= 3
              if ccNotIncluded.empty? && ccNotExcluded.empty?
                Bake.formatter.printInfo("Info: CompilationCheck passed")
              end
            end

          elsif !ccChecks.empty?
            if Bake.options.verbose >= 3
              Bake.formatter.printInfo("Info: CompilationCheck passed")
            end
          end
        end
        
        
        Bake.formatter.printSuccess("\n#{taskType} done.")
      end
    end
  rescue SystemExit
    Bake.formatter.printError("\n#{taskType} failed.") if ExitHelper.exit_code != 0
  end

end

#makeBlocksObject



230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/tocxx.rb', line 230

def makeBlocks
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|

      prebuild = !@prebuild.nil?
      if @prebuild and @prebuild.has_key?projName
        prebuild = false if (@prebuild[projName].include?"" or @prebuild[projName].include?config.name)
      end

      block = Blocks::Block.new(config, @referencedConfigs, prebuild, @configTcMap[config])
      Blocks::ALL_BLOCKS[config.qname] = block
    end
  end
end

#makeDepOverviewObject



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/tocxx.rb', line 245

def makeDepOverview
  return if !Bake.options.dev_features.any? {|feature| feature.start_with?("dep-overview=") }
  Blocks::ALL_BLOCKS.each do |name,block|
    block.bes.each do |depInc|
      @@include_deps[block.projectDir] = Set.new if !@@include_deps.has_key?(block.projectDir)
      if (Metamodel::Dependency === depInc)
        c = @referencedConfigs[depInc.name].detect { |configRef| configRef.name == depInc.config }
        @@include_deps[block.projectDir] << Blocks::ALL_BLOCKS[c.qname].projectDir
      else
        @@include_deps[block.projectDir] << depInc.name
      end
    end
  end
  ExitHelper.exit(0)
end

#makeDotObject



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# File 'lib/tocxx.rb', line 383

def makeDot
    if Bake.options.dotFilename
      filename = Bake.options.dotFilename
    else
      filename = Bake.options.main_dir + "/" + Bake.options.build_config + ".dot"
    end
    File.open(filename, 'w') do |file|
      puts "Creating #{filename}"

      onlyProjectName = nil
      onlyConfigName = nil
      if Bake.options.project
        splitted = Bake.options.project.split(',')
        onlyProjectName = splitted[0]
        onlyConfigName = splitted[1] if splitted.length == 2
      end

      file.write "# Generated by bake\n"
      file.write "# Example to show the graph: dot #{File.basename(filename)} -Tpng -o out.png\n"
      file.write "# Example to reduce the graph: tred #{File.basename(filename)} | dot -Tpng -o out.png\n\n"

      if onlyProjectName
        starting = onlyProjectName
        if onlyConfigName
          ending = Bake.options.dotShowProjOnly ? "" : "_"+onlyConfigName
        else
          ending = ""
        end
      else
        starting = Bake.options.main_project_name
        ending = Bake.options.dotShowProjOnly ? "" : "_"+Bake.options.build_config
      end
      file.write "digraph \"#{starting}#{ending}\" {\n\n"

      file.write "  concentrate = true\n\n"

      if onlyProjectName
        if not @referencedConfigs.include? onlyProjectName
          Bake.formatter.printError("Error: project #{onlyProjectName} not found")
          ExitHelper.exit(1)
        end
        if onlyConfigName
          if not @referencedConfigs[onlyProjectName].any? {|c| c.name == onlyConfigName}
            Bake.formatter.printError("Error: project #{onlyProjectName} with config #{onlyConfigName} not found")
            ExitHelper.exit(1)
          end
        end
      end

      foundProjs = {}
      @referencedConfigs.each do |projName, configs|
        depsToProj = []
        configs.each do |config|
          the_c = Blocks::ALL_BLOCKS[config.parent.name+","+config.name]
          the_c.besDirect.each do |d|
            next if Metamodel::IncludeDir === d
            if onlyProjectName
              next if config.parent.name != onlyProjectName && d.name != onlyProjectName
              if onlyConfigName
                leftSide  = config.name        == onlyConfigName && config.parent.name == onlyProjectName
                rightSide = d.config           == onlyConfigName && d.name             == onlyProjectName
                next if !leftSide && !rightSide
              end
            end
            if Bake.options.dotShowProjOnly
              next if depsToProj.include?d.name
              next if d.name == projName
              c1 = ""
              c2 = ""
            else
              c1 = ",#{config.name}"
              c2 = ",#{d.config}"
            end
            file.write "  \"#{Blocks::ALL_BLOCKS[config.qname].projectDir}#{c1}\" -> "+
              "\"#{Blocks::ALL_BLOCKS[d.name+','+d.config].projectDir}#{c2}\"\n"
            depsToProj << d.name

            foundProjs[config.parent.name] = []           if not foundProjs.include? config.parent.name
            foundProjs[config.parent.name] << config.name if not foundProjs[config.parent.name].include? config.name
            foundProjs[d.name] = []        if not foundProjs.include? d.name
            foundProjs[d.name] << d.config if not foundProjs[d.name].include? d.config
          end
        end
      end
      file.write "\n"

      if Bake.options.dotShowProjOnly
        @referencedConfigs.each do |projName, configs|
          next if Bake.options.project and not foundProjs.include?projName
          file.write "  \"#{Blocks::ALL_BLOCKS[configs[0].qname].projectDir}\" [label = \"#{projName}\"]\n"
        end
      else
        @referencedConfigs.each do |projName, configs|
          next if Bake.options.project and not foundProjs.include?projName
          dirName = Blocks::ALL_BLOCKS[configs[0].qname].projectDir
          file.write "  subgraph \"cluster_#{dirName}\" {\n"
          file.write "    label =\"#{projName}\"\n"
          configs.each do |config|
            next if Bake.options.project and not foundProjs[projName].include? config.name
            file.write "    \"#{dirName},#{config.name}\" [label = \"#{config.name}\", style =  filled, fillcolor = #{config.color}]\n"
          end
          file.write "  }\n\n"
        end
      end

      file.write "}\n"
    end

    ExitHelper.exit(0) if !Bake.options.dotAndCompile
end

#makeGraphObject



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/tocxx.rb', line 293

def makeGraph
  mainConfig = @referencedConfigs[Bake.options.main_project_name].select { |c| c.name == Bake.options.build_config }.first
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|
      block = Blocks::ALL_BLOCKS[config.qname]
      if (config == mainConfig)
        @correctOrder = []
        @corOrderActive = true
      end
      addDependencies(block, config)
      if (config == mainConfig)
        @correctOrder.unshift(block)
        @corOrderActive = false
      end
    end
  end
  Blocks::ALL_BLOCKS.each do |name,block|
    block.dependencies.uniq!
  end

  # inject dependencies
  num_interations = 0
  begin
    if (num_interations > 0) and Bake.options.debug and Bake.options.verbose >= 3
      puts "Inject dependencies, iteration #{num_interations}:"
      Blocks::ALL_BLOCKS.each do |name,block|
        puts block.config.qname
        block.bes.select{|b| Metamodel::Dependency === b}.each { |d| puts "- #{d.name},#{d.config}" }
      end
    end

    counter = 0
    @correctOrder.reverse.each do |block|
      name = block.config.qname
      difr = []
      diba = []
      block.bes.each do |d|
        if Metamodel::Dependency === d
          next if d.inject == ""
          dqname = "#{d.name},#{d.config}"
          next if name == dqname
          if d.inject == "front"
            difr << d
          elsif d.inject == "back"
            diba << d
          end
          d.inject = "" # this prevents injecting to injected deps
          d.setInjected
        elsif Metamodel::IncludeDir === d
          if d.inject == "front" || d.infix == "front"
            difr << d
          elsif d.inject == "back" || d.infix == "back" 
            diba << d
          end
          d.inject = "" # this prevents injecting to injected deps
          d.infix = ""
        end
      end
      next if difr.empty? && diba.empty?

      block.bes.each do |dep|
        next unless Metamodel::Dependency === dep
        difr2 = difr.select{|d| Metamodel::IncludeDir === d || d != dep}
        diba2 = diba.select{|d| Metamodel::IncludeDir === d || d != dep}
        fde = Blocks::ALL_BLOCKS[dep.name+","+dep.config]
        l1 = fde.bes.length 
        fde.bes = (difr2 + fde.bes + diba2).uniq
        fde.besDirect = (difr2 + fde.besDirect + diba2).uniq
        l2 = fde.bes.length
        counter += 1 if (l2 != l1)
      end
    end
    num_interations += 1
  end while counter > 0
end

#makeIncsObject



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/tocxx.rb', line 261

def makeIncs
  Blocks::ALL_BLOCKS.each do |name,block|
    bes2 = []
    block.bes.each do |inc|
      rootsFound = false
      if Metamodel::IncludeDir === inc
        if inc.name == "___ROOTS___"
          Bake.options.roots.each do |r|
            i = Metamodel::IncludeDir.new
            i.name = r.dir
            i.inherit = inc.inherit
            i.inject = inc.inject
            i.infix = inc.infix
            i.parent = inc.parent
            bes2 << i
          end
          rootsFound = true
        else
          if inc.parent == block.config 
            Dir.chdir(block.projectDir) do
              i = block.convPath(inc,nil,true)
              inc.name  = File.expand_path(Pathname.new(i).cleanpath)
            end
          end
        end
      end
      bes2 << inc if !rootsFound
    end
    block.bes = bes2
  end
end

#makeUniqObject



369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/tocxx.rb', line 369

def makeUniq
  Blocks::ALL_BLOCKS.each do |name,block|
    bes2 = []
    blockSet = Set.new
    block.bes.each do |b|
      n = Metamodel::Dependency === b ? b.name+","+b.config : b.name + "," + b.inherit.to_s
      next if blockSet.include?n
      blockSet << n
      bes2 << b
    end
    block.bes = bes2
  end
end

#substVarsObject



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/tocxx.rb', line 84

def substVars
  Subst.itute(@mainConfig, Bake.options.main_project_name, true, @configTcMap[@mainConfig], @referencedConfigs, @configTcMap)
  @referencedConfigs.each do |projName, configs|
    configs.each do |config|
      if config != @mainConfig
        Subst.itute(config, projName, false, @configTcMap[config], @referencedConfigs, @configTcMap)
      end
    end
  end
  Subst.resolveOutputDir
end