Home | History | Annotate | Download | only in tools
      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 # 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 #
    211 ifdef 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
    216 endif
    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 #
    226 all:
    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 #
    234 install:
    235 .PHONY: install
    236 
    237 ifdef SEL_LDR
    238 STANDALONE = 1
    239 endif
    240 
    241 OUTBASE ?= .
    242 ifdef STANDALONE
    243 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/standalone_$(CONFIG)
    244 else
    245 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/$(CONFIG)
    246 endif
    247 STAMPDIR ?= $(OUTDIR)
    248 LIBDIR ?= $(NACL_SDK_ROOT)/lib
    249 
    250 
    251 #
    252 # Target to remove temporary files
    253 #
    254 .PHONY: clean
    255 clean:
    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 #
    281 define DEPEND_RULE
    282 ifndef IGNORE_DEPS
    283 .PHONY: rebuild_$(1)
    284 
    285 rebuild_$(1) :| $(STAMPDIR)/dir.stamp
    286 ifeq (,$(2))
    287 	+$(MAKE) -C $(NACL_SDK_ROOT)/src/$(1) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3)
    288 else
    289 	+$(MAKE) -C $(2) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3)
    290 endif
    291 
    292 all: rebuild_$(1)
    293 $(STAMPDIR)/$(1).stamp: rebuild_$(1)
    294 
    295 else
    296 
    297 .PHONY: $(STAMPDIR)/$(1).stamp
    298 $(STAMPDIR)/$(1).stamp:
    299 	@echo Ignore $(1)
    300 endif
    301 endef
    302 
    303 ifeq ($(TOOLCHAIN),win)
    304 ifdef STANDALONE
    305 HOST_EXT = .exe
    306 else
    307 HOST_EXT = .dll
    308 endif
    309 else
    310 ifdef STANDALONE
    311 HOST_EXT =
    312 else
    313 HOST_EXT = .so
    314 endif
    315 endif
    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 #
    324 ifeq ($(CONFIG),Release)
    325 POSIX_FLAGS ?= -g -O2 -pthread -MMD -DNDEBUG
    326 NACL_LDFLAGS ?= -O2
    327 PNACL_LDFLAGS ?= -O2
    328 else
    329 POSIX_FLAGS ?= -g -O0 -pthread -MMD -DNACL_SDK_DEBUG
    330 endif
    331 
    332 NACL_CFLAGS ?= -Wno-long-long -Werror
    333 NACL_CXXFLAGS ?= -Wno-long-long -Werror
    334 NACL_LDFLAGS += -Wl,-as-needed -pthread
    335 
    336 #
    337 # Default Paths
    338 #
    339 INC_PATHS := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) --include-dirs) $(EXTRA_INC_PATHS)
    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 bionic))
    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 ifneq ($(OSNAME),win)
    480   CHROME_PATH_ESCAPE := $(subst $(SPACE),\ ,$(CHROME_PATH))
    481   SANDBOX_ARGS :=
    482 else
    483   CHROME_PATH_ESCAPE := $(CHROME_PATH)
    484   SANDBOX_ARGS := --no-sandbox
    485 endif
    486 
    487 GDB_PATH := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) --tool=gdb)
    488 
    489 .PHONY: check_for_chrome
    490 check_for_chrome:
    491 ifeq (,$(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.)
    494 else
    495 	$(warning Using chrome at: $(CHROME_PATH))
    496 endif
    497 PAGE ?= index.html
    498 PAGE_TC_CONFIG ?= "$(PAGE)?tc=$(TOOLCHAIN)&config=$(CONFIG)"
    499 
    500 .PHONY: run
    501 run: 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
    508 run_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 
    512 GDB_ARGS += -D $(GDB_PATH)
    513 # PNaCl's nexe is acquired with "remote get nexe <path>" instead of the NMF.
    514 ifeq (,$(findstring $(TOOLCHAIN),pnacl))
    515 GDB_ARGS += -D --eval-command="nacl-manifest $(abspath $(OUTDIR))/$(TARGET).nmf"
    516 GDB_ARGS += -D $(GDB_DEBUG_TARGET)
    517 endif
    518 
    519 .PHONY: debug
    520 debug: 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
    528 serve: all
    529 	$(HTTPD_PY) -C $(CURDIR)
    530 endif
    531 
    532 # uppercase aliases (for backward compatibility)
    533 .PHONY: CHECK_FOR_CHROME DEBUG LAUNCH RUN
    534 CHECK_FOR_CHROME: check_for_chrome
    535 DEBUG: debug
    536 LAUNCH: run
    537 RUN: run
    538 
    539 endif  # TOOLCHAIN is valid...
    540 
    541 endif  # TOOLCHAIN=all
    542