5

Undocumented qmakeで説明されているように、qmake プロジェクト ファイルで追加のコンパイラを宣言しました。

TEST = somefile.h

test_c.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp
test_c.input = TEST
test_c.commands = C:/somedir/some.exe /i ${QMAKE_FILE_IN} /o ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp
test_c.variable_out = SOURCES
test_c.name = MyTestC

QMAKE_EXTRA_COMPILERS += test_c

そして、これはうまくいきます。しかし、ヘッダーファイルも生成したいと思います。このファイル (>1 が TEST にある場合はファイル) を解析するための 2 つ目のカスタム ツールを簡単に作成できますが、各ファイルを 2 回解析したくありません。私は試した:

test_c.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp \
    ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_2.cpp

追加のコンパイラが実行ごとに 2 つのファイルを作成できることをテストするためです。" " のようなエラーが予想されましfile somefile_2.cpp doesn't existたが、プロジェクトはエラーなしでコンパイルされ、2 番目の出力ファイルは無視されます。Makefilesomefile_2.cppには存在しません。

今、私は2つの変種について考えています:

  1. 必要なすべての出力ファイルが一度に保存されるアーカイブを生成する追加のコンパイラを作成します。を設定tool1.variable_out = TOOL_1_OUTし、さらに 2 つの追加のコンパイラを追加しtoolN.input = TOOL_1_OUTて、アーカイブされたファイル (ツールごとに 1 つ) を "解凍" し、いくつかの変数に追加します。

    この場合、1 つの入力ファイルごとに 3 つの実行が呼び出されます。これは最適ではありませんが、少なくともパーサーはファイルごとに 1 回だけ実行されます。

  2. .output_functionオプションを試してみてください。現在と同じ名前を返す qmake 関数を作成しますが、.output2 番目のファイル名を に追加しますHEADERS

PS MinGW x32 4.7、QtCreator 2.7.1、Qt 5.1.0、C++11 を使用しています。

4

2 に答える 2

2

これは問題なく動作します (バリアント #1):

MY_COMP = src/precompiled.h \
    src/file2.h

GENERATE_FOLDER = generated/

# build package file
my_build.clean = $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_build.depends = [somepath]/my_precompiler.exe
my_build.output = $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_build.input = MY_COMP
my_build.commands = [somepath]/my_precompiler.exe /i ${QMAKE_FILE_IN} /o $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_build.variable_out = MY_PACKAGES
my_build.name = "package build"

# unpack cpp
my_unpack_cpp.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_cpp.depends = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_cpp.output = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_cpp.input = MY_PACKAGES
my_unpack_cpp.commands = [somepath]/my_precompiler.exe /unpack cpp /i ${QMAKE_FILE_IN} /o $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_cpp.variable_out = GENERATED_SOURCES
my_unpack_cpp.dependency_type = TYPE_C
my_unpack_cpp.name = "unpack code"
my_unpack_cpp.CONFIG = no_link

# unpack header
my_unpack_h.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_h.output = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_h.input = MY_PACKAGES
my_unpack_h.commands = [somepath]/my_precompiler.exe /unpack h /i ${QMAKE_FILE_IN} /o $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h
my_unpack_h.variable_out = HEADERS
my_unpack_h.name = "unpack header"
my_unpack_h.CONFIG = no_link

QMAKE_EXTRA_COMPILERS += my_build my_unpack_h my_unpack_cpp

この手法を使用すると、1 回の解析あたりの出力ファイル数は異なる場合がありますが、もちろん、プロジェクト内のすべてのファイルで一定になる場合があります。

my_precompilerオプションが保持されていない場合はファイルを解析し、unpack2 つのファイル (cpp + h) を 2 つの QBuffer に構築します。その後、ビルドしたデータを QFile に書き込むだけです。

QDataStream ds(&file);
ds.setVersion(QDataStream::Qt_5_1);

ds << qCompress(output_cpp.data(), 9);
ds << qCompress(output_h.data(), 9);

file.close();

実際、生成されたファイルが小さすぎて圧縮サイズが小さすぎてヘッダー zlib - sizeof(.pack) > size(.h + .h) のサイズを超えたため、現在 qCompress は有益ではありません。

開梱:

QByteArray ba;

QDataStream ds(&file);
ds.setVersion(QDataStream::Qt_5_1);

ds >> ba;

if(unpack != "cpp")
{
 ds >> ba;
}
file.close();  

ba = qUncompress(ba);

file.setFileName(output);
if(!file.open(QFile::WriteOnly | QFile::Truncate)) return 1;

file.write(ba);
file.close();

生成時:

  1. 生成されたヘッダーの先頭に #include "元のヘッダー" を記述します
  2. 生成されたコードの先頭に #include "生成されたヘッダー" を記述します

したがって、私はこれを設定しました:

my_unpack_cpp.depends = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h

/unpack cpp (したがって、ビルド) は、必要なヘッダー ファイルをビルドした後に実行されます。この:

my_build.depends = [somepath]/my_precompiler.exe

ビルドされたパックのセット (および生成された cpp+h) は my_precompiler に依存するため、プリコンパイラを変更して再ビルドすると、すべてが再ビルドされます。

PS IMHO これらの行は、再構築する前にクリーナーとして機能する必要があります。

my_build.clean = $${GENERATE_FOLDER}gen_${QMAKE_FILE_BASE}.pack
my_unpack_cpp.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.cpp
my_unpack_h.clean = $${GENERATE_FOLDER}${QMAKE_FILE_BASE}.h

しかし、彼らはそうしません:(現在、私はそれを無視しますが、.packの構築が失敗した場合、以前に構築されたpack-fileが使用されます

于 2013-06-17T06:26:32.837 に答える
2

あなたのバリアント #2 は正しい考えです。これは私のために働く:

defineReplace(addToHeaders) {
    source = $$1
    source_split = $$split(source, ".")
    source_without_extension = $$first(source_split)
    HEADERS += ${QMAKE_VAR_OBJECTS_DIR}$${source_without_extension}_1.h
    return(${QMAKE_VAR_OBJECTS_DIR}$${source_without_extension}_1.cpp)
}
defineReplace(FILE_IN_addToHeaders) {
    # qmake emits a warning unless this function is defined; not sure why.
}

TEST = somefile.h

test_c.output_function = addToHeaders
test_c.input = TEST
test_c.commands = cp ${QMAKE_FILE_IN} ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.cpp ; cp ${QMAKE_FILE_IN} ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_1.h
test_c.variable_out = SOURCES
test_c.name = MyTestC

QMAKE_EXTRA_COMPILERS += test_c

somefile_1.cpp と somefile_1.h をビルドする Makefile が生成され、somefile_1.cpp が SOURCES に追加され、somefile_1.h が HEADERS に追加されます。

于 2013-06-13T01:49:19.257 に答える