Build-Systeme Teil 3: SCons



  • weiß jemand wie ich scons wieder löschen kann??
    bei removescons bekomme ich nur eine Fehlermeldung das das programm zurzeit läuft.



  • Welches OS verwendest du denn?



  • ich verwende WinXP.

    ich hab glaube totalen mist gebaut bei der installation.

    zuerst hab ich es in eine Python installation(2.2) die es schon auf dem system gab installiert. nur da passierte nichts wenn ich scons in der shell eingegeben habe.

    dachte es liegt an Python habe python 2.5 installiert und scons auchnochmal.
    wieder konnte ich scons nicht starten.
    dann habe ich den pfad von python2.5 zum systempfad hinzugefügt.
    dann kannte er den befehl scons, nur leider will er bei mir nun das scons öffnen das ich bei python 2.2 installiert hatte...leck.

    jetzt möchte ich gerne wissen wie ich das scons schön wieder vom rechner entfernen kann.



  • nash35 schrieb:

    ich verwende WinXP.

    ich hab glaube totalen mist gebaut bei der installation.

    zuerst hab ich es in eine Python installation(2.2) die es schon auf dem system gab installiert. nur da passierte nichts wenn ich scons in der shell eingegeben habe.

    dachte es liegt an Python habe python 2.5 installiert und scons auchnochmal.
    wieder konnte ich scons nicht starten.
    dann habe ich den pfad von python2.5 zum systempfad hinzugefügt.
    dann kannte er den befehl scons, nur leider will er bei mir nun das scons öffnen das ich bei python 2.2 installiert hatte...leck.

    jetzt möchte ich gerne wissen wie ich das scons schön wieder vom rechner entfernen kann.

    Wie hast du scons installiert?



  • einfach den aktuellen Win32 installer benutzt



  • nash35 schrieb:

    einfach den aktuellen Win32 installer benutzt

    Dann deinstallierst du in dem du in den Systemsteurungen auf Software gehst und dann SCons rauspickst.



  • damn jetzt taucht es doch in der Systemsteurungen auf.

    Frage, muss man bei SCons noch irgendwas angeben einen Pfad zum compiler(habe VC 2005) oder so?
    so richtig hab ich das mit der idee von scons nämlich noch nicht geblick..



  • nash35 schrieb:

    Frage, muss man bei SCons noch irgendwas angeben einen Pfad zum compiler(habe VC 2005) oder so?
    so richtig hab ich das mit der idee von scons nämlich noch nicht geblick..

    SCons zieht sich den Pfad zum Visual C++ Compiler normalerweise aus den Umgebungsvariablen. Funktioniert denn dies nicht?



  • nun ja ich möchte ein projekt mit scons kompilieren:

    D:\Programmierung\Reflex>scons
    scons: Reading SConscript files ...
    ValueError: list.remove(x): x not in list:
    File "D:\Programmierung\Reflex\SConstruct", line 18:
    'python/SConscript'])
    File "D:\Programmierung\Python25\scons-0.97\SCons\Script\SConscript.py", line
    583:
    return apply(method, args, kw)
    File "D:\Programmierung\Python25\scons-0.97\SCons\Script\SConscript.py", line
    520:
    return apply(_SConscript, [self.fs,] + files, subst_kw)
    File "D:\Programmierung\Python25\scons-0.97\SCons\Script\SConscript.py", line
    245:
    exec _file_ in call_stack[-1].globals
    File "D:\Programmierung\Reflex\python\SConscript", line 58:
    py_files.remove('./genreflex/genreflex-rootcint.py')
    D:\Programmierung\Reflex>

    und das kommt dabei raus?

    hat jemand vielleicht ein anderes test projekt das ich kompilieren kann?



  • Gib bitte mal den Inhalt der SConstruct an.



  • es handelt sich dabei um das Projekt hier
    http://seal-reflex.web.cern.ch/seal-reflex/download.html

    und das ist der inhalt der SConstruct

    from os import curdir
    from os.path import realpath
    
    opts = Options('custom.py')
    
    opts.Add(BoolOption   ('test',    'Set to 1 if tests shall be compiled', 0))
    opts.Add(PathOption   ('prefix',  'The installation directory of Reflex', realpath(curdir)))
    opts.Add(PackageOption('gccxml',  'The >binary< directory of gccxml',     'no'))
    opts.Add(PackageOption('cppunit', 'The >root< directory of CppUnit',      'no'))
    
    env = Environment(options=opts)
    Export('env')
    
    Help(opts.GenerateHelpText(env))
    
    SConscript(['src/SConscript',
                'inc/SConscript',
                'python/SConscript'])
    
    if env['test'] : SConscript('test/SConscript')
    
    env.Alias('install', env['prefix'])
    


  • ihr könnt wohl auch nix damit anfangen, gell?

    mhm ich hab an den Entwickler geschrieben, mal sehen was der dazu sagt.



  • nash35 schrieb:

    ihr könnt wohl auch nix damit anfangen, gell?

    Ne, ehrlich gesagt nicht.



  • Weiß jemand wie ich am einfachsten in verschiedenen *.in Dateien @VERSION@ durch eine Version ersetzen kann? Ich mach es jetzt so:

    import os
    
    version = "0.6.9"
    
    #Replace @VERSION@ in certain files
    files = ["jngl.pc.in", "autopackage/default.apspec.in"]
    for filename in files:
    	newfilename = filename.replace(".in", "")
    	t = Command(newfilename, filename, "sed 's/@VERSION@/" + version + "/g' $SOURCE > $TARGET")
    	Clean(t, newfilename) # Make sure scons -c does clean up tidily
    

    Nur das geht leider nur unter Linux (wegen dem sed-Befehl). Da muss es doch aus was vorgefertiges geben, oder?



  • Ich hoffe ich bin hier richtig, oder sollte man zu Fragen doch lieber einen eigenen Thread auf machen?

    Naja, zu meiner Frage. Und zwar löst SCons bei mir die Abhängigkeiten nicht richtig auf. Ich hab hier ein Projekt welches aus fünf Unterprojekten besteht. Vier dieser Unterprojekte erstellen jeweils eine statische Bibliothek und das fünfte Projekt (eine Binärdatei) bindet diese Biblotheken alle ein. Im Rootverzeichnis habe ich eine SConstruct Datei und in den Build-Verzeichnissen der Unterprojekte jeweils eine SConscript Datei.

    Solange ich nur die 4 Bibliotheken erstellen lasse funktioniert auch alles wunderbar. Aber sobald ich das Projekt mit der Binärdatei, welche die Bibliotheken einbindet, mit aufnehmen kommt SCons aus dem Tritt. Es kompiliert nämlich das Projekt mit der Binärdatei einfach zwischen durch obwohl die Projekte mit den Bibliotheken noch gar nicht alle fertig sind. Logisch dass er dann die Binärdatei nicht gescheit linken kann wenn noch nicht alle Bibliotheken fertig sind.

    Ich habe allerdings versucht meine SConstruct und SConscript Datei so portabel wie möglich zu gestalten damit man diese ohne viele verändern zu müssen auch in anderen Projekten verwenden kann. Evtl. ist mir dort ein grober Schnitzer unterlaufen. Hier mal meine Dateien:

    SConstruct:

    # Projekte (Verzeichnisse) angeben in der Reihenfolge ihrer Abhaengigkeiten.
    # Das erste Projekt ist das unabhaengigste.
    # ["<Projektverzeichnis>", "<Verzeichnis in dem das SConscript liegt>"]
    projects = [["lib1","/build"],
                ["lib2", "/build"],
                ["lib3", "/build"],
                ["lib4", "/build"],
                ["binary", ""]]
    
    # Ab hier muss nichts mehr veraender werden
    print "===================={ Beginne Buildvorgang }===================="
    print "Projekte:"
    for project, build_dir in projects:
    	print "* " + project
    print ""
    
    projectList = ""
    for project, build_dir in projects:
            projectList += project + build_dir + "/SConscript "
    
    SConscript(Split(projectList))
    

    SCon\1:

    from scons_utils import *
    
    # ==============={ Projektspezifische Einstellungen }===============
    # Die Dateiendung der Sourcecodedateien (z.B. *.cpp fuer C++)
    SOURCE_EXTENSION = ".cpp"
    
    # Der Name des zu erstellenden
    OUTPUT_NAME      = "lib1"
    
    # Verzeichnis in welches das fertige Kompilat hinterlegt werden soll
    # (inkl. eventueller temporaerer Zwischendateien (z.B. *.obj))
    BUILD_DIR        = "../build"
    
    # Verzeichnis in dem die Sourcecodedateien liegen (normal "../src")
    # Ein einfaches "." geht leider nicht weil damit die Funktion getSourceFiles() nicht klar kommt
    SRC_DIR          = "../src"
    
    # Verzeichnis in dem die Headerdateien liegen (normal "../include")
    INCLUDE_DIR      = "../include"
    
    # Pfad zu den Bibliotheken
    LIB_PATH         = ""
    
    # Benoetigte Bibliotheken
    LIBS             = ""
    
    # Typ des zu erstellenden Projekts
    # OutputTypeEnum.bin(): Binaerdatei
    # OutputTypeEnum.staticlib(): Statische Bibliothek (z.B. *.lib)
    # OutputTypeEnum.sharedlib(): Dynamische Bibliothek (z.B. *.dll)
    OUTPUT_TYPE      = OutputTypeEnum.staticlib()
    # ==================================================================
    
    # Buildprozess. Hier muss eigentlich nichts veraendert werden.
    env = Environment()
    env.BuildDir(BUILD_DIR, SRC_DIR, duplicate=0)
    src_files = getSourceFiles(SRC_DIR, SOURCE_EXTENSION)
    src_files = Split(src_files)
    
    for i in range(0, len(src_files)):
    	src_files[i] = BUILD_DIR + "/" + src_files[i]
    
    objects = Object(src_files, CPPPATH = INCLUDE_DIR)
    if OUTPUT_TYPE == OutputTypeEnum.bin():
    	env.Program(OUTPUT_NAME, objects, LIBS = LIBS, LIBPATH = LIB_PATH)
    elif OUTPUT_TYPE == OutputTypeEnum.staticlib():
    	env.StaticLibrary(OUTPUT_NAME, objects, LIBS = LIBS, LIBPATH = LIB_PATH)
    elif OUTPUT_TYPE == OutputTypeEnum.sharedlib():
    	env.SharedLibrary(OUTPUT_NAME, objects, LIBS = LIBS, LIBPATH = LIB_PATH)
    

    scons_utils.py:

    import os, string
    
    # Rekursives durchsuchen eines Verzeichnisses nach allen Sourcefiles.
    # Durch die Rekursion werden alle Unterverzeichnisse mit druchsucht.
    def getSourceFiles(dir, src_ext, subpath = ""):
    	srcFiles = ""
    
    	for node in os.listdir(dir):
    		path = dir + "/" + node
    
    		if node.endswith(src_ext):
    			srcFiles += subpath + node + " "
    		elif os.path.isdir(path):			
    			subpath += node + "/"			
    			srcFiles += getSourceFiles(path, src_ext, subpath)
    	return srcFiles
    
    # Enumeration fuer den Output-Typ
    # bin():       Binary (z.B. *.exe)
    # staticlib(): Statische Bibliothek (z.B. *.lib)
    # sharedlib(): Dynamische Bibliothek (z.B. *.dll)
    class OutputTypeEnum:
    	@staticmethod
    	def bin(): return "bin"
    	@staticmethod
    	def staticlib(): return "staticlib"
    	@staticmethod
    	def sharedlib(): return "sharedlib"
    

    Die scons_utils.py habe ich geschrieben um ein paar Dinge zu erleichtern, aber ich denke das ist alles selbsterklärend. Ich hoffe die Länge der Dateien ist nicht zu abschreckend 😉

    Bei der SConscript Datei für das Binary werden zusätzlich halt noch die Bibliotheken bei der LIBS-Variablen mit angegeben.



  • Ehrlich gesagt weiß ich nicht, wie man dein Problem SCons-intern beheben kann, da SCons ja keine Reihenfolge für die Builds definiert... außer per Depends-Funktion, aber das ist nicht so das richtige Mittel.

    Ich würde einfach ein Skript schreiben, welches zuerst die vier Libs baut und dann die binary.



  • Danke für die Antwort.

    Wenn es wirklich nicht anders geht werd ich das wohl tun müssen, auch wenn ich stark gehoft habe dass genau diese Arbeit auch intelligent von SCons erledigt wird. Gerade der fünfte Beitrag von __HIRSCH_H__ hat sich in meinen Ohren nämlich so angehört als wenn in seinem Projekt der "Buildaufbau" sehr ähnlich ist wie in meinem Projekt (wenn nicht sogar noch komplexer) und SCons die Abhängigkeiten unter den verschiedenen Biblotheken aufdröseln könnte und genau weiß was es zuerst kompilieren muss.



  • BugJoe schrieb:

    Danke für die Antwort.

    Wenn es wirklich nicht anders geht werd ich das wohl tun müssen, auch wenn ich stark gehoft habe dass genau diese Arbeit auch intelligent von SCons erledigt wird. Gerade der fünfte Beitrag von __HIRSCH_H__ hat sich in meinen Ohren nämlich so angehört als wenn in seinem Projekt der "Buildaufbau" sehr ähnlich ist wie in meinem Projekt (wenn nicht sogar noch komplexer) und SCons die Abhängigkeiten unter den verschiedenen Biblotheken aufdröseln könnte und genau weiß was es zuerst kompilieren muss.

    Wenn ich mehrere voneinander abhängige Bibliotheken oder Programme baue, mach ich das meistens so, dass ich den Rückgabewert der SharedLibrary Funktion an die entsprechende Program oder SharedLibrary Funktion der abhängigen Bibliothek übergebe.
    Beispiel:

    lib1 = SharedLibrary(myFiles)
    lib2 = SharedLibrary([otherFiles, lib1])
    prog = Program([moreFiles, lib2])
    

    Dann bestimmt scons die Abhängigkeit korrekt.
    Tip: Du kannst die lib/prog objekte aus den Unterverzeichnissen mit Return('lib1') zurückgeben.

    Ich hoffe es hilft dir weiter und du kannst das Konzept in deinen generischen Ansatz einbauen. Wenn ich scons scripte schreibe sind die eigentlich immer massgeschneidert und ziemlich naiv runtergehackt (KISS-Prinzip).



  • Ja, vielen Dank für die Antwort. Werd ich morgen gleich mal ausprobieren. Aber das hört sich sehr gut an 🙂



  • Sehr schöner Artikel. 👍

    Aber ich hab ein Problem mit boost und CheckCXXHeader() vielleicht hat von euch einer eine Idee, meine bisherige google-Suche war nicht erfolgreich.

    if not conf.CheckCXXHeader('boost/test/unit_test.hpp'):
    		print 'Could not find boost/test/unit_test.hpp . Please install boost (www.boost.org)'
    		Exit(1)
    

    Boost ist installiert und die Header liegen auch unter /usr/include/boost/... wenn man das Exit(1) raus nimmt kompiliert auch alles.

    Was ist falsch an der Prüfung, bzw. was mache ich falsch an der Stelle?
    Muss ich noch die System-Include-Verzeichnisse irgendwo angeben?

    Danke


Anmelden zum Antworten