1# Copyright 2003 Christopher Currie 2# Copyright 2006 Dave Abrahams 3# Copyright 2003, 2004, 2005, 2006 Vladimir Prus 4# Copyright 2005-2007 Mat Marcus 5# Copyright 2005-2007 Adobe Systems Incorporated 6# Copyright 2007-2010 Rene Rivera 7# Distributed under the Boost Software License, Version 1.0. 8# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 9 10# Please see http://article.gmane.org/gmane.comp.lib.boost.build/3389/ 11# for explanation why it's a separate toolset. 12 13import feature : feature ; 14import toolset : flags ; 15import type ; 16import common ; 17import generators ; 18import path : basename ; 19import version ; 20import property-set ; 21import regex ; 22import errors ; 23 24## Use a framework. 25feature framework : : free ; 26 27## The MacOSX version to compile for, which maps to the SDK to use (sysroot). 28feature macosx-version : : propagated link-incompatible symmetric optional ; 29 30## The minimal MacOSX version to target. 31feature macosx-version-min : : propagated optional ; 32 33## A dependency, that is forced to be included in the link. 34feature force-load : : free dependency incidental ; 35 36############################################################################# 37 38_ = " " ; 39 40if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ] 41{ 42 .debug-configuration = true ; 43} 44 45feature.extend toolset : darwin ; 46import gcc ; 47toolset.inherit-generators darwin : gcc : gcc.mingw.link gcc.mingw.link.dll ; 48 49generators.override darwin.prebuilt : builtin.prebuilt ; 50generators.override darwin.searched-lib-generator : searched-lib-generator ; 51 52# Override default do-nothing generators. 53generators.override darwin.compile.c.pch : pch.default-c-pch-generator ; 54generators.override darwin.compile.c++.pch : pch.default-cpp-pch-generator ; 55 56type.set-generated-target-suffix PCH : <toolset>darwin : gch ; 57 58toolset.inherit-rules darwin : gcc : localize ; 59toolset.inherit-flags darwin : gcc 60 : <runtime-link>static 61 <architecture>arm/<address-model>32 62 <architecture>arm/<address-model>64 63 <architecture>arm/<instruction-set> 64 <architecture>x86/<address-model>32 65 <architecture>x86/<address-model>64 66 <architecture>x86/<instruction-set> 67 <architecture>power/<address-model>32 68 <architecture>power/<address-model>64 69 <architecture>power/<instruction-set> 70 <inlining>full ; 71 72# Options: 73# 74# <root>PATH 75# Platform root path. The common autodetection will set this to 76# "/Developer". And when a command is given it will be set to 77# the corresponding "*.platform/Developer" directory. 78# 79rule init ( version ? : command * : options * : requirement * ) 80{ 81 # First time around, figure what is host OSX version 82 if ! $(.host-osx-version) 83 { 84 .host-osx-version = [ MATCH "^([0-9.]+)" 85 : [ SHELL "/usr/bin/sw_vers -productVersion" ] ] ; 86 if $(.debug-configuration) 87 { 88 ECHO notice\: OSX version on this machine is $(.host-osx-version) ; 89 } 90 } 91 92 # - The root directory of the tool install. 93 local root = [ feature.get-values <root> : $(options) ] ; 94 95 # - The bin directory where to find the commands to execute. 96 local bin ; 97 98 # - The configured compile driver command. 99 local command = [ common.get-invocation-command darwin : g++ : $(command) ] ; 100 101 # The version as reported by the compiler 102 local real-version ; 103 104 # - Autodetect the root and bin dir if not given. 105 if $(command) 106 { 107 bin ?= [ common.get-absolute-tool-path $(command[1]) ] ; 108 if $(bin) = "/usr/bin" 109 { 110 root ?= /Developer ; 111 } 112 else 113 { 114 local r = $(bin:D) ; 115 r = $(r:D) ; 116 root ?= $(r) ; 117 } 118 } 119 120 # - Autodetect the version if not given. 121 if $(command) 122 { 123 # - The 'command' variable can have multiple elements. When calling 124 # the SHELL builtin we need a single string. 125 local command-string = $(command:J=" ") ; 126 real-version = [ MATCH "^([0-9.]+)" 127 : [ SHELL "$(command-string) -dumpversion" ] ] ; 128 version ?= $(real-version) ; 129 } 130 131 .real-version.$(version) = $(real-version) ; 132 133 # - Define the condition for this toolset instance. 134 local condition = 135 [ common.check-init-parameters darwin $(requirement) : version $(version) ] ; 136 137 # - Set the toolset generic common options. 138 common.handle-options darwin : $(condition) : $(command) : $(options) ; 139 140 # - GCC 4.0 and higher in Darwin does not have -fcoalesce-templates. 141 if $(real-version) < "4.0.0" 142 { 143 flags darwin.compile.c++ OPTIONS $(condition) : -fcoalesce-templates ; 144 } 145 # - GCC 4.2 and higher in Darwin does not have -Wno-long-double. 146 if $(real-version) < "4.2.0" 147 { 148 flags darwin.compile OPTIONS $(condition) : -Wno-long-double ; 149 } 150 # - GCC on Darwin with -pedantic, suppress unsupported long long warning 151 flags darwin.compile OPTIONS $(condition)/<warnings>all : -Wno-long-long ; 152 153 # - GCC on El Capitan (10.11) does not support -finline-functions 154 if "10.11.0" <= $(.host-osx-version) 155 { 156 flags darwin.compile OPTIONS $(condition)/<inlining>full : -Wno-inline ; 157 } 158 159 # - The symbol strip program. 160 local strip ; 161 if <striper> in $(options) 162 { 163 # We can turn off strip by specifying it as empty. In which 164 # case we switch to using the linker to do the strip. 165 flags darwin.link.dll OPTIONS 166 $(condition)/<main-target-type>LIB/<link>shared/<address-model>32/<strip>on : -Wl,-x ; 167 flags darwin.link.dll OPTIONS 168 $(condition)/<main-target-type>LIB/<link>shared/<address-model>/<strip>on : -Wl,-x ; 169 flags darwin.link OPTIONS 170 $(condition)/<main-target-type>EXE/<address-model>32/<strip>on : -s ; 171 flags darwin.link OPTIONS 172 $(condition)/<main-target-type>EXE/<address-model>/<strip>on : -s ; 173 } 174 else 175 { 176 # Otherwise we need to find a strip program to use. And hence 177 # also tell the link action that we need to use a strip 178 # post-process. 179 flags darwin.link NEED_STRIP $(condition)/<strip>on : "" ; 180 strip = 181 [ common.get-invocation-command darwin 182 : strip : [ feature.get-values <striper> : $(options) ] : $(bin) : search-path ] ; 183 flags darwin.link .STRIP $(condition) : $(strip[1]) ; 184 if $(.debug-configuration) 185 { 186 ECHO notice\: using strip for $(condition) at $(strip[1]) ; 187 } 188 } 189 190 # - The archive builder (libtool is the default as creating 191 # archives in darwin is complicated. 192 local archiver = 193 [ common.get-invocation-command darwin 194 : libtool : [ feature.get-values <archiver> : $(options) ] : $(bin) : search-path ] ; 195 flags darwin.archive .LIBTOOL $(condition) : $(archiver[1]) ; 196 if $(.debug-configuration) 197 { 198 ECHO notice\: using archiver for $(condition) at $(archiver[1]) ; 199 } 200 201 # - Initialize the SDKs available in the root for this tool. 202 local sdks = [ init-available-sdk-versions $(condition) : $(root) ] ; 203 204 #~ ECHO --- ; 205 #~ ECHO --- bin :: $(bin) ; 206 #~ ECHO --- root :: $(root) ; 207 #~ ECHO --- version :: $(version) ; 208 #~ ECHO --- condition :: $(condition) ; 209 #~ ECHO --- strip :: $(strip) ; 210 #~ ECHO --- archiver :: $(archiver) ; 211 #~ ECHO --- sdks :: $(sdks) ; 212 #~ ECHO --- ; 213 #~ EXIT ; 214} 215 216# Add and set options for a discovered SDK version. 217local rule init-sdk ( condition * : root ? : version + : version-feature ? ) 218{ 219 local rule version-to-feature ( version + ) 220 { 221 switch $(version[1]) 222 { 223 case appletv* : 224 { 225 return $(version[1])-$(version[2-]:J=.) ; 226 } 227 case iphone* : 228 { 229 return $(version[1])-$(version[2-]:J=.) ; 230 } 231 case mac* : 232 { 233 return $(version[2-]:J=.) ; 234 } 235 case * : 236 { 237 return $(version:J=.) ; 238 } 239 } 240 } 241 242 if $(version-feature) 243 { 244 if $(.debug-configuration) 245 { 246 ECHO notice\: available sdk for $(condition)/<macosx-version>$(version-feature) at $(root) ; 247 } 248 249 # Add the version to the features for specifying them. 250 if ! $(version-feature) in [ feature.values macosx-version ] 251 { 252 feature.extend macosx-version : $(version-feature) ; 253 } 254 if ! $(version-feature) in [ feature.values macosx-version-min ] 255 { 256 feature.extend macosx-version-min : $(version-feature) ; 257 } 258 259 # Set the flags the version needs to compile with, first 260 # generic options. 261 flags darwin.compile OPTIONS $(condition)/<macosx-version>$(version-feature) 262 : -isysroot $(root) ; 263 flags darwin.link OPTIONS $(condition)/<macosx-version>$(version-feature) 264 : -isysroot $(root) ; 265 266 # Then device variation options. 267 switch $(version[1]) 268 { 269 case appletvsim* : 270 { 271 local N = $(version[2]) ; 272 if ! $(version[3]) { N += 00 ; } 273 else if [ regex.match (..) : $(version[3]) ] { N += $(version[3]) ; } 274 else { N += 0$(version[3]) ; } 275 if ! $(version[4]) { N += 00 ; } 276 else if [ regex.match (..) : $(version[4]) ] { N += $(version[4]) ; } 277 else { N += 0$(version[4]) ; } 278 N = $(N:J=) ; 279 flags darwin.compile OPTIONS <macosx-version-min>$(version-feature) 280 : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ; 281 flags darwin.link OPTIONS <macosx-version-min>$(version-feature) 282 : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ; 283 } 284 285 case appletv* : 286 { 287 flags darwin.compile OPTIONS <macosx-version-min>$(version-feature) 288 : -mtvos-version-min=$(version[2-]:J=.) ; 289 flags darwin.link OPTIONS <macosx-version-min>$(version-feature) 290 : -mtvos-version-min=$(version[2-]:J=.) ; 291 } 292 293 case iphonesim* : 294 { 295 local N = $(version[2]) ; 296 if ! $(version[3]) { N += 00 ; } 297 else if [ regex.match (..) : $(version[3]) ] { N += $(version[3]) ; } 298 else { N += 0$(version[3]) ; } 299 if ! $(version[4]) { N += 00 ; } 300 else if [ regex.match (..) : $(version[4]) ] { N += $(version[4]) ; } 301 else { N += 0$(version[4]) ; } 302 N = $(N:J=) ; 303 flags darwin.compile OPTIONS <macosx-version-min>$(version-feature) 304 : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ; 305 flags darwin.link OPTIONS <macosx-version-min>$(version-feature) 306 : -D__IPHONE_OS_VERSION_MIN_REQUIRED=$(N) ; 307 } 308 309 case iphone* : 310 { 311 flags darwin.compile OPTIONS <macosx-version-min>$(version-feature) 312 : -miphoneos-version-min=$(version[2-]:J=.) ; 313 flags darwin.link OPTIONS <macosx-version-min>$(version-feature) 314 : -miphoneos-version-min=$(version[2-]:J=.) ; 315 } 316 317 case mac* : 318 { 319 flags darwin.compile OPTIONS <macosx-version-min>$(version-feature) 320 : -mmacosx-version-min=$(version[2-]:J=.) ; 321 flags darwin.link OPTIONS <macosx-version-min>$(version-feature) 322 : -mmacosx-version-min=$(version[2-]:J=.) ; 323 } 324 } 325 326 if $(version[3]) > 0 327 { 328 # We have a minor version of an SDK. We want to set up 329 # previous minor versions, plus the current minor version. 330 # So we recurse to set up the previous minor versions, up to 331 # the current version. 332 local minor-minus-1 = [ CALC $(version[3]) - 1 ] ; 333 return 334 [ init-sdk $(condition) : $(root) 335 : $(version[1-2]) $(minor-minus-1) : [ version-to-feature $(version[1-2]) $(minor-minus-1) ] ] 336 $(version-feature) ; 337 } 338 else 339 { 340 return $(version-feature) ; 341 } 342 } 343 else if $(version[4]) 344 { 345 # We have a patch version of an SDK. We want to set up 346 # both the specific patch version, and the minor version. 347 # So we recurse to set up the patch version. Plus the minor version. 348 return 349 [ init-sdk $(condition) : $(root) 350 : $(version[1-3]) : [ version-to-feature $(version[1-3]) ] ] 351 [ init-sdk $(condition) : $(root) 352 : $(version) : [ version-to-feature $(version) ] ] ; 353 } 354 else 355 { 356 # Yes, this is intentionally recursive. 357 return 358 [ init-sdk $(condition) : $(root) 359 : $(version) : [ version-to-feature $(version) ] ] ; 360 } 361} 362 363# Determine the MacOSX SDK versions installed and their locations. 364local rule init-available-sdk-versions ( condition * : root ? ) 365{ 366 root ?= /Developer ; 367 local sdks-root = $(root)/SDKs ; 368 local sdks = [ GLOB $(sdks-root) : MacOSX*.sdk AppleTVOS*.sdk AppleTVSimulator*.sdk iPhoneOS*.sdk iPhoneSimulator*.sdk ] ; 369 local result ; 370 for local sdk in $(sdks) 371 { 372 local sdk-match = [ MATCH "([^0-9]+)([0-9]+)[.]([0-9x]+)[.]?([0-9x]+)?" : $(sdk:D=) ] ; 373 local sdk-platform = $(sdk-match[1]:L) ; 374 local sdk-version = $(sdk-match[2-]) ; 375 if $(sdk-version) 376 { 377 switch $(sdk-platform) 378 { 379 case macosx : 380 { 381 sdk-version = mac $(sdk-version) ; 382 } 383 case appletvos : 384 { 385 sdk-version = appletv $(sdk-version) ; 386 } 387 case appletvsimulator : 388 { 389 sdk-version = appletvsim $(sdk-version) ; 390 } 391 case iphoneos : 392 { 393 sdk-version = iphone $(sdk-version) ; 394 } 395 case iphonesimulator : 396 { 397 sdk-version = iphonesim $(sdk-version) ; 398 } 399 case * : 400 { 401 sdk-version = $(sdk-version:J=-) ; 402 } 403 } 404 result += [ init-sdk $(condition) : $(sdk) : $(sdk-version) ] ; 405 } 406 } 407 return $(result) ; 408} 409 410# Generic options. 411flags darwin.compile OPTIONS <flags> ; 412 413# The following adds objective-c support to darwin. 414# Thanks to http://thread.gmane.org/gmane.comp.lib.boost.build/13759 415 416generators.register-c-compiler darwin.compile.m : OBJECTIVE_C : OBJ : <toolset>darwin ; 417generators.register-c-compiler darwin.compile.mm : OBJECTIVE_CPP : OBJ : <toolset>darwin ; 418 419rule setup-address-model ( targets * : sources * : properties * ) 420{ 421 local ps = [ property-set.create $(properties) ] ; 422 local arch = [ $(ps).get <architecture> ] ; 423 local instruction-set = [ $(ps).get <instruction-set> ] ; 424 local address-model = [ $(ps).get <address-model> ] ; 425 local osx-version = [ $(ps).get <macosx-version> ] ; 426 local gcc-version = [ $(ps).get <toolset-darwin:version> ] ; 427 gcc-version = $(.real-version.$(gcc-version)) ; 428 local options ; 429 430 local support-ppc64 = 1 ; 431 432 osx-version ?= $(.host-osx-version) ; 433 434 switch $(osx-version) 435 { 436 case iphone* : 437 { 438 support-ppc64 = ; 439 } 440 441 case * : 442 if $(osx-version) && ! [ version.version-less [ regex.split $(osx-version) \\. ] : 10 6 ] 443 { 444 # When targeting 10.6: 445 # - gcc 4.2 will give a compiler errir if ppc64 compilation is requested 446 # - gcc 4.0 will compile fine, somehow, but then fail at link time 447 support-ppc64 = ; 448 } 449 } 450 switch $(arch) 451 { 452 case combined : 453 { 454 if $(address-model) = 32_64 { 455 if $(support-ppc64) { 456 options = -arch i386 -arch ppc -arch x86_64 -arch ppc64 ; 457 } else { 458 # Build 3-way binary 459 options = -arch i386 -arch ppc -arch x86_64 ; 460 } 461 } else if $(address-model) = 64 { 462 if $(support-ppc64) { 463 options = -arch x86_64 -arch ppc64 ; 464 } else { 465 errors.user-error "64-bit PPC compilation is not supported when targeting OSX 10.6 or later" ; 466 } 467 } else { 468 options = -arch i386 -arch ppc ; 469 } 470 } 471 472 case x86 : 473 { 474 if $(address-model) = 32_64 { 475 options = -arch i386 -arch x86_64 ; 476 } else if $(address-model) = 64 { 477 options = -arch x86_64 ; 478 } else { 479 options = -arch i386 ; 480 } 481 } 482 483 case power : 484 { 485 if ! $(support-ppc64) 486 && ( $(address-model) = 32_64 || $(address-model) = 64 ) 487 { 488 errors.user-error "64-bit PPC compilation is not supported when targeting OSX 10.6 or later" ; 489 } 490 491 if $(address-model) = 32_64 { 492 options = -arch ppc -arch ppc64 ; 493 } else if $(address-model) = 64 { 494 options = -arch ppc64 ; 495 } else { 496 options = -arch ppc ; 497 } 498 } 499 500 case arm : 501 { 502 if $(instruction-set) { 503 options = -arch$(_)$(instruction-set) ; 504 } else { 505 options = -arch arm ; 506 } 507 } 508 } 509 510 if $(options) 511 { 512 OPTIONS on $(targets) += $(options) ; 513 } 514} 515 516rule compile.m ( targets * : sources * : properties * ) 517{ 518 LANG on $(<) = "-x objective-c" ; 519 gcc.set-fpic-options $(targets) : $(sources) : $(properties) ; 520 setup-address-model $(targets) : $(sources) : $(properties) ; 521} 522 523actions compile.m 524{ 525 "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" 526} 527 528rule compile.mm ( targets * : sources * : properties * ) 529{ 530 LANG on $(<) = "-x objective-c++" ; 531 gcc.set-fpic-options $(targets) : $(sources) : $(properties) ; 532 setup-address-model $(targets) : $(sources) : $(properties) ; 533} 534 535actions compile.mm 536{ 537 "$(CONFIG_COMMAND)" $(LANG) $(OPTIONS) $(USER_OPTIONS) -D$(DEFINES) -I"$(INCLUDES)" -c -o "$(<)" "$(>)" 538} 539 540# Set the max header padding to allow renaming of libs for installation. 541flags darwin.link.dll OPTIONS : -headerpad_max_install_names ; 542 543# To link the static runtime we need to link to all the core runtime libraries. 544flags darwin.link OPTIONS <runtime-link>static 545 : -nodefaultlibs -shared-libgcc -lstdc++-static -lgcc_eh -lgcc -lSystem ; 546 547# Strip as much as possible when optimizing. 548flags darwin.link OPTIONS <optimization>speed : -Wl,-dead_strip -no_dead_strip_inits_and_terms ; 549flags darwin.link OPTIONS <optimization>space : -Wl,-dead_strip -no_dead_strip_inits_and_terms ; 550 551# Dynamic/shared linking. 552flags darwin.compile OPTIONS <link>shared : -dynamic ; 553 554# Misc options. 555flags darwin.compile OPTIONS : -gdwarf-2 -fexceptions ; 556#~ flags darwin.link OPTIONS : -fexceptions ; 557 558# Add the framework names to use. 559flags darwin.link FRAMEWORK <framework> ; 560 561# 562flags darwin.link FORCE_LOAD <force-load> ; 563 564# This is flag is useful for debugging the link step 565# uncomment to see what libtool is doing under the hood 566#~ flags darwin.link.dll OPTIONS : -Wl,-v ; 567 568# set up the -F option to include the paths to any frameworks used. 569local rule prepare-framework-path ( target + ) 570{ 571 # The -framework option only takes basename of the framework. 572 # The -F option specifies the directories where a framework 573 # is searched for. So, if we find <framework> feature 574 # with some path, we need to generate property -F option. 575 local framework-paths = [ on $(target) return $(FRAMEWORK:D) ] ; 576 577 # Be sure to generate no -F if there's no path. 578 for local framework-path in $(framework-paths) 579 { 580 if $(framework-path) != "" 581 { 582 FRAMEWORK_PATH on $(target) += -F$(framework-path) ; 583 } 584 } 585} 586 587rule link ( targets * : sources * : properties * ) 588{ 589 DEPENDS $(targets) : [ on $(targets) return $(FORCE_LOAD) ] ; 590 setup-address-model $(targets) : $(sources) : $(properties) ; 591 prepare-framework-path $(<) ; 592} 593 594# Note that using strip without any options was reported to result in broken 595# binaries, at least on OS X 10.5.5, see: 596# http://svn.boost.org/trac/boost/ticket/2347 597# So we pass -S -x. 598actions link bind LIBRARIES FORCE_LOAD 599{ 600 "$(CONFIG_COMMAND)" -L"$(LINKPATH)" -o "$(<)" "$(>)" -Wl,-force_load$(_)"$(FORCE_LOAD)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(FRAMEWORK_PATH) -framework$(_)$(FRAMEWORK:D=:S=) $(OPTIONS) $(USER_OPTIONS) 601 $(NEED_STRIP)"$(.STRIP)" $(NEED_STRIP)-S $(NEED_STRIP)-x $(NEED_STRIP)"$(<)" 602} 603 604rule link.dll ( targets * : sources * : properties * ) 605{ 606 setup-address-model $(targets) : $(sources) : $(properties) ; 607 prepare-framework-path $(<) ; 608} 609 610actions link.dll bind LIBRARIES 611{ 612 "$(CONFIG_COMMAND)" -dynamiclib -Wl,-single_module -install_name "$(<:B)$(<:S)" -L"$(LINKPATH)" -o "$(<)" "$(>)" "$(LIBRARIES)" -l$(FINDLIBS-SA) -l$(FINDLIBS-ST) $(FRAMEWORK_PATH) -framework$(_)$(FRAMEWORK:D=:S=) $(OPTIONS) $(USER_OPTIONS) 613} 614 615# We use libtool instead of ar to support universal binary linking 616# TODO: Find a way to use the underlying tools, i.e. lipo, to do this. 617actions piecemeal archive 618{ 619 "$(.LIBTOOL)" -static -o "$(<:T)" $(ARFLAGS) "$(>:T)" 620} 621