Mam problem z refaktoryzacją systemu budowy opartego na scons. Mamy drzewo źródłowe C/C++ z kilkoma różnymi obiektami wyjściowymi (biblioteki dll, pliki wykonywalne, pliki wykonywalne testów) i nieco niejednorodny układ dla plików źródłowych (chociaż większość z nich znajduje się w katalogach "module" z katalogami src/
i .scons dziedziczenie środowiska budowlanego
Jednym z moich największych problemów z bieżącą konfiguracją jest to, że naprawdę chcemy, aby wszystkie te produkty kompilacji były budowane z domyślnymi opcjami kompilatora. Nasz obecny układ ma główny plik SConstruct, który wywołuje wiele plików pod-SCONScript w podkatalogach, które następnie budują kawałki większych produktów kompilacji (na przykład .a
). Domyślnie funkcja SConscript()
w scons nie przekazuje ani nie dziedziczy bieżącego obiektu środowiska konstrukcyjnego do wywoływanego pliku SConstruct. Oznacza to, że obecnie wszystkie z tych plików podskryptów SConstrip używają własnych, różnych środowisk konstrukcyjnych.
Nowy układ, który próbuję zestawić, ma główne środowisko konstrukcyjne, które jest zestawiane razem z korzeniami drzewa źródłowego wraz ze wszystkimi niezbędnymi CFLAGS i wymaganiami kompilacji, których potrzebujemy. Chciałbym, aby to środowisko konstrukcyjne było przekazywane do plików pod-SConscript, dzięki czemu wiem, że każdy plik .c
i .cpp
w naszym drzewie kompilacji jest budowany za pomocą tego samego wiersza poleceń.
Nie jestem pewien, jak to zrobić w scons. Dostępne są funkcje Import()
i , ale są to w zasadzie brzydkie zmienne globalne - wywołujący plik SConstruct nie ma dużej kontroli nad tym, co robi plik podkontekstury ze zmienną globalną, która jest Export()
'wyd. Czy istnieje jakiś czysty sposób, w zasadzie przekazujący plik pod-SConscript do obecnego środowiska konstrukcyjnego jako parametru, bez konieczności modyfikowania go? Coś może podoba:
master_env = Environment()
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ])
### add other stuff that we want everything to use
SConscript('somelibrary/SConstruct', inherited_environment=master_env.Clone())
### master_env has now been used to build a
### .dll in somelibrary/, but any variations
### made to somelibrary/SConstruct's inherited
### env haven't contaminated master_env
wiem, że mogę zrobić coś niezgrabne i rodzaju brutto takiego:
clobber_env = Environment()
master_env = Environment()
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ])
call_somelibrary_sconstruct(master_env)
def call_somelibrary_sconstruct(env):
param_env = env.Clone()
Export('param_env')
SConstript('somelibrary/SConstruct')
# because we don't want any contamination of our global variable
# between SConscript calls. I'm not even sure if this is necessary
# or does what I think it does because I'm not sure how this ugly
# Export()'d global variable environment works with locals like
# param_env here.
param_env = clobber_env
Export('param_env')
Czy istnieje elegancki sposób to zrobić?
Aktualizacja:
Więc Grałem około z tym trochę więcej, i wygląda na to tak długo, jak to zrobić w pliku mistrz SConstruct:
def build_somelib(env):
Export(env=env.Clone())
somelib = SConscript('somelib/SConscript')
return somelib
master_env = Environment()
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ])
build_somelib(master_env)
a potem w somelib/SConscript
Import('env')
env.Append(CXXFLAGS=['-weirdoption1', ... ])
lib = env.StaticLibrary('somelib', source=['source1.cpp', 'source2.cpp', ...])
Return("lib")
następnie master_env
w głównym SConstruct pozostało nieskażone. To było dla mnie ważne, że Export(env=env.Clone())
działa, ponieważ nie chciałem polegać na wszystkich pod-SConscriptach, aby wykonać funkcję Clone() bezpieczeństwa - ta zasada powinna być nadrzędnymi plikami SConscript/SConstruct.
Nadal jest trochę brzydko, aby mieć nazwę env
jako nazwę parametru według zasad.
Dzięki Tom. Jedna rzecz do dodania: jeśli "env" niekoniecznie jest drugim argumentem, można użyć składni: "exports = 'env''. –
Niestety, nadal pozostawia to klonowanie do uznania modułu podrzędnego, więc nie ma gwarancji, że następny moduł to zrobi. –