1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 # 6 # GNU Make based build file. For details on GNU Make see: 7 # http://www.gnu.org/software/make/manual/make.html 8 # 9 10 # 11 # Toolchain 12 # 13 # By default the VALID_TOOLCHAINS list contains pnacl, newlib and glibc. If 14 # your project only builds in one or the other then this should be overridden 15 # accordingly. 16 # 17 ifneq ($(ENABLE_BIONIC),) 18 ALL_TOOLCHAINS ?= pnacl newlib glibc bionic 19 else 20 ALL_TOOLCHAINS ?= pnacl newlib glibc 21 endif 22 23 VALID_TOOLCHAINS ?= $(ALL_TOOLCHAINS) 24 TOOLCHAIN ?= $(word 1,$(VALID_TOOLCHAINS)) 25 26 # 27 # Top Make file, which we want to trigger a rebuild on if it changes 28 # 29 TOP_MAKE := $(word 1,$(MAKEFILE_LIST)) 30 31 32 # 33 # Figure out which OS we are running on. 34 # 35 GETOS := python $(NACL_SDK_ROOT)/tools/getos.py 36 NACL_CONFIG := python $(NACL_SDK_ROOT)/tools/nacl_config.py 37 FIXDEPS := python $(NACL_SDK_ROOT)/tools/fix_deps.py -c 38 OSNAME := $(shell $(GETOS)) 39 40 41 # 42 # TOOLCHAIN=all recursively calls this Makefile for all VALID_TOOLCHAINS. 43 # 44 ifeq ($(TOOLCHAIN),all) 45 46 # Define the default target 47 all: 48 49 # 50 # Generate a new MAKE command for each TOOLCHAIN. 51 # 52 # Note: We use targets for each toolchain (instead of an explicit recipe) so 53 # each toolchain can be built in parallel. 54 # 55 # $1 = Toolchain Name 56 # 57 define TOOLCHAIN_RULE 58 TOOLCHAIN_TARGETS += $(1)_TARGET 59 .PHONY: $(1)_TARGET 60 $(1)_TARGET: 61 +$(MAKE) TOOLCHAIN=$(1) $(MAKECMDGOALS) 62 endef 63 64 # 65 # The target for all versions 66 # 67 USABLE_TOOLCHAINS=$(filter $(OSNAME) $(ALL_TOOLCHAINS),$(VALID_TOOLCHAINS)) 68 69 ifeq ($(NO_HOST_BUILDS),1) 70 USABLE_TOOLCHAINS:=$(filter-out $(OSNAME),$(USABLE_TOOLCHAINS)) 71 endif 72 73 # Define the toolchain targets for all usable toolchains via the macro. 74 $(foreach tool,$(USABLE_TOOLCHAINS),$(eval $(call TOOLCHAIN_RULE,$(tool)))) 75 76 .PHONY: all clean install 77 all: $(TOOLCHAIN_TARGETS) 78 clean: $(TOOLCHAIN_TARGETS) 79 install: $(TOOLCHAIN_TARGETS) 80 81 else # TOOLCHAIN=all 82 83 # 84 # Verify we selected a valid toolchain for this example 85 # 86 ifeq (,$(findstring $(TOOLCHAIN),$(VALID_TOOLCHAINS))) 87 88 # Only fail to build if this is a top-level make. When building recursively, we 89 # don't care if an example can't build with this toolchain. 90 ifeq ($(MAKELEVEL),0) 91 $(warning Availbile choices are: $(VALID_TOOLCHAINS)) 92 $(error Can not use TOOLCHAIN=$(TOOLCHAIN) on this example.) 93 else 94 95 # Dummy targets for recursive make with unsupported toolchain... 96 .PHONY: all clean install 97 all: 98 clean: 99 install: 100 101 endif 102 103 else # TOOLCHAIN is valid... 104 105 # 106 # Build Configuration 107 # 108 # The SDK provides two sets of libraries, Debug and Release. Debug libraries 109 # are compiled without optimizations to make debugging easier. By default 110 # this will build a Release configuration. When debugging via "make debug", 111 # build the debug configuration by default instead. 112 # 113 ifneq (,$(findstring debug,$(MAKECMDGOALS))) 114 CONFIG ?= Debug 115 else 116 CONFIG ?= Release 117 endif 118 119 120 # 121 # Verify we selected a valid configuration for this example. 122 # 123 VALID_CONFIGS ?= Debug Release 124 ifeq (,$(findstring $(CONFIG),$(VALID_CONFIGS))) 125 $(warning Availbile choices are: $(VALID_CONFIGS)) 126 $(error Can not use CONFIG=$(CONFIG) on this example.) 127 endif 128 129 130 # 131 # Note for Windows: 132 # The GCC and LLVM toolchains (include the version of Make.exe that comes 133 # with the SDK) expect and are capable of dealing with the '/' seperator. 134 # For this reason, the tools in the SDK, including Makefiles and build scripts 135 # have a preference for POSIX style command-line arguments. 136 # 137 # Keep in mind however that the shell is responsible for command-line escaping, 138 # globbing, and variable expansion, so those may change based on which shell 139 # is used. For Cygwin shells this can include automatic and incorrect expansion 140 # of response files (files starting with '@'). 141 # 142 # Disable DOS PATH warning when using Cygwin based NaCl tools on Windows. 143 # 144 ifeq ($(OSNAME),win) 145 CYGWIN?=nodosfilewarning 146 export CYGWIN 147 endif 148 149 150 # 151 # If NACL_SDK_ROOT is not already set, then set it relative to this makefile. 152 # 153 THIS_MAKEFILE := $(CURDIR)/$(lastword $(MAKEFILE_LIST)) 154 NACL_SDK_ROOT ?= $(realpath $(dir $(THIS_MAKEFILE))/..) 155 156 157 # 158 # Check that NACL_SDK_ROOT is set to a valid location. 159 # We use the existence of tools/oshelpers.py to verify the validity of the SDK 160 # root. 161 # 162 ifeq (,$(wildcard $(NACL_SDK_ROOT)/tools/oshelpers.py)) 163 $(error NACL_SDK_ROOT is set to an invalid location: $(NACL_SDK_ROOT)) 164 endif 165 166 167 # 168 # If this makefile is part of a valid nacl SDK, but NACL_SDK_ROOT is set 169 # to a different location this is almost certainly a local configuration 170 # error. 171 # 172 LOCAL_ROOT := $(realpath $(dir $(THIS_MAKEFILE))/..) 173 ifneq (,$(wildcard $(LOCAL_ROOT)/tools/oshelpers.py)) 174 ifneq ($(realpath $(NACL_SDK_ROOT)), $(realpath $(LOCAL_ROOT))) 175 $(error common.mk included from an SDK that does not match the current NACL_SDK_ROOT) 176 endif 177 endif 178 179 180 # 181 # Alias for standard POSIX file system commands 182 # 183 OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py 184 WHICH := $(OSHELPERS) which 185 ifdef V 186 RM := $(OSHELPERS) rm 187 CP := $(OSHELPERS) cp 188 MKDIR := $(OSHELPERS) mkdir 189 MV := $(OSHELPERS) mv 190 else 191 RM := @$(OSHELPERS) rm 192 CP := @$(OSHELPERS) cp 193 MKDIR := @$(OSHELPERS) mkdir 194 MV := @$(OSHELPERS) mv 195 endif 196 197 198 199 # 200 # Compute path to requested NaCl Toolchain 201 # 202 TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain) 203 204 205 # 206 # Check for required minimum SDK version. 207 # 208 ifdef NACL_SDK_VERSION_MIN 209 VERSION_CHECK:=$(shell $(GETOS) --check-version=$(NACL_SDK_VERSION_MIN) 2>&1) 210 ifneq ($(VERSION_CHECK),) 211 $(error $(VERSION_CHECK)) 212 endif 213 endif 214 215 216 # 217 # The default target 218 # 219 # If no targets are specified on the command-line, the first target listed in 220 # the makefile becomes the default target. By convention this is usually called 221 # the 'all' target. Here we leave it blank to be first, but define it later 222 # 223 all: 224 .PHONY: all 225 226 227 # 228 # The install target is used to install built libraries to thier final destination. 229 # By default this is the NaCl SDK 'lib' folder. 230 # 231 install: 232 .PHONY: install 233 234 ifdef SEL_LDR 235 STANDALONE = 1 236 endif 237 238 OUTBASE ?= . 239 ifdef STANDALONE 240 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/standalone_$(CONFIG) 241 else 242 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/$(CONFIG) 243 endif 244 STAMPDIR ?= $(OUTDIR) 245 LIBDIR ?= $(NACL_SDK_ROOT)/lib 246 247 248 # 249 # Target to remove temporary files 250 # 251 .PHONY: clean 252 clean: 253 $(RM) -f $(TARGET).nmf 254 $(RM) -rf $(OUTDIR) 255 $(RM) -rf user-data-dir 256 257 258 # 259 # Rules for output directories. 260 # 261 # Output will be places in a directory name based on Toolchain and configuration 262 # be default this will be "newlib/Debug". We use a python wrapped MKDIR to 263 # proivde a cross platform solution. The use of '|' checks for existance instead 264 # of timestamp, since the directory can update when files change. 265 # 266 %dir.stamp : 267 $(MKDIR) -p $(dir $@) 268 @echo Directory Stamp > $@ 269 270 271 # 272 # Dependency Macro 273 # 274 # $1 = Name of stamp 275 # $2 = Directory for the sub-make 276 # $3 = Extra Settings 277 # 278 define DEPEND_RULE 279 ifndef IGNORE_DEPS 280 .PHONY: rebuild_$(1) 281 282 rebuild_$(1) :| $(STAMPDIR)/dir.stamp 283 ifeq (,$(2)) 284 +$(MAKE) -C $(NACL_SDK_ROOT)/src/$(1) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3) 285 else 286 +$(MAKE) -C $(2) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3) 287 endif 288 289 all: rebuild_$(1) 290 $(STAMPDIR)/$(1).stamp: rebuild_$(1) 291 292 else 293 294 .PHONY: $(STAMPDIR)/$(1).stamp 295 $(STAMPDIR)/$(1).stamp: 296 @echo Ignore $(1) 297 endif 298 endef 299 300 ifeq ($(TOOLCHAIN),win) 301 ifdef STANDALONE 302 HOST_EXT = .exe 303 else 304 HOST_EXT = .dll 305 endif 306 else 307 ifdef STANDALONE 308 HOST_EXT = 309 else 310 HOST_EXT = .so 311 endif 312 endif 313 314 315 # 316 # Common Compile Options 317 # 318 # For example, -DNDEBUG is added to release builds by default 319 # so that calls to assert(3) are not included in the build. 320 # 321 ifeq ($(CONFIG),Release) 322 POSIX_FLAGS ?= -g -O2 -pthread -MMD -DNDEBUG 323 NACL_LDFLAGS ?= -O2 324 PNACL_LDFLAGS ?= -O2 325 else 326 POSIX_FLAGS ?= -g -O0 -pthread -MMD -DNACL_SDK_DEBUG 327 endif 328 329 ifdef STANDALONE 330 POSIX_FLAGS += -DSEL_LDR=1 331 endif 332 333 NACL_CFLAGS ?= -Wno-long-long -Werror 334 NACL_CXXFLAGS ?= -Wno-long-long -Werror 335 NACL_LDFLAGS += -Wl,-as-needed -pthread 336 337 # 338 # Default Paths 339 # 340 INC_PATHS := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) --include-dirs) $(EXTRA_INC_PATHS) 341 LIB_PATHS := $(NACL_SDK_ROOT)/lib $(EXTRA_LIB_PATHS) 342 343 # 344 # Define a LOG macro that allow a command to be run in quiet mode where 345 # the command echoed is not the same as the actual command executed. 346 # The primary use case for this is to avoid echoing the full compiler 347 # and linker command in the default case. Defining V=1 will restore 348 # the verbose behavior 349 # 350 # $1 = The name of the tool being run 351 # $2 = The target file being built 352 # $3 = The full command to run 353 # 354 ifdef V 355 define LOG 356 $(3) 357 endef 358 else 359 ifeq ($(OSNAME),win) 360 define LOG 361 @echo $(1) $(2) && $(3) 362 endef 363 else 364 define LOG 365 @echo " $(1) $(2)" && $(3) 366 endef 367 endif 368 endif 369 370 371 # 372 # Convert a source path to a object file path. 373 # 374 # $1 = Source Name 375 # $2 = Arch suffix 376 # 377 define SRC_TO_OBJ 378 $(OUTDIR)/$(basename $(subst ..,__,$(1)))$(2).o 379 endef 380 381 382 # 383 # Convert a source path to a dependency file path. 384 # We use the .deps extension for dependencies. These files are generated by 385 # fix_deps.py based on the .d files which gcc generates. We don't reference 386 # the .d files directly so that we can avoid the the case where the compile 387 # failed but still generated a .d file (in that case the .d file would not 388 # be processed by fix_deps.py) 389 # 390 # $1 = Source Name 391 # $2 = Arch suffix 392 # 393 define SRC_TO_DEP 394 $(patsubst %.o,%.deps,$(call SRC_TO_OBJ,$(1),$(2))) 395 endef 396 397 # 398 # The gcc-generated deps files end in .d 399 # 400 define SRC_TO_DEP_PRE_FIXUP 401 $(patsubst %.o,%.d,$(call SRC_TO_OBJ,$(1),$(2))) 402 endef 403 404 405 # 406 # If the requested toolchain is a NaCl or PNaCl toolchain, the use the 407 # macros and targets defined in nacl.mk, otherwise use the host sepecific 408 # macros and targets. 409 # 410 ifneq (,$(findstring $(TOOLCHAIN),linux mac)) 411 include $(NACL_SDK_ROOT)/tools/host_gcc.mk 412 endif 413 414 ifneq (,$(findstring $(TOOLCHAIN),win)) 415 include $(NACL_SDK_ROOT)/tools/host_vc.mk 416 endif 417 418 ifneq (,$(findstring $(TOOLCHAIN),glibc newlib bionic)) 419 include $(NACL_SDK_ROOT)/tools/nacl_gcc.mk 420 endif 421 422 ifneq (,$(findstring $(TOOLCHAIN),pnacl)) 423 include $(NACL_SDK_ROOT)/tools/nacl_llvm.mk 424 endif 425 426 # 427 # File to redirect to to in order to hide output. 428 # 429 ifeq ($(OSNAME),win) 430 DEV_NULL = nul 431 else 432 DEV_NULL = /dev/null 433 endif 434 435 436 # 437 # Variables for running examples with Chrome. 438 # 439 RUN_PY := python $(NACL_SDK_ROOT)/tools/run.py 440 HTTPD_PY := python $(NACL_SDK_ROOT)/tools/httpd.py 441 442 # Add this to launch Chrome with additional environment variables defined. 443 # Each element should be specified as KEY=VALUE, with whitespace separating 444 # key-value pairs. e.g. 445 # CHROME_ENV=FOO=1 BAR=2 BAZ=3 446 CHROME_ENV ?= 447 448 # Additional arguments to pass to Chrome. 449 CHROME_ARGS += --enable-nacl --enable-pnacl --no-first-run 450 CHROME_ARGS += --user-data-dir=$(CURDIR)/user-data-dir 451 452 453 # Paths to Debug and Release versions of the Host Pepper plugins 454 PPAPI_DEBUG = $(abspath $(OSNAME)/Debug/$(TARGET)$(HOST_EXT));application/x-ppapi-debug 455 PPAPI_RELEASE = $(abspath $(OSNAME)/Release/$(TARGET)$(HOST_EXT));application/x-ppapi-release 456 457 458 SYSARCH := $(shell $(GETOS) --nacl-arch) 459 SEL_LDR_PATH := python $(NACL_SDK_ROOT)/tools/sel_ldr.py 460 461 # 462 # Common Compile Options 463 # 464 ifeq ($(CONFIG),Debug) 465 SEL_LDR_ARGS += --debug-libs 466 endif 467 468 ifndef STANDALONE 469 # 470 # Assign a sensible default to CHROME_PATH. 471 # 472 CHROME_PATH ?= $(shell $(GETOS) --chrome 2> $(DEV_NULL)) 473 474 # 475 # Verify we can find the Chrome executable if we need to launch it. 476 # 477 478 NULL := 479 SPACE := $(NULL) # one space after NULL is required 480 ifneq ($(OSNAME),win) 481 CHROME_PATH_ESCAPE := $(subst $(SPACE),\ ,$(CHROME_PATH)) 482 SANDBOX_ARGS := 483 else 484 CHROME_PATH_ESCAPE := $(CHROME_PATH) 485 SANDBOX_ARGS := --no-sandbox 486 endif 487 488 GDB_PATH := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) --tool=gdb) 489 490 .PHONY: check_for_chrome 491 check_for_chrome: 492 ifeq (,$(wildcard $(CHROME_PATH_ESCAPE))) 493 $(warning No valid Chrome found at CHROME_PATH=$(CHROME_PATH)) 494 $(error Set CHROME_PATH via an environment variable, or command-line.) 495 else 496 $(warning Using chrome at: $(CHROME_PATH)) 497 endif 498 PAGE ?= index.html 499 PAGE_TC_CONFIG ?= "$(PAGE)?tc=$(TOOLCHAIN)&config=$(CONFIG)" 500 501 .PHONY: run 502 run: check_for_chrome all $(PAGE) 503 $(RUN_PY) -C $(CURDIR) -P $(PAGE_TC_CONFIG) \ 504 $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH_ESCAPE) \ 505 $(CHROME_ARGS) \ 506 --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)" 507 508 .PHONY: run_package 509 run_package: check_for_chrome all 510 @echo "$(TOOLCHAIN) $(CONFIG)" > $(CURDIR)/run_package_config 511 $(CHROME_PATH_ESCAPE) --load-and-launch-app=$(CURDIR) $(CHROME_ARGS) 512 513 GDB_ARGS += -D $(GDB_PATH) 514 # PNaCl's nexe is acquired with "remote get nexe <path>" instead of the NMF. 515 ifeq (,$(findstring $(TOOLCHAIN),pnacl)) 516 GDB_ARGS += -D --eval-command="nacl-manifest $(abspath $(OUTDIR))/$(TARGET).nmf" 517 GDB_ARGS += -D $(GDB_DEBUG_TARGET) 518 endif 519 520 .PHONY: debug 521 debug: check_for_chrome all $(PAGE) 522 $(RUN_PY) $(GDB_ARGS) \ 523 -C $(CURDIR) -P $(PAGE_TC_CONFIG) \ 524 $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH_ESCAPE) \ 525 $(CHROME_ARGS) $(SANDBOX_ARGS) --enable-nacl-debug \ 526 --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)" 527 528 .PHONY: serve 529 serve: all 530 $(HTTPD_PY) -C $(CURDIR) 531 endif 532 533 # uppercase aliases (for backward compatibility) 534 .PHONY: CHECK_FOR_CHROME DEBUG LAUNCH RUN 535 CHECK_FOR_CHROME: check_for_chrome 536 DEBUG: debug 537 LAUNCH: run 538 RUN: run 539 540 endif # TOOLCHAIN is valid... 541 542 endif # TOOLCHAIN=all 543