1@page page_scons SCons
2
3# Introduction to SCons
4
5SCons is an open source build system written in the Python language, similar to GNU Make. It uses a different approach than the usual Makefile, but instead uses SConstruct and SConscript files instead. These files are also Python scripts that can be written using standard Python syntax, so the Python standard library can be called in SConstruct, SConscript files for a variety of complex processing, not limited to the rules set by the Makefile.
6
7A detailed [SCons user manual](http://www.scons.org/doc/production/HTML/scons-user/index.html) can be found on the SCons website. This section describes the basic usage of SCons and how to use the SCons tool in RT-Thread.
8
9## What is Construction Tool
10
11A software construction tool is a piece of software that compiles source code into an executable binary program according to certain rules or instructions. This is the most basic and important feature of building tools. In fact, these are not the only functions of construction tools. Usually these rules have a certain syntax and are organized into files. These files are used to control the behavior of the build tool, and you can do other things besides software building.
12
13The most popular build tool today is GNU Make. Many well-known open source software, such as the Linux kernel, are built using Make. Make detects the organization and dependencies of the file by reading the Makefile and completes the commands specified in the Makefile.
14
15Due to historical reasons, the syntax of the Makefile is confusing, which is not conducive to beginners. In addition, it is not convenient to use Make on the Windows platform, you need to install the Cygwin environment. To overcome the shortcomings of Make, other build tools have been developed, such as CMake and SCons.
16
17## RT-Thread Construciton Tool
18
19RT-Thread was built using Make/Makefile in the earlier stage. Starting from 0.3.x, the RT-Thread development team gradually introduced the SCons build system. The only goal of introducing SCons is to get everyone out of the complex Makefile configuration, IDE configuration, and focus on RT-Thread function development.
20
21Some may doubt the difference between the build tools described here and the IDE. The IDE completes the build through the operation of the graphical interface. Most IDEs generate script files like Makefile or SConscript based on the source code added by the user, and call the tools like Make or SCons to build the source code.
22
23## Install SCons
24
25It needs to be installed on the PC host before using the SCons system because it is written in the Python language, so you need to install the Python runtime environment before using SCons.
26
27The Env configuration tool provided by RT-Thread comes with SCons and Python, so using SCons on Windows platforms does not require the installation of these two software.
28
29In Linux and BSD environments, Python should already be installed by default, which is also the Python environment of the 2.x version. At this time, you only need to install SCons. For example, in Ubuntu you can install SCons with the following command:
30
31`sudo apt-get install scons`
32
33# Basic Functions of SCons
34
35The RT-Thread build system supports multiple compilers, including ARM GCC, MDK, IAR, VisualStudio, and Visual DSP. The mainstream ARM Cortex M0, M3, M4 platforms, basically all support ARM GCC, MDK, IAR. Some BSPs may only support one compiler, and readers can read the currently supported compiler by reading the CROSS_TOOL option in rtconfig.py under the BSP directory.
36
37If it is a chip on the ARM platform, you can use the Env tool and enter the scons command to compile the BSP directly. At this time, the ARM GCC compiler is used by default because the Env tool comes with the ARM GCC compiler. Compile a BSP using the scons command as shown below, and the SCons will be based on this BSP.
38
39![Compile BSP using scons](figures/scons_compile.png)
40
41If the user wants to use another compiler that the BSP already supports to compile the project, or if the BSP is a non-ARM platform chip, then you can't compile the project directly with the scons command. You need to install the corresponding compiler yourself and specify the compiler path to use. Before compiling the project, you can use the following two commands in the Env command line interface to specify the compiler path for the MDK and the compiler path to MDK.
42
43```c
44set RTT_CC=keil
45set RTT_EXEC_PATH=C:/Keilv5
46```
47
48## Commonly Used SCons Commands
49
50This section describes the SCons commands that are commonly used in RT-Thread. SCons not only completes basic compilation, but also generates MDK/IAR/VS projects.
51
52### scons
53
54Go to the BSP project directory to be compiled in the Env command line window, and then use this command to compile the project directly. If some source files are modified after executing the  `scons` command, and the scons command is executed again, SCons will incrementally compile and compile only the modified source files and link them.
55
56
57`scons` can also be followed by a `-s` parameter, the command `scons -s`,  which differs from the `scons` command in that it does not print specific internal commands.
58
59### scons -c
60
61Clear the compilation target. This command clears the temporary and target files generated when `scons` is executed.
62
63### scons --target=XXX
64
65If you use mdk/iar for project development, when you open or close some components, you need to use one of the following commands to regenerate the corresponding customized project, then compile and download in mdk/iar.
66
67```c
68scons --target=iar
69scons --target=mdk4
70scons --target=mdk5
71```
72
73In the Env command line window, enter the BSP project directory to be compiled. After using the `scons --target=mdk5` command, a new MDK project file named project.uvprojx will be generated in the BSP directory. Double-click it to open and you can use MDK to compile and debug. Using the `scons --target=iar` command will generate a new IAR project file named project.eww. Users who are not used to SCons can use this method. If project.uvproj fails to open, please delete project.uvopt and rebuild the project.
74
75Under `bsp/simulator` directory , you can use the following command to generate a project for vs2012 or a project for vs2005.
76
77```c
78scons --target=vs2012
79Scons --target=vs2005
80```
81
82If you provide template files for other IDE projects in the BSP directory, you can also use this command to generate corresponding new projects, such as ua, vs, cb, cdk.
83
84This command can also be followed by a `-s` parameter, such as the command  `scons –target=mdk5 -s`, which does not print specific internal commands when executing this command.
85
86> To generate a MDK or IAR project file, the prerequisite is that there is a project template file in the BSP directory, and then the scons will add relevant source code, header file search path, compilation parameters, link parameters, etc. according to the template file. As for which chip this project is for, it is directly specified by this engineering template file. So in most cases, this template file is an empty project file that is used to assist SCons in generating project.uvprojx or project.eww.
87
88### scons -jN
89
90Multi-threaded compilation target, you can use this command to speed up compilation on multi-core computers. In general, a cpu core can support 2 threads. Use the `scons -j4`  command on a dual-core machine.
91
92> If you just want to look at compilation errors or warnings, it's best not to use the -j parameter so that the error message won't be mixed with multiple files in parallel.
93
94### scons --dist
95
96Build a project framework. Using this command will generate the `dist` directory in the BSP directory, this is the directory structure of the development project, including RT-Thread source code and BSP related projects, irrelevant BSP folder and libcpu will be removed, and you can freely copy this work to any directory.
97
98### scons --verbose
99
100By default, output compiled with the scons command does not display compilation parameters as follows:
101
102```c
103D:\repository\rt-thread\bsp\stm32f10x>scons
104scons: Reading SConscript files ...
105scons: done reading SConscript files.
106scons: Building targets ...
107scons: building associated VariantDir targets: build
108CC build\applications\application.o
109CC build\applications\startup.o
110CC build\components\drivers\serial\serial.o
111...
112```
113
114The effect of using the scons –verbose command is as follows:
115
116```c
117armcc -o build\src\mempool.o -c --device DARMSTM --apcs=interwork -ID:/Keil/ARM/
118RV31/INC -g -O0 -DUSE_STDPERIPH_DRIVER -DSTM32F10X_HD -Iapplications -IF:\Projec
119t\git\rt-thread\applications -I. -IF:\Project\git\rt-thread -Idrivers -IF:\Proje
120ct\git\rt-thread\drivers -ILibraries\STM32F10x_StdPeriph_Driver\inc -IF:\Project
121\git\rt-thread\Libraries\STM32F10x_StdPeriph_Driver\inc -ILibraries\STM32_USB-FS
122-Device_Driver\inc -IF:\Project\git\rt-thread\Libraries\STM32_USB-FS-Device_Driv
123er\inc -ILibraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x -IF:\Project\git\rt-thre
124...
125```
126
127# SCons Advanced
128
129SCons uses SConscript and SConstruct files to organize the source structure. Usually a project has only one SConstruct, but there will be multiple SConscripts. In general, an SConscript will be placed in each subdirectory where the source code is stored.
130
131In order to make RT-Thread better support multiple compilers and to easily adjust compilation parameters, RT-Thread creates a separate file for each BSP called `rtconfig.py`. So the following three files exist in every RT-Thread BSP directory: `rtconfig.py`, `SConstruct`, and `SConscript`, which control the compilation of the BSP. There is only one SConstruct file in a BSP, but there are multiple SConscript files. It can be said that the SConscript file is the main force of the organization source code.
132
133RT-Thread SConscript files are also present in most source folders. These files are "found" by the SConscript file in the BSP directory to add the source code corresponding to the macro defined in rtconfig.h to the compiler. The following article will take stm32f10x-HAL BSP as an example to explain how SCons builds the project.
134
135## SCons Build-In Functions
136
137If you want to add some of your own source code to the SCons build environment, you can usually create or modify an existing SConscript file. The SConscript file can control the addition of source files and can specify the group of files (similar to the concept of Groups in IDEs such as MDK/IAR).
138
139SCons provides a lot of built-in functions to help us quickly add source code, and with these simple Python statements we can add or remove source code to our project. The following is a brief introduction to some common functions.
140
141### GetCurrentDir()
142
143Get current directory.
144
145###  Glob('\*.c')
146
147Get all C files in the current directory. Modify the value of the parameter to match the suffix to match all files of the current directory.
148
149### GetDepend(macro)
150
151This function is defined in the script file in the `tools` directory. It reads the configuration information from the rtconfig.h file with the macro name in rtconfig.h. This method (function) returns true if rtconfig.h has a macro turned on, otherwise it returns false.
152
153### Split(str)
154
155Split the string str into a list list.
156
157### DefineGroup(name, src, depend,**parameters)
158
159This is a method (function) of RT-Thread based on the SCons extension. DefineGroup is used to define a component. A component can be a directory (under a file or subdirectory) and a Group or folder in some subsequent IDE project files.
160
161Parameter description of `DefineGroup() ` :
162
163|**Parameter**|**D**escription                 |
164|-------|------------------------------------|
165| name       | name of Group      |
166| src        | The files contained in the Group generally refer to C/C++ source files. For convenience, you can also use the Glob function to list the matching files in the directory where the SConscript file is located by using a wildcard. |
167| depend     | The options that the Group depends on when compiling (for example, the FinSH component depends on the RT_USING_FINSH macro definition). The compile option generally refers to the RT_USING_xxx macro defined in rtconfig.h. When the corresponding macro is defined in the rtconfig.h configuration file, then this group will be added to the build environment for compilation. If the dependent macro is not defined in rtconfig.h, then this Group will not be added to compile. Similarly, when using scons to generate as an IDE project file, if the dependent macros are not defined, the corresponding Group will not appear in the project file. |
168| parameters | Configure other parameters, the values can be found in the table below. You do not need to configure all parameters in actual use. |
169
170parameters that could be added:
171
172|**P**arameter|**Description**                                      |
173|------------|--------------------------------------------------|
174| CCFLAGS    | source file compilation parameters |
175| CPPPATH    | head file path                          |
176| CPPDEFINES | Link parameter                    |
177| LIBRARY    | Include this parameter, the object file generated by the component will be packaged into a library file |
178
179### SConscript(dirs,variant_dir,duplicate)
180
181Read the new SConscript file, and the parameter description of the SConscript() function is as follows:
182
183|**Parameter** |**Description**                           |
184|-------------|---------------------------------------|
185| dirs        | SConscript file path |
186| variant_dir | Specify the path to store the generated target file |
187| duiplicate  | Set whether to copy or link the source file to variant_dir |
188
189# SConscript Examples
190
191Below we will use a few SConscript as an example to explain how to use the scons tool.
192
193## SConscript Example 1
194
195Let's start with the SConcript file in the stm32f10x-HAL BSP directory. This file manages all the other SConscript files under the BSP, as shown below.
196
197```c
198import os
199cwd = str(Dir('#'))
200objs = []
201list = os.listdir(cwd)
202for d in list:
203    path = os.path.join(cwd, d)
204       if os.path.isfile(os.path.join(path, 'SConscript')):
205        objs = objs + SConscript(os.path.join(d, 'SConscript'))
206Return('objs')
207```
208
209* `import os:` Importing the Python system programming os module, you can call the functions provided by the os module to process files and directories.
210
211* `cwd = str(Dir('#')):` Get the top-level directory of the project and assign it to the string variable cwd, which is the directory where the project's SConstruct is located, where it has the same effect as  `cwd = GetCurrentDir()` .
212
213* `objs = []:` An empty list variable objs is defined.
214
215* `list = os.listdir(cwd):` Get all the subdirectories under the current directory and save them to the variable list.
216
217* This is followed by a python for loop that walks through all the subdirectories of the BSP and runs the SConscript files for those subdirectories. The specific operation is to take a subdirectory of the current directory, use  `os.path.join(cwd,d)` to splicing into a complete path, and then determine whether there is a file named SConscript in this subdirectory. If it exists, execute `objs = objs + SConscript(os.path.join(d,'SConscript'))` . This sentence uses a built-in function `SConscript()` provided by SCons, which can read in a new SConscript file and add the source code specified in the SConscript file to the source compilation list objs.
218
219With this SConscript file, the source code required by the BSP project is added to the compilation list.
220
221## SConscript Example 2
222
223So what about stm32f10x-HAL BSP other SConcript files? Let's take a look at the SConcript file in the drivers directory, which will manage the source code under the drivers directory. The drivers directory is used to store the underlying driver code implemented by the driver framework provided by RT-Thread.
224
225```c
226Import('rtconfig')
227from building import *
228
229cwd = GetCurrentDir()
230
231# add the general drivers.
232src = Split("""
233board.c
234stm32f1xx_it.c
235""")
236
237if GetDepend(['RT_USING_PIN']):
238    src += ['drv_gpio.c']
239if GetDepend(['RT_USING_SERIAL']):
240    src += ['drv_usart.c']
241if GetDepend(['RT_USING_SPI']):
242    src += ['drv_spi.c']
243if GetDepend(['RT_USING_USB_DEVICE']):
244    src += ['drv_usb.c']
245if GetDepend(['RT_USING_SDCARD']):
246    src += ['drv_sdcard.c']
247
248if rtconfig.PLATFORM in ['gcc']:
249    src += ['gcc_startup.s']
250
251CPPPATH = [cwd]
252
253group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
254
255Return('group')
256
257```
258
259* `Import('rtconfig'):` Import the rtconfig object, and the rtconfig.CROSS_TOOL used later is defined in this rtconfig module.
260
261* `from building import *:` All the contents of the building module are imported into the current module, and the DefineGroup used later is defined in this module.
262
263* `cwd = GetCurrentDir():` Get the current path and save it to the string variable cwd.
264
265The next line uses the `Split()`  function to split a file string into a list, the effect of which is equivalent to
266
267`src = ['board.c','stm32f1xx_it.c']`
268
269Later, `if` judgement and `GetDepend ()` are used to check whether a macro in `rtconfig.h` is open or not, and if so,  `src += [src_name]`  is used to append the source code file to the list variable src.
270
271* `CPPPATH = [cwd]:`  Save the current path to a list variable CPPPATH.
272
273The last line uses DefineGroup to create a group called Drivers, which corresponds to the grouping in the MDK or IAR. The source code file for this group is the file specified by src, and the dependency is empty to indicate that the group does not depend on any macros of rtconfig.h.
274
275`CPPPATH =CPPPATH` means to add the current path to the system's header file path. The CPPPATH on the left is a built-in parameter in the DefineGroup that represents the header file path. The CPPPATH on the right is defined in the previous line of this document. This way we can reference the header files in the drivers directory in other source code.
276
277## SConscript Example 3
278
279Let's take a look at the SConcript file in the applications directory, which will manage the source code under the applications directory for the user's own application code.
280
281```c
282from building import *
283
284cwd = GetCurrentDir()
285src = Glob('*.c')
286CPPPATH = [cwd, str(Dir('#'))]
287
288group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
289
290Return('group')
291```
292
293`src = Glob('*.c'):` Get all the C files in the current directory.
294
295`CPPPATH = [cwd, str(Dir('#'))]:` Save the current path and the path of the project's SConstruct to the list variable CPPPATH.
296
297The last line uses DefineGroup to create a group called `Applications`. The source code file for this group is the file specified by src. If the dependency is empty, the group does not depend on any rtconfig.h macros, and the path saved by CPPPATH is added to the system header search path. Such application directories and header files in the stm32f10x-HAL BSP directory can be referenced elsewhere in the source code.
298
299To sum up, this source program will add all c programs in the current directory to the group `Applications`, so if you add or delete files in this directory, you can add files to the project or delete them from the project. It is suitable for adding source files in batches.
300
301## SConscript Example 4
302
303Below is the contents of the RT-Thread source code `component/finsh/SConscript` file, which will manage the source code under the finsh directory.
304
305```c
306Import('rtconfig')
307from building import *
308
309cwd     = GetCurrentDir()
310src     = Split('''
311shell.c
312symbol.c
313cmd.c
314''')
315
316fsh_src = Split('''
317finsh_compiler.c
318finsh_error.c
319finsh_heap.c
320finsh_init.c
321finsh_node.c
322finsh_ops.c
323finsh_parser.c
324finsh_var.c
325finsh_vm.c
326finsh_token.c
327''')
328
329msh_src = Split('''
330msh.c
331msh_cmd.c
332msh_file.c
333''')
334
335CPPPATH = [cwd]
336if rtconfig.PLATFORM in ['armcc', 'armclang']:
337    LINKFLAGS = '--keep *.o(FSymTab)'
338
339    if not GetDepend('FINSH_USING_MSH_ONLY'):
340        LINKFLAGS = LINKFLAGS + '--keep *.o(VSymTab)'
341else:
342    LINKFLAGS = ''
343
344if GetDepend('FINSH_USING_MSH'):
345    src = src + msh_src
346if not GetDepend('FINSH_USING_MSH_ONLY'):
347    src = src + fsh_src
348
349group = DefineGroup('finsh', src, depend = ['RT_USING_FINSH'], CPPPATH = CPPPATH, LINKFLAGS = LINKFLAGS)
350
351Return('group')
352```
353
354Let's take a look at the contents of the first Python conditional statement in the file. If the compilation tool is keil, the variable `LINKFLAGS = '--keep *.o(FSymTab)'`  left blank.
355
356DefinGroup also creates the file specified by src in the finsh directory as a finsh group. `depend = ['RT_USING_FINSH']` indicates that this group depends on the macro RT_USING_FINSH in `rtconfig.h`. When the macro RT_USING_FINSH is opened in rtconfig.h, the source code in the finsh group will be compiled, otherwise SCons will not compile.
357
358Then add the finsh directory to the system header directory so that we can reference the header files in the finsh directory in other source code.
359
360`LINKFLAGS = LINKFLAGS` has the same meaning as `CPPPATH = CPPPATH` . The LINKFLAGS on the left represents the link parameter, and the LINKFLAGS on the right is the value defined by the previous if else statement. That is, specify the link parameters for the project.
361
362# Manage Projects with SCons
363
364The previous section on the SConscript related to the RT-Thread source code is explained in detail, you should also know some common ways to write SConscript files, this section will guide you how to use SCons to manage your own projects.
365
366## Add App Code
367
368As mentioned earlier, the Applications folder under BSP is used to store the user's own application code. Currently there is only one main.c file. If the user's application code is not a lot, it is recommended that the relevant source files be placed under this folder. Two simple files hello.c and hello.h have been added under the Applications folder, as shown below.
369
370```c
371/* file: hello.h */
372
373#ifndef _HELLO_H_
374#define _HELLO_H_
375
376int hello_world(void);
377
378#endif /* _HELLO_H_ */
379
380/* file: hello.c */
381#include <stdio.h>
382#include <finsh.h>
383#include <rtthread.h>
384
385int hello_world(void)
386{
387    rt_kprintf("Hello, world!\n");
388
389    return 0;
390}
391
392MSH_CMD_EXPORT(hello_world, Hello world!)
393```
394
395The SConcript file in the applications directory will add all source files in the current directory to the project. You need to use the `scons --target=xxx` command to add the 2 new files to your project. Note that the project will be regenerated each time a new file is added.
396
397## Add Module
398
399As mentioned above, in the case that there are not many source code files, it is recommended that all source code files be placed in the applications folder. If the user has a lot of source code and wants to create your own project module, or need to use other modules that you have obtained, what would be appropriate?
400
401Take also hello.c and hello.h mentioned above for example, these two files will be managed in a separate folder, and have their own grouping in the MDK project file, and can be selected through menuconfig whether to use This module. Add a hello folder under BSP.
402
403![New added hello folder](figures/hello.png)
404
405Noticed that there is an additional SConscript file in the folder. If you want to add some of your own source code to the SCons build environment, you can usually create or modify an existing SConscript file. Refer to the above analysis of the SConscript file for the RT-Thread source code. The contents of this new hello module SConscript file are as follows:
406
407```c
408from building import *
409
410cwd          = GetCurrentDir()
411include_path = [cwd]
412src          = []
413
414if GetDepend(['RT_USING_HELLO']):
415    src += ['hello.c']
416
417group = DefineGroup('hello', src, depend = [''], CPPPATH = include_path)
418
419Return('group')
420```
421
422Through the above simple lines of code, a new group hello is created, and the source file to be added to the group can be controlled by the macro definition, and the directory where the group is located is added to the system header file path. So how is the custom macro RT_USING_HELLO defined? Here is a new file called Kconfig. Kconfig is used to configure the kernel, and the configuration interface generated by the menuconfig command used when configuring the system with Env relies on the Kconfig file. The menuconfig command generates a configuration interface for the user to configure the kernel by reading the various Kconfig files of the project. Finally, all configuration-related macro definitions are automatically saved to the rtconfig.h file in the BSP directory. Each BSP has an rtconfig.h file. That is the configuration information of this BSP.
423
424There is already a Kconfig file for this BSP in the stm32f10x-HAL BSP directory, and we can add the configuration options we need based on this file. The following configuration options have been added to the hello module. The # sign is followed by a comment.
425
426```shell
427menu "hello module"                            # create a "hello module" menu
428
429    config RT_USING_HELLO                      # RT_USING_HELLO configuration options
430        bool "Enable hello module"             # RT_USING_HELLO is a bool variable and display as "Enable hello module"
431        default y                              # RT_USING_HELLO can take values y and n, default y
432        help                                   # If use help, it would display "this hello module only used for test"
433        this hello module only used for test
434
435    config RT_HELLO_NAME                       # RT_HELLO_NAME configuration options
436        string "hello name"                    # RT_HELLO_NAME is a string variable and the menu show as "hello name"
437        default "hello"                        # default name is "hello"
438
439    config RT_HELLO_VALUE                      # RT_HELLO_VALUE configuration options
440        int "hello value"                      # RT_HELLO_VALUE is an int variable and the menu show as "hello value"
441        default 8                              # the default value is 8
442
443endmenu                                        # the hello menu is end
444
445```
446
447After entering the stm32f10x-HAL BSP directory using the Env tool, you can use the menuconfig command to see the configuration menu of the new hello module at the bottom of the main page. After entering the menu, the following figure is displayed.
448
449![hello Module Configuration Menu](figures/hello-menu.png)
450
451You can also modify the value of the hello value.
452
453![Modify the Value of Hello Value](figures/hello-value.png)
454
455After saving the configuration, exit the configuration interface and open the rtconfig.h file in the stm32f10x-HAL BSP directory. You can see that the configuration information of the hello module is available.
456
457![hello Module Related Macro Definition](figures/hello-rtconfig.png)
458
459**Note: Use the scons --target=XXX command to generate a new project each time menuconfig is configured.**
460
461Because the RT_USING_HELLO macro has been defined in rtconfig.h, the source file for hello.c is added to the new project when the project is newly built.
462
463The above simply enumerates the configuration options for adding your own modules to the Kconfig file. Users can also refer to @ref page_env, which also explains how to modify and add configuration options. They can also view the Kconfig documentation in your own Baidu to implement other more complex configuration options.
464
465## Add Library
466
467If you want to add an extra library to your project, you need to pay attention to the naming of the binary library by different toolchains. For example, the GCC toolchain, which recognizes library names such as `libabc.a`, specifies `abc` instead of `libabc` when specifying a library. So you need to pay special attention to the SConscript file when linking additional libraries. In addition, when specifying additional libraries, it is also a good idea to specify the corresponding library search path. Here is an example:
468
469```c
470Import('rtconfig')
471from building import *
472
473cwd = GetCurrentDir()
474src = Split('''
475''')
476
477LIBPATH = [cwd + '/libs']
478LIBS = ['abc']
479
480group = DefineGroup('ABC', src, depend = [''], LIBS = LIBS, LIBPATH=LIBPATH)
481```
482
483LIBPATH specifies the path to the library, and LIBS specifies the name of the library. If the toolchain is GCC, the name of the library should be libabc.a; if the toolchain is armcc, the name of the library should be abc.lib.`LIBPATH = [cwd + '/libs']` indicates that the search path for the library is the 'libs' directory in the current directory.
484
485## Compiler Options
486
487`rtconfig.py` is a RT-Thread standard compiler configuration file that controls most of the compilation options. It is a script file written in Python and is used to do the following:
488
489* Specify the compiler (choose one of the multiple compilers you support).
490- Specify compiler parameters such as compile options, link options, and more.
491
492When we compile the project using the scons command, the project is compiled according to the compiler configuration options of `rtconfig.py`. The following code is part of the rtconfig.py code in the stm32f10x-HAL BSP directory.
493
494```c
495import os
496
497# toolchains options
498ARCH='arm'
499CPU='cortex-m3'
500CROSS_TOOL='gcc'
501
502if os.getenv('RTT_CC'):
503    CROSS_TOOL = os.getenv('RTT_CC')
504
505# cross_tool provides the cross compiler
506# EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR
507
508if  CROSS_TOOL == 'gcc':
509    PLATFORM    = 'gcc'
510    EXEC_PATH   = '/usr/local/gcc-arm-none-eabi-5_4-2016q3/bin/'
511elif CROSS_TOOL == 'keil':
512    PLATFORM    = 'armcc'
513    EXEC_PATH   = 'C:/Keilv5'
514elif CROSS_TOOL == 'iar':
515    PLATFORM    = 'iccarm'
516    EXEC_PATH   = 'C:/Program Files/IAR Systems/Embedded Workbench 6.0 Evaluation'
517
518if os.getenv('RTT_EXEC_PATH'):
519    EXEC_PATH = os.getenv('RTT_EXEC_PATH')
520
521BUILD = 'debug'
522
523if PLATFORM == 'gcc':
524    # toolchains
525    PREFIX = 'arm-none-eabi-'
526    CC = PREFIX + 'gcc'
527    AS = PREFIX + 'gcc'
528    AR = PREFIX + 'ar'
529    LINK = PREFIX + 'gcc'
530    TARGET_EXT = 'elf'
531    SIZE = PREFIX + 'size'
532    OBJDUMP = PREFIX + 'objdump'
533    OBJCPY = PREFIX + 'objcopy'
534
535    DEVICE = '-mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections'
536    CFLAGS = DEVICE
537    AFLAGS = '-c' + DEVICE + '-x assembler-with-cpp'
538    LFLAGS = DEVICE + '-Wl,--gc-sections,-Map=rtthread-stm32.map,-cref,-u,Reset_Handler -T stm32_rom.ld'
539```
540
541Where CFLAGS is the compile option for C files, AFLAGS is the compile option for assembly files, and LFLAGS is the link option. The BUILD variable controls the level of code optimization. The default BUILD variable takes the value 'debug', which is compiled using debug mode, with an optimization level of 0. If you modify this variable to something else, it will compile with optimization level 2. The following are all possible ways to write (in short, no 'debug').
542
543```shell
544BUILD = ''
545BUILD = 'release'
546BUILD = 'hello, world'
547```
548
549It is recommended to use the debug mode to compile during the development phase, without optimization, and then consider optimization after the product is stable.
550
551The specific meaning of these options needs to refer to the compiler manual, such as `armcc` used above is the underlying compiler of MDK. The meaning of its compile options is detailed in MDK help.
552
553As mentioned earlier, if the user wants to compile the project with another compiler when executing the scons command, you can use the relevant commands to specify the compiler and compiler paths on the command line side of Env. However, this modification is only valid for the current Env process. When you open it again, you need to re-use the command settings. We can directly modify the `rtconfig.py` file to achieve the purpose of permanently configuring the compiler. In general, we only need to modify the CROSS_TOOL and EXEC_PATH options below.
554
555* CROSS_TOOL:Specify the compiler. The optional values are keil, gcc, iar. Browse `rtconfig.py` to see the compilers supported by the current BSP. If MDK is installed on your machine, you can modify CROSS_TOOL to keil and use MDK to compile the project.
556
557* EXEC_PATH: The installation path of the compiler. There are two points to note here:
558
559(1) When installing the compiler (such as MDK, GNU GCC, IAR, etc.), do not install it in a path with Chinese or spaces. Otherwise, some errors will occur when parsing the path. Some programs are installed by default into the  `C:\Program Files` directory with spaces in between. It is recommended to choose other paths during installation to develop good development habits.
560
561(2) When modifying EXEC_PATH, you need to pay attention to the format of the path. On Windows platforms, the default path splitter is the backslash  `“\”`, which is used for escape characters in both C and Python. So when modifying the path, you can change `“\”` to `“/”`or add r (python-specific syntax for raw data).
562
563Suppose a compiler is installed under `D:\Dir1\Dir2`. The following are the correct ways to write:
564
565* EXEC_PATH = `r'D:\\Dir1\\Dir2'`  Note that with the string `r` in front of the string, `“\”`can be used normally.
566
567* EXEC_PATH = `'D:/Dir1/Dir2'`   Note that instead of `“/”`, there is no `r` in front.
568
569* EXEC_PATH = `'D:\\Dir1\\Dir2'` Note that the escapement of  `“\”` s used here to escape `“\”` itself.
570
571* This is the wrong way to write: EXEC_PATH = `'D:\\Dir1\\Dir2'`。
572
573If the rtconfig.py file has the following code, comment out the following code when configuring your own compiler.
574
575```c
576if os.getenv('RTT_CC'):
577    CROSS_TOOL = os.getenv('RTT_CC')
578... ...
579if os.getenv('RTT_EXEC_PATH'):
580    EXEC_PATH = os.getenv('RTT_EXEC_PATH')
581```
582
583The above 2 `if` judgments will set CROSS_TOOL and EXEC_PATH to the default value of Env.
584
585After the compiler is configured, we can use SCons to compile the BSP of RT-Thread. Open a command line window in the BSP directory and execute the  `scons` command to start the compilation process.
586
587## RT-Thread Auxiliary Compilation Script
588
589In the tools directory of the RT-Thread source code, there are some auxiliary compiled scripts defined by RT-Thread, such as the project files for automatically generating RT-Thread for some IDE. The most important of these is the building.py script.
590
591## SCons Further Usage
592
593For a complex, large-scale system, it is obviously more than just a few files in a directory. It is probably a combination of several folders at the first level.
594
595In SCons, you can write SConscript script files to compile files in these relatively independent directories, and you can also use the Export and Import functions in SCons to share data between SConstruct and SConscript files (that is, an object data in Python). For more information on how to use SCons, please refer to the [SCons Official Documentation](https://scons.org/documentation.html).
596
597