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