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