天天看點

scons使用(帶小例子和makefile對比)

一、簡介

  1. scons 和 make 都是 都是用來管理項目編譯的。
  2. scons 通過 SConscript 檔案管理編譯。make通過makefile管理編譯
  3. scons 一般這樣管理 項目編譯。

    在頂層的 SConstruct 檔案中, 使用函數 DefaultEnvironment 。

    CPPPATH=[’./’];

    TOOLS_PREFIX=‘arm-linux-’

    Environment(CCFLAGS = CCFLAGS,

    CC=TOOLS_PREFIX+‘gcc’,

    CXX=TOOLS_PREFIX+‘g++’,

    LD=TOOLS_PREFIX+‘g++’,

    AR=TOOLS_PREFIX+‘ar’,

    STRIP=TOOLS_PREFIX+‘strip’,

    LIBS = LIBS,

    LIBPATH = LIBPATH,

    CPPPATH = CPPPATH,

    LINKFLAGS = LINKFLAGS,

    OS_SUBSYSTEM_CONSOLE=OS_SUBSYSTEM_CONSOLE,

    OS_SUBSYSTEM_WINDOWS=OS_SUBSYSTEM_WINDOWS);

    設定好要編譯的子目錄

    SConscriptFiles=[’./hello/SConscript’];

    SConscript(SConscriptFiles);

    而後在下層目錄中:

    env = DefaultEnvironment().Clone();

    env.Program(target=‘hello’,source=‘hello.c’);

    而後在頂層目錄執行scons指令編譯。

二、scons和makefile 對應關系

功能 make實作 scons實作 備注
指定包含頭檔案的實作 使用 -I 指定-I./ -I/opt/build/include CPPPATH =["./","…/Include"];這是一個清單
添加編譯選項 使用-直接指定,比如 -O3 -Wall.一般放在CFLAGS中 CCFLAGS="-DDEBUG -DHAS_TEST";這是一個字元串。
指定編譯器 CC= CC=‘mipsel-linux-’ + ‘gcc’ ; 這是一個字元串
指定要連結的庫 LIBS="-lpthread -lcurl" LIBS=[‘pthread’,‘curl’]; 這是一個清單
安裝 建立一個install目标;install: env.Install(’/bin’, source = [‘desmon’]);其實可以在生成的時候指定目錄,就不需要執行install操作了。
clean 建立一個clean目标;clean: env.Clean(’/bin’, ['desmon]);如果沒有寫clean預設會把新生成的内容删掉。
生成靜态庫 ar rcs -o libtest.a hello1.o hello2.o env.StaticLibrary(target=‘libtest’,source=[‘hello1.c’,‘hello2.c’]); 使用env.Library(target=‘libtest’,source=[‘hello1.c’,‘hello2.c’]);預設生成的是靜态庫
生成動态庫 gcc -shared -o libtest.so name1.o name2.o name3.o env.SharedLibrary(‘libtest’, [‘name1**.**o’, ‘name2.o’, ‘name3.c’])
生成可執行程式 gcc -o hello hello.c env.Program(target=‘hello’,source=[‘hello.c’]);
編譯多個目錄 SUBDIR=xxx xxx xxx ; for i in $(SUBDIRS); do $(MAKE) -C $$i all; sleep 2; done;要使用for循環周遊

将要編譯的目錄放到清單SConscriptFiles中。執行SConscript(SConscriptFiles);

SConscriptFiles=[’./src/SConscript’,’./test/SConscript’];

SConscript(SConscriptFiles);

導入環境變量 export HAS_CURL 1 導入os,然後使用os.environ[‘HAS_CURL’]=‘1’;
連結庫的路徑 -L./;使用 -L指定 LIBPATH=[’./’]; 使用LIBPATH指定。

三、scons 的常用方法

  1. 操作路徑。
    1. 經常會有要組裝路徑的情況。
      os.path.join(root, subdir);
    2. 使用這個方法将路徑組裝起來。
  2. 擷取目前路徑。
    1. os.getcwd()。其實是python 的os子產品。不過很有用。
  3. 設定環境變量
    1. os.environ [‘key’]=‘value’; 也是python os子產品的使用。
  4. 通路某個檔案夾下的某些檔案。
    1. Glob(’./*.c’); 目前目錄下的所有的.c檔案。并且傳回一個清單
    2. Glob(’./lcd*.c’);通路目前目錄下所有的lcd開頭的.c檔案,并且傳回一個清單。
  5. 建立env對象,管理編譯參數
    1. 一般在最上層的SConstruct檔案中,會執行DefaultEnvironment(CCFLAGS = CCFLAGS,

      CC=TOOLS_PREFIX+‘gcc’,

      CXX=TOOLS_PREFIX+‘g++’,

      LD=TOOLS_PREFIX+‘g++’,

      AR=TOOLS_PREFIX+‘ar’,

      STRIP=TOOLS_PREFIX+‘strip’,

      LIBS = LIBS,

      LIBPATH = LIBPATH,

      CPPPATH = CPPPATH,

      LINKFLAGS = LINKFLAGS,

      OS_SUBSYSTEM_CONSOLE=OS_SUBSYSTEM_CONSOLE,

      OS_SUBSYSTEM_WINDOWS=OS_SUBSYSTEM_WINDOWS);類似這樣,傳入需要的參數。

    2. 而後在子目錄中,使用env = DefaultEnvironment().Clone();
    3. 然後可以執行其它的操作。比如 env.Program(target=‘hello’,source=‘hello.c’);這樣會根據頂層目錄傳入的參數對hello.c進行編譯。
    4. 可以使用evn[‘CPPPATH’] 來通路目前頭檔案包含路徑。這是字典的資料結構。頂層目錄也可以使用這種方法指派。

四、簡單案例

  1. 現在有個小項目,目錄結構如下:
    scons使用(帶小例子和makefile對比)
  2. 頂層SConstruct檔案内容。指定在目前目錄,或者是在 ‘./hello’ 目錄找 包含的頭檔案。
    CPPPATH=['./','./hello'];
    
    DefaultEnvironment(CPPPATH=CPPPATH);
    
    ConstructScriptFiles=['./hello/ConstructScript'];
    
    SConscript(ConstructScriptFiles);
               
  3. hello/ConstructScript檔案内容。這裡指定利用./hello.c 生成 test可執行程式。
    sources = ['./hello.c'];
    env = DefaultEnvironment().Clone();
    env.Program(target='test',source=sources);
    
               
  4. hello.c 檔案内容。這裡注意 include<hello.h>是 用的尖括号。也就是說如果你不指定hello.h的目錄的話,是找不到的。
    #include<hello.h>
      
    int main()
    {
            printf(HELLO);
            printf("\n");
            return 0;
    }
               
  5. hello.h 檔案内容
    #include<stdio.h>
      
    #define HELLO "Hello World"
    
               
  6. 在頂層執行scons,将生成test檔案。
scons使用(帶小例子和makefile對比)

繼續閱讀