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 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