2016-02-29 3 views
0

Мы используем косвенность при определении зависимостей библиотеки, например,Scons LIBS linking, как удалить дубликаты LIBS?

env.Program(TARGET, SOURCE, LIBS = [ $LIBS_A, $LIBS_B, $LIBS_C ]) 

LIBS_A, LIBS_B и LIBS_C указаны в других файлах SConscript.

Пусть:

LIBS_A/Sconscript has LIBS_A = [ foo, bar, baz ] 
LIBS_B/Sconscript has LIBS_B = [ foo, bar, bat ] 
LIBS_C/Sconscript has LIBS_C = [ foo, bar, ben ] 

Затем конечный линкер линия будет иметь:

-lfoo -lbar -lbaz -lfoo -lbar -lbat -lfoo -lbar -lben 

Как мы можем удалить дубликаты и иметь компоновщик линии следующим образом:

-lfoo -lbar -lbaz -lbat -lben 
+0

Хмм, если вы хотите, чтобы все эти библиотеки появлялись только один раз, вы должны указать их только один раз для «LIBS». Предоставление lib несколько раз могло бы иметь смысл, когда задействованы круговые зависимости между библиотеками и объектами ... поэтому SCons не сможет решить эту проблему автоматически. – dirkbaechle

+0

Было бы полезно, если образец кода, который вы представляете, фактически запущен .. env.Program не может работать. – bdbaddog

ответ

1

Как это. файлы полностью перечислены.

main.cxx

#include <iostream> 

int main() 
{ 
    std::cout << "Hello World!"; 
} 

SConstruct

env=Environment() 

Export('env') 

for l in ['A','B','C']: 
    env.SConscript("LIBS_%s/SConscript"%l) 

env.Program('myprogram',['main.cxx'], LIBS = list(set(env['LIBS_A'] + env['LIBS_B'] + env['LIBS_C']))) 

LIBS_A/SConscript Импорт ('окр')

env['LIBS_A'] = ['foo','bar','baz'] 

LIBS_B/SConscript Импорт ('окр')

env['LIBS_B'] = ['foo','bar','bat'] 

LIBS_C/SConscript Import ('окр')

env['LIBS_C'] = ['foo','bar','ben'] 

Урожайность:

g++ -o myprogram main.o -lbaz -lbat -lfoo -lbar -lben

Если ни один из них не будет работать для вас, вот более сложный путь, который должен:

class foo(object): 
    def __init__(self, arg): 
     self.arg = arg 

    def __call__(self, target, source, env, for_signature): 
     print "LIBS_A: %s LIBS_B: %s"%(env['LIBS_A'],env['LIBS_B']) 
     rc = list(set(env['LIBS_A']+env['LIBS_B'])) 
     print "Unique: %s"%rc 
     print "SIG:%s"%for_signature 
     return rc 

# Will call our foo method to uniquify LIBS_* 
env=Environment(FOO=foo, BAR="${FOO('$LIBS_A $LIBS_B')}") 

env.Command('foo.XXXXX','foo.in',action="echo LIBS: $LIBS",LIBS="$BAR", 
      LIBS_A=['a','b','c','d','e','f','f','b'], 
      LIBS_B=['b','d','e','g','x']) 
+0

Спасибо за ответ, однако я не вижу, чтобы это работало для нашей ситуации. Я все-таки попробовал это и получил эту ошибку: TypeError: unhashable type: 'list': Я думаю, причина в том, что это не работает, потому что мы используем $ notation (чтобы отложить интерполяцию до тех пор, пока фактически не вызывается команда, а не когда его читают сёны). Это важно, потому что значение, о котором идет речь, может быть не полным в момент его чтения. Поэтому мы используем $ LIB_A и $ LIB_B и $ LIB_C. Эти ценности, в свою очередь, могут также использовать $ notation в своих SConscripts. – rkemp

+0

Сценарии в цикле for должны определять свои локальные зависимости lib так: env ['LIBS_A'] = ['foo', 'bar', 'baz'], ... и так далее, , чтобы Затем SConstruct мог использовать нотацию $ LIBS_A. Ключевым моментом является использование $ notation.Это объясняется тем, что LIBS_B зависит от LIBS_Z, поэтому он будет определен как env ['LIBS_B'] = ['foo', 'bar', 'baz', '$ LIBS_Z'], тем самым приводя к зависимостям LIBS_Z без учета чтобы знать их. Представьте, что это происходит для десятков и десятков библиотек, мы получаем команду компоновщика, в которой есть десятки дублированных библиотек, потому что это график зависимости. – rkemp

+0

Вышеупомянутое будет работать, если вы знали, что у вас могут быть все заявления SConscript до вашего заявления программы. Тогда вы бы сделали что-то вроде; env ['LIBS_A'] = []. env ['LIBS_A'] + = env.Library ('mylibrary', [sources]) для каждой библиотеки, встроенной в SConscript. Это проще, чем вы предлагаете. Будет ли это работать для вас? Помните, что порядок скриптов имеет значение при построении любых структур данных python, используемых в вашем SConscript/SConstruct. Но, конечно же, только строит дерево зависимостей и не должно влиять на порядок выполнения команды. – bdbaddog

1

Это сработало для меня. Большое спасибо @bdbaddog

class uniquify_libs(object): 
    def __init__(self, arg): 
    self.arg = arg 

    def __call__(self, target, source, env, for_signature): 
    rc = list(set(env.subst(env[self.arg])[0].split())) 
    return rc 

LIBS = ['$LIBS_A', '$LIBS_B'] ## defined in other SConscripts 

Program(
    target = TARGET, 
    source = SOURCE, 
    UNIQUE = uniquify_libs, 
    MYLIBS = LIBS, 
    LIBS = "${UNIQUE('MYLIBS')}", 
) 
+0

Вы очень желанны. . :) – bdbaddog