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 VALID_TOOLCHAINS ?= pnacl 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) pnacl newlib glibc,$(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 Release configuration. When debugging via "make debug", 105 # build the debug configuration by default instead. 106 # 107 ifneq (,$(findstring debug,$(MAKECMDGOALS))) 108 CONFIG ?= Debug 109 else 110 CONFIG ?= Release 111 endif 112 113 114 # 115 # Verify we selected a valid configuration for this example. 116 # 117 VALID_CONFIGS ?= Debug Release 118 ifeq (,$(findstring $(CONFIG),$(VALID_CONFIGS))) 119 $(warning Availbile choices are: $(VALID_CONFIGS)) 120 $(error Can not use CONFIG=$(CONFIG) on this example.) 121 endif 122 123 124 # 125 # Note for Windows: 126 # The GCC and LLVM toolchains (include the version of Make.exe that comes 127 # with the SDK) expect and are capable of dealing with the '/' seperator. 128 # For this reason, the tools in the SDK, including Makefiles and build scripts 129 # have a preference for POSIX style command-line arguments. 130 # 131 # Keep in mind however that the shell is responsible for command-line escaping, 132 # globbing, and variable expansion, so those may change based on which shell 133 # is used. For Cygwin shells this can include automatic and incorrect expansion 134 # of response files (files starting with '@'). 135 # 136 # Disable DOS PATH warning when using Cygwin based NaCl tools on Windows. 137 # 138 ifeq ($(OSNAME),win) 139 CYGWIN?=nodosfilewarning 140 export CYGWIN 141 endif 142 143 144 # 145 # If NACL_SDK_ROOT is not already set, then set it relative to this makefile. 146 # 147 THIS_MAKEFILE := $(CURDIR)/$(lastword $(MAKEFILE_LIST)) 148 NACL_SDK_ROOT ?= $(realpath $(dir $(THIS_MAKEFILE))/..) 149 150 151 # 152 # Check that NACL_SDK_ROOT is set to a valid location. 153 # We use the existence of tools/oshelpers.py to verify the validity of the SDK 154 # root. 155 # 156 ifeq (,$(wildcard $(NACL_SDK_ROOT)/tools/oshelpers.py)) 157 $(error NACL_SDK_ROOT is set to an invalid location: $(NACL_SDK_ROOT)) 158 endif 159 160 161 # 162 # If this makefile is part of a valid nacl SDK, but NACL_SDK_ROOT is set 163 # to a different location this is almost certainly a local configuration 164 # error. 165 # 166 LOCAL_ROOT := $(realpath $(dir $(THIS_MAKEFILE))/..) 167 ifneq (,$(wildcard $(LOCAL_ROOT)/tools/oshelpers.py)) 168 ifneq ($(realpath $(NACL_SDK_ROOT)), $(realpath $(LOCAL_ROOT))) 169 $(error common.mk included from an SDK that does not match the current NACL_SDK_ROOT) 170 endif 171 endif 172 173 174 # 175 # Alias for standard POSIX file system commands 176 # 177 OSHELPERS = python $(NACL_SDK_ROOT)/tools/oshelpers.py 178 WHICH := $(OSHELPERS) which 179 ifdef V 180 RM := $(OSHELPERS) rm 181 CP := $(OSHELPERS) cp 182 MKDIR := $(OSHELPERS) mkdir 183 MV := $(OSHELPERS) mv 184 else 185 RM := @$(OSHELPERS) rm 186 CP := @$(OSHELPERS) cp 187 MKDIR := @$(OSHELPERS) mkdir 188 MV := @$(OSHELPERS) mv 189 endif 190 191 192 193 # 194 # Compute path to requested NaCl Toolchain 195 # 196 TC_PATH := $(abspath $(NACL_SDK_ROOT)/toolchain) 197 198 199 # 200 # Check for required minimum SDK version. 201 # 202 ifdef NACL_SDK_VERSION_MIN 203 VERSION_CHECK:=$(shell $(GETOS) --check-version=$(NACL_SDK_VERSION_MIN) 2>&1) 204 ifneq ($(VERSION_CHECK),) 205 $(error $(VERSION_CHECK)) 206 endif 207 endif 208 209 210 # 211 # The default target 212 # 213 # If no targets are specified on the command-line, the first target listed in 214 # the makefile becomes the default target. By convention this is usually called 215 # the 'all' target. Here we leave it blank to be first, but define it later 216 # 217 all: 218 .PHONY: all 219 220 221 # 222 # The install target is used to install built libraries to thier final destination. 223 # By default this is the NaCl SDK 'lib' folder. 224 # 225 install: 226 .PHONY: install 227 228 ifdef SEL_LDR 229 STANDALONE = 1 230 endif 231 232 OUTBASE ?= . 233 ifdef STANDALONE 234 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/standalone_$(CONFIG) 235 else 236 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/$(CONFIG) 237 endif 238 STAMPDIR ?= $(OUTDIR) 239 LIBDIR ?= $(NACL_SDK_ROOT)/lib 240 241 242 # 243 # Target to remove temporary files 244 # 245 .PHONY: clean 246 clean: 247 $(RM) -f $(TARGET).nmf 248 $(RM) -rf $(OUTDIR) 249 $(RM) -rf user-data-dir 250 251 252 # 253 # Rules for output directories. 254 # 255 # Output will be places in a directory name based on Toolchain and configuration 256 # be default this will be "newlib/Debug". We use a python wrapped MKDIR to 257 # proivde a cross platform solution. The use of '|' checks for existance instead 258 # of timestamp, since the directory can update when files change. 259 # 260 %dir.stamp : 261 $(MKDIR) -p $(dir $@) 262 @echo Directory Stamp > $@ 263 264 265 # 266 # Dependency Macro 267 # 268 # $1 = Name of stamp 269 # $2 = Directory for the sub-make 270 # $3 = Extra Settings 271 # 272 define DEPEND_RULE 273 ifndef IGNORE_DEPS 274 .PHONY: rebuild_$(1) 275 276 rebuild_$(1) :| $(STAMPDIR)/dir.stamp 277 ifeq (,$(2)) 278 +$(MAKE) -C $(NACL_SDK_ROOT)/src/$(1) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3) 279 else 280 +$(MAKE) -C $(2) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3) 281 endif 282 283 all: rebuild_$(1) 284 $(STAMPDIR)/$(1).stamp: rebuild_$(1) 285 286 else 287 288 .PHONY: $(STAMPDIR)/$(1).stamp 289 $(STAMPDIR)/$(1).stamp: 290 @echo Ignore $(1) 291 endif 292 endef 293 294 ifeq ($(TOOLCHAIN),win) 295 ifdef STANDALONE 296 HOST_EXT = .exe 297 else 298 HOST_EXT = .dll 299 endif 300 else 301 ifdef STANDALONE 302 HOST_EXT = 303 else 304 HOST_EXT = .so 305 endif 306 endif 307 308 309 # 310 # Common Compile Options 311 # 312 # For example, -DNDEBUG is added to release builds by default 313 # so that calls to assert(3) are not included in the build. 314 # 315 ifeq ($(CONFIG),Release) 316 POSIX_FLAGS ?= -g -O2 -pthread -MMD -DNDEBUG 317 NACL_LDFLAGS ?= -O2 318 PNACL_LDFLAGS ?= -O2 319 else 320 POSIX_FLAGS ?= -g -O0 -pthread -MMD -DNACL_SDK_DEBUG 321 endif 322 323 ifdef STANDALONE 324 POSIX_FLAGS += -DSEL_LDR=1 325 endif 326 327 NACL_CFLAGS ?= -Wno-long-long -Werror 328 NACL_CXXFLAGS ?= -Wno-long-long -Werror 329 NACL_LDFLAGS += -Wl,-as-needed -pthread 330 331 # 332 # Default Paths 333 # 334 ifeq (,$(findstring $(TOOLCHAIN),linux mac win)) 335 INC_PATHS ?= $(NACL_SDK_ROOT)/include $(NACL_SDK_ROOT)/include/$(TOOLCHAIN) $(EXTRA_INC_PATHS) 336 else 337 INC_PATHS ?= $(NACL_SDK_ROOT)/include/$(OSNAME) $(NACL_SDK_ROOT)/include $(EXTRA_INC_PATHS) 338 endif 339 340 LIB_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 # 353 ifdef V 354 define LOG 355 $(3) 356 endef 357 else 358 ifeq ($(OSNAME),win) 359 define LOG 360 @echo $(1) $(2) && $(3) 361 endef 362 else 363 define LOG 364 @echo " $(1) $(2)" && $(3) 365 endef 366 endif 367 endif 368 369 370 # 371 # Convert a source path to a object file path. 372 # 373 # $1 = Source Name 374 # $2 = Arch suffix 375 # 376 define SRC_TO_OBJ 377 $(OUTDIR)/$(basename $(subst ..,__,$(1)))$(2).o 378 endef 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 # 392 define SRC_TO_DEP 393 $(patsubst %.o,%.deps,$(call SRC_TO_OBJ,$(1),$(2))) 394 endef 395 396 # 397 # The gcc-generated deps files end in .d 398 # 399 define SRC_TO_DEP_PRE_FIXUP 400 $(patsubst %.o,%.d,$(call SRC_TO_OBJ,$(1),$(2))) 401 endef 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 # 409 ifneq (,$(findstring $(TOOLCHAIN),linux mac)) 410 include $(NACL_SDK_ROOT)/tools/host_gcc.mk 411 endif 412 413 ifneq (,$(findstring $(TOOLCHAIN),win)) 414 include $(NACL_SDK_ROOT)/tools/host_vc.mk 415 endif 416 417 ifneq (,$(findstring $(TOOLCHAIN),glibc newlib)) 418 include $(NACL_SDK_ROOT)/tools/nacl_gcc.mk 419 endif 420 421 ifneq (,$(findstring $(TOOLCHAIN),pnacl)) 422 include $(NACL_SDK_ROOT)/tools/nacl_llvm.mk 423 endif 424 425 # 426 # File to redirect to to in order to hide output. 427 # 428 ifeq ($(OSNAME),win) 429 DEV_NULL = nul 430 else 431 DEV_NULL = /dev/null 432 endif 433 434 435 # 436 # Variables for running examples with Chrome. 437 # 438 RUN_PY := python $(NACL_SDK_ROOT)/tools/run.py 439 HTTPD_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 445 CHROME_ENV ?= 446 447 # Additional arguments to pass to Chrome. 448 CHROME_ARGS += --enable-nacl --enable-pnacl --no-first-run 449 CHROME_ARGS += --user-data-dir=$(CURDIR)/user-data-dir 450 451 452 # Paths to Debug and Release versions of the Host Pepper plugins 453 PPAPI_DEBUG = $(abspath $(OSNAME)/Debug/$(TARGET)$(HOST_EXT));application/x-ppapi-debug 454 PPAPI_RELEASE = $(abspath $(OSNAME)/Release/$(TARGET)$(HOST_EXT));application/x-ppapi-release 455 456 457 SYSARCH := $(shell $(GETOS) --nacl-arch) 458 SEL_LDR_PATH := python $(NACL_SDK_ROOT)/tools/sel_ldr.py 459 460 # 461 # Common Compile Options 462 # 463 ifeq ($(CONFIG),Debug) 464 SEL_LDR_ARGS += --debug-libs 465 endif 466 467 ifndef STANDALONE 468 # 469 # Assign a sensible default to CHROME_PATH. 470 # 471 CHROME_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 477 NULL := 478 SPACE := $(NULL) # one space after NULL is required 479 CHROME_PATH_ESCAPE := $(subst $(SPACE),\ ,$(CHROME_PATH)) 480 481 .PHONY: check_for_chrome 482 check_for_chrome: 483 ifeq (,$(wildcard $(CHROME_PATH_ESCAPE))) 484 $(warning No valid Chrome found at CHROME_PATH=$(CHROME_PATH)) 485 $(error Set CHROME_PATH via an environment variable, or command-line.) 486 else 487 $(warning Using chrome at: $(CHROME_PATH)) 488 endif 489 PAGE ?= index.html 490 PAGE_TC_CONFIG ?= "$(PAGE)?tc=$(TOOLCHAIN)&config=$(CONFIG)" 491 492 .PHONY: run 493 run: check_for_chrome all $(PAGE) 494 $(RUN_PY) -C $(CURDIR) -P $(PAGE_TC_CONFIG) \ 495 $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH_ESCAPE) \ 496 $(CHROME_ARGS) --no-sandbox \ 497 --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)" 498 499 .PHONY: run_package 500 run_package: check_for_chrome all 501 @echo "$(TOOLCHAIN) $(CONFIG)" > $(CURDIR)/run_package_config 502 $(CHROME_PATH_ESCAPE) --load-and-launch-app=$(CURDIR) $(CHROME_ARGS) 503 504 GDB_ARGS += -D $(TC_PATH)/$(OSNAME)_x86_newlib/bin/x86_64-nacl-gdb 505 GDB_ARGS += -D --eval-command="nacl-manifest $(abspath $(OUTDIR))/$(TARGET).nmf" 506 GDB_ARGS += -D $(GDB_DEBUG_TARGET) 507 508 .PHONY: debug 509 debug: check_for_chrome all $(PAGE) 510 $(RUN_PY) $(GDB_ARGS) \ 511 -C $(CURDIR) -P $(PAGE_TC_CONFIG) \ 512 $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH_ESCAPE) \ 513 $(CHROME_ARGS) --enable-nacl-debug \ 514 --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)" 515 516 .PHONY: serve 517 serve: all 518 $(HTTPD_PY) -C $(CURDIR) 519 endif 520 521 # uppercase aliases (for backward compatibility) 522 .PHONY: CHECK_FOR_CHROME DEBUG LAUNCH RUN 523 CHECK_FOR_CHROME: check_for_chrome 524 DEBUG: debug 525 LAUNCH: run 526 RUN: run 527 528 endif # TOOLCHAIN is valid... 529 530 endif # TOOLCHAIN=all 531