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 #
    208 ifdef NACL_SDK_VERSION_MIN
    209   VERSION_CHECK:=$(shell $(GETOS) --check-version=$(NACL_SDK_VERSION_MIN) 2>&1)
    210   ifneq ($(VERSION_CHECK),)
    211     $(error $(VERSION_CHECK))
    212   endif
    213 endif
    214 
    215 
    216 #
    217 # The default target
    218 #
    219 # If no targets are specified on the command-line, the first target listed in
    220 # the makefile becomes the default target.  By convention this is usually called
    221 # the 'all' target.  Here we leave it blank to be first, but define it later
    222 #
    223 all:
    224 .PHONY: all
    225 
    226 
    227 #
    228 # The install target is used to install built libraries to thier final destination.
    229 # By default this is the NaCl SDK 'lib' folder.
    230 #
    231 install:
    232 .PHONY: install
    233 
    234 ifdef SEL_LDR
    235 STANDALONE = 1
    236 endif
    237 
    238 OUTBASE ?= .
    239 ifdef STANDALONE
    240 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/standalone_$(CONFIG)
    241 else
    242 OUTDIR := $(OUTBASE)/$(TOOLCHAIN)/$(CONFIG)
    243 endif
    244 STAMPDIR ?= $(OUTDIR)
    245 LIBDIR ?= $(NACL_SDK_ROOT)/lib
    246 
    247 
    248 #
    249 # Target to remove temporary files
    250 #
    251 .PHONY: clean
    252 clean:
    253 	$(RM) -f $(TARGET).nmf
    254 	$(RM) -rf $(OUTDIR)
    255 	$(RM) -rf user-data-dir
    256 
    257 
    258 #
    259 # Rules for output directories.
    260 #
    261 # Output will be places in a directory name based on Toolchain and configuration
    262 # be default this will be "newlib/Debug".  We use a python wrapped MKDIR to
    263 # proivde a cross platform solution. The use of '|' checks for existance instead
    264 # of timestamp, since the directory can update when files change.
    265 #
    266 %dir.stamp :
    267 	$(MKDIR) -p $(dir $@)
    268 	@echo Directory Stamp > $@
    269 
    270 
    271 #
    272 # Dependency Macro
    273 #
    274 # $1 = Name of stamp
    275 # $2 = Directory for the sub-make
    276 # $3 = Extra Settings
    277 #
    278 define DEPEND_RULE
    279 ifndef IGNORE_DEPS
    280 .PHONY: rebuild_$(1)
    281 
    282 rebuild_$(1) :| $(STAMPDIR)/dir.stamp
    283 ifeq (,$(2))
    284 	+$(MAKE) -C $(NACL_SDK_ROOT)/src/$(1) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3)
    285 else
    286 	+$(MAKE) -C $(2) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3)
    287 endif
    288 
    289 all: rebuild_$(1)
    290 $(STAMPDIR)/$(1).stamp: rebuild_$(1)
    291 
    292 else
    293 
    294 .PHONY: $(STAMPDIR)/$(1).stamp
    295 $(STAMPDIR)/$(1).stamp:
    296 	@echo Ignore $(1)
    297 endif
    298 endef
    299 
    300 ifeq ($(TOOLCHAIN),win)
    301 ifdef STANDALONE
    302 HOST_EXT = .exe
    303 else
    304 HOST_EXT = .dll
    305 endif
    306 else
    307 ifdef STANDALONE
    308 HOST_EXT =
    309 else
    310 HOST_EXT = .so
    311 endif
    312 endif
    313 
    314 
    315 #
    316 # Common Compile Options
    317 #
    318 # For example, -DNDEBUG is added to release builds by default
    319 # so that calls to assert(3) are not included in the build.
    320 #
    321 ifeq ($(CONFIG),Release)
    322 POSIX_FLAGS ?= -g -O2 -pthread -MMD -DNDEBUG
    323 NACL_LDFLAGS ?= -O2
    324 PNACL_LDFLAGS ?= -O2
    325 else
    326 POSIX_FLAGS ?= -g -O0 -pthread -MMD -DNACL_SDK_DEBUG
    327 endif
    328 
    329 ifdef STANDALONE
    330 POSIX_FLAGS += -DSEL_LDR=1
    331 endif
    332 
    333 NACL_CFLAGS ?= -Wno-long-long -Werror
    334 NACL_CXXFLAGS ?= -Wno-long-long -Werror
    335 NACL_LDFLAGS += -Wl,-as-needed -pthread
    336 
    337 #
    338 # Default Paths
    339 #
    340 INC_PATHS := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) --include-dirs) $(EXTRA_INC_PATHS)
    341 LIB_PATHS := $(NACL_SDK_ROOT)/lib $(EXTRA_LIB_PATHS)
    342 
    343 #
    344 # Define a LOG macro that allow a command to be run in quiet mode where
    345 # the command echoed is not the same as the actual command executed.
    346 # The primary use case for this is to avoid echoing the full compiler
    347 # and linker command in the default case.  Defining V=1 will restore
    348 # the verbose behavior
    349 #
    350 # $1 = The name of the tool being run
    351 # $2 = The target file being built
    352 # $3 = The full command to run
    353 #
    354 ifdef V
    355 define LOG
    356 $(3)
    357 endef
    358 else
    359 ifeq ($(OSNAME),win)
    360 define LOG
    361 @echo   $(1) $(2) && $(3)
    362 endef
    363 else
    364 define LOG
    365 @echo "  $(1) $(2)" && $(3)
    366 endef
    367 endif
    368 endif
    369 
    370 
    371 #
    372 # Convert a source path to a object file path.
    373 #
    374 # $1 = Source Name
    375 # $2 = Arch suffix
    376 #
    377 define SRC_TO_OBJ
    378 $(OUTDIR)/$(basename $(subst ..,__,$(1)))$(2).o
    379 endef
    380 
    381 
    382 #
    383 # Convert a source path to a dependency file path.
    384 # We use the .deps extension for dependencies.  These files are generated by
    385 # fix_deps.py based on the .d files which gcc generates.  We don't reference
    386 # the .d files directly so that we can avoid the the case where the compile
    387 # failed but still generated a .d file (in that case the .d file would not
    388 # be processed by fix_deps.py)
    389 #
    390 # $1 = Source Name
    391 # $2 = Arch suffix
    392 #
    393 define SRC_TO_DEP
    394 $(patsubst %.o,%.deps,$(call SRC_TO_OBJ,$(1),$(2)))
    395 endef
    396 
    397 #
    398 # The gcc-generated deps files end in .d
    399 #
    400 define SRC_TO_DEP_PRE_FIXUP
    401 $(patsubst %.o,%.d,$(call SRC_TO_OBJ,$(1),$(2)))
    402 endef
    403 
    404 
    405 #
    406 # If the requested toolchain is a NaCl or PNaCl toolchain, the use the
    407 # macros and targets defined in nacl.mk, otherwise use the host sepecific
    408 # macros and targets.
    409 #
    410 ifneq (,$(findstring $(TOOLCHAIN),linux mac))
    411 include $(NACL_SDK_ROOT)/tools/host_gcc.mk
    412 endif
    413 
    414 ifneq (,$(findstring $(TOOLCHAIN),win))
    415 include $(NACL_SDK_ROOT)/tools/host_vc.mk
    416 endif
    417 
    418 ifneq (,$(findstring $(TOOLCHAIN),glibc newlib bionic))
    419 include $(NACL_SDK_ROOT)/tools/nacl_gcc.mk
    420 endif
    421 
    422 ifneq (,$(findstring $(TOOLCHAIN),pnacl))
    423 include $(NACL_SDK_ROOT)/tools/nacl_llvm.mk
    424 endif
    425 
    426 #
    427 # File to redirect to to in order to hide output.
    428 #
    429 ifeq ($(OSNAME),win)
    430 DEV_NULL = nul
    431 else
    432 DEV_NULL = /dev/null
    433 endif
    434 
    435 
    436 #
    437 # Variables for running examples with Chrome.
    438 #
    439 RUN_PY := python $(NACL_SDK_ROOT)/tools/run.py
    440 HTTPD_PY := python $(NACL_SDK_ROOT)/tools/httpd.py
    441 
    442 # Add this to launch Chrome with additional environment variables defined.
    443 # Each element should be specified as KEY=VALUE, with whitespace separating
    444 # key-value pairs. e.g.
    445 # CHROME_ENV=FOO=1 BAR=2 BAZ=3
    446 CHROME_ENV ?=
    447 
    448 # Additional arguments to pass to Chrome.
    449 CHROME_ARGS += --enable-nacl --enable-pnacl --no-first-run
    450 CHROME_ARGS += --user-data-dir=$(CURDIR)/user-data-dir
    451 
    452 
    453 # Paths to Debug and Release versions of the Host Pepper plugins
    454 PPAPI_DEBUG = $(abspath $(OSNAME)/Debug/$(TARGET)$(HOST_EXT));application/x-ppapi-debug
    455 PPAPI_RELEASE = $(abspath $(OSNAME)/Release/$(TARGET)$(HOST_EXT));application/x-ppapi-release
    456 
    457 
    458 SYSARCH := $(shell $(GETOS) --nacl-arch)
    459 SEL_LDR_PATH := python $(NACL_SDK_ROOT)/tools/sel_ldr.py
    460 
    461 #
    462 # Common Compile Options
    463 #
    464 ifeq ($(CONFIG),Debug)
    465 SEL_LDR_ARGS += --debug-libs
    466 endif
    467 
    468 ifndef STANDALONE
    469 #
    470 # Assign a sensible default to CHROME_PATH.
    471 #
    472 CHROME_PATH ?= $(shell $(GETOS) --chrome 2> $(DEV_NULL))
    473 
    474 #
    475 # Verify we can find the Chrome executable if we need to launch it.
    476 #
    477 
    478 NULL :=
    479 SPACE := $(NULL) # one space after NULL is required
    480 ifneq ($(OSNAME),win)
    481   CHROME_PATH_ESCAPE := $(subst $(SPACE),\ ,$(CHROME_PATH))
    482   SANDBOX_ARGS :=
    483 else
    484   CHROME_PATH_ESCAPE := $(CHROME_PATH)
    485   SANDBOX_ARGS := --no-sandbox
    486 endif
    487 
    488 GDB_PATH := $(shell $(NACL_CONFIG) -t $(TOOLCHAIN) --tool=gdb)
    489 
    490 .PHONY: check_for_chrome
    491 check_for_chrome:
    492 ifeq (,$(wildcard $(CHROME_PATH_ESCAPE)))
    493 	$(warning No valid Chrome found at CHROME_PATH=$(CHROME_PATH))
    494 	$(error Set CHROME_PATH via an environment variable, or command-line.)
    495 else
    496 	$(warning Using chrome at: $(CHROME_PATH))
    497 endif
    498 PAGE ?= index.html
    499 PAGE_TC_CONFIG ?= "$(PAGE)?tc=$(TOOLCHAIN)&config=$(CONFIG)"
    500 
    501 .PHONY: run
    502 run: check_for_chrome all $(PAGE)
    503 	$(RUN_PY) -C $(CURDIR) -P $(PAGE_TC_CONFIG) \
    504 	    $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH_ESCAPE) \
    505 	    $(CHROME_ARGS) \
    506 	    --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)"
    507 
    508 .PHONY: run_package
    509 run_package: check_for_chrome all
    510 	@echo "$(TOOLCHAIN) $(CONFIG)" > $(CURDIR)/run_package_config
    511 	$(CHROME_PATH_ESCAPE) --load-and-launch-app=$(CURDIR) $(CHROME_ARGS)
    512 
    513 GDB_ARGS += -D $(GDB_PATH)
    514 # PNaCl's nexe is acquired with "remote get nexe <path>" instead of the NMF.
    515 ifeq (,$(findstring $(TOOLCHAIN),pnacl))
    516 GDB_ARGS += -D --eval-command="nacl-manifest $(abspath $(OUTDIR))/$(TARGET).nmf"
    517 GDB_ARGS += -D $(GDB_DEBUG_TARGET)
    518 endif
    519 
    520 .PHONY: debug
    521 debug: check_for_chrome all $(PAGE)
    522 	$(RUN_PY) $(GDB_ARGS) \
    523 	    -C $(CURDIR) -P $(PAGE_TC_CONFIG) \
    524 	    $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH_ESCAPE) \
    525 	    $(CHROME_ARGS) $(SANDBOX_ARGS) --enable-nacl-debug \
    526 	    --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)"
    527 
    528 .PHONY: serve
    529 serve: all
    530 	$(HTTPD_PY) -C $(CURDIR)
    531 endif
    532 
    533 # uppercase aliases (for backward compatibility)
    534 .PHONY: CHECK_FOR_CHROME DEBUG LAUNCH RUN
    535 CHECK_FOR_CHROME: check_for_chrome
    536 DEBUG: debug
    537 LAUNCH: run
    538 RUN: run
    539 
    540 endif  # TOOLCHAIN is valid...
    541 
    542 endif  # TOOLCHAIN=all
    543