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