Ist es möglich bei Visual Studio 2010 ein C# Programm auch für Linux zu kompilieren?



  • Dravere schrieb:

    Schliesslich ist .Net wie Java eine interpretierte Sprache.

    Bis zu dem Satz hat alles im Beitrag gestimmt 🙂 .Net Code wird in keinster Weise interpretiert. Er wird immer vor der Ausführung durch den JIT Compiler in nativen Code kompiliert. Bei Java ist es nen bissle uneindeutiger, in aller Regel wird da heute aber auch kaum mehr was interpretiert.



  • JIT
    Natürlich werden in Java der meiste wenn nicht sogar der vollständige Byte-Code nativ kompiliert. Deswegen dauert der Erststart einer Anwendung lange, wenns aber erst läuft dann läuft es verdammt flüssig. Bestimmte Algorhitmen laufen durch den intelligenten JIT unter Java sogar schneller als einer von einem C++-Compiler generierter (ja, flamet mich zu, ist aber so 😃 )

    .NET-Executables sind in der Regel auch nichts anderes als Byte-Code, nur halt eben mit einem PE-Header für das Framework.



  • Zwergli schrieb:

    Dravere schrieb:

    Schliesslich ist .Net wie Java eine interpretierte Sprache.

    Bis zu dem Satz hat alles im Beitrag gestimmt 🙂 .Net Code wird in keinster Weise interpretiert. Er wird immer vor der Ausführung durch den JIT Compiler in nativen Code kompiliert. Bei Java ist es nen bissle uneindeutiger, in aller Regel wird da heute aber auch kaum mehr was interpretiert.

    Genau.
    Und wenn überhaupt, dann müsste man sagen dass die IL bzw. der Bytecode die "interpretierte Sprache" ist. Sowohl Java als auch C# werden zu 100% compiliert, ohne JIT, direkt vom Compiler.
    Nur dass der Compiler dann üblicherweise keinen Maschinencode für existierende Maschinen ausspuckt, sondern die IL/den Bytecode für die jeweilige VM.



  • hustbaer schrieb:

    Nur dass der Compiler dann üblicherweise keinen Maschinencode für existierende Maschinen ausspuckt, sondern die IL/den Bytecode für die jeweilige VM.

    Hmm, im Falle von .NET wird der Code vor der ersten Ausführung auf der Zielmachine compiliert. Das ist gerade eine der Stärken von .NET, da der JIT aif der Zielmachine Optimierungen gezielt für CPU, Speicher etc berücksichtigen kann.



  • loks schrieb:

    hustbaer schrieb:

    Nur dass der Compiler dann üblicherweise keinen Maschinencode für existierende Maschinen ausspuckt, sondern die IL/den Bytecode für die jeweilige VM.

    Hmm, im Falle von .NET wird der Code vor der ersten Ausführung auf der Zielmachine compiliert. Das ist gerade eine der Stärken von .NET, da der JIT aif der Zielmachine Optimierungen gezielt für CPU, Speicher etc berücksichtigen kann.

    C# wird vom "normalen" Compiler vollständig nach IL übersetzt.
    Der IL-Code wird dann vor der Ausführung erstmal geJITed. Vom .NET Framework. Das ist halt so, müsste aber nicht so sein.

    Im Falle Java z.B. gibt es CPUs, die Java-Bytecode "native" ausführen können. OK, diese CPUs übersetzen das intern natürlich erstmal in was anderes, aber das machen sie halt selbst. Genau so wie ein Pentium/Core2/Athlon/Core i/... den x86 bzw. AMD64 Code erstmal intern in was anderes übersetzt.

    Sogesehen besteht zwischen Java, C# und C++ kein grundlegender Unterschied was das Thema "compiliert vs. geJITed vs. interpretiert" angeht.


  • Administrator

    Der JIT bei Java und .Net ist eigentlich nur ein Interpreter. Somit sind Java und .Net für mich interpretierte Sprachen. Der JIT ist für mich in dem Ganzen nur ein Optimierungstool. Man kann da auch andere Beispiele nehmen. Lua ist auch interpretiert und hat ebenfalls einen JIT mit LuaJIT. Wenn ich mich recht Erinnere gibt es ebenfalls für Python, welches eine interpretierte Sprache ist, einen JIT. Die Browser-Hersteller setzen inzwischen bei der interpretierten Sprache Javascript ebenfalls einen JIT ein.

    Nichts desto trotz bleiben dies alle interpretierte Sprachen. Sie werden eben nicht direkt in Maschinensprache übersetzt. Und oft kann auch der JIT nicht alles in Maschinensprache übersetzen oder muss zur Laufzeit Dinge neu übersetzen, in dem er die entsprechenden Bereiche neu interpretiert.

    Der JIT könnte man fast auf ein Cache für Maschinencode reduzieren. Ein reines Optimierungswerkzeug.

    Grüssli



  • @Dravere
    Diese Argumentation lässt sich genau so auf AMD64 Code anwenden.

    Wichtig ist IMO trotzdem noch die Unterscheidung IL <-> C#.
    C# wird niemals niemals nie interpretiert.

    IL zwar auch nicht, aber da kann man durchaus streiten. D.h. auf IL bezogen verstehe ich deine Argumentation, auch wenn ich die Sache anders sehe.
    Auf C# bezogen ist sie aber einfach nur falsch 🤡

    EDIT

    Und oft kann auch der JIT nicht alles in Maschinensprache übersetzen oder muss zur Laufzeit Dinge neu übersetzen,

    Hast du ein Beispiel? Wenn selbstmodifizierender Code o.ä. erlaubt wäre, dann OK. Wenn Code zur Laufzeit neu generiert wird auch. Aber davon abgesehen fällt mir jetzt nix ein.

    in dem er die entsprechenden Bereiche neu interpretiert.

    Der JITer compiliert, oder wenn du willst: übersetzt. Er interpretiert aber schonmal sicher nix. Also bei .NET. Bei Java weiss ich nicht, ich glaube da gab's mal Implementierungen die erstmal alles interpretiert haben mit automatischem profiling, und dann profile-guided geJITet haben. Bzw. zumindest hat man sich das unter Javarianern damals so erzählt.


  • Administrator

    @hustbear,
    Gut, C#, VB.Net, F#, usw. wird in CIL oder IL übersetzt und danach interpretiert. Das ist für mich aber ein eher unwichtiger Unterschied. Ob CIL oder C#, Java oder Java-Bytecode es ist einfach nur eine andere Form des Gleichen.

    Vielleicht müsste man auch zuerst mal definieren, was überhaupt eine interpretierte Sprache ausmacht. Ist für dich z.B. Javascript eine interpretierte Sprache? Obwohl heute viele Implementierungen einen JIT verwenden? Oder hängt dies auch mit der Ausführungsumgebung zusammen? Somit könnte auch C# (nicht CIL!) interpretiert sein, da es C# Interpreter gibt 😉

    Ich sehe meistens ein Hauptproblem bei solch einer Diskussion. Die Leute wollen "ihre" Sprache nicht als interpretiert abstempeln, weil sie damit etwas langsames verbinden.

    Naja, ich will mich hier jetzt nicht ausführlicher äussern, da ich meine Argumente nur schlecht rüber bringen kann. Ich bin ***** müde und schlafe gleich auf der Tastatur ein 😉

    Grüssli



  • Dravere schrieb:

    @hustbear,
    Gut, C#, VB.Net, F#, usw. wird in CIL oder IL übersetzt und danach interpretiert. Das ist für mich aber ein eher unwichtiger Unterschied. Ob CIL oder C#, Java oder Java-Bytecode es ist einfach nur eine andere Form des Gleichen.

    Also für mich ist das ein wichtiger Unterschied.

    Vielleicht müsste man auch zuerst mal definieren, was überhaupt eine interpretierte Sprache ausmacht.

    Müsste man wohl.

    * Eine Sprache die nur interpretiert und nie (vollständig) native übersetzt werden kann. Schliesst fast alle Sprachen aus.
    * Eine Sprache die auch interpretiert werden kann. Schliesst fast alle Sprachen ein.
    * Eine Sprache die üblicherweise interpretiert wird. Ist etwas schwammig. Und schliesst IMO C#, Lua etc. aus.
    * Eine Sprache die üblicherweise (zumindest teilweise) zur Runtime interpretiert oder geJITed wird.

    Ich glaube aber dass du was ganz anderes meinst, wo IMO der Begriff "interpretiert" schon gar nicht angebracht ist. Nämlich das Vorhandensein von viel Meta-Infos, und diversen Features die sich mit compilierten Sprachen nur mit Einbindung eines Compilers machen lassen. Wie z.B. das "Ausführen von Strings".

    ----

    Wenns dich morgen noch freut schreib vielleicht mal ganz grob was du dir als Definition vorgestellt hättest.



  • Hallo,

    die Unterscheidung zwischen kompiliert und interpretiert ist eigentlich ganz einfach zu machen. Bei der Kompilation wird Maschinencode generiert wird, sprich selber lauffähig, bei der Interpretation wird die Anweisung nicht in Maschinencode umgewandelt, sondern der Interpreter führt die Anweisung aus. Es ist also eine zweite Instanz zur Durchführung der eigentlichen Aktion notwendig.

    .Net Code liegt nach der Kompilation durch den "Sprachencompiler" (C#, VB.Net, C++/CLI usw.) als Byte Code (hier CIL) vor, das ist natürlich richtig. Aber dieser Bytecode wird immer! vor der Ausführung in Maschinencode kompiliert durch den JIT Compiler und erst dieser Maschinencode wird direkt ausgeführt. Deshalb ist die Verwendung des Begriffes interpretiert bei .Net völlig falsch, da da nichts interpretiert wird. Die Möglichkeit Bytecode zu interpretieren gibts bei .Net gar nicht.

    Bei Java gibts dagegen beides. Bei den ersten Versionen wurde der Java Bytecode interpretiert, aber den JIT Compiler gibts da mittlerweile auch schon ewig und der wird heute defaultmäßig eingesetzt.

    Dieser ganze Prozess Prozess bei .Net ist nicht ganz einfach zu sehen für den User, da der Sprachencompiler wie schon gesagt wurde, eine PE Datei (mit der Endung exe) erzeugt die CIL enthält. Der JIT Compiler erzeugt aber keine neue Datei, sondern ersetzt in genau dieser Datei den Bytecode durch entsprechenden, kompilierten Maschinencode und dieser wird dann ausgeführt. Deshalb ist der ganze Prozess auch so undurchsichtig von außen und man könnte auf die Idee kommen das die .Net Runtime direkt den Bytecode verwendet, dem ist aber nicht so. Ob eine Exe jetzt Bytecode oder schon Maschinencode enthält (vielleicht durch ngen schon vorerzeugt),sieht man der Datei ohne tiefere Betrachtung nicht an.

    Aber da gibts gute Literatur zu wie z.B. "CLR via C#" von Jeffrey Richter.

    Der deutsche Wikibeitrag zu Interpreter ist übrigens falsch. Dort wird geschrieben, dass der JIT Compiler den Code in Maschinencode kompiliert der direkt ausgeführt wird und im nächsten Satz wird gesagt, dass der JIT Compiler ein Interpreter ist 😕
    Der englische dagegen erklärts richtig: http://en.wikipedia.org/wiki/Interpreter_(computing).



  • @Zwergli: Guter Beitrag! 👍



  • Kann man ja nachvollziehen.
    Wenn man eine .Net Applikation das erste mal auf ein System startet ist es recht langsam, das liegt daran das der IL Code in den AssemblyCache gebaut wird und von dort dann nur noch ausgeführt. Beim nächsten start merkt die Runtime dann das sich der IL nicht geändert hat und der Build noch da ist und startet direkt ohne bau.
    Dadurch sind alle nachfolgenden Starts der selben Applikation schneller.



  • Zwergli schrieb:

    die Unterscheidung zwischen kompiliert und interpretiert ist eigentlich ganz einfach zu machen. Bei der Kompilation wird Maschinencode generiert wird, sprich selber lauffähig, bei der Interpretation wird die Anweisung nicht in Maschinencode umgewandelt, sondern der Interpreter führt die Anweisung aus.
    http://en.wikipedia.org/wiki/Interpreter_(computing).

    Dem will ich widersprechen. Interpreter können mindestens in zwei Architekturformen vorkommen.

    - Code liegt als Datenstruktur vor, der über eine Maschinenform(Stack oder Register) getrieben wird (Abstrakte Maschine)
    - Code wird zur Laufzeit in Maschinencode transformiert.



  • Und wo ist jetzt der Widerspruch?



  • David W schrieb:

    Und wo ist jetzt der Widerspruch?

    Seine Aussage war, dass beim Interpreter nicht ins Maschinenform übersetzt wird.



  • Und was soll man mit deinem Widerspruch jetzt anfangen? Ein Argument wär nicht schlecht.



  • Zeus schrieb:

    Interpreter können mindestens in zwei Architekturformen vorkommen
    ...
    Code wird zur Laufzeit in Maschinencode transformiert.

    Das ist kein Interpreter! Wenn Code von einer Form in eine andere umgesetzt wird, ist das eine Kompilation.

    Meine Aussage im vorherigen Beitrag war da vielleicht nicht ganz korrekt:

    Bei der Kompilation wird Maschinencode generiert

    stimmt so natürlich nicht ganz. Das ist sehr oft der Fall, aber im Prinzip ist die Compilation allgemein nur eine Umsetzung von einer Form in eine andere.

    Ich glaube der Grund warum es soviel Missverständnis gibt, sind die verschiedenen Mischformen die auftreten können.

    Es gibt ja durchaus Systeme die Code aus der Ursprungssprache erst in eine Zwischenform überführen (das ist eindeutig Compilation) und diese dann interpretieren indem ein Interpreter den Code verarbeitet und die Aktionen ausführt die der Code beschreibt. Sowas gibts z.B. wenn Java Bytecode interpretiert wird. Aber JIT Compiler interpretieren nichts, da sie ja nicht selber den Code ausführen sondern in Maschinensprache übersetzen und die wird dann durch die CPU ausgeführt.

    Bei .Net ist im Prinzip einfach der Compiliervorgang in zwei klar zu unterscheidene Stufen unterteilt. Erst Sprachcompiler(z.B: C# -> CIL) und dann JIT Compiler (CIL -> Maschinencode). Bei vielen anderen Sprachen wo der Compiler direkt ausführbaren Code ausspuckt wird auch nichts anderes gemacht. Erst wird die Ursprungssprache in eine Zwischenform gebracht wo dann optimiert wird etc. und dann wird daraus der Maschinencode erstellt. Nur das es dort ein Programm macht, und bei .Net und Java ist das in zwei Teile unterteilt die zu verschiedenen Zeiten stattfinden. Ich weiß beim besten Willen nicht wie man da auf die Idee kommt da wird was interpretiert.



  • http://en.wikipedia.org/wiki/Just-in-time_compilation schrieb:

    Interpreted code is translated from a high-level language to a machine code continuously during every execution, whereas statically compiled code is translated into machine code before execution, and only requires this translation once.

    Genauso hab ich auch im Compilerbau gelernt, dass ein Interpreter ein Compiler ist mit dem unterschied, dass dein Eingabeprogramm in einem Form vorhanden ist, die vom Prozessor nicht verstanden wird. Die Compilerphase sind die Gleiche. In diesem Sinn ist der C#-Übersetzen ein Compiler ist, und der JIT-Compiler ein Interpreter ist(der Compiler im Name ist durchaus berechtigt, weil er im Kontext von sich selbst ein Compiler ist, aber im Bezug zum Anwendungsstart ein Interpreter ist).

    Im diesen Sinn hab ich gerade mein Widerspruch eliminiert.


  • Administrator

    hustbaer schrieb:

    Wenns dich morgen noch freut schreib vielleicht mal ganz grob was du dir als Definition vorgestellt hättest.

    Wenn es mich noch freut? Ich muss ja wohl fast, weil ich die ganze Diskussion überhaupt ausgelöst habe 😃

    Aber zuerst etwas zum bisher geschriebenen. Ich bin mir ziemlich sicher, dass wir hier alle genau wissen, wie ein JIT funktioniert (z.B. unter .Net), und halte es daher für unnötig auf sprachliche Ungenauigkeiten einzugehen. Meiner Meinung nach läuft dies alles nur auf eine andere Sichtweise/Definition hinaus. Die Definition von Zwergli ist meiner Meinung nach somit nicht falsch. Sie ist einfach nur eine andere Betrachtungsweise.

    Ich selber sehe den JIT-Compiler als wichtiges Tool in der aktuellen Entwicklungsstufe eines Interpreters an. Ich definiere womöglich für eure Verhältnisse einen Interpreter etwas zu offen. Für mich ist ein Interpreter einfach ein Programm, welches benötigt wird, um ein anderes Programm auszuführen. Programm I interpretiert Programm B und sorgt dafür, dass B ausgeführt wird. Wie diese Ausführung passieren muss, lasse ich bewusst offen. Bei einem Interpreter mit einem JIT, wird halt eine Kompilierung z.B. zu Maschinencode durchgeführt, das Resultat wird gespeichert (daher sprach ich weiter vorne von einem Cache) und ausgeführt. Der JIT ist für mich ein Teil eines Interpreters.

    Der JIT-Kompiler ist für mich wirklich nur ein Kompiler. Und ein Kompiler führt nunmal nichts aus, sondern übersetzt nur. Das Ganze um den JIT-Kompiler ist für mich der Interpreter. Und daher sind Java, .Net Sprachen, usw. für mich interpretierte Sprachen, weil sie einen Interpreter benötigen.

    Grüssli



  • Hallo,

    Zeus schrieb:

    http://en.wikipedia.org/wiki/Just-in-time_compilation schrieb:

    Interpreted code is translated from a high-level language to a machine code continuously during every execution, whereas statically compiled code is translated into machine code before execution, and only requires this translation once.

    ..., und der JIT-Compiler ein Interpreter ist(der Compiler im Name ist durchaus berechtigt, weil er im Kontext von sich selbst ein Compiler ist, aber im Bezug zum Anwendungsstart ein Interpreter ist).

    Dem zitierten von Wikipedia stimm ich vollkommen zu da es genau meine Argumentation stützt. .Net Code wird einmalig in Maschinencode kompiliert, nicht jedes mal so wie es die zitierte Definition ja von Interpretern verlangt - > Sprich, da ist nichts von wegen Interpretation. Nur weil die endgültige Compilation von Bytecode in Maschinencode praktisch on the fly beim Programmstart durchgeführt wird ist es doch nicht auf einmal eine Interpretation.

    Dravere schrieb:

    Für mich ist ein Interpreter einfach ein Programm, welches benötigt wird, um ein anderes Programm auszuführen.

    Da geh ich mit. Bei interpretiertem Code ist der Interpreter derjenige der den Code ausführt und nicht das Programm selber weils in Maschinencode vorliegt. Nun die Frage - welches Programm führt den .Net Code aus? Gar keins, der Code liegt zur Ausführungszeit nänmlich in Maschinencode vor und wird direkt durch die CPU ausgeführt und nicht durch ein anderes Programm. Daher kann das ganze nicht interpretiert sein, weil einfach kein Programm da ist zum interpretieren.

    Ich definiere womöglich für eure Verhältnisse einen Interpreter etwas zu offen

    Du definierst sie einfach falsch im Kontext der Softwareentwicklung. Nur weil man umgangssprachlich vielleicht manches freier sieht, heißt das noch lange nicht das es technisch gültig ist. Ist genauso bei dem Thema "Echtzeit". Nur die wenigsten die das Wort hier im Forum verwenden, wissen was das wirklich bedeutet und verwechseln Echtzeit mit Gleichzeitigkeit/Schnelligkeit, dabei gibt es ganz klare technische Definitionen und da ist es egal wenn man selber was anderes meint. Das ist dann falsch.

    Du schreibst am Ende kommt bei .Net Maschinencode raus der direkt ausgeführt wird und nimmst irgendwo die Behauptung her da ist nen Interpreter im Spiel. Bei anderen Sprache wie C oder C++ kommt am Ende auch Maschinencode raus, ist das für dich auch interpretiert?


Anmelden zum Antworten