Skip to content

Instantly share code, notes, and snippets.

@chitacan
Last active January 7, 2016 12:51
Show Gist options
  • Save chitacan/7086879 to your computer and use it in GitHub Desktop.
Save chitacan/7086879 to your computer and use it in GitHub Desktop.
octobersky.js v8 스터디 발표자료

make v8

v8 의 Make 를 분석해 보자.

why we need to hack makefile?

어떤 기술을 응용해 무언가를 만들고자 할 때, 필요한 것 중 하나는 그 기술이 어떻게 구성되어 있는지 확인하는 것. 각각의 구성품들을 살펴보며, 새로운 아이디어를 얻을 수 있다.(레고)

오픈소스의 구성품들은 Makefile에 모두 기술되어 있다.

그리고 코드를 어디서 부터 보아야 할 지, 그 시작점을 찾을 수도 있다.

V8 Makefile에 사용된 용어정리

  • nacl : native client
  • ia32 : intel architecture 32bit(x86-32 로도 불림)
  • x64 : 64bit architecture (x86 명령어 셋의 64비트 버전)
  • gyp : generate your project 의 약자로 크로미움 프로젝트에서 visual studio, xcode 용 프로젝트 파일을 생성하기위해 만들어진 툴(각 플랫폼에 맞는 makefile을 생성해 낸다). 파이선으로 이루어져 있으며 메타파일은 JSON과 거의 유사한 포맷을 가진다.

Makefile 알아보기

기본적인 구조

target ... : prerequisites ...
             recipe
             ...
             ...

make는 아래의 5가지 재료로 구성된다.

  • explicit rule
  • implicit rule
  • variable definition(function)
  • directive (contional 등)
  • comments

이런게 있네?

  • PHONY target
    • 타겟을 phony로 지정한다는 것은 타겟은 허구(fictional) 이며 실제 파일을 생성하지 않는 다는 것을 표시하는 것.(참고)
    • clean 과 같이 파일을 생성하지 않는 타겟이 있을 때, 동일 디렉토리에 clean 파일이 생기면 make가 동작하지 않는 것을 막기 위함
    • recursive make를 병렬로 수행하기 위해서는 각 디렉토리별 타겟들을 phony로 선언해야 하는데, 현재 디렉토리에 타겟과 같은 디렉토리가 이미 존재하기 때문이다. (타겟과 동일한 이름이 현재 디렉토리에 있다면 make가 수행되지 않을 수 있다.)
    • special built-in target
  • @ 기호를 사용해 해당라인의 결과만 출력할 수 있다. 예를 들어, 아래의 코드는 hello world 를 출력한다.
    HELLO = 'hellc
         world'
    all : ; @echo $(HELLO)
    
  • make 시 변수의 값을 인자로 전달하기
    • make library=shared 와 같이 실행하면,
    • Makefile 내에서 $(library)로 참조가 가능하다.
  • recipe의 변수를 참조하기 위해서는 double dollar($$)를 사용해야 한다.
  • $$ 은 Secondary Expansion.
  • prerequisites 에 |(pipe) 로 명시되면 왼쪽은 순서에 상관없지만 오른쪽은 순서대로 생성되어야 함(Prerequisite-Types)

debug Makefile

make -pn

  • -p : print internal database, 모든 룰과 변수들을 출력할 수 있다.
  • -n : dry run, 필요한 타겟에 대한 정보들을 출력한다. 하지만 실제로 make를 수행하지는 않는다.
  • 이 두 옵션을 활용하면 makefile을 디버깅하는데 많은 정보를 얻을 수 있으며, 생성된 database 파일은 다음과 같은 정보들이 포함되어 있다.
    • 완전하게 해석된 실행 명령어
    • 변수들(automatic, default)
    • 해석된 룰들(target, prerequisites, recipe)
  • Options-Summary 참고

$(info), $(warning), $(error) 와 같은 출력용 메소드들을 활용. 아래와 같이 사용할 수 있다.

$(info $(GYPFLAGS))

특히 $(error msg) 메소드를 활용해 특정 타겟을 바로 종료하면서, 어떤 파일이 어느 시점에 생성되는지 알 수 있다.

V8의 Makefile 분석

v8을 빌드하기 위해서는 v8 디렉토리에서 아래의 명령어를 실행해야 한다.

$ make dependencies
$ make <TARGET>

v8의 빌드 과정을 간단하게 살펴보면 다음과 같다.

  • 현재 플랫폼에 맞는 환경변수를 설정
  • gyp 를 사용해 Makefile.target 생성
  • 생성된 Makefile.target 으로 빌드 수행

Makefile의 target 설정

make를 실행할때, make로 인해 생성되는 파일들이 어떤 플랫폼을 위한 파일들인지 지정해야 하며, 이를 target 이라고 한다.

주요 target (주석 에서 확인 가능)

target description
default(no target specified) ia32, x64, arm의 release, debug 타겟을 모두 빌드한다.
dependencies gyp, icu46(international components for unicode) 을 설치한다.
native 현재 호스트의 아키텍쳐를 릴리즈 모드로 빌드
android 안드로이드용 바이너리를 빌드
check 생성된 타겟을 테스트한다. 테스트는 tools/run-tests.py로 수행한다.
buildbot buildbot 전용 타겟(gyp buildbot??)
clean 생성된 타겟을 삭제한다.

특정 아키텍쳐 선택(모드가 명시되지 않으면 default로 release, debug 모두 빌드한다.)

[arch].[mode].[check]

(e.g. "ia32.release", "ia32.release.check", "x64.clean")

option description
arch ia32, x64, arm, mipsel
mode release, debug
check check

빌드가 제대로 되었는지는 check 타겟으로 확인한다.

uname -a 로 내 플랫폼의 아키텍쳐 확인

gyp 에 대한 의문

chromium, V8 프로젝트는 기존의 메타 Makefile generator(autoconf, cmake) 를 사용하지 않고 gyp를 사용했을까?(여기 참고)

기존의 툴들은

  • 크로스 플랫폼 제네레이션(윈도우에서 xcode용 프로젝트 생성)을 지원하지 못했다.
  • 커맨드라인 플래그에만 의존해 프로젝트 설정을 조작할 수 있었다.
  • public / private 모듈의 개념이 없었다.

gyp의 실행 옵션은 $ build/gyp/gyp --help 를 통해 확인할 수 있다.

xcode, visual studio 용 프로젝트 파일을 생성하기 위해서는 build\gyp_v8 파일을 실행하자

Makefile 분석

Makefile의 목표는 선택한 타겟의 Makefile.[target] 파일과 컴파일에 필요한 내용들을 out/ 디렉토리에 생성하는 것이다.

예를 들어 아래와 같음 명령어로 make를 수해하면

$ make x64.release

out/Makefile.x64 타겟을 통해 makefile인 Makefile.x64out 디렉토리에 만들어 낸다. 이 때 Makefile.x64를 생성하기 위해 실행되는 코드는 다음과 같다.

	GYP_GENRATORS=make \
	build/gyp/gyp --generator-output="out" build/all.gyp \
	-Ibuild/standalone.gypi --depth=. -S.x64  -Dv8_enable_backtrace=1 -Darm_fpu=default -Darm_float_abi=default

생성된 out 디렉토리의 상세구조를 살펴보면

├── Makefile.x64
├── build
│   ├── All.target.x64.mk
│   └── all.Makefile
├── environment
├── gyp-mac-tool
├── preparser
│   ├── preparser.Makefile
│   └── preparser.target.x64.mk
├── samples
│   ├── lineprocessor.target.x64.mk
│   ├── process.target.x64.mk
│   ├── samples.Makefile
│   └── shell.target.x64.mk
├── src
│   ├── d8.Makefile
│   ├── d8.target.x64.mk
│   └── d8_js2c.target.x64.mk
├── test
│   └── cctest
│       ├── cctest.Makefile
│       ├── cctest.target.x64.mk
│       └── resources.target.x64.mk
└── tools
    └── gyp
        ├── js2c.target.x64.mk
        ├── mksnapshot.x64.target.x64.mk
        ├── postmortem-metadata.target.x64.mk
        ├── v8.Makefile
        ├── v8.target.x64.mk
        ├── v8_base.x64.target.x64.mk
        ├── v8_nosnapshot.x64.target.x64.mk
        ├── v8_shell.target.x64.mk
        └── v8_snapshot.target.x64.mk

Makefile.x64 파일은 x64 타겟을 통해 실행된다.

make -C "out" -f Makefile.x64 \
    CXX="c++" LINK="g++" \
    BUILDTYPE=Release \
    builddir="/Users/chitacan/git/node_project/node/deps/v8/out/x64.release"

all.gyp

all.gyp 파일에는 다른 make 파일들(preparser/preparser.target.x64.mk, samples/shell.target.x64.mk등)을 생성하기 위한 디펜던시들이 더 선언되어 있다.

'../preparser/preparser.gyp:*',
'../samples/samples.gyp:*',
'../src/d8.gyp:d8',
'../test/cctest/cctest.gyp:*',

이 gyp 파일들 읽어 위에서 살펴본 out 디렉토리에 *.mk 파일들이 생성되는 것

Makefile.x64

CC, CFLAGS 등은 Variables Used by Implicit Rules 참고

Command definitions 부터 컴파일에 사용될 커맨드들을 미리 정의

  • c, c++, obj-c, obj-c++ 을 빌드할 커맨드를 미리 만든다.
  • 여기서 선언된 커맨드들은 do_cmd 함수에 의해 호출된다. 모든 컴파일 및 명령어들은 이 함수에 인자를 다르게 전달하여 호출된다.

precompiled header(pch) 용 커맨드도 만든다.

Makefile.x64는 주로 환경변수와 사용하게될 커맨드들을 미리정의하는 데에 사용되며 실제로 모듈들은 include 로 포함되는 다른 Makefile 들에 의해 실행된다.

js2c

out/tools/gyp/js2c.target.x64.mk 타겟으로 js2c.stamp 생성하기 위한 타겟이다.

make -f Makefile.x64 로 실행하면 가장먼저 libraries.cc 파일을 생성해 컴파일하기 시작한다. 이때 libraries.ccout/tools/gyp/js2c.target.x64.mk 에 의해서 컴파일됨

주목해야 할 부분은 tools/js2c.py 인데, 자바스크립트 파일들을 바이너리로 읽어 library.cc 파일의 char array에 추가한다. 이때 추가된 라이브러리들은 V8의 기본적으로 임베디드 되는 라이브러리들 이다.

생성된 libraries.ccout/x64.release/obj/gen/libraries.cc 에서 확인할 수 있다.

v8_base.x64

out/tools/gyp/v8_base.x64.target.x64.mk 의 타겟으로 libv8_base.x64.a 생성하기 위한 타겟이다.

v8_nosnapshot.x64

out/tools/gyp/v8_nosnapshot.x64.target.x64.mk 의 타겟으로 libv8_nosnapshot.x64.a 생성하기 위한 타겟이다.

v8_snapshot

out/tools/gyp/v8_snapshot.target.x64.mk 의 타겟으로 libv8_snapshot.a 생성하기 위한 타겟이다.

d8

뭐 저런 라이브러리들이 out/x64.release 디렉토리에 만들어지고, v8 프로젝트의 실행 바이너리인 d8src/d8.target.x64.mk 에 의해 생성된다.

d8이 만들어지기 위해 필요한 파일들은 d8.o, d8-debug.o, d8-js.o, d8-posix.o, libv8_base.x64.a, libv8_snapshot.a 이며 이들을 만들기 위한 파일들을 살펴보면 다음과 같다.

Prerequisites Prerequisites of Prerequisites
d8.o d8.cc
v8.stamp
d8_js2c.stamp
libv8_base.x64.a
libv8_snapshot.a
js2c.stamp
d8-debug.o d8-debug.cc
v8.stamp
d8_js2c.stamp
libv8_base.x64.a
libv8_snapshot.a
js2c.stamp
libv8_base.x64.a
libv8_snapshot.a
js2c.stamp
d8-posix.o d8-posix.cc
v8.stamp
d8_js2c.stamp
libv8_base.x64.a
libv8_snapshot.a
js2c.stamp
libv8_base.x64.a accessors.o 를 비롯해 좀 많음
libv8_snapshot.a libraries.o
experimental-libraries.o
snapshot.o
snapshot.cc

Prerequisites of Prerequisites 에게 필요한 파일들은 make-x64-database에서 d8.cc: 와 같은 키워드로 검색하면 금방 찾을 수 있다.

IDE 용 프로젝트 파일 생성

build/gyp_v8 파일을 실행하면, build 디렉토리를 포함해 src, preparser 디렉토리에 *.xcodeproj 를 생성해 준다.

build/all.xcodeprojxcode로 열면 열리는데 gyp가 생성한 프로젝트 파일에서는 com.apple.compilers.llvmgcc42 만 쓰게 되어 있어서 욜라 에러가 떨어짐

시작점

d8.ccmain 은 어떨까?

$ gdb -d . --args out/x64.release/d8

궁금증들

  • 생성된 out/gyp-mac-tool 이라는 파이선 스크립트의 정확한 역할은 무엇일까?( flock을 emulate 한다는데...)

flock은 파일에 생성된 lock을 해제시켜주는 듯?

# We borrow heavily from the kernel build setup, though we are simpler since
# we don't have Kconfig tweaking settings on us.
# The implicit make rules have it looking for RCS files, among other things.
# We instead explicitly write all the rules we care about.
# It's even quicker (saves ~200ms) to pass -r on the command line.
MAKEFLAGS=-r
# The source directory tree.
srcdir := ..
abs_srcdir := $(abspath $(srcdir))
# The name of the builddir.
builddir_name ?= out
# The V=1 flag on command line makes us verbosely print command lines.
ifdef V
quiet=
else
quiet=quiet_
endif
# Specify BUILDTYPE=Release on the command line for a release build.
BUILDTYPE ?= Debug
# Directory all our build output goes into.
# Note that this must be two directories beneath src/ for unit tests to pass,
# as they reach into the src/ directory for data with relative paths.
builddir ?= $(builddir_name)/$(BUILDTYPE)
abs_builddir := $(abspath $(builddir))
depsdir := $(builddir)/.deps
# Object output directory.
obj := $(builddir)/obj
abs_obj := $(abspath $(obj))
# We build up a list of every single one of the targets so we can slurp in the
# generated dependency rule Makefiles in one pass.
all_deps :=
# C++ apps need to be linked with g++.
#
# Note: flock is used to seralize linking. Linking is a memory-intensive
# process so running parallel links can often lead to thrashing. To disable
# the serialization, override LINK via an envrionment variable as follows:
#
# export LINK=g++
#
# This will allow make to invoke N linker processes as specified in -jN.
LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX)
CC.target ?= $(CC)
CFLAGS.target ?= $(CFLAGS)
CXX.target ?= $(CXX)
CXXFLAGS.target ?= $(CXXFLAGS)
LINK.target ?= $(LINK)
LDFLAGS.target ?= $(LDFLAGS)
AR.target ?= $(AR)
ARFLAGS.target ?= crs
# N.B.: the logic of which commands to run should match the computation done
# in gyp's make.py where ARFLAGS.host etc. is computed.
# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
# to replicate this environment fallback in make as well.
CC.host ?= gcc
CFLAGS.host ?=
CXX.host ?= g++
CXXFLAGS.host ?=
LINK.host ?= g++
LDFLAGS.host ?=
AR.host ?= ar
ARFLAGS.host := crs
# Define a dir function that can handle spaces.
# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
# "leading spaces cannot appear in the text of the first argument as written.
# These characters can be put into the argument value by variable substitution."
empty :=
space := $(empty) $(empty)
# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
replace_spaces = $(subst $(space),?,$1)
unreplace_spaces = $(subst ?,$(space),$1)
dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
# Flags to make gcc output dependency info. Note that you need to be
# careful here to use the flags that ccache and distcc can understand.
# We write to a dep file on the side first and then rename at the end
# so we can't end up with a broken dep file.
depfile = $(depsdir)/$(call replace_spaces,$@).d
DEPFLAGS = -MMD -MF $(depfile).raw
# We have to fixup the deps output in a few ways.
# (1) the file output should mention the proper .o file.
# ccache or distcc lose the path to the target, so we convert a rule of
# the form:
# foobar.o: DEP1 DEP2
# into
# path/to/foobar.o: DEP1 DEP2
# (2) we want missing files not to cause us to fail to build.
# We want to rewrite
# foobar.o: DEP1 DEP2 \
# DEP3
# to
# DEP1:
# DEP2:
# DEP3:
# so if the files are missing, they're just considered phony rules.
# We have to do some pretty insane escaping to get those backslashes
# and dollar signs past make, the shell, and sed at the same time.
# Doesn't work with spaces, but that's fine: .d files have spaces in
# their names replaced with other characters.
define fixup_dep
# The depfile may not exist if the input file didn't have any #includes.
touch $(depfile).raw
# Fixup path as in (1).
sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
# Add extra rules as in (2).
# We remove slashes and replace spaces with new lines;
# remove blank lines;
# delete the first line and append a colon to the remaining lines.
sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
grep -v '^$$' |\
sed -e 1d -e 's|$$|:|' \
>> $(depfile)
rm $(depfile).raw
endef
# Command definitions:
# - cmd_foo is the actual command to run;
# - quiet_cmd_foo is the brief-output summary of the command.
quiet_cmd_cc = CC($(TOOLSET)) $@
cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
quiet_cmd_cxx = CXX($(TOOLSET)) $@
cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
quiet_cmd_objc = CXX($(TOOLSET)) $@
cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
quiet_cmd_objcxx = CXX($(TOOLSET)) $@
cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
# Commands for precompiled header files.
quiet_cmd_pch_c = CXX($(TOOLSET)) $@
cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
quiet_cmd_pch_m = CXX($(TOOLSET)) $@
cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
# gyp-mac-tool is written next to the root Makefile by gyp.
# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
# already.
quiet_cmd_mac_tool = MACTOOL $(4) $<
cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
quiet_cmd_infoplist = INFOPLIST $@
cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
quiet_cmd_touch = TOUCH $@
cmd_touch = touch $@
quiet_cmd_copy = COPY $@
# send stderr to /dev/null to ignore messages when linking directories.
cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
quiet_cmd_alink = LIBTOOL-STATIC $@
cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool -static -o $@ $(filter %.o,$^)
quiet_cmd_link = LINK($(TOOLSET)) $@
cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
# TODO(thakis): Find out and document the difference between shared_library and
# loadable_module on mac.
quiet_cmd_solink = SOLINK($(TOOLSET)) $@
cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
# -bundle -single_module here (for osmesa.so).
quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
# Define an escape_quotes function to escape single quotes.
# This allows us to handle quotes properly as long as we always use
# use single quotes and escape_quotes.
escape_quotes = $(subst ','\'',$(1))
# This comment is here just to include a ' to unconfuse syntax highlighting.
# Define an escape_vars function to escape '$' variable syntax.
# This allows us to read/write command lines with shell variables (e.g.
# $LD_LIBRARY_PATH), without triggering make substitution.
escape_vars = $(subst $$,$$$$,$(1))
# Helper that expands to a shell command to echo a string exactly as it is in
# make. This uses printf instead of echo because printf's behaviour with respect
# to escape sequences is more portable than echo's across different shells
# (e.g., dash, bash).
exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
# Helper to compare the command we're about to run against the command
# we logged the last time we ran the command. Produces an empty
# string (false) when the commands match.
# Tricky point: Make has no string-equality test function.
# The kernel uses the following, but it seems like it would have false
# positives, where one string reordered its arguments.
# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
# $(filter-out $(cmd_$@), $(cmd_$(1))))
# We instead substitute each for the empty string into the other, and
# say they're equal if both substitutions produce the empty string.
# .d files contain ? instead of spaces, take that into account.
command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
$(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
# Helper that is non-empty when a prerequisite changes.
# Normally make does this implicitly, but we force rules to always run
# so we can check their command lines.
# $? -- new prerequisites
# $| -- order-only dependencies
prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
# Helper that executes all postbuilds, and deletes the output file when done
# if any of the postbuilds failed.
define do_postbuilds
@E=0;\
for p in $(POSTBUILDS); do\
eval $$p;\
F=$$?;\
if [ $$F -ne 0 ]; then\
E=$$F;\
fi;\
done;\
if [ $$E -ne 0 ]; then\
rm -rf "$@";\
exit $$E;\
fi
endef
# do_cmd: run a command via the above cmd_foo names, if necessary.
# Should always run for a given target to handle command-line changes.
# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
# Third argument, if non-zero, makes it do POSTBUILDS processing.
# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
# spaces already and dirx strips the ? characters.
define do_cmd
$(if $(or $(command_changed),$(prereq_changed)),
@$(call exact_echo, $($(quiet)cmd_$(1)))
@mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
$(if $(findstring flock,$(word 2,$(cmd_$1))),
@$(cmd_$(1))
@echo " $(quiet_cmd_$(1)): Finished",
@$(cmd_$(1))
)
@$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
@$(if $(2),$(fixup_dep))
$(if $(and $(3), $(POSTBUILDS)),
$(call do_postbuilds)
)
)
endef
# Declare the "all" target first so it is the default,
# even though we don't have the deps yet.
.PHONY: all
all:
# Use FORCE_DO_CMD to force a target to run. Should be coupled with
# do_cmd.
.PHONY: FORCE_DO_CMD
FORCE_DO_CMD:
TOOLSET := target
# Suffix rules, putting all outputs into $(obj).
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD
@$(call do_cmd,objc,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD
@$(call do_cmd,objcxx,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
@$(call do_cmd,cc,1)
# Try building from generated source, too.
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD
@$(call do_cmd,objc,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD
@$(call do_cmd,objcxx,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
@$(call do_cmd,cxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD
@$(call do_cmd,objc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD
@$(call do_cmd,objcxx,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
@$(call do_cmd,cc,1)
$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
@$(call do_cmd,cc,1)
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,build/All.target.x64.mk)))),)
include build/All.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,preparser/preparser.target.x64.mk)))),)
include preparser/preparser.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,samples/lineprocessor.target.x64.mk)))),)
include samples/lineprocessor.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,samples/process.target.x64.mk)))),)
include samples/process.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,samples/shell.target.x64.mk)))),)
include samples/shell.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,src/d8.target.x64.mk)))),)
include src/d8.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,src/d8_js2c.target.x64.mk)))),)
include src/d8_js2c.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,test/cctest/cctest.target.x64.mk)))),)
include test/cctest/cctest.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,test/cctest/resources.target.x64.mk)))),)
include test/cctest/resources.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/js2c.target.x64.mk)))),)
include tools/gyp/js2c.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/mksnapshot.x64.target.x64.mk)))),)
include tools/gyp/mksnapshot.x64.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/postmortem-metadata.target.x64.mk)))),)
include tools/gyp/postmortem-metadata.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/v8.target.x64.mk)))),)
include tools/gyp/v8.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/v8_base.x64.target.x64.mk)))),)
include tools/gyp/v8_base.x64.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/v8_nosnapshot.x64.target.x64.mk)))),)
include tools/gyp/v8_nosnapshot.x64.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/v8_shell.target.x64.mk)))),)
include tools/gyp/v8_shell.target.x64.mk
endif
ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
$(findstring $(join ^,$(prefix)),\
$(join ^,tools/gyp/v8_snapshot.target.x64.mk)))),)
include tools/gyp/v8_snapshot.target.x64.mk
endif
quiet_cmd_regen_makefile = ACTION Regenerating $@
cmd_regen_makefile = ./build/gyp/gyp -fmake --ignore-environment -S.x64 "--toplevel-dir=." -Ibuild/standalone.gypi "--depth=." "--generator-output=out" "-Dv8_target_arch=x64" "-Dv8_enable_backtrace=1" "-Darm_fpu=default" "-Darm_float_abi=default" build/all.gyp
Makefile.x64: $(srcdir)/samples/samples.gyp $(srcdir)/src/d8.gyp $(srcdir)/preparser/preparser.gyp $(srcdir)/test/cctest/cctest.gyp $(srcdir)/build/standalone.gypi $(srcdir)/build/common.gypi $(srcdir)/build/all.gyp $(srcdir)/tools/gyp/v8.gyp
$(call do_cmd,regen_makefile)
# "all" is a concatenation of the "all" targets from all the included
# sub-makefiles. This is just here to clarify.
all:
# Add in dependency-tracking rules. $(all_deps) is the list of every single
# target in our tree. Only consider the ones with .d (dependency) info:
d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
ifneq ($(d_files),)
# Rather than include each individual .d file, concatenate them into a
# single file which make is able to load faster. We split this into
# commands that take 1000 files at a time to avoid overflowing the
# command line.
$(shell cat $(wordlist 1,1000,$(d_files)) > $(depsdir)/all.deps)
ifneq ($(word 1001,$(d_files)),)
$(error Found unprocessed dependency files (gyp didn't generate enough rules!))
endif
# make looks for ways to re-generate included makefiles, but in our case, we
# don't have a direct way. Explicitly telling make that it has nothing to do
# for them makes it go faster.
$(depsdir)/all.deps: ;
include $(depsdir)/all.deps
endif
@imazine
Copy link

imazine commented Oct 25, 2013

으아 이거 한번 읽어서 머리에 들어올 내용이 아닌... ㄷ ㄷ ㄷ

잘보고있어요 #수고하셨씁니다 #땡큐베리머치

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment