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