aboutsummaryrefslogtreecommitdiffstats
path: root/tools/build
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2014-12-29 07:51:45 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-02-11 16:30:03 -0500
commitc819e2cf2eb6f65d3208d195d7a0edef6108d533 (patch)
treea48b290466be4cb3851299ee0728a733982f06ff /tools/build
parent39f5704399042fff5f0d5f6af32bbbc3e787a897 (diff)
tools build: Add new build support
Adding new build framework into 'tools/build' to be used by tools. There's no change for actual building at this point, it comes in the next patches. The idea and more details are explained in the 'tools/build/Documentation/Build.txt' file. I adopted everything from the kernel build system, with some changes to allow for multiple binaries build definitions. While the kernel's build output is single image (forget modules) we need to be able to build several binaries/libraries. The basic idea is that sser provides 'Build' files with objects definitions like: perf-y += a.o perf-y += b.o libperf-y += c.o libperf-y += d.o and the build framework outputs files: perf-in.o # a.o, b.o compiled in libperf-in.o # c.o, d.o compiled in Signed-off-by: Jiri Olsa <jolsa@kernel.org> Tested-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Tested-by: Will Deacon <will.deacon@arm.com> Cc: Alexis Berlemont <alexis.berlemont@gmail.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-fbj22h4av0otlxupwcmrxgpa@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/build')
-rw-r--r--tools/build/Build.include81
-rw-r--r--tools/build/Documentation/Build.txt139
-rw-r--r--tools/build/Makefile.build97
-rw-r--r--tools/build/tests/ex/Build8
-rw-r--r--tools/build/tests/ex/Makefile23
-rw-r--r--tools/build/tests/ex/a.c5
-rw-r--r--tools/build/tests/ex/arch/Build2
-rw-r--r--tools/build/tests/ex/arch/e.c5
-rw-r--r--tools/build/tests/ex/arch/f.c5
-rw-r--r--tools/build/tests/ex/b.c5
-rw-r--r--tools/build/tests/ex/c.c5
-rw-r--r--tools/build/tests/ex/d.c5
-rw-r--r--tools/build/tests/ex/empty/Build0
-rw-r--r--tools/build/tests/ex/ex.c19
-rwxr-xr-xtools/build/tests/run.sh42
15 files changed, 441 insertions, 0 deletions
diff --git a/tools/build/Build.include b/tools/build/Build.include
new file mode 100644
index 000000000000..4c8daaccb82a
--- /dev/null
+++ b/tools/build/Build.include
@@ -0,0 +1,81 @@
1###
2# build: Generic definitions
3#
4# Lots of this code have been borrowed or heavily inspired from parts
5# of kbuild code, which is not credited, but mostly developed by:
6#
7# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
8# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
9#
10
11###
12# Convenient variables
13comma := ,
14squote := '
15
16###
17# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
18dot-target = $(dir $@).$(notdir $@)
19
20###
21# filename of target with directory and extension stripped
22basetarget = $(basename $(notdir $@))
23
24###
25# The temporary file to save gcc -MD generated dependencies must not
26# contain a comma
27depfile = $(subst $(comma),_,$(dot-target).d)
28
29###
30# Check if both arguments has same arguments. Result is empty string if equal.
31arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
32 $(filter-out $(cmd_$@), $(cmd_$(1))) )
33
34###
35# Escape single quote for use in echo statements
36escsq = $(subst $(squote),'\$(squote)',$1)
37
38# Echo command
39# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
40echo-cmd = $(if $($(quiet)cmd_$(1)),\
41 echo ' $(call escsq,$($(quiet)cmd_$(1)))';)
42
43###
44# Replace >$< with >$$< to preserve $ when reloading the .cmd file
45# (needed for make)
46# Replace >#< with >\#< to avoid starting a comment in the .cmd file
47# (needed for make)
48# Replace >'< with >'\''< to be able to enclose the whole string in '...'
49# (needed for the shell)
50make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
51
52###
53# Find any prerequisites that is newer than target or that does not exist.
54# PHONY targets skipped in both cases.
55any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
56
57###
58# if_changed_dep - execute command if any prerequisite is newer than
59# target, or command line has changed and update
60# dependencies in the cmd file
61if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
62 @set -e; \
63 $(echo-cmd) $(cmd_$(1)); \
64 cat $(depfile) > $(dot-target).cmd; \
65 printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
66
67# if_changed - execute command if any prerequisite is newer than
68# target, or command line has changed
69if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
70 @set -e; \
71 $(echo-cmd) $(cmd_$(1)); \
72 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
73
74###
75# C flags to be used in rule definitions, includes:
76# - depfile generation
77# - global $(CFLAGS)
78# - per target C flags
79# - per object C flags
80# - BUILD_STR macro to allow '-D"$(variable)"' constructs
81c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
new file mode 100644
index 000000000000..00ad2d608727
--- /dev/null
+++ b/tools/build/Documentation/Build.txt
@@ -0,0 +1,139 @@
1Build Framework
2===============
3
4The perf build framework was adopted from the kernel build system, hence the
5idea and the way how objects are built is the same.
6
7Basically the user provides set of 'Build' files that list objects and
8directories to nest for specific target to be build.
9
10Unlike the kernel we don't have a single build object 'obj-y' list that where
11we setup source objects, but we support more. This allows one 'Build' file to
12carry a sources list for multiple build objects.
13
14a) Build framework makefiles
15----------------------------
16
17The build framework consists of 2 Makefiles:
18
19 Build.include
20 Makefile.build
21
22While the 'Build.include' file contains just some generic definitions, the
23'Makefile.build' file is the makefile used from the outside. It's
24interface/usage is following:
25
26 $ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
27
28where:
29
30 KSRC - is the path to kernel sources
31 DIR - is the path to the project to be built
32 OBJECT - is the name of the build object
33
34When succefully finished the $(DIR) directory contains the final object file
35called $(OBJECT)-in.o:
36
37 $ ls $(DIR)/$(OBJECT)-in.o
38
39which includes all compiled sources described in 'Build' makefiles.
40
41a) Build makefiles
42------------------
43
44The user supplies 'Build' makefiles that contains a objects list, and connects
45the build to nested directories.
46
47Assume we have the following project structure:
48
49 ex/a.c
50 /b.c
51 /c.c
52 /d.c
53 /arch/e.c
54 /arch/f.c
55
56Out of which you build the 'ex' binary ' and the 'libex.a' library:
57
58 'ex' - consists of 'a.o', 'b.o' and libex.a
59 'libex.a' - consists of 'c.o', 'd.o', 'e.o' and 'f.o'
60
61The build framework does not create the 'ex' and 'libex.a' binaries for you, it
62only prepares proper objects to be compiled and grouped together.
63
64To follow the above example, the user provides following 'Build' files:
65
66 ex/Build:
67 ex-y += a.o
68 ex-y += b.o
69
70 libex-y += c.o
71 libex-y += d.o
72 libex-y += arch/
73
74 ex/arch/Build:
75 libex-y += e.o
76 libex-y += f.o
77
78and runs:
79
80 $ make -f tools/build/Makefile.build dir=. obj=ex
81 $ make -f tools/build/Makefile.build dir=. obj=libex
82
83which creates the following objects:
84
85 ex/ex-in.o
86 ex/libex-in.o
87
88that contain request objects names in Build files.
89
90It's only a matter of 2 single commands to create the final binaries:
91
92 $ ar rcs libex.a libex-in.o
93 $ gcc -o ex ex-in.o libex.a
94
95You can check the 'ex' example in 'tools/build/tests/ex' for more details.
96
97b) Rules
98--------
99
100The build framework provides standard compilation rules to handle .S and .c
101compilation.
102
103It's possible to include special rule if needed (like we do for flex or bison
104code generation).
105
106c) CFLAGS
107---------
108
109It's possible to alter the standard object C flags in the following way:
110
111 CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
112 CFLAGS_gtk += '...' - alters CFLAGS for gtk build object
113
114This C flags changes has the scope of the Build makefile they are defined in.
115
116
117d) Dependencies
118---------------
119
120For each built object file 'a.o' the '.a.cmd' is created and holds:
121
122 - Command line used to built that object
123 (for each object)
124
125 - Dependency rules generated by 'gcc -Wp,-MD,...'
126 (for compiled object)
127
128All existing '.cmd' files are included in the Build process to follow properly
129the dependencies and trigger a rebuild when necessary.
130
131
132e) Single rules
133---------------
134
135It's possible to build single object file by choice, like:
136
137 $ make util/map.o # objects
138 $ make util/map.i # preprocessor
139 $ make util/map.s # assembly
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
new file mode 100644
index 000000000000..ae203f21cc86
--- /dev/null
+++ b/tools/build/Makefile.build
@@ -0,0 +1,97 @@
1###
2# Main build makefile.
3#
4# Lots of this code have been borrowed or heavily inspired from parts
5# of kbuild code, which is not credited, but mostly developed by:
6#
7# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
8# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
9#
10
11PHONY := __build
12__build:
13
14ifeq ($(V),1)
15 quiet =
16else
17 quiet=quiet_
18endif
19
20build-dir := $(srctree)/tools/build
21
22# Generic definitions
23include $(build-dir)/Build.include
24
25# Init all relevant variables used in build files so
26# 1) they have correct type
27# 2) they do not inherit any value from the environment
28subdir-y :=
29obj-y :=
30subdir-y :=
31subdir-obj-y :=
32
33# Build definitions
34build-file := $(dir)/Build
35include $(build-file)
36
37# Compile command
38quiet_cmd_cc_o_c = CC $@
39 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
40
41# Link agregate command
42# If there's nothing to link, create empty $@ object.
43quiet_cmd_ld_multi = LD $@
44 cmd_ld_multi = $(if $(strip $(obj-y)),\
45 $(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@)
46
47# Build rules
48$(OUTPUT)%.o: %.c FORCE
49 $(call if_changed_dep,cc_o_c)
50
51$(OUTPUT)%.o: %.S FORCE
52 $(call if_changed_dep,cc_o_c)
53
54# Gather build data:
55# obj-y - list of build objects
56# subdir-y - list of directories to nest
57# subdir-obj-y - list of directories objects 'dir/$(obj)-in.o'
58obj-y := $($(obj)-y)
59subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
60obj-y := $(patsubst %/, %/$(obj)-in.o, $(obj-y))
61subdir-obj-y := $(filter %/$(obj)-in.o, $(obj-y))
62
63# '$(OUTPUT)/dir' prefix to all objects
64prefix := $(subst ./,,$(OUTPUT)$(dir)/)
65obj-y := $(addprefix $(prefix),$(obj-y))
66subdir-obj-y := $(addprefix $(prefix),$(subdir-obj-y))
67
68# Final '$(obj)-in.o' object
69in-target := $(prefix)$(obj)-in.o
70
71PHONY += $(subdir-y)
72
73$(subdir-y):
74 @$(MAKE) -f $(build-dir)/Makefile.build dir=$(dir)/$@ obj=$(obj)
75
76$(sort $(subdir-obj-y)): $(subdir-y) ;
77
78$(in-target): $(obj-y) FORCE
79 $(call rule_mkdir)
80 $(call if_changed,ld_multi)
81
82__build: $(in-target)
83 @:
84
85PHONY += FORCE
86FORCE:
87
88# Include all cmd files to get all the dependency rules
89# for all objects included
90targets := $(wildcard $(sort $(obj-y) $(in-target)))
91cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
92
93ifneq ($(cmd_files),)
94 include $(cmd_files)
95endif
96
97.PHONY: $(PHONY)
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build
new file mode 100644
index 000000000000..0e6c3e6767e6
--- /dev/null
+++ b/tools/build/tests/ex/Build
@@ -0,0 +1,8 @@
1ex-y += ex.o
2ex-y += a.o
3ex-y += b.o
4ex-y += empty/
5
6libex-y += c.o
7libex-y += d.o
8libex-y += arch/
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
new file mode 100644
index 000000000000..52d2476073a3
--- /dev/null
+++ b/tools/build/tests/ex/Makefile
@@ -0,0 +1,23 @@
1export srctree := ../../../..
2export CC := gcc
3export LD := ld
4export AR := ar
5
6build := -f $(srctree)/tools/build/Makefile.build dir=. obj
7ex: ex-in.o libex-in.o
8 gcc -o $@ $^
9
10ex.%: FORCE
11 make -f $(srctree)/tools/build/Makefile.build dir=. $@
12
13ex-in.o: FORCE
14 make $(build)=ex
15
16libex-in.o: FORCE
17 make $(build)=libex
18
19clean:
20 find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
21 rm -f ex ex.i ex.s
22
23.PHONY: FORCE
diff --git a/tools/build/tests/ex/a.c b/tools/build/tests/ex/a.c
new file mode 100644
index 000000000000..851762798c83
--- /dev/null
+++ b/tools/build/tests/ex/a.c
@@ -0,0 +1,5 @@
1
2int a(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/arch/Build b/tools/build/tests/ex/arch/Build
new file mode 100644
index 000000000000..55506189efae
--- /dev/null
+++ b/tools/build/tests/ex/arch/Build
@@ -0,0 +1,2 @@
1libex-y += e.o
2libex-y += f.o
diff --git a/tools/build/tests/ex/arch/e.c b/tools/build/tests/ex/arch/e.c
new file mode 100644
index 000000000000..beaa4a1d7ba8
--- /dev/null
+++ b/tools/build/tests/ex/arch/e.c
@@ -0,0 +1,5 @@
1
2int e(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/arch/f.c b/tools/build/tests/ex/arch/f.c
new file mode 100644
index 000000000000..7c3e9e9da5b7
--- /dev/null
+++ b/tools/build/tests/ex/arch/f.c
@@ -0,0 +1,5 @@
1
2int f(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/b.c b/tools/build/tests/ex/b.c
new file mode 100644
index 000000000000..c24ff9ca9a97
--- /dev/null
+++ b/tools/build/tests/ex/b.c
@@ -0,0 +1,5 @@
1
2int b(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/c.c b/tools/build/tests/ex/c.c
new file mode 100644
index 000000000000..e216d0217499
--- /dev/null
+++ b/tools/build/tests/ex/c.c
@@ -0,0 +1,5 @@
1
2int c(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/d.c b/tools/build/tests/ex/d.c
new file mode 100644
index 000000000000..80dc0f06151b
--- /dev/null
+++ b/tools/build/tests/ex/d.c
@@ -0,0 +1,5 @@
1
2int d(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/empty/Build b/tools/build/tests/ex/empty/Build
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/build/tests/ex/empty/Build
diff --git a/tools/build/tests/ex/ex.c b/tools/build/tests/ex/ex.c
new file mode 100644
index 000000000000..dc42eb2e1a67
--- /dev/null
+++ b/tools/build/tests/ex/ex.c
@@ -0,0 +1,19 @@
1
2int a(void);
3int b(void);
4int c(void);
5int d(void);
6int e(void);
7int f(void);
8
9int main(void)
10{
11 a();
12 b();
13 c();
14 d();
15 e();
16 f();
17
18 return 0;
19}
diff --git a/tools/build/tests/run.sh b/tools/build/tests/run.sh
new file mode 100755
index 000000000000..5494f8ea7567
--- /dev/null
+++ b/tools/build/tests/run.sh
@@ -0,0 +1,42 @@
1#!/bin/sh
2
3function test_ex {
4 make -C ex V=1 clean > ex.out 2>&1
5 make -C ex V=1 >> ex.out 2>&1
6
7 if [ ! -x ./ex/ex ]; then
8 echo FAILED
9 exit -1
10 fi
11
12 make -C ex V=1 clean > /dev/null 2>&1
13 rm -f ex.out
14}
15
16function test_ex_suffix {
17 make -C ex V=1 clean > ex.out 2>&1
18
19 # use -rR to disable make's builtin rules
20 make -rR -C ex V=1 ex.o >> ex.out 2>&1
21 make -rR -C ex V=1 ex.i >> ex.out 2>&1
22 make -rR -C ex V=1 ex.s >> ex.out 2>&1
23
24 if [ -x ./ex/ex ]; then
25 echo FAILED
26 exit -1
27 fi
28
29 if [ ! -f ./ex/ex.o -o ! -f ./ex/ex.i -o ! -f ./ex/ex.s ]; then
30 echo FAILED
31 exit -1
32 fi
33
34 make -C ex V=1 clean > /dev/null 2>&1
35 rm -f ex.out
36}
37echo -n Testing..
38
39test_ex
40test_ex_suffix
41
42echo OK