3

SCons は、ファイルのグループから zip ファイルを生成する Zip ビルダーを提供します。たとえば、foo次のようなフォルダがあるとします。

foo/
foo/blah.txt

foo.zipフォルダーからzip ファイルを作成しますfoo

env.Zip('foo.zip', 'foo/')

これにより、zip ファイルが生成されます。

$ unzip -l foo.zip
Archive:  foo.zip
  foo/
  foo/foo.txt

ただし、VariantDirfoo を含む of barを使用しているとします。

bar/
bar/foo/
bar/foo/foo.txt

にいるため、VariantDir効果がわずかに異なりますが、同じコマンドを使用して zip ファイルを作成します。

env.Zip('foo.zip', 'foo/')

これにより、zip ファイルが生成されます。

$ unzip -l bar/foo.zip
Archive:  bar/foo.zip
  bar/foo/
  bar/foo/foo.txt

問題はbar/、zip 内の各ファイルの追加のプレフィックスです。これが SCons でない場合、簡単な解決策は cd してbarそこから zip を呼び出すことですcd bar; zip -r foo.zip foo/。ただし、これは SCons では奇妙/困難であり、とにかく非常に SCons らしくないようです。より良い解決策はありますか?

4

3 に答える 3

5

このタスクを実行する SCons Builder を作成できます。標準の Python zipfile を使用して、zip ファイルを作成できます。を利用しzipfile.writeて、追加するファイルと、zip 内での名前を指定できます。

zf.write('foo/bar', 'bar') # save foo/bar as bar

正しいパスを取得するにos.path.relpathは、ベース ファイルのパスを使用して、ファイル全体へのパスを見つけます。

最後に、os.walk追加したいディレクトリの内容をウォークスルーし、前の 2 つの関数を呼び出してそれらを最終的な zip に正しく追加します。

import os.path
import zipfile

def zipbetter(target, source, env):
    # Open the zip file with appending, so multiple calls will add more files
    zf = zipfile.ZipFile(str(target[0]), 'a', zipfile.ZIP_DEFLATED)
    for s in source:
        # Find the path of the base file
        basedir = os.path.dirname(str(s))
        if s.isdir():
            # If the source is a directory, walk through its files
            for dirpath, dirnames, filenames in os.walk(str(s)):
                for fname in filenames:
                    path = os.path.join(dirpath, fname)
                    if os.path.isfile(path):
                        # If this is a file, write it with its relative path
                        zf.write(path, os.path.relpath(path, basedir))
        else:
            # Otherwise, just write it to the file
            flatname = os.path.basename(str(s))
            zf.write(str(s), flatname)
    zf.close()

# Make a builder using the zipbetter function, that takes SCons files
zipbetter_bld = Builder(action = zipbetter,
                        target_factory = SCons.Node.FS.default_fs.Entry,
                        source_factory = SCons.Node.FS.default_fs.Entry)

# Add the builder to the environment
env.Append(BUILDERS = {'ZipBetter' : zipbetter_bld})

通常の SCons と同じように呼び出しますZip:

env.ZipBetter('foo.zip', 'foo/')
于 2012-05-29T04:56:43.480 に答える
1

ディレクトリは確かにSConsの課題になる可能性があります。ファイルが「プロジェクト内」にあると仮定して、Zip()ファイルに含めるファイルのディレクトリを次のように指定する方法はいくつかあります。

  1. ルートプロジェクトディレクトリを基準にして、パスの前に「#」を付けます。このオプションには、あなたが述べたように、完全なディレクトリが含まれます
  2. 特定のSConscriptファイルに関連します。同じディレクトリ内のファイルを指定するか、SConscriptに関連するサブディレクトリを指定します。

2番目のオプションが必要なようです。あなたの場合、zipしたいのと同じディレクトリにSConscriptファイルがありfooますか?これは、variant_dirでも機能するはずです。

于 2012-05-29T05:27:42.437 に答える