Jednym ze sposobów, aby to zrobić, jest monkey patch funkcja emiterów obiektów, która zamienia kod C++ na pliki obiektów, które można linkować. Istnieją 2 takie funkcje emitera; jeden dla obiektów statycznych i jeden dla obiektów współużytkowanych. Oto przykład, który można skopiować wkleić do SConstruct:
import sys
import SCons.Defaults
import SCons.Builder
OriginalShared = SCons.Defaults.SharedObjectEmitter
OriginalStatic = SCons.Defaults.StaticObjectEmitter
def DoLint(env, source):
for s in source:
env.Lint(s.srcnode().path + ".lint", s)
def SharedObjectEmitter(target, source, env):
DoLint(env, source)
return OriginalShared(target, source, env)
def StaticObjectEmitter(target, source, env):
DoLint(env, source)
return OriginalStatic(target, source, env)
SCons.Defaults.SharedObjectEmitter = SharedObjectEmitter
SCons.Defaults.StaticObjectEmitter = StaticObjectEmitter
linter = SCons.Builder.Builder(
action=['$PYTHON $LINT $LINT_OPTIONS $SOURCE','date > $TARGET'],
suffix='.lint',
src_suffix='.cpp')
# actual build
env = Environment()
env.Append(BUILDERS={'Lint': linter})
env["PYTHON"] = sys.executable
env["LINT"] = "cpplint.py"
env["LINT_OPTIONS"] = ["--filter=-whitespace,+whitespace/tab", "--verbose=3"]
env.Program("test", Glob("*.cpp"))
Nic zbyt skomplikowane o nim naprawdę. Ustawiłeś LINT na ścieżce do swojej kopii cpplint.py i ustawiłeś LINT_OPTIONS dla swojego projektu. Jedynym bitem wartym uwagi jest tworzenie pliku TARGET, jeśli test przechodzi z wykorzystaniem wiersza poleceń date
. Jeśli chcesz być platformą crossową, to musiałaby się zmienić.
Dodanie białej listy jest teraz po prostu regularne kod Python, coś jak:
whitelist = """"
src/legacy_code.cpp
src/by_the_PHB.cpp
"""".split()
def DoLint(env, source):
for s in source:
src = s.srcnode().path
if src not in whitelist:
env.Lint(+ ".lint", s)
Wydaje cpplint.py robi wyjście prawidłowy stan błędu. Gdy występują błędy, zwraca 1, w przeciwnym razie zwraca 0. Nie ma więc dodatkowej pracy. Jeśli sprawdzanie kłaczków nie powiedzie się, nie powiedzie się kompilacja.
To rozwiązanie działa z opcją -j, ale pliki C++ mogą się kompilować, ponieważ nie istnieją żadne niejawne zależności między fałszem danych wyjściowych a celem pliku obiektu. Możesz dodać tam wyraźne env.Depends
, aby wymusić, że wynik ".lint" zależy od celu obiektu. Jak to jest prawdopodobnie wystarczające, ponieważ sama kompilacja się nie powiedzie (scons daje niezerowy kod powrotu), jeśli istnieją jakiekolwiek pozostałe problemy związane z lintem, nawet po wszystkich kompilacjach C++. Aby wszystko było jasne zależy kod byłoby coś takiego w funkcji DoLint:
def DoLint(env, source, target):
for i in range(len(source)):
s = source[i]
out = env.Lint(s.srcnode().path + ".lint", s)
env.Depends(target[i], out)
Aby to działało muszę znać cel wyprzedzeniem. Jak mogę uzyskać listę wszystkich plików .cc/cpp/c oraz .h/hpp w moim projekcie? Muszę również wykluczyć nagłówki, takie jak nagłówki systemowe i doładowania. – Jonathan
@ Jonathan, możesz to zrobić za pomocą dwuwierszowego skryptu. – ismail
@ İsmail, Najlepiej byłoby użyć węzłów już zebranych przez mój skrypt SCONS. Patrzę na moduły SCons.Action, SCons.Job i SCons.Node, ale nie jest oczywiste, gdzie oczekujące kompilacje są w kolejce. – Jonathan