Distutils compile()関数が使用する実際のコマンドを取得するには?

私はDistutils setup.pyスクリプトを使ってnew_compiler()。compile()を使ってテストプログラムをコンパイルして、ある種の機能(例えばMPI)がシステム上で利用可能であることを確認します。

私の問題は、compile()呼び出しでコンパイルエラーが発生するケースが1つありますが、同じ小さなテストプログラムを手動でコンパイルすることはできません。エラーは標準ヘッダー(mpi.h)内にあります。すべての私の実際のソースファイルにもこのヘッダーが含まれていますが、コンパイルは正常です!この特定の小切手は持っていると非常に便利ですが、なぜそうでなければ失敗するのかを理解する必要があります。

だから私の質問は、どのように実際のコマンドをccompiler.compile()で使用するのですか?

3
よく知られていないPythonのいろいろな行に気をつけなければ、PythonのソースDistutilsを見ることができます。私はちょっと突っ込んだけど、あなたのために良い答えを見つけることができませんでした。私のマシンでは、ccompilerは/usr/lib64/python2.7/distutils/ccompiler.pyにあります。
追加された 著者 Adam Wagner,

3 答え

Adam(Wagner)のコメントは始まるべき正しい場所です:あなたはDistutilsのソースコードを捜す必要があります。多くの抽象レベルがありますので、いくつかの異なるファイルを使って実行をトレースする必要がありますが、ここでは要点です:

  • The package distutils.ccompiler includes an abstract class CCompiler which handles invoking the actual compiler. It has methods for the various tasks a compiler needs to perform: preprocess, compile, and link. CCompiler itself does not implement any of these methods except for compile, but even there it delegates the actual compiler invocation to the method _compile. So you need to check the subclass of CCompiler that is used on your platform and look at its implementation of _compile.
  • There are several different subclasses of CCompiler, each implemented in its own package, but the "big two" are distutils.unixccompiler.UnixCCompiler (which invokes the native compiler on a UNIX-like system) and distutils.msvccompiler.MSVCCompiler (which invokes Visual Studio). Both of these use the function distutils.spawn.spawn to actually run the external process.
  • In the source for distutils.spawn.spawn, you'll notice that each command is logged at the level INFO before it is run. But the catch is, this doesn't use Python's builtin logging system; rather it uses Distutils' custom logger implemented in distutils.log.
  • If you now look at the source for distutils.log, you'll see that there is a function set_verbosity which sets the logging level. Unfortunately, it isn't tied to any of the other debugging infrastructure in Distutils (such as the DISTUTILS_DEBUG environment variable), so you'll need to manually call

    distutils.log.set_verbosity(1)
    

    somewhere in your setup script, before any compilation commands are run. Once you do that, all compilation commands (and who knows what other information) should be printed to standard output.

3
追加された

これは非常に遅いですが、誰かが不思議に思うような場合に備えて、Python内で(ログを確認せずに)これを行う方法を見つけました。

import distutils.sysconfig
import distutils.ccompiler
compiler = distutils.ccompiler.new_compiler()
distutils.sysconfig.customize_compiler(compiler)
print compiler.compiler_so   # This attribute is what you want

"compiler_so"属性は、distutilsが何かをコンパイルするときに使用するすべての引数のリストです。実際にコンパイルを開始すると、ファイル名と -c (オブジェクトファイル用)が追加されます。

編集:私はmacOSとLinuxでこれをテストしただけで、Windows上で動作するようには見えません。

EDIT2:distutilsがExtension()のインスタンスを処理する前に、完全なコマンドではなく、引数だけを追加する必要があります。残りの引数は拡張機能固有のもので、引数ソース、include_dirs、define_macrosのようにExtensionクラスを作成するときに指定します。

If you want the full raw command that distutils runs, the only way I know of (without parsing logs) is to grab the command string at the last minute after all the processing and right before the spawn function. Here is an incredibly hacky way of doing it:

# Put this at the very top of all your imports 
import distutils.spawn
old_spawn = distutils.spawn.spawn
def my_spawn(*args, **kwargs):
    print " ".join(args[0]) # <-- this is your command right here 
    old_spawn(*args, **kwargs)
distutils.spawn.spawn = my_spawn

より洗練されたことは、distutilsをフォークし、この機能を追加することですが、それは多くの仕事やもののようです。

2
追加された
これは間違っています。私はちょうどこれを出て、sysconfigの部分がなくてコンパイルを実行するだけでなく、 -v のプレアグルを追加しました。これは完全に異なる引数のセットです。ここのsysconfigは、別のスクリプト(make、csh、bashなど)と比較しようとしているときにコンパイラを呼び出すときに見られないコマンドラインを作成します。
追加された 著者 searchengine27,
いいえ、GCCコンパイラドライバを使用しているLinux RedHatにありますが、これは機能しません。これは、OSではなく sysconfig ライブラリと関係があります。 sysconfig を使わずに distutils.log.set_verbosity(1)を使用してstdoutを見て、やり直してください。実際のコマンドラインを取得する方法は、 CCompiler.compile を呼び出す前に sys.stdout を自分の cStringIO.StringIO 真のstdoutに sys.stdout を置き、真のstdoutとstdoutではない他のハンドラに StringIO をダンプしてください。
追加された 著者 searchengine27,
これはUnixタイプのシステムでのみ動作するようです。あなたはWindowsにいますか?
追加された 著者 sciencectn,
MSVCCompilerのように、 "compile_options"という属性にコンパイルargsを入れます。
追加された 著者 sciencectn,
私は私の答えは明らかではないと思います。これは、拡張機能を処理する前にosに固有の一般的な引数です(私がdistutilsについて話しているので、拡張インスタンスを作成していると仮定します)。ソースファイルとオブジェクトファイルが不明な場合、完全なコマンドを取得することはできません。これを行う唯一の方法は、distutils.spawn.spawnの引数 "cmd"を拡張機能を処理した後に傍受することです: bitbucket.org/carljm/python-distutils/src/…
追加された 著者 sciencectn,
スケッチーな猿のパッチのハックのための更新された答えを見てください(完全に動作します)
追加された 著者 sciencectn,

さらに、リンカフラグを表示する場合は、次の操作を実行できます。

import distutils.sysconfig
import distutils.ccompiler
compiler = distutils.ccompiler.new_compiler()
distutils.sysconfig.customize_compiler(compiler)
print compiler.linker_so   # This gives linker information
1
追加された