Scons 五:完整的工程

工程的组织目录如下:

├── core

│   ├── inc

│   │   └── bsp.h

│   ├── SConscript

│   ├── src

│   │   ├── fsm.c

│   │   ├── fsm.h

│   │   ├── log.c

│   │   ├── log.h

│   │   └── SConscript

│   ├── test1.c

│   └── test1.h

├── main.c

├── phy

│   ├── inc

│   │   └── phy_inc.h

│   ├── SConscript

│   ├── src

│   │   └── Sconscript

│   ├── test2.c

│   └── test2.h

├── Sconstruct

└── wifi

    ├── inc

    │   └── protol.h

    ├── SConscript

    ├── src

    │   └── SConscript

    ├── test3.c

└── test3.h

分成3个模块core,phy,wifi。每个模块目录下都有inc和src两个文件夹。分别放.h和.c文件。首先来看core模块

Inc中包含bsp.h文件

内容如下。定义了x变量

#define x 1

Src下面分别有fsm.c, fsm.h,log.c,log.h,SConscript

Fsm.c

#include <stdio.h>

#include "fsm.h"

 

void fsm_print()

{

    printf("fsm_log_level=%d\n",fsm_level);

    printf("fsm_print\n");

}

Fsm.h

#define fsm_level 1

void fsm_print();

 

log.c

#include <stdio.h>

#include "log.h"

 

void log_print()

{

    printf("log_print\n");

}

 

log.h

void log_print();

 

SConscript的内容。编译所有的.c文件并且返回所有的obj文件

from SCons.Script import *

from scons.SCons import *

 

Import('env')

 

source_file_list=[]

def find_source_file():

    for file in os.listdir(os.getcwd()):

        if file.endswith('.c'):

            c_path=os.path.join(os.getcwd(),file)

            source_file_list.append(c_path)

 

find_source_file()

 

fsm_object=env.Object(source_file_list)

Return('fsm_object')

 

在core目录下有test1.c,test1.h, SConscript

Tets1.c

 

#include <stdio.h>

#include "bsp.h"

 

void core_test()

{

    printf("x=%d\n",x);

    printf("core_test1\n");

}

 

Test1.h

void core_test();

 

SConscript

import sys

import os

import re

from SCons.Script import *

from scons.SCons import *

Import('env')

subdir = ''

subdir +='src '

 

source_file_list=[]

include_file_list=[]

 

incdir = ''

incdir +='inc '

object_list=[]

 

def find_source_file():

    for file in os.listdir(os.getcwd()):

        if file.endswith('.c'):

            c_path=os.path.join(os.getcwd(),file)

            source_file_list.append(c_path)

 

def scons_script_recursive():

    print("scons_script_recursive,subdir=%s\n" % subdir)

    subdir_list=subdir.split(' ')

    print(subdir_list)

    subdir_list.pop()

    for dir in subdir_list:

        dir_path=os.path.join(os.getcwd(),dir)

        obj=SConscript(os.path.join(dir_path,'SConscript'))

        object_list.append(obj)

 

 

def get_include_path():

    dir_tmp=incdir.split(' ')

    dir_tmp.pop()

    for include_file in dir_tmp:

        include_file_path=os.path.join(os.getcwd(),include_file)

        include_file_path_env=include_file_path+' '

        env.Append(include=include_file_path_env)

        include_file_list.append(include_file_path)

 

 

 

scons_script_recursive()

get_include_path()

find_source_file()

core_object=env.Object(source_file_list,CPPPATH=include_file_list)

object_list.append(core_object)

env.Library('core',object_list)

 

1 首先递归的执行子目录下的SConscript,并且将返回的obj对象append到object_list

2 找到当前目录下所有的.c文件并编译成object文件append到object_list

3 将object_list中的所有.o文件打包成.a文件供后面连接使用

 

同样的步骤适合phy和wifi模块

Phy模块test2.c

#include <stdio.h>

#include "phy_inc.h"



void phy_test()

{

    printf("phy=%d\n",phy);

    printf("phy_test1\n");

}

 

Test2.h

void phy_test();

 

phy_inc.h

#define phy 3

 

 

wifi模块

test3.c

#include <stdio.h>

#include "protol.h"

 

void wifi_test()

{

    printf("version=%d\n",version);

    printf("wifi_test1\n");

}

 

Test3.h

void wifi_test();

 

protol.h

#define version 4

 

 

最后main.c的代码如下:

#include <stdio.h>

#include "test1.h"

#include "test2.h"

#include "test3.h"

#include "fsm.h"

#include "log.h"



void main()

{

    printf("test1.c\n");

    iot_core_test();

    phy_test();

    wifi_test();

    fsm_print();

    log_print();

}

 

SConscript:

import sys

import os

import re

from SCons.Script import *

from scons.SCons import *

from build_software import *

 

env = Environment()

env['subdir']='core '

env.Append(subdir='phy ')

env.Append(subdir='wifi ')

env['include']=''

Export('env')

print(env['subdir'])

 

source_file_list=[]

 

target='main'

 

link_path=['core','phy','wifi']

obj_list=[]

obj_path_list=[]

 

 

include_path_list=[]

 

inc_path = 'core/src '

 

 

def find_source_file():

    for file in os.listdir(os.getcwd()):

        if file.endswith('.c'):

            source_file_list.append(file)

 

 

def find_all_object_file():

    complete_path=[]

    for link in link_path:

        complete_path.append(os.path.join(os.getcwd(),link))

    for path in complete_path:

        for root,dir,files in os.walk(path):

            for f in files:

                if f.endswith('.o'):

                    print(f)

                    obj_path_list.append(root)

                    obj_list.append(f)

 

 

 

def find_all_include_path():

    tmp_path_list=inc_path.split(' ')

    for tmp_path in tmp_path_list:

        tmp_path=os.path.join(os.getcwd(),tmp_path)+' '

        env.Append(include=tmp_path)

    include_path=env['include'].split(' ')

    include_path.pop()

    for path in include_path:

        include_path_list.append(path)

    for l in link_path:

        include_path_list.append(os.path.join(os.getcwd(),l))

 

def get_target():

    Progress("get_target")

    main=env.Program('main.c',CPPPATH=include_path_list,LIBS=obj_list)

 

 

 

subdir_path=env['subdir'].split(' ')

subdir_path.pop()

 

 

def sub_scons():

    path_list=[]

    for scons_file in subdir_path:

        path=os.path.join(os.getcwd(),scons_file)

        path_list.append(os.path.join(path,'SConscript'))

    SConscript(path_list)

    complete_flag=True

 

 

sub_scons()

find_source_file()

find_all_include_path()

env.Append(LIBPATH=['./core','./phy','./wifi'])

env.Program('main.c',CPPPATH=include_path_list,LIBS=link_path)

 

1 执行子目录的SConscript文件

2 找到当前目录下的所有c文件

3 找到所有的include路径

4 设置外部链接library的路径和名称,最终编译main.c文件

 

最终执行结果:

scons: Reading SConscript files ...

scons_script_recursive,subdir=src

['src', '']

scons: done reading SConscript files.

scons: Building targets ...

gcc -o core/src/fsm.o -c core/src/fsm.c

gcc -o core/src/log.o -c core/src/log.c

gcc -o core/test1.o -c -Icore/inc core/test1.c

ar rc core/libcore.a iot_core/src/fsm.o iot_core/src/log.o core/test1.o

ranlib core/libiot_core.a

gcc -o main.o -c -Iiot_core/inc -Iphy/inc -Iwifi/inc -Iiot_core/src -I. -Iiot_core -Iphy -Iwifi main.c

gcc -o phy/test2.o -c -Iphy/inc phy/test2.c

ar rc phy/libphy.a phy/test2.o

ranlib phy/libphy.a

gcc -o wifi/test3.o -c -Iwifi/inc wifi/test3.c

ar rc wifi/libwifi.a wifi/test3.o

ranlib wifi/libwifi.a

gcc -o main main.o -Liot_core -Lphy -Lwifi -lcore -lphy -lwifi

scons: done building targets.

如果我们想将目标文件安装到系统路径中去,也就是可以运行命令的方式那样运行目标文件。可以用install的方式。

在Sconstruct的最后几行修改如下:将最终编译的文件安装到/usr/local/bin目录下

tar=env.Program('main.c',CPPPATH=include_path_list,LIBS=link_path)
env.Install('/usr/local/bin',tar)
env.Alias('install','/usr/local/bin')

执行命令sudo scons install

会增加如下的打印:表示main安装到了/usr/local/bin下

Install file: "main" as "/usr/local/bin/main"

posted @ 2020-06-15 11:55  red_leaf_412  阅读(819)  评论(0编辑  收藏  举报