2

C++ ソース ファイルから情報を抽出してヘッダー ファイルに書き込む Python スクリプトがあります。この生成されたヘッダーが変更されるたびに (まれにしか発生しません)、(GCC プリコンパイル済みヘッダー機能を使用して) 再コンパイルしたいと考えています。

明らかに、スクリプトを呼び出すコマンドはソース ファイルに依存し、再コンパイル コマンドはスクリプトによって生成されたヘッダー ファイルに依存します。

add_custom_command(OUTPUT "file.pch.h" COMMAND <script> DEPENDS "file.cpp")
add_custom_command(OUTPUT "file.pch.h.gch" COMMAND <compile> DEPENDS "file.pch.h")

しかし、現在file.pch.h.gchは依存してfile.cppおり、変更されるたびに再コンパイルされます。どうすればこれを回避できますか?

4

1 に答える 1

3

スクリプトにヘッダーを一時ファイルに書き込んでもらい、file.pch.h変更された場合にのみ既存のファイルにコピーします。その後、(高速)スクリプトは変更されるたびに実行されfile.cppますが、プリコンパイル済みヘッダーは、変更された場合にのみ再プリコンパイルされます。

スクリプトを変更したくない場合は、別のmove-if-changeスクリプトを使用して、次の行に沿ってコマンドを実行できます。

myscript < file.cpp > file.pch.h.tmp && move-if-change file.pch.h.tmp file.pch.h

Cmakeでこれを行うためのより良い方法があるかもしれませんが、これはMakeでこの問題を解決するための昔ながらの方法です。


これがCMakeの実例です。

メインプログラム、foo.c

#include "foo.pch.h"

#ifndef FOO_PCH
#include <stdio.h>
#endif

int main() {
    printf("Hello, world\n");
    return 0;
}

プリコンパイル済みヘッダーを生成するプログラムmake-pch

#!/bin/bash

(echo '#define FOO_PCH 1'
 awk '/^#endif/ { p = 0 }
      p { print $0 }
      /^#ifndef FOO_PCH/ { p = 1 }') < foo.c > foo.pch.h.tmp

if ! cmp -s foo.pch.h{.tmp,}; then
    echo 'Header changed, updating'
    mv foo.pch.h{.tmp,}
else
    echo 'Header not changed'
    rm -f foo.pch.h.tmp
fi

そしてCMakeLists.txt

cmake_minimum_required(VERSION 2.8)
add_executable(foo foo.c foo.pch.h.gch)
add_custom_command(OUTPUT "foo.pch.h" COMMAND ./make-pch DEPENDS "foo.c")
add_custom_command(OUTPUT "foo.pch.h.gch"
                   COMMAND echo calling gcc
                   COMMAND gcc foo.pch.h
                   DEPENDS "foo.pch.h")

それを構築しましょう:

$ cmake .
-- The C compiler identification is GNU 4.2.1
-- The CXX compiler identification is Clang 4.1.0
-- Checking whether C compiler has -isysroot
-- Checking whether C compiler has -isysroot - yes
-- Checking whether C compiler supports OSX deployment target flag
-- Checking whether C compiler supports OSX deployment target flag - yes
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/andrew/sx/14662471
$ make
[ 33%] Generating foo.pch.h
Header changed, updating
[ 66%] Generating foo.pch.h.gch
calling gcc
Scanning dependencies of target foo
[100%] Building C object CMakeFiles/foo.dir/foo.c.o
Linking C executable foo
[100%] Built target foo
$ ./foo
Hello, world
$ # it’s up-to-date, so calling make again does nothing
$ make
[100%] Built target foo
$ Let’s change the C file
$ sed -i -e 's/Hello, world/Hello there, world/' foo.c
$ make
[ 33%] Generating foo.pch.h
Header not changed
Scanning dependencies of target foo
[ 33%] Generating foo.pch.h
Header not changed
[ 66%] Building C object CMakeFiles/foo.dir/foo.c.o
Linking C executable foo
[100%] Built target foo
$ # note that the precompiled header was *not* recompiled
$ ./foo
Hello there, world
$ # now let’s add a header file
$ sed -i -e $'s/stdio.h>/stdio.h>\\\n#include <stdlib.h>/' foo.c
$ make
[ 33%] Generating foo.pch.h
Header changed, updating
[ 66%] Generating foo.pch.h.gch
calling gcc
Scanning dependencies of target foo
[100%] Building C object CMakeFiles/foo.dir/foo.c.o
Linking C executable foo
[100%] Built target foo
$ # the precompiled header file *was* recompiled
于 2013-02-02T17:08:16.697 に答える