| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Notes: | 3 # Notes: |
| 4 # | 4 # |
| 5 # This is all roughly based on the Makefile system used by the Linux | 5 # This is all roughly based on the Makefile system used by the Linux |
| 6 # kernel, but is a non-recursive make -- we put the entire dependency | 6 # kernel, but is a non-recursive make -- we put the entire dependency |
| 7 # graph in front of make and let it figure it out. | 7 # graph in front of make and let it figure it out. |
| 8 # | 8 # |
| 9 # The code below generates a separate .mk file for each target, but | 9 # The code below generates a separate .mk file for each target, but |
| 10 # all are sourced by the top-level Makefile. This means that all | 10 # all are sourced by the top-level Makefile. This means that all |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 import pprint | 28 import pprint |
| 29 | 29 |
| 30 generator_default_variables = { | 30 generator_default_variables = { |
| 31 'EXECUTABLE_PREFIX': '', | 31 'EXECUTABLE_PREFIX': '', |
| 32 'EXECUTABLE_SUFFIX': '', | 32 'EXECUTABLE_SUFFIX': '', |
| 33 'OS': 'linux', | 33 'OS': 'linux', |
| 34 'STATIC_LIB_PREFIX': 'lib', | 34 'STATIC_LIB_PREFIX': 'lib', |
| 35 'SHARED_LIB_PREFIX': 'lib', | 35 'SHARED_LIB_PREFIX': 'lib', |
| 36 'STATIC_LIB_SUFFIX': '.a', | 36 'STATIC_LIB_SUFFIX': '.a', |
| 37 'SHARED_LIB_SUFFIX': '.so', | 37 'SHARED_LIB_SUFFIX': '.so', |
| 38 'INTERMEDIATE_DIR': '$(obj)/geni', | 38 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/geni', |
| 39 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', | 39 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', |
| 40 'PRODUCT_DIR': '$(builddir)', | 40 'PRODUCT_DIR': '$(builddir)', |
| 41 'LIB_DIR': '$(obj)', | 41 'LIB_DIR': '$(obj)', |
| 42 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. | 42 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. |
| 43 'RULE_INPUT_PATH': '$(abspath $<)', | 43 'RULE_INPUT_PATH': '$(abspath $<)', |
| 44 | 44 |
| 45 # These appear unused -- ??? | 45 # These appear unused -- ??? |
| 46 'RULE_INPUT_EXT': 'XXXEXT$(suffix $^)', | 46 'RULE_INPUT_EXT': 'XXXEXT$(suffix $^)', |
| 47 'RULE_INPUT_NAME': 'XXXNAME$(notdir $(basename $^)0', | 47 'RULE_INPUT_NAME': 'XXXNAME$(notdir $(basename $^)0', |
| 48 'CONFIGURATION_NAME': '$(BUILDTYPE)', | 48 'CONFIGURATION_NAME': '$(BUILDTYPE)', |
| 49 } | 49 } |
| 50 | 50 |
| 51 # Make supports multiple toolsets |
| 52 generator_supports_multiple_toolsets = True |
| 51 | 53 |
| 52 def ensure_directory_exists(path): | 54 def ensure_directory_exists(path): |
| 53 dir = os.path.dirname(path) | 55 dir = os.path.dirname(path) |
| 54 if dir and not os.path.exists(dir): | 56 if dir and not os.path.exists(dir): |
| 55 os.makedirs(dir) | 57 os.makedirs(dir) |
| 56 | 58 |
| 57 # Header of toplevel Makefile. | 59 # Header of toplevel Makefile. |
| 58 # This should go into the build tree, but it's easier to keep it here for now. | 60 # This should go into the build tree, but it's easier to keep it here for now. |
| 59 SHARED_HEADER = ("""\ | 61 SHARED_HEADER = ("""\ |
| 60 # We borrow heavily from the kernel build setup, though we are simpler since | 62 # We borrow heavily from the kernel build setup, though we are simpler since |
| (...skipping 23 matching lines...) Expand all Loading... |
| 84 # Object output directory. | 86 # Object output directory. |
| 85 obj := $(builddir)/obj | 87 obj := $(builddir)/obj |
| 86 abs_obj := $(abspath $(obj)) | 88 abs_obj := $(abspath $(obj)) |
| 87 | 89 |
| 88 # We build up a list of all targets so we can slurp in the generated | 90 # We build up a list of all targets so we can slurp in the generated |
| 89 # dependency rule Makefiles in one pass. | 91 # dependency rule Makefiles in one pass. |
| 90 all_targets := | 92 all_targets := |
| 91 | 93 |
| 92 # C++ apps need to be linked with g++. Not sure what's appropriate. | 94 # C++ apps need to be linked with g++. Not sure what's appropriate. |
| 93 LINK := $(CXX) | 95 LINK := $(CXX) |
| 94 RANLIB ?= ranlib | 96 |
| 97 CC.target ?= $(CC) |
| 98 CXX.target ?= $(CXX) |
| 99 LINK.target ?= $(LINK) |
| 100 AR.target ?= $(AR) |
| 101 RANLIB.target ?= ranlib |
| 102 |
| 103 CC.host ?= gcc |
| 104 CXX.host ?= g++ |
| 105 LINK.host ?= g++ |
| 106 AR.host ?= ar |
| 107 RANLIB.host ?= ranlib |
| 95 | 108 |
| 96 # Flags to make gcc output dependency info. Note that you need to be | 109 # Flags to make gcc output dependency info. Note that you need to be |
| 97 # careful here to use the flags that ccache and distcc can understand. | 110 # careful here to use the flags that ccache and distcc can understand. |
| 98 # We write to a temporary dep file first and then rename at the end | 111 # We write to a temporary dep file first and then rename at the end |
| 99 # so we can't end up with a broken dep file. | 112 # so we can't end up with a broken dep file. |
| 100 depfile = $@.d | 113 depfile = $@.d |
| 101 DEPFLAGS = -MMD -MF $(depfile).tmp | 114 DEPFLAGS = -MMD -MF $(depfile).tmp |
| 102 | 115 |
| 103 # We have to fixup the deps output in a few ways. | 116 # We have to fixup the deps output in a few ways. |
| 104 # First, the file output should to mention the proper .o file. | 117 # First, the file output should to mention the proper .o file. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 124 -e "/./s|$$|:|" $(depfile).tmp >> $(depfile).tmp | 137 -e "/./s|$$|:|" $(depfile).tmp >> $(depfile).tmp |
| 125 cat $(depfile).tmp >> $(depfile) | 138 cat $(depfile).tmp >> $(depfile) |
| 126 rm -f $(depfile).tmp | 139 rm -f $(depfile).tmp |
| 127 endef | 140 endef |
| 128 """ | 141 """ |
| 129 """ | 142 """ |
| 130 # Command definitions: | 143 # Command definitions: |
| 131 # - cmd_foo is the actual command to run; | 144 # - cmd_foo is the actual command to run; |
| 132 # - quiet_cmd_foo is the brief-output summary of the command. | 145 # - quiet_cmd_foo is the brief-output summary of the command. |
| 133 | 146 |
| 134 quiet_cmd_cc = CC $@ | 147 quiet_cmd_cc = CC($(TOOLSET)) $@ |
| 135 cmd_cc = $(CC) $(CFLAGS) $(DEPFLAGS) -c -o $@ $< | 148 cmd_cc = $(CC.$(TOOLSET)) $(CFLAGS) $(DEPFLAGS) -c -o $@ $< |
| 136 | 149 |
| 137 quiet_cmd_cxx = CXX $@ | 150 quiet_cmd_cxx = CXX($(TOOLSET)) $@ |
| 138 cmd_cxx = $(CXX) $(CXXFLAGS) $(DEPFLAGS) -c -o $@ $< | 151 cmd_cxx = $(CXX.$(TOOLSET)) $(CXXFLAGS) $(DEPFLAGS) -c -o $@ $< |
| 139 | 152 |
| 140 quiet_cmd_alink = AR+RANLIB $@ | 153 quiet_cmd_alink = AR+RANLIB($(TOOLSET)) $@ |
| 141 cmd_alink = rm -f $@ && $(AR) rc $@ $(filter %.o,$^) && $(RANLIB) $@ | 154 cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) rc $@ $(filter %.o,$^) && $(RANLIB.$(TO
OLSET)) $@ |
| 142 | 155 |
| 143 quiet_cmd_touch = TOUCH $@ | 156 quiet_cmd_touch = TOUCH $@ |
| 144 cmd_touch = touch $@ | 157 cmd_touch = touch $@ |
| 145 | 158 |
| 146 quiet_cmd_copy = COPY $@ | 159 quiet_cmd_copy = COPY $@ |
| 147 cmd_copy = ln -f $< $@ || cp -af $< $@ | 160 cmd_copy = ln -f $< $@ || cp -af $< $@ |
| 148 | 161 |
| 149 # Due to circular dependencies between libraries :(, we wrap the | 162 # Due to circular dependencies between libraries :(, we wrap the |
| 150 # special "figure out circular dependencies" flags around the entire | 163 # special "figure out circular dependencies" flags around the entire |
| 151 # input list during linking. | 164 # input list during linking. |
| 152 quiet_cmd_link = LINK $@ | 165 quiet_cmd_link = LINK($(TOOLSET)) $@ |
| 153 cmd_link = $(LINK) $(LDFLAGS) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD,
$^) -Wl,--end-group $(LIBS) | 166 cmd_link = $(LINK.$(TOOLSET)) $(LDFLAGS) -o $@ -Wl,--start-group $(filter-out FO
RCE_DO_CMD, $^) -Wl,--end-group $(LIBS) |
| 154 | 167 |
| 155 # Shared-object link (for generating .so). | 168 # Shared-object link (for generating .so). |
| 156 # Set SONAME to the library filename so our binaries don't reference the local, | 169 # Set SONAME to the library filename so our binaries don't reference the local, |
| 157 # absolute paths used on the link command-line. | 170 # absolute paths used on the link command-line. |
| 158 # TODO: perhaps this can share with the LINK command above? | 171 # TODO: perhaps this can share with the LINK command above? |
| 159 quiet_cmd_solink = SOLINK $@ | 172 quiet_cmd_solink = SOLINK($(TOOLSET)) $@ |
| 160 cmd_solink = $(LINK) -shared $(LDFLAGS) -Wl,-soname=$(@F) -o $@ -Wl,--start-grou
p $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) | 173 cmd_solink = $(LINK.$(TOOLSET)) -shared $(LDFLAGS) -Wl,-soname=$(@F) -o $@ -Wl,-
-start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) |
| 161 """ | 174 """ |
| 162 r""" | 175 r""" |
| 163 # Define an escape_quotes function to escape single quotes. | 176 # Define an escape_quotes function to escape single quotes. |
| 164 # This allows us to handle quotes properly as long as we always use | 177 # This allows us to handle quotes properly as long as we always use |
| 165 # use single quotes and escape_quotes. | 178 # use single quotes and escape_quotes. |
| 166 escape_quotes = $(subst ','\'',$(1)) | 179 escape_quotes = $(subst ','\'',$(1)) |
| 167 # This comment is here just to include a ' to unconfuse syntax highlighting. | 180 # This comment is here just to include a ' to unconfuse syntax highlighting. |
| 168 # Define an escape_vars function to escape '$' variable syntax. | 181 # Define an escape_vars function to escape '$' variable syntax. |
| 169 # This allows us to read/write command lines wth shell variables (e.g. | 182 # This allows us to read/write command lines wth shell variables (e.g. |
| 170 # $LD_LIBRARY_PATH), without triggering make substitution. | 183 # $LD_LIBRARY_PATH), without triggering make substitution. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 # Declare "all" target first so it is the default, even though we don't have the | 220 # Declare "all" target first so it is the default, even though we don't have the |
| 208 # deps yet. | 221 # deps yet. |
| 209 .PHONY: all | 222 .PHONY: all |
| 210 all: | 223 all: |
| 211 | 224 |
| 212 # Use FORCE_DO_CMD to force a target to run. Should be coupled with | 225 # Use FORCE_DO_CMD to force a target to run. Should be coupled with |
| 213 # do_cmd. | 226 # do_cmd. |
| 214 .PHONY: FORCE_DO_CMD | 227 .PHONY: FORCE_DO_CMD |
| 215 FORCE_DO_CMD: | 228 FORCE_DO_CMD: |
| 216 | 229 |
| 230 """) |
| 231 |
| 232 SHARED_HEADER_SUFFIX_RULES = ("""\ |
| 217 # Suffix rules, putting all outputs into $(obj). | 233 # Suffix rules, putting all outputs into $(obj). |
| 218 $(obj)/%.o: $(srcdir)/%.c FORCE_DO_CMD | 234 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD |
| 219 @$(call do_cmd,cc,1) | 235 @$(call do_cmd,cc,1) |
| 220 | 236 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD |
| 221 $(obj)/%.o: $(srcdir)/%.s FORCE_DO_CMD | |
| 222 @$(call do_cmd,cc) | 237 @$(call do_cmd,cc) |
| 223 | 238 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD |
| 224 $(obj)/%.o: $(srcdir)/%.S FORCE_DO_CMD | |
| 225 @$(call do_cmd,cc) | 239 @$(call do_cmd,cc) |
| 226 | 240 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD |
| 227 $(obj)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD | |
| 228 @$(call do_cmd,cxx,1) | 241 @$(call do_cmd,cxx,1) |
| 229 $(obj)/%.o: $(srcdir)/%.cc FORCE_DO_CMD | 242 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD |
| 230 @$(call do_cmd,cxx,1) | 243 @$(call do_cmd,cxx,1) |
| 231 $(obj)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD | 244 $(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD |
| 232 @$(call do_cmd,cxx,1) | 245 @$(call do_cmd,cxx,1) |
| 233 | 246 |
| 234 # Try building from generated source, too. | 247 # Try building from generated source, too. |
| 235 $(obj)/%.o: $(obj)/%.c FORCE_DO_CMD | 248 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD |
| 236 @$(call do_cmd,cc,1) | 249 @$(call do_cmd,cc,1) |
| 237 $(obj)/%.o: $(obj)/%.cc FORCE_DO_CMD | 250 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD |
| 238 @$(call do_cmd,cxx,1) | 251 @$(call do_cmd,cxx,1) |
| 239 $(obj)/%.o: $(obj)/%.cpp FORCE_DO_CMD | 252 $(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD |
| 253 » @$(call do_cmd,cxx,1) |
| 254 |
| 255 $(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD |
| 256 » @$(call do_cmd,cc,1) |
| 257 $(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD |
| 258 » @$(call do_cmd,cxx,1) |
| 259 $(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD |
| 240 @$(call do_cmd,cxx,1) | 260 @$(call do_cmd,cxx,1) |
| 241 """) | 261 """) |
| 242 | 262 |
| 243 # This gets added to the very beginning of the Makefile. | 263 # This gets added to the very beginning of the Makefile. |
| 244 SHARED_HEADER_SRCDIR = ("""\ | 264 SHARED_HEADER_SRCDIR = ("""\ |
| 245 # The source directory tree. | 265 # The source directory tree. |
| 246 srcdir := %s | 266 srcdir := %s |
| 247 | 267 |
| 248 """) | 268 """) |
| 249 | 269 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 """Translate a compilable filename to its .o target.""" | 306 """Translate a compilable filename to its .o target.""" |
| 287 return os.path.splitext(filename)[0] + '.o' | 307 return os.path.splitext(filename)[0] + '.o' |
| 288 | 308 |
| 289 | 309 |
| 290 def QuoteIfNecessary(string): | 310 def QuoteIfNecessary(string): |
| 291 if '"' in string: | 311 if '"' in string: |
| 292 string = '"' + string.replace('"', '\\"') + '"' | 312 string = '"' + string.replace('"', '\\"') + '"' |
| 293 return string | 313 return string |
| 294 | 314 |
| 295 | 315 |
| 296 def Objectify(path): | |
| 297 """Convert a path to its output directory form.""" | |
| 298 if '$(' in path: | |
| 299 return path | |
| 300 return '$(obj)/' + path | |
| 301 | |
| 302 srcdir_prefix = '' | 316 srcdir_prefix = '' |
| 303 def Sourceify(path): | 317 def Sourceify(path): |
| 304 """Convert a path to its source directory form.""" | 318 """Convert a path to its source directory form.""" |
| 305 if '$(' in path: | 319 if '$(' in path: |
| 306 return path | 320 return path |
| 307 return srcdir_prefix + path | 321 return srcdir_prefix + path |
| 308 | 322 |
| 309 | 323 |
| 310 # Map from qualified target to path to output. | 324 # Map from qualified target to path to output. |
| 311 target_outputs = {} | 325 target_outputs = {} |
| (...skipping 23 matching lines...) Expand all Loading... |
| 335 | 349 |
| 336 ensure_directory_exists(output_filename) | 350 ensure_directory_exists(output_filename) |
| 337 | 351 |
| 338 self.fp = open(output_filename, 'w') | 352 self.fp = open(output_filename, 'w') |
| 339 | 353 |
| 340 self.fp.write(header) | 354 self.fp.write(header) |
| 341 | 355 |
| 342 self.path = base_path | 356 self.path = base_path |
| 343 self.target = spec['target_name'] | 357 self.target = spec['target_name'] |
| 344 self.type = spec['type'] | 358 self.type = spec['type'] |
| 359 self.toolset = spec['toolset'] |
| 345 | 360 |
| 346 deps, link_deps = self.ComputeDeps(spec) | 361 deps, link_deps = self.ComputeDeps(spec) |
| 347 | 362 |
| 348 # Some of the generation below can add extra output, sources, or | 363 # Some of the generation below can add extra output, sources, or |
| 349 # link dependencies. All of the out params of the functions that | 364 # link dependencies. All of the out params of the functions that |
| 350 # follow use names like extra_foo. | 365 # follow use names like extra_foo. |
| 351 extra_outputs = [] | 366 extra_outputs = [] |
| 352 extra_sources = [] | 367 extra_sources = [] |
| 353 extra_link_deps = [] | 368 extra_link_deps = [] |
| 354 | 369 |
| 355 self.output = self.ComputeOutput(spec) | 370 self.output = self.ComputeOutput(spec) |
| 356 self._INSTALLABLE_TARGETS = ('executable', 'loadable_module', | 371 self._INSTALLABLE_TARGETS = ('executable', 'loadable_module', |
| 357 'shared_library') | 372 'shared_library') |
| 358 if self.type in self._INSTALLABLE_TARGETS: | 373 if self.type in self._INSTALLABLE_TARGETS: |
| 359 self.alias = os.path.basename(self.output) | 374 self.alias = os.path.basename(self.output) |
| 360 else: | 375 else: |
| 361 self.alias = self.output | 376 self.alias = self.output |
| 362 | 377 |
| 378 self.WriteLn("TOOLSET := " + self.toolset) |
| 379 |
| 363 # Actions must come first, since they can generate more OBJs for use below. | 380 # Actions must come first, since they can generate more OBJs for use below. |
| 364 if 'actions' in spec: | 381 if 'actions' in spec: |
| 365 self.WriteActions(spec['actions'], extra_sources, extra_outputs) | 382 self.WriteActions(spec['actions'], extra_sources, extra_outputs) |
| 366 | 383 |
| 367 # Rules must be early like actions. | 384 # Rules must be early like actions. |
| 368 if 'rules' in spec: | 385 if 'rules' in spec: |
| 369 self.WriteRules(spec['rules'], extra_sources, extra_outputs) | 386 self.WriteRules(spec['rules'], extra_sources, extra_outputs) |
| 370 | 387 |
| 371 if 'copies' in spec: | 388 if 'copies' in spec: |
| 372 self.WriteCopies(spec['copies'], extra_outputs) | 389 self.WriteCopies(spec['copies'], extra_outputs) |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 self.WriteLn("# Flags passed to only C (and not C++) files."); | 597 self.WriteLn("# Flags passed to only C (and not C++) files."); |
| 581 self.WriteList(config.get('cflags_c'), 'CFLAGS_C_%s' % configname) | 598 self.WriteList(config.get('cflags_c'), 'CFLAGS_C_%s' % configname) |
| 582 self.WriteLn("# Flags passed to only C++ (and not C) files."); | 599 self.WriteLn("# Flags passed to only C++ (and not C) files."); |
| 583 self.WriteList(config.get('cflags_cc'), 'CFLAGS_CC_%s' % configname) | 600 self.WriteList(config.get('cflags_cc'), 'CFLAGS_CC_%s' % configname) |
| 584 includes = config.get('include_dirs') | 601 includes = config.get('include_dirs') |
| 585 if includes: | 602 if includes: |
| 586 includes = map(Sourceify, map(self.Absolutify, includes)) | 603 includes = map(Sourceify, map(self.Absolutify, includes)) |
| 587 self.WriteList(includes, 'INCS_%s' % configname, prefix='-I') | 604 self.WriteList(includes, 'INCS_%s' % configname, prefix='-I') |
| 588 | 605 |
| 589 sources = filter(Compilable, sources) | 606 sources = filter(Compilable, sources) |
| 590 objs = map(Objectify, map(self.Absolutify, map(Target, sources))) | 607 objs = map(self.Objectify, map(self.Absolutify, map(Target, sources))) |
| 591 self.WriteList(objs, 'OBJS') | 608 self.WriteList(objs, 'OBJS') |
| 592 | 609 |
| 593 self.WriteLn('# Add to the list of files we specially track ' | 610 self.WriteLn('# Add to the list of files we specially track ' |
| 594 'dependencies for.') | 611 'dependencies for.') |
| 595 self.WriteLn('all_targets += $(OBJS)') | 612 self.WriteLn('all_targets += $(OBJS)') |
| 596 self.WriteLn() | 613 self.WriteLn() |
| 597 | 614 |
| 598 # Make sure our dependencies are built first. | 615 # Make sure our dependencies are built first. |
| 599 if deps: | 616 if deps: |
| 600 self.WriteMakeRule(['$(OBJS)'], deps, | 617 self.WriteMakeRule(['$(OBJS)'], deps, |
| 601 comment = 'Make sure our dependencies are built ' | 618 comment = 'Make sure our dependencies are built ' |
| 602 'before any of us.', | 619 'before any of us.', |
| 603 order_only = True) | 620 order_only = True) |
| 604 | 621 |
| 605 # Make sure the actions and rules run first. | 622 # Make sure the actions and rules run first. |
| 606 # If they generate any extra headers etc., the per-.o file dep tracking | 623 # If they generate any extra headers etc., the per-.o file dep tracking |
| 607 # will catch the proper rebuilds, so order only is still ok here. | 624 # will catch the proper rebuilds, so order only is still ok here. |
| 608 if extra_outputs: | 625 if extra_outputs: |
| 609 self.WriteMakeRule(['$(OBJS)'], extra_outputs, | 626 self.WriteMakeRule(['$(OBJS)'], extra_outputs, |
| 610 comment = 'Make sure our actions/rules run ' | 627 comment = 'Make sure our actions/rules run ' |
| 611 'before any of us.', | 628 'before any of us.', |
| 612 order_only = True) | 629 order_only = True) |
| 613 | 630 |
| 614 if objs: | 631 if objs: |
| 615 extra_link_deps.append('$(OBJS)') | 632 extra_link_deps.append('$(OBJS)') |
| 616 self.WriteLn("""\ | 633 self.WriteLn("""\ |
| 617 # CFLAGS et al overrides must be target-local. | 634 # CFLAGS et al overrides must be target-local. |
| 618 # See "Target-specific Variable Values" in the GNU Make manual.""") | 635 # See "Target-specific Variable Values" in the GNU Make manual.""") |
| 636 self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)") |
| 619 self.WriteLn("$(OBJS): CFLAGS := $(CFLAGS_$(BUILDTYPE)) " | 637 self.WriteLn("$(OBJS): CFLAGS := $(CFLAGS_$(BUILDTYPE)) " |
| 620 "$(CFLAGS_C_$(BUILDTYPE)) " | 638 "$(CFLAGS_C_$(BUILDTYPE)) " |
| 621 "$(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))") | 639 "$(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))") |
| 622 self.WriteLn("$(OBJS): CXXFLAGS := $(CFLAGS_$(BUILDTYPE)) " | 640 self.WriteLn("$(OBJS): CXXFLAGS := $(CFLAGS_$(BUILDTYPE)) " |
| 623 "$(CFLAGS_CC_$(BUILDTYPE)) " | 641 "$(CFLAGS_CC_$(BUILDTYPE)) " |
| 624 "$(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))") | 642 "$(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))") |
| 625 | 643 |
| 626 self.WriteLn() | 644 self.WriteLn() |
| 627 | 645 |
| 628 | 646 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 641 elif self.type == 'none': | 659 elif self.type == 'none': |
| 642 target = '%s.stamp' % target | 660 target = '%s.stamp' % target |
| 643 elif self.type == 'settings': | 661 elif self.type == 'settings': |
| 644 return None | 662 return None |
| 645 elif self.type == 'executable': | 663 elif self.type == 'executable': |
| 646 target = spec.get('product_name', target) | 664 target = spec.get('product_name', target) |
| 647 else: | 665 else: |
| 648 print ("ERROR: What output file should be generated?", | 666 print ("ERROR: What output file should be generated?", |
| 649 "typ", self.type, "target", target) | 667 "typ", self.type, "target", target) |
| 650 | 668 |
| 651 path = spec.get('product_dir', os.path.join('$(obj)', self.path)) | 669 path = spec.get('product_dir', os.path.join('$(obj).' + self.toolset, |
| 670 self.path)) |
| 652 return os.path.join(path, target) | 671 return os.path.join(path, target) |
| 653 | 672 |
| 654 | 673 |
| 655 def ComputeDeps(self, spec): | 674 def ComputeDeps(self, spec): |
| 656 """Compute the dependencies of a gyp spec. | 675 """Compute the dependencies of a gyp spec. |
| 657 | 676 |
| 658 Returns a tuple (deps, link_deps), where each is a list of | 677 Returns a tuple (deps, link_deps), where each is a list of |
| 659 filenames that will need to be put in front of make for either | 678 filenames that will need to be put in front of make for either |
| 660 building (deps) or linking (link_deps). | 679 building (deps) or linking (link_deps). |
| 661 """ | 680 """ |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 phony: if true, the rule does not actually generate the named output, the | 801 phony: if true, the rule does not actually generate the named output, the |
| 783 output is just a name to run the rule | 802 output is just a name to run the rule |
| 784 """ | 803 """ |
| 785 if comment: | 804 if comment: |
| 786 self.WriteLn('# ' + comment) | 805 self.WriteLn('# ' + comment) |
| 787 if phony: | 806 if phony: |
| 788 self.WriteLn('.PHONY: ' + ' '.join(outputs)) | 807 self.WriteLn('.PHONY: ' + ' '.join(outputs)) |
| 789 # TODO(evanm): just make order_only a list of deps instead of these hacks. | 808 # TODO(evanm): just make order_only a list of deps instead of these hacks. |
| 790 order_insert = '| ' if order_only else '' | 809 order_insert = '| ' if order_only else '' |
| 791 force_append = ' FORCE_DO_CMD' if force else '' | 810 force_append = ' FORCE_DO_CMD' if force else '' |
| 811 if actions: |
| 812 self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0]) |
| 792 self.WriteLn('%s: %s%s%s' % (outputs[0], order_insert, ' '.join(inputs), | 813 self.WriteLn('%s: %s%s%s' % (outputs[0], order_insert, ' '.join(inputs), |
| 793 force_append)) | 814 force_append)) |
| 794 if actions: | 815 if actions: |
| 795 for action in actions: | 816 for action in actions: |
| 796 self.WriteLn('\t%s' % action) | 817 self.WriteLn('\t%s' % action) |
| 797 if len(outputs) > 1: | 818 if len(outputs) > 1: |
| 798 # If we have more than one output, a rule like | 819 # If we have more than one output, a rule like |
| 799 # foo bar: baz | 820 # foo bar: baz |
| 800 # that for *each* output we must run the action, potentially | 821 # that for *each* output we must run the action, potentially |
| 801 # in parallel. That is not what we're trying to write -- what | 822 # in parallel. That is not what we're trying to write -- what |
| 802 # we want is that we run the action once and it generates all | 823 # we want is that we run the action once and it generates all |
| 803 # the files. | 824 # the files. |
| 804 # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html | 825 # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html |
| 805 # discusses this problem and has this solution: | 826 # discusses this problem and has this solution: |
| 806 # 1) Write the naive rule that would produce parallel runs of | 827 # 1) Write the naive rule that would produce parallel runs of |
| 807 # the action. | 828 # the action. |
| 808 # 2) Make the outputs seralized on each other, so we won't start | 829 # 2) Make the outputs seralized on each other, so we won't start |
| 809 # a a parallel run until the first run finishes, at which point | 830 # a a parallel run until the first run finishes, at which point |
| 810 # we'll have generated all the outputs and we're done. | 831 # we'll have generated all the outputs and we're done. |
| 811 self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0])) | 832 self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0])) |
| 812 self.WriteLn() | 833 self.WriteLn() |
| 813 | 834 |
| 814 | 835 |
| 815 def WriteLn(self, text=''): | 836 def WriteLn(self, text=''): |
| 816 self.fp.write(text + '\n') | 837 self.fp.write(text + '\n') |
| 817 | 838 |
| 818 | 839 |
| 840 def Objectify(self, path): |
| 841 """Convert a path to its output directory form.""" |
| 842 if '$(' in path: |
| 843 path = path.replace('$(obj)/', '$(obj).%s/' % self.toolset) |
| 844 return path |
| 845 return '$(obj).%s/%s' % (self.toolset, path) |
| 846 |
| 819 def Absolutify(self, path): | 847 def Absolutify(self, path): |
| 820 """Convert a subdirectory-relative path into a base-relative path. | 848 """Convert a subdirectory-relative path into a base-relative path. |
| 821 Skips over paths that contain variables.""" | 849 Skips over paths that contain variables.""" |
| 822 if '$(' in path: | 850 if '$(' in path: |
| 823 return path | 851 return path |
| 824 return os.path.normpath(os.path.join(self.path, path)) | 852 return os.path.normpath(os.path.join(self.path, path)) |
| 825 | 853 |
| 826 | 854 |
| 827 def FixupArgPath(self, arg): | 855 def FixupArgPath(self, arg): |
| 828 if '/' in arg or '.h.' in arg: | 856 if '/' in arg or '.h.' in arg: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 843 | 871 |
| 844 def GenerateOutput(target_list, target_dicts, data, params): | 872 def GenerateOutput(target_list, target_dicts, data, params): |
| 845 options = params['options'] | 873 options = params['options'] |
| 846 generator_flags = params.get('generator_flags', {}) | 874 generator_flags = params.get('generator_flags', {}) |
| 847 builddir_name = generator_flags.get('output_dir', 'out') | 875 builddir_name = generator_flags.get('output_dir', 'out') |
| 848 | 876 |
| 849 # TODO: search for the first non-'Default' target. This can go | 877 # TODO: search for the first non-'Default' target. This can go |
| 850 # away when we add verification that all targets have the | 878 # away when we add verification that all targets have the |
| 851 # necessary configurations. | 879 # necessary configurations. |
| 852 default_configuration = None | 880 default_configuration = None |
| 881 toolsets = set([target_dicts[target]['toolset'] for target in target_list]) |
| 853 for target in target_list: | 882 for target in target_list: |
| 854 spec = target_dicts[target] | 883 spec = target_dicts[target] |
| 855 if spec['default_configuration'] != 'Default': | 884 if spec['default_configuration'] != 'Default': |
| 856 default_configuration = spec['default_configuration'] | 885 default_configuration = spec['default_configuration'] |
| 857 break | 886 break |
| 858 if not default_configuration: | 887 if not default_configuration: |
| 859 default_configuration = 'Default' | 888 default_configuration = 'Default' |
| 860 | 889 |
| 861 srcdir = '.' | 890 srcdir = '.' |
| 862 makefile_name = 'Makefile' + options.suffix | 891 makefile_name = 'Makefile' + options.suffix |
| 863 makefile_path = os.path.join(options.depth, makefile_name) | 892 makefile_path = os.path.join(options.depth, makefile_name) |
| 864 if options.generator_output: | 893 if options.generator_output: |
| 865 global srcdir_prefix | 894 global srcdir_prefix |
| 866 makefile_path = os.path.join(options.generator_output, makefile_path) | 895 makefile_path = os.path.join(options.generator_output, makefile_path) |
| 867 srcdir = gyp.common.RelativePath('.', options.generator_output) | 896 srcdir = gyp.common.RelativePath('.', options.generator_output) |
| 868 srcdir_prefix = '$(srcdir)/' | 897 srcdir_prefix = '$(srcdir)/' |
| 869 ensure_directory_exists(makefile_path) | 898 ensure_directory_exists(makefile_path) |
| 870 root_makefile = open(makefile_path, 'w') | 899 root_makefile = open(makefile_path, 'w') |
| 871 root_makefile.write(SHARED_HEADER_SRCDIR % srcdir) | 900 root_makefile.write(SHARED_HEADER_SRCDIR % srcdir) |
| 872 root_makefile.write(SHARED_HEADER_BUILDDIR_NAME % builddir_name) | 901 root_makefile.write(SHARED_HEADER_BUILDDIR_NAME % builddir_name) |
| 873 root_makefile.write(SHARED_HEADER.replace('__default_configuration__', | 902 root_makefile.write(SHARED_HEADER.replace('__default_configuration__', |
| 874 default_configuration)) | 903 default_configuration)) |
| 904 for toolset in toolsets: |
| 905 root_makefile.write('TOOLSET := %s\n' % toolset) |
| 906 root_makefile.write(SHARED_HEADER_SUFFIX_RULES) |
| 875 | 907 |
| 876 # Find the list of targets that derive from the gyp file(s) being built. | 908 # Find the list of targets that derive from the gyp file(s) being built. |
| 877 needed_targets = set() | 909 needed_targets = set() |
| 878 for build_file in params['build_files']: | 910 for build_file in params['build_files']: |
| 879 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): | 911 for target in gyp.common.AllTargets(target_list, target_dicts, build_file): |
| 880 needed_targets.add(target) | 912 needed_targets.add(target) |
| 881 | 913 |
| 882 build_files = set() | 914 build_files = set() |
| 883 for qualified_target in target_list: | 915 for qualified_target in target_list: |
| 884 # target_list is all the targets defined in all referenced gyp files, so | 916 # target_list is all the targets defined in all referenced gyp files, so |
| 885 # weed out the ones that aren't actually needed for this build. We could | 917 # weed out the ones that aren't actually needed for this build. We could |
| 886 # generate the .mk even for unneeded targets, as long as we don't | 918 # generate the .mk even for unneeded targets, as long as we don't |
| 887 # reference them in the top-level Makefile, but skipping them entirely | 919 # reference them in the top-level Makefile, but skipping them entirely |
| 888 # should work too. | 920 # should work too. |
| 889 if qualified_target not in needed_targets: | 921 if qualified_target not in needed_targets: |
| 890 continue | 922 continue |
| 891 build_file, target = gyp.common.BuildFileAndTarget('', qualified_target)[:2] | 923 build_file, target, toolset = gyp.common.ParseQualifiedTarget( |
| 924 qualified_target) |
| 892 build_files.add(gyp.common.RelativePath(build_file, options.depth)) | 925 build_files.add(gyp.common.RelativePath(build_file, options.depth)) |
| 893 included_files = data[build_file]['included_files'] | 926 included_files = data[build_file]['included_files'] |
| 894 for included_file in included_files: | 927 for included_file in included_files: |
| 895 # The included_files entries are relative to the dir of the build file | 928 # The included_files entries are relative to the dir of the build file |
| 896 # that included them, so we have to undo that and then make them relative | 929 # that included them, so we have to undo that and then make them relative |
| 897 # to the root dir. | 930 # to the root dir. |
| 898 build_files.add(gyp.common.RelativePath( | 931 build_files.add(gyp.common.RelativePath( |
| 899 gyp.common.UnrelativePath(included_file, build_file), options.depth)) | 932 gyp.common.UnrelativePath(included_file, build_file), options.depth)) |
| 900 | 933 |
| 901 # Paths in gyp files are relative to the .gyp file, but we want | 934 # Paths in gyp files are relative to the .gyp file, but we want |
| 902 # paths relative to the source root for the master makefile. Grab | 935 # paths relative to the source root for the master makefile. Grab |
| 903 # the path of the .gyp file as the base to relativize against. | 936 # the path of the .gyp file as the base to relativize against. |
| 904 # E.g. "foo/bar" when we're constructing targets found "foo/bar/baz.gyp". | 937 # E.g. "foo/bar" when we're constructing targets found "foo/bar/baz.gyp". |
| 905 base_path = gyp.common.RelativePath(os.path.dirname(build_file), | 938 base_path = gyp.common.RelativePath(os.path.dirname(build_file), |
| 906 options.depth) | 939 options.depth) |
| 907 # We write the .mk file in the base_path directory. | 940 # We write the .mk file in the base_path directory. |
| 908 output_file = os.path.join(options.depth, | 941 output_file = os.path.join(options.depth, |
| 909 base_path, | 942 base_path, |
| 910 target + options.suffix + '.mk') | 943 target + '.' + toolset + options.suffix + '.mk') |
| 911 | 944 |
| 912 if options.generator_output: | 945 if options.generator_output: |
| 913 output_file = os.path.join(options.generator_output, output_file) | 946 output_file = os.path.join(options.generator_output, output_file) |
| 914 | 947 |
| 915 spec = target_dicts[qualified_target] | 948 spec = target_dicts[qualified_target] |
| 916 configs = spec['configurations'] | 949 configs = spec['configurations'] |
| 917 | 950 |
| 918 writer = MakefileWriter() | 951 writer = MakefileWriter() |
| 919 writer.Write(qualified_target, base_path, output_file, spec, configs) | 952 writer.Write(qualified_target, base_path, output_file, spec, configs) |
| 920 | 953 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 932 ' '.join(map(Sourceify, build_files)), | 965 ' '.join(map(Sourceify, build_files)), |
| 933 gyp.common.EncodePOSIXShellList( | 966 gyp.common.EncodePOSIXShellList( |
| 934 [gyp.common.FixIfRelativePath(params['gyp_binary'], options.depth), | 967 [gyp.common.FixIfRelativePath(params['gyp_binary'], options.depth), |
| 935 '-fmake'] + | 968 '-fmake'] + |
| 936 gyp.RegenerateFlags(options) + | 969 gyp.RegenerateFlags(options) + |
| 937 build_files_args))) | 970 build_files_args))) |
| 938 | 971 |
| 939 root_makefile.write(SHARED_FOOTER) | 972 root_makefile.write(SHARED_FOOTER) |
| 940 | 973 |
| 941 root_makefile.close() | 974 root_makefile.close() |
| OLD | NEW |