[IOT-3011] Deprecate PlatformConfig to match C++
[iotivity.git] / scons_script_how_to.txt
1 TODO: WARNING: this file is out of date
2
3 == How to write IoTivity build scripts ==
4
5 IoTivity projects are built with Scons. Scons is a cross-platform build tool,
6 it's quite similar to 'make'. 'SConstruct' is the entrance of scons build, it's
7 equivalent to 'Makefile' to 'make'.
8
9 This document only a brief reference. Detail about how to write scons script,
10 please refer to:
11         http://www.scons.org/doc/production/HTML/scons-user.html#
12
13 == Background: How to control source code compiling ==
14
15 Environment is a base conception of Scons. An environment is a collection of
16 values that can affect how a program is built.
17
18 e.g. There is a C file named hello.c, enter the following into a file named
19 SConstruct:
20         env = Environment()
21         env.Program('H', 'hello.c')
22
23 When run Scons in console, following will be executed:
24 cc -o hello.o -c hello.c
25 cc -o H hello.o
26
27 If you would like keep debug information in the binary, '-g' flag should be added
28 when build the source code. To do this, append a C compiler flags as following:
29         env = Environment()
30         env.AppendUnique(CFLAGS = ['-g'])
31         env.Program('H', 'hello.c')
32
33 When run Scons, following will be executed:
34 cc -o hello.o -c -g hello.c
35 cc -o H hello.o
36
37 In above example, 'CFLAGS' is changed. Following list the frequently used keys:
38
39 CFLAGS: General options that are passed to the C compiler
40 CCFLAGS: General options that are passed to the C & C++ compiler
41 CXXFLAGS: General options that are passed to the C++ compiler
42 CPPPATH: The directories that the preprocessor will search for include headers.
43 CPPDEFINES: Platform independent specification of C preprocessor definitions.
44
45 Note: CPPPATH and CPPDEFINES is common for all compiler. But others are
46 compiler specific, when change the key value, it may required to specify the
47 target platform(actually the compiler).
48
49 e.g.
50         env.AppendUnique(CPPPATH = ['.', 'include'])
51         env.AppendUnique(CPPDEFINES = ['NDEBUG', 'VER_TEST'])
52 Above two lines are fine for all target platform. but below line:
53         env.AppenUnique(CXXFLAGS = ['-g'])
54 is only fine for gcc compiler, as '-g' is a gcc flag, other compiler may don't
55 understand it. so it may should be:
56         if target_os not in ['windows', 'winrt']:
57                 env.AppenUnique(CXXFLAGS = ['-g'])
58
59 Still take the hello.c as example. Assume hello.h is in ./include/ directory,
60 #include "hello.h"
61 int main(int argc, char** argv)
62 {
63 #ifdef LANG_FR
64     printf("Bonjour\n");
65 #else
66         printf("Hello\n");
67 #endif
68 }
69
70 The Scons configure file should as following:
71         env = Environment()
72         env.AppendUnique(CFLAGS = ['-g'])
73         env.AppendUnique(CPPPATH = ['include'])
74         env.AppendUnique(CPPDEFINES = ['LANG_FR'])
75         env.Program('H', 'hello.c')
76
77 When run Scons, following will be executed:
78 cc -o hello.o -c -g -Iinclude -DLANG_FR hello.c
79 cc -o H hello.o
80
81 === Get extra information ===
82
83 In above example, 'target_os' is used. How to get it?
84
85 User can build IoTivity project on Linux / Windows / MAC OSX for various
86 targets (Linux, Tizen, Android, Windows, MAC OSX, iOS ...). Most
87 platform specific configurations have been done in the common scripts which are in
88 build_common. The common scripts prepare an environment named 'env' with
89 target platform specific configuration.
90
91 When write IoTivity project build script, you can get this environment as
92 following:
93         Import('env')
94
95 You can use 'env' directly after import it(it isn't recommended). You can also
96 clone a new environment and update its keys(recommended).
97
98         new_env1 = Clone('env')
99         new_env2 = Clone('env')
100         new_env1.AppendUnqiue(xxx = [...])
101         new_env2.AppendUnqiue(xxx = [...])
102
103 The 'env' environment contains platform specific configuration, besides, there is
104 some common information. You can get the information with following line:
105         env.get('XXX')
106 or
107         env['XXX']
108
109 XXX is the information name, below are the extra information added by IoTivity
110 common scripts:
111 BUILD_DIR: the path of the build directory, all output are in this directory
112 SRC_DIR: the path of the top directory of the source code
113 RELEASE: build type, boolean. True - release build, False - debug build
114 TARGET_OS: the name of the target OS. The possible value depends on the host
115         platform. Bellow is the list of host and possible target OS. (darwin means
116         MAC OSX)
117                 linux: linux / android / tizen (means on Linux, you can build the
118                         project for Linux/Android/Tizen)
119                 windows: windows / winrt / android
120                 darwin: darwin / ios / android
121
122 TARGET_ARCH: the target CPU arch. Its possible value depends on the target OS.
123         Bellow list the target OS and allowed CPU architecture.
124                 linux: x86 / x86_64 / arm / arm64 (means if the target OS is Linux, the CPU
125                         arch can be x86/x86_64/arm/arm64)
126                 android: x86 / x86_64 / armeabi / armeabi-v7a / armeabi-v7a-hard / arm64-v8a
127                 windows: x86 / amd64 / arm
128                 winrt: arm
129                 darwin: i386 / x86_64
130                 ios: i386 / x86_64 / armv7 / armv7s / arm64,
131
132 === Extra functions ===
133
134 For convenience, in the common scripts, some extra functions are added:
135
136 PrintTargets(): print all target names in the help information.
137 AppendTarget(name, target = None): add a target name into targets list, when use
138         PrintTargets, the target name will be print
139 # @param name - the name of the target(s)(user defined name)
140 # @param target - Final binary, file(s) etc generated after build.
141
142 InstallTarget(files, name): it takes the same action as AppendTarget, besides,
143         it installs the 'files' to BUILD_DIR.
144
145 Functions for external library management:
146
147 PrepareLib(libname, lib = None, path = None, script = None): Check whether a
148 library exists, if not, notify user to install it or try to download the source
149 code and build it
150 # @param libname - the name of the library try to prepare
151 # @param lib - the lib(.so, .a etc) to check (a library may include more then
152 #      one lib, e.g. boost, includes boost_thread, boost_system ...
153 # @param path - the path of the library building script, if it's not set,
154 #                       by default, it's <src_dir>/extlibs/<libname>/
155 # @param script - the building script, by default, it's 'SConscript'
156
157 Download(target, url): Download source code from URL 'url' and save as 'target'.
158 # @param target - the name of the source code package to be saved as
159 # @param url - the URL from which to download the source code
160
161 Configure(cwd, cmd): Run configure command(such as: bootstrap, configure etc.
162 usually it's done before build a library)
163 # @param cwd - the work directory, full path or relative path to the directory
164                 where the library build script in
165 # @param cmd - the command to run, can be a script or system command
166
167 Install_head_file(file): Install header file(s) to <src_dir>/deps/<target_os>/include
168 # @param file - the head file(s) to install
169
170 Install_lib(lib): Install library binaries to <src_dir>/deps/<target_os>/lib/<arch>
171 # @param lib - the library binary(.so, .a etc) to install
172
173 ==== Scripts Hierarchy ====
174
175 Scons provides a function 'SConscript(scripts, [exports, variant_dir, duplicate])'
176 It tells scons to execute one or more subsidiary configuration files(A script,
177 usually named SConscript). Take below project hierarchy as example to show how
178 to organise the scripts.
179
180                 prj
181                 |-------prj_1
182                 |               |--------sub_prj_11
183                 |               |--------sub_prj_..
184                 |               |--------sub_prj_1n
185                 |-------prj_2
186                 |
187                 | ... ...
188                 |
189                 |-------prj_n
190
191 As above project hierarchy, in 'SConstruct' file in the 'prj' directory, there
192 should include some lines like these:
193
194 #Please change this part according to the organisation of your projects.
195 #Note: To make the output is in build_dir, the path of the scripts should
196 #be relevant to build_dir
197 SConscript(build_dir + 'prj_1/SConscript')
198 SConscript(build_dir + 'prj_2/SConscript')
199 ... ...
200 SConscript(build_dir + 'prj_n/SConscript')
201
202
203 It's the same, in the 'prj_1/SConscript', there should include lines like
204 these:
205 SConscript('sub_prj_11/SConscript')
206 ... ...
207 SConscript('sub_prj_1n/SConscript')
208
209 The path is relevant to 'prj_1/SConscript'. You can also use the full path
210 (build_dir + 'prj_1/sub_prj_1x/SConscript'), but it's not recommended.
211
212 Above just to show a recommended way to manage subsidiary scripts. You don't
213 need strictly follow it.
214
215 ==== The content of a typical script ====
216
217 After run the scripts in build_common (usually it's done at the beginning of
218 SConstruct), an global environment 'env' is exported, 'env' has include the
219 default configuration of the target OS and arch. 'env' is used in all projects,
220 should avoid to change its keys. To avoid change 'env', usually clone 'env' and
221 update it according to the requirement of current sub project. Then specify the
222 target (usually binary) to build.
223
224 Below is an example:
225         # import the global environment 'env'
226         Import('env')
227
228         # Clone a new environment from 'env'
229         new_env = env.Clone()
230
231         # Update the new environment, usually include add header file paths,
232         # library path, libs to link and other compiler flags. This part is
233         # optional.
234         new_env.AppendUnique(xxx = [ .... ])
235
236         # Specify the target(application, library, object or others) to build
237         ts = new_env.Program('program_name', [source_list])
238
239         # Install the target (optional)
240         # If it's an important library or daemon to be published
241         new_env.InstallTarget(ts, 'target_name')
242 or
243         # If it's examples or test program or others will not be published
244         new_env.AppendTarget('target_name', ts)
245
246 ==== Tips ====
247 1. library order: if A lib use B lib, both A and B are linked to target T, when
248         specify libraries, A should in front of B, otherwise there may be link
249         error. e.g.
250                 xx_env.AppendUnique(LIBS = ['A', 'B'])
251
252 2. On android:
253         (1)'pthread' is in libc. So don't use '-lpthread' for android
254         (2)By default 'rtti' and 'exception' is disabled, to enable it, you need
255         add flags '-frtti' and '-fexceptions'
256         (3)If STL is used, need link 'gnustl_shared' library