集成 armcc 到 scons

集成 armcc 到 scons

集成 armcc 到 scons 中並不是件容易的事情,如果只是修改 CC/CXX/AR/LINK 幾個環境變量,scons 會用 Visual C++的參數調用方式,比如-c 成了/c,導致 armcc 無法識別。

花了半天時間去閱讀 scons 的源碼後,在 SCons/Tool 目錄下發現,每種編譯器都有一個類似插件的 tool,目測沒有發現 armcc 的 tool,自己爲 armcc 寫一個 tool,應該可以解決這個問題。

ToolsForFools 這篇文章中,瞭解到可以自己定義 tool,只要放到項目的 site_scons/site_tools 目錄下即可。

爲了支持 armcc,我們在 site_scons/site_tools/armcc 目錄中創建一個 armcc 的 tool,從頭編寫一個 tool 還是比較麻煩的,考慮到 armcc 和 cc 類似,就直接把 SCons/Tool/cc.py 拷貝到 site_scons/site_tools/armcc/__init__.py,然後在此基礎上進行修改。

在下面這行代碼之後

add_common_cc_variables(env)

增加下面的代碼:

    armcc = SCons.Tool.find_program_path(env, 'armcc.exe');
    armar = SCons.Tool.find_program_path(env, 'armar.exe');
    armlink = SCons.Tool.find_program_path(env, 'armlink.exe');

    env['CC']      = armcc
    env['CXX']     = armcc
    env['AR']      = armar
    env['LINK']      = armlink
    env['CXXCOM']    = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
    env['ARFLAGS']     = SCons.Util.CLVar('--create -r')
    env['ARCOM']       = '$AR $ARFLAGS $TARGET $SOURCES'
    env['OBJSUFFIX']      = '.o'
    env['LIBPREFIX']      = 'lib'
    env['LIBSUFFIX']      = '.a'

參考 scons 的 Tool 中的代碼,在 SConstruct 文件中,加入下面的代碼,來啓用我們前面定義的 armcc:

env = DefaultEnvironment();
SCons.Tool.Tool('armcc')(env)

使用 scons 編譯,編譯正常了,但是在 armar 生成.a 文件時,出現下面的錯誤:

The command line is too long.

這主要是.o 文件太多所致,armar 並不像 ar 那樣可以通過@符合去文件讀取參數,不過 armar 可以先創建一個.a 文件,然後一個一個的往裏面追加.o 文件。

從 scons 的源碼發現,命令最終是在 SCons/Platform/win32.py 裏調用的。但這是系統文件,直接修改它並不明智,我們還是寫一個 tool 來解決這個問題吧。

爲了避免從頭去實現,把 SCons/Platform/win32.py 拷貝到 site_scons/site_tools/win4armcc/__init__.py,然後再去修改。

  • 先修改下面幾個變量的值爲:
    env['OBJSUFFIX']      = '.o'
    env['LIBPREFIX']      = 'lib'
    env['LIBSUFFIX']      = '.a'
  • 增加一個 exists 函數
def exists(env):
    return True
  • 重新實現 spawn 函數。
def exe_ar(sh, cmd, args, env):
    armar = args[0]
    #args[1] is --create
    #args[2] is -r
    target = args[3];
    objs = args[4:]
    for i in range(len(objs)):
        ARFLAGS='-r'
        if i == 0:
            ARFLAGS='--create -r'

        all_args= [armar, target,  ARFLAGS, objs[i] ]
        sargs = ' '.join(all_args).replace('\\', '/');
        print(str(i) + ': ' + sargs);
        exec_spawn([sh, '/C', sargs], env)

def spawn(sh, escape, cmd, args, env):
    if cmd.endswith('armar.exe'):
        exe_ar(sh, cmd, args, env);
    else:
        sargs = ' '.join(args).replace('\\', '/');
        return exec_spawn([sh, '/C', sargs], env)

同樣,在 SConstruct 文件中啓用 win4armcc。

SCons.Tool.Tool('win4armcc')(env)

好了,現在可以用scons調用armcc了。

完整示例請參考:awtk-scons-armcc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章