common.mk revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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#
12# Toolchain
13#
14# By default the VALID_TOOLCHAINS list contains newlib and glibc.  If your
15# project only builds in one or the other then this should be overridden
16# accordingly.
17#
18VALID_TOOLCHAINS?=newlib glibc
19TOOLCHAIN?=$(word 1,$(VALID_TOOLCHAINS))
20
21
22#
23# Top Make file, which we want to trigger a rebuild on if it changes
24#
25TOP_MAKE:=$(word 1,$(MAKEFILE_LIST))
26
27
28#
29# Figure out which OS we are running on.
30#
31GETOS=python $(NACL_SDK_ROOT)/tools/getos.py
32OSNAME:=$(shell $(GETOS))
33
34
35#
36# Verify we selected a valid toolchain for this example
37#
38ifeq (,$(findstring $(TOOLCHAIN),$(VALID_TOOLCHAINS)))
39  $(warning Availbile choices are: $(VALID_TOOLCHAINS))
40  $(error Can not use TOOLCHAIN=$(TOOLCHAIN) on this example.)
41endif
42
43
44#
45# Build Configuration
46#
47# The SDK provides two sets of libraries, Debug and Release.  Debug libraries
48# are compiled without optimizations to make debugging easier.  By default
49# this will build a Debug configuration.
50#
51CONFIG?=Debug
52
53
54#
55# Note for Windows:
56#   The GCC and LLVM toolchains (include the version of Make.exe that comes
57# with the SDK) expect and are capable of dealing with the '/' seperator.
58# For this reason, the tools in the SDK, including Makefiles and build scripts
59# have a preference for POSIX style command-line arguments.
60#
61# Keep in mind however that the shell is responsible for command-line escaping,
62# globbing, and variable expansion, so those may change based on which shell
63# is used.  For Cygwin shells this can include automatic and incorrect expansion
64# of response files (files starting with '@').
65#
66# Disable DOS PATH warning when using Cygwin based NaCl tools on Windows.
67#
68ifeq ($(OSNAME),win)
69  CYGWIN?=nodosfilewarning
70  export CYGWIN
71endif
72
73
74#
75# If NACL_SDK_ROOT is not already set, then set it relative to this makefile.
76#
77THIS_MAKEFILE:=$(CURDIR)/$(lastword $(MAKEFILE_LIST))
78NACL_SDK_ROOT?=$(realpath $(dir $(THIS_MAKEFILE))/..)
79
80
81#
82# Check that NACL_SDK_ROOT is set to a valid location.
83# We use the existence of tools/oshelpers.py to verify the validity of the SDK
84# root.
85#
86ifeq (,$(wildcard $(NACL_SDK_ROOT)/tools/oshelpers.py))
87  $(error NACL_SDK_ROOT is set to an invalid location: $(NACL_SDK_ROOT))
88endif
89
90
91#
92# If this makefile is part of a valid nacl SDK, but NACL_SDK_ROOT is set
93# to a different location this is almost certainly a local configuration
94# error.
95#
96LOCAL_ROOT:=$(realpath $(dir $(THIS_MAKEFILE))/..)
97ifneq (,$(wildcard $(LOCAL_ROOT)/tools/oshelpers.py))
98  ifneq ($(realpath $(NACL_SDK_ROOT)), $(realpath $(LOCAL_ROOT)))
99    $(error common.mk included from an SDK that does not match the current NACL_SDK_ROOT)
100  endif
101endif
102
103
104#
105# Alias for standard POSIX file system commands
106#
107OSHELPERS=python $(NACL_SDK_ROOT)/tools/oshelpers.py
108WHICH:=$(OSHELPERS) which
109ifdef V
110RM:=$(OSHELPERS) rm
111CP:=$(OSHELPERS) cp
112MKDIR:=$(OSHELPERS) mkdir
113MV:=$(OSHELPERS) mv
114else
115RM:=@$(OSHELPERS) rm
116CP:=@$(OSHELPERS) cp
117MKDIR:=@$(OSHELPERS) mkdir
118MV:=@$(OSHELPERS) mv
119endif
120
121
122
123#
124# Compute path to requested NaCl Toolchain
125#
126TC_PATH:=$(abspath $(NACL_SDK_ROOT)/toolchain)
127
128
129#
130# Check for required minimum SDK version.
131#
132ifdef NACL_SDK_VERSION_MIN
133  VERSION_CHECK:=$(shell $(GETOS) --check-version=$(NACL_SDK_VERSION_MIN) 2>&1)
134  ifneq ($(VERSION_CHECK),)
135    $(error $(VERSION_CHECK))
136  endif
137endif
138
139
140#
141# The default target
142#
143# If no targets are specified on the command-line, the first target listed in
144# the makefile becomes the default target.  By convention this is usually called
145# the 'all' target.  Here we leave it blank to be first, but define it later
146#
147all:
148
149
150#
151# Target a toolchain
152#
153# $1 = Toolchain Name
154#
155define TOOLCHAIN_RULE
156.PHONY: all_$(1)
157all_$(1):
158	+$(MAKE) TOOLCHAIN=$(1)
159TOOLCHAIN_LIST+=all_$(1)
160endef
161
162
163#
164# The target for all versions
165#
166USABLE_TOOLCHAINS=$(filter $(OSNAME) newlib glibc pnacl,$(VALID_TOOLCHAINS))
167
168ifeq ($(NO_HOST_BUILDS),1)
169USABLE_TOOLCHAINS:=$(filter-out $(OSNAME),$(USABLE_TOOLCHAINS))
170endif
171
172$(foreach tool,$(USABLE_TOOLCHAINS),$(eval $(call TOOLCHAIN_RULE,$(tool),$(dep))))
173
174.PHONY: all_versions
175all_versions: $(TOOLCHAIN_LIST)
176
177
178OUTBASE?=.
179OUTDIR:=$(OUTBASE)/$(TOOLCHAIN)/$(CONFIG)
180STAMPDIR?=$(OUTDIR)
181LIBDIR?=$(NACL_SDK_ROOT)/lib
182
183
184#
185# Target to remove temporary files
186#
187.PHONY: clean
188clean:
189	$(RM) -f $(TARGET).nmf
190	$(RM) -fr $(OUTDIR)
191
192
193#
194# Rules for output directories.
195#
196# Output will be places in a directory name based on Toolchain and configuration
197# be default this will be "newlib/Debug".  We use a python wrapped MKDIR to
198# proivde a cross platform solution. The use of '|' checks for existance instead
199# of timestamp, since the directory can update when files change.
200#
201%dir.stamp :
202	$(MKDIR) -p $(dir $@)
203	@echo Directory Stamp > $@
204
205
206#
207# Dependency Macro
208#
209# $1 = Name of stamp
210# $2 = Directory for the sub-make
211# $3 = Extra Settings
212#
213define DEPEND_RULE
214ifndef $(IGNORE_DEPS)
215.PHONY : rebuild_$(1)
216
217rebuild_$(1) :| $(STAMPDIR)/dir.stamp
218ifeq (,$(2))
219	+$(MAKE) -C $(NACL_SDK_ROOT)/src/$(1) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3)
220else
221	+$(MAKE) -C $(2) STAMPDIR=$(abspath $(STAMPDIR)) $(abspath $(STAMPDIR)/$(1).stamp) $(3)
222endif
223
224all: rebuild_$(1)
225$(STAMPDIR)/$(1).stamp : rebuild_$(1)
226
227else
228
229.PHONY : $(STAMPDIR)/$(1).stamp
230$(STAMPDIR)/$(1).stamp :
231	@echo Ignore $(1)
232endif
233endef
234
235
236ifeq ($(TOOLCHAIN),win)
237HOST_EXT=.dll
238else
239HOST_EXT=.so
240endif
241
242
243#
244# Common Compile Options
245#
246ifeq ($(CONFIG),Release)
247POSIX_FLAGS?=-g -O2 -pthread -MMD
248else
249POSIX_FLAGS?=-g -O0 -pthread -MMD -DNACL_SDK_DEBUG
250endif
251
252NACL_CFLAGS?=-Wno-long-long -Werror
253NACL_CXXFLAGS?=-Wno-long-long -Werror
254NACL_LDFLAGS?=-Wl,-as-needed
255
256#
257# Default Paths
258#
259ifeq (,$(findstring $(TOOLCHAIN),linux mac win))
260INC_PATHS?=$(NACL_SDK_ROOT)/include $(EXTRA_INC_PATHS)
261else
262INC_PATHS?=$(NACL_SDK_ROOT)/include/$(OSNAME) $(NACL_SDK_ROOT)/include $(EXTRA_INC_PATHS)
263endif
264
265LIB_PATHS?=$(NACL_SDK_ROOT)/lib $(EXTRA_LIB_PATHS)
266
267#
268# Define a LOG macro that allow a command to be run in quiet mode where
269# the command echoed is not the same as the actual command executed.
270# The primary use case for this is to avoid echoing the full compiler
271# and linker command in the default case.  Defining V=1 will restore
272# the verbose behavior
273#
274# $1 = The name of the tool being run
275# $2 = The target file being built
276# $3 = The full command to run
277#
278ifdef V
279define LOG
280$(3)
281endef
282else
283ifeq ($(OSNAME),win)
284define LOG
285@echo   $(1) $(2) && $(3)
286endef
287else
288define LOG
289@echo "  $(1) $(2)" && $(3)
290endef
291endif
292endif
293
294
295#
296# Convert a source path to a object file path.
297#
298# $1 = Source Name
299# $2 = Arch suffix
300#
301define SRC_TO_OBJ
302$(OUTDIR)/$(basename $(subst ..,__,$(1)))$(2).o
303endef
304
305
306#
307# Convert a source path to a dependency file path.
308#
309# $1 = Source Name
310# $2 = Arch suffix
311#
312define SRC_TO_DEP
313$(patsubst %.o,%.d,$(call SRC_TO_OBJ,$(1),$(2)))
314endef
315
316
317#
318# If the requested toolchain is a NaCl or PNaCl toolchain, the use the
319# macros and targets defined in nacl.mk, otherwise use the host sepecific
320# macros and targets.
321#
322ifneq (,$(findstring $(TOOLCHAIN),linux mac))
323include $(NACL_SDK_ROOT)/tools/host_gcc.mk
324endif
325
326ifneq (,$(findstring $(TOOLCHAIN),win))
327include $(NACL_SDK_ROOT)/tools/host_vc.mk
328endif
329
330ifneq (,$(findstring $(TOOLCHAIN),glibc newlib))
331include $(NACL_SDK_ROOT)/tools/nacl_gcc.mk
332endif
333
334ifneq (,$(findstring $(TOOLCHAIN),pnacl))
335include $(NACL_SDK_ROOT)/tools/nacl_llvm.mk
336endif
337
338#
339# File to redirect to to in order to hide output.
340#
341ifeq ($(OSNAME),win)
342DEV_NULL=nul
343else
344DEV_NULL=/dev/null
345endif
346
347#
348# Assign a sensible default to CHROME_PATH.
349#
350CHROME_PATH?=$(shell python $(NACL_SDK_ROOT)/tools/getos.py --chrome 2> $(DEV_NULL))
351
352#
353# Verify we can find the Chrome executable if we need to launch it.
354#
355.PHONY: check_for_chrome
356check_for_chrome:
357ifeq (,$(wildcard $(CHROME_PATH)))
358	$(warning No valid Chrome found at CHROME_PATH=$(CHROME_PATH))
359	$(error Set CHROME_PATH via an environment variable, or command-line.)
360else
361	$(warning Using chrome at: $(CHROME_PATH))
362endif
363
364
365#
366# Variables for running examples with Chrome.
367#
368RUN_PY:=python $(NACL_SDK_ROOT)/tools/run.py
369
370# Add this to launch Chrome with additional environment variables defined.
371# Each element should be specified as KEY=VALUE, with whitespace separating
372# key-value pairs. e.g.
373# CHROME_ENV=FOO=1 BAR=2 BAZ=3
374CHROME_ENV?=
375
376# Additional arguments to pass to Chrome.
377CHROME_ARGS+=--enable-nacl --enable-pnacl --incognito --ppapi-out-of-process
378
379
380# Paths to Debug and Release versions of the Host Pepper plugins
381PPAPI_DEBUG=$(abspath $(OSNAME)/Debug/$(TARGET)$(HOST_EXT));application/x-ppapi-debug
382PPAPI_RELEASE=$(abspath $(OSNAME)/Release/$(TARGET)$(HOST_EXT));application/x-ppapi-release
383
384
385PAGE?=index.html
386PAGE_TC_CONFIG="$(PAGE)?tc=$(TOOLCHAIN)&config=$(CONFIG)"
387
388.PHONY: run
389run: check_for_chrome all
390ifeq (,$(wildcard $(PAGE)))
391	$(error No valid HTML page found at $(PAGE))
392endif
393	$(RUN_PY) -C $(CURDIR) -P $(PAGE_TC_CONFIG) \
394	    $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH) $(CHROME_ARGS) \
395	    --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)"
396
397.PHONY: run_package
398run_package: check_for_chrome all
399	$(CHROME_PATH) --load-and-launch-app=$(CURDIR) --enable-nacl --enable-pnacl
400
401
402SYSARCH=$(shell python $(NACL_SDK_ROOT)/tools/getos.py --nacl-arch)
403GDB_ARGS+=-D $(TC_PATH)/$(OSNAME)_x86_$(TOOLCHAIN)/bin/$(SYSARCH)-nacl-gdb
404GDB_ARGS+=-D $(abspath $(OUTDIR))/$(TARGET)_$(SYSARCH).nexe
405
406.PHONY: debug
407debug: check_for_chrome all
408	$(RUN_PY) $(GDB_ARGS) \
409	    -C $(CURDIR) -P $(PAGE_TC_CONFIG) \
410	    $(addprefix -E ,$(CHROME_ENV)) -- $(CHROME_PATH) $(CHROME_ARGS) \
411	    --enable-nacl-debug \
412	    --register-pepper-plugins="$(PPAPI_DEBUG),$(PPAPI_RELEASE)"
413
414
415# uppercase aliases (for backward compatibility)
416.PHONY: CHECK_FOR_CHROME DEBUG LAUNCH RUN
417CHECK_FOR_CHROME: check_for_chrome
418DEBUG: debug
419LAUNCH: run
420RUN: run
421