オンザフライで C (または C++) コードを生成し、それをコンパイルしてdlopen
-ing することについて言及しています。
MELT (GCC を拡張するためのドメイン固有言語)でも同じことをしています。
コードを(一時的な)ファイルに入れないようにする正当な理由はありません。生成された C または C++ の 100 万行の行でさえ、非常に高速に記述できます (MELT では、数秒未満であり、その時間のほとんどは I/O ではありません!)。はるかに遅いコンパイル (少なくとも数十秒) と、C または C++ コードを生成する目的は、特に GCC (または他のコンパイラ) によって提供される最適化を利用することです。ファイルの生成を回避すると、ほんの数ミリ秒で済みます (違いを大幅に測定することさえできません)。
したがって、ファイルを一時*.c
ファイルに生成し(ハッシュまたはタイムスタンプ手法を使用して一意のファイル名を生成できます)、GCCにコンパイルさせて*.so
(おそらく、MELTで行うように、fork
いくつかのプロセスを-ingすることにより)、それを削除しますmake
一時ファイル (おそらく を使用atexit
)。
ところで、この手法は、現在の PC での人間の操作と実質的に互換性があります。MELT には read-eval-print-loop があり、対話ごとに数百行の新しい C++ ファイルを生成し、それをコンパイルして dlopen-s します。これは非常に便利です!
ファイルの生成を回避するのは苦痛であり、得られるものはごくわずかです。tmpfs
Linux のファイルシステム (例: )で生成することができます/tmp/
。ほとんどの時間は、GCC がそのファイルをコンパイルするのに費やされます (特に、最適化などでコンパイルする場合gcc -O -fPIC -shared somefile.c -o someplugin.so
)。(プログラムによって) ディスクに書き込み、GCC によってそれを読み取る (さらには C の場合は解析する) 時間はごくわずかです。GCC の-ftime-reportオプションを使用して、GCC が時間を費やしている場所を把握します。GCC にパス-O
するとすぐに解析されません。
GCC やその他の C コンパイラのバージョンによっては、stdinを入力として拒否する場合があります。一部の C コンパイラはmmap
、C ソース ファイルを必要とする場合があります (たとえば、Glibc"rm"
で as モードを使用するなど)。一般に、 Cは非標準であるため、ファイルfopen
ではないものをコンパイルするなど...ゲインは無視できるため、それを行うことは避けたほうがよいでしょう。*.c
最適化をまったく気にせず、C (C++ ではない) を非常に遅いマシン コードにすばやくコンパイルしたい場合は、代わりにライブラリを持つ tinycc (少なくとも 32 ビット マシンでは、64 ビットではバグがある可能性があります) を使用することを検討してください。文字列内のいくつかの C コードをコンパイルできます。tcc
一部のlibtcc.a
C コードは非常に高速に (GCC の 10 倍以上) コンパイルできますが、生成されたマシン コードのパフォーマンスは非常に悪いです (非常に遅く、最適化されていないコード)。
GCC が生成された C コードをコンパイルしたら、もちろんremove
、生成されたソース コード ファイルをコンパイルできます。.so
(そして、編集した後に削除することもできますdlopen
)。
ところで、clang++
生成された C++ ファイルをコンパイルするために使用できます。また、代わりに LLVM を使用することもできます (ファイルを使用せずに内部 LLVM 表現を生成することもできます)。
この回答も参照してください。
共有ライブラリを生成し、作成した関数をロードする必要がある実行時コード生成を行っています。
libgccjit、LLVM、asmjitなどの JIT コンパイルライブラリの使用も検討してください。SBCL (ほぼすべてのREPL対話でマシンコードを生成する)も調べてください。もちろん、システムに関連する呼び出し規約とABIを理解する必要があります。したがって、これ、elf(5)、および Drepper の論文How To Write Shared Librariesもお読みください。