Cプリプロセッサを使用して、ファイルが存在するかどうかを確認できますか?

StackOverflow https://stackoverflow.com/questions/142877

  •  02-07-2019
  •  | 
  •  

質問

非常に大きなコードベース(読み取り:数千のモジュール)があり、そのコードはすべて、さまざまなC ++コンパイラを備えたさまざまなオペレーティングシステムで実行される多数のプロジェクトで共有されています。言うまでもなく、ビルドプロセスの維持は非常に面倒な作業です。

コードベースには、ファイルが存在しない場合にプリプロセッサが特定の #includes を無視する方法がある場合にのみ、コードを大幅にクリーンアップする場所がいくつかあります。現在のフォルダー。誰でもそれを達成する方法を知っていますか?

現在、共有ファイルの #include の周りに #ifdef を使用し、2番目のプロジェクト固有のファイルで #include はプロジェクトに存在します。これは機能しますが、見苦しいです。多くの場合、プロジェクトにファイルを追加または削除するときに、定義を適切に更新することを忘れます。このファイルを最新の状態に保つためのビルド前ツールの作成を検討しましたが、プリプロセッサでこれを行うプラットフォームに依存しない方法がある場合は、代わりにその方法を使用します。アイデアはありますか?

役に立ちましたか?

解決

通常、これは、ファイルをインクルードしようとするとプリプロセッサを実行しようとするスクリプトを使用して行われます。プリプロセッサがエラーを返すかどうかに応じて、スクリプトは生成された.hファイルを適切な#define(または#undef)で更新します。 bashでは、スクリプトは次のように漠然と見えるかもしれません:

cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
 then
  echo '#define HAVE_ASDF_H 1' >> config.h
 else 
  echo '#ifdef HAVE_ASDF_H' >> config.h
  echo '# undef HAVE_ASDF_H' >> config.h
  echo '#endif' >> config.h
 fi

このような移植性チェック(および他の何千もの)を移植可能に操作するためのかなり徹底したフレームワークは、 autoconfです。

他のヒント

小さな更新

一部のコンパイラは __ has_include(header-name)をサポートする場合があります。

C ++ 17標準 P0061R1 )。

コンパイラサポート

  • Clang
  • 5.XのGCC
  • VS2015 Update 2のVisual Studio(?)

例(clangウェブサイトから):

// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif

ソース

欠落しているヘッダー用の特別なフォルダーを作成し、そのフォルダーを最後に検索するようにします
(コンパイラ固有-環境変数&quot; INCLUDES&quot;の最後の項目、そのようなもの)

次に、header1.hが欠落している場合は、そのフォルダーにスタブを作成します

header1.h:

#define header1_is_missing

これでいつでも書くことができます

#include <header1.h>
#ifdef header1_is_missing

   // there is no header1.h 

#endif

プリプロセッサ自体はファイルの存在を識別できませんが、ビルド環境を使用して確実に識別できます。私はほとんどmakeに精通しているので、makefileで次のようなことができます。

ifdef $(test -f filename && echo "present")
  DEFINE=-DFILENAME_PRESENT
endif

もちろん、VisualStudioのような他のビルド環境でこれに類似するものを見つける必要がありますが、確かに存在します。

現在のディレクトリに存在するファイルの名前を表す#definesのリストを含むインクルードファイルを生成するビルド前のステップを実行することもできます。

#define EXISTS_FILE1_C
#define EXISTS_FILE1_H
#define EXISTS_FILE2_C

次に、ソースコード内からそのファイルをインクルードすると、ソースは EXISTS _ * の定義をテストして、ファイルが存在するかどうかを確認できます。

私が知る限り、cppにはファイルの存在に関するディレクティブがありません。

プラットフォーム間で同じmakeを使用している場合は、Makefileから少し助けを借りてこれを達成できる場合があります。 Makefileでファイルの存在を検出できます:

foo.o: foo.c
    if [ -f header1.h ]; then CFLAGS+=-DHEADER1_INC

@Greg Hewgillが述べているように、#includeを条件付きにすることができます:

#ifdef HEADER1_INC
#include <header1.h>
#endif

別の可能性:必要に応じて含めたいすべてのヘッダーの長さゼロのバージョンをディレクトリに追加します。このディレクトリに last オプションとして-I引数を渡します。

GCC cppは、インクルードディレクトリを順番に検索します。以前のディレクトリでヘッダーファイルが見つかった場合、それを使用します。そうでなければ、最終的に長さゼロのファイルを見つけて、満足します。

他のcpp実装も、指定された順序でインクルードディレクトリを検索すると想定しています。

Symbian OSでも同様のことをしなければなりませんでした。これは私がそれをやった方法です: ファイル&quot; file_strange.h&quot;を確認したいとしましょう。存在し、そのファイルの存在に応じていくつかのヘッダーを含めるか、いくつかのライブラリにリンクします。

最初に、そのファイルの存在を確認するための小さなバッチファイルを作成します。

autoconfは優れていますが、多くの小さなプロジェクトにとっては過剰なキルです。

---------- check.bat

@echo off

IF EXIST [\epoc32\include\domain\middleware\file_strange] GOTO NEW_API
GOTO OLD_API
GOTO :EOF

:NEW_API
echo.#define NEW_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

:OLD_API
echo.#define OLD_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

---------- check.batが終了

次にgnumakeファイルを作成しました

---------- checkmedialist.mk

do_nothing :
    @rem do_nothing

MAKMAKE : 
        check.bat

BLD : do_nothing

CLEAN : do_nothing

LIB : do_nothing

CLEANLIB : do_nothing

RESOURCE : do_nothing

FREEZE : do_nothing

SAVESPACE : do_nothing

RELEASABLES : do_nothing

FINAL : do_nothing

---------- check.mkが終了

check.mkファイルをbld.infファイルに含めます。MMPファイルの前にある必要があります

PRJ_MMPFILES
gnumakefile checkmedialist.mk

現在、コンパイル時にファイル file_strange_supported.h に適切なフラグが設定されます。 このフラグは、cppファイルまたはmmpファイルでも使用できます。 たとえばmmpで

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
LIBRARY newapi.lib
#else
LIBRARY oldapi.lib
#endif

および.cpp

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
CStrangeApi* api = Api::NewLC();
#else
// ..
#endif

ここおよびインターネット上でのいくつかの主張に反して、Visual Studio 2015は __ has_include 機能をサポートしていません-少なくとも私の経験によると。アップデート3でテスト済み。

VS 2017は「バージョン15」とも呼ばれているという事実から噂が生じた可能性があります。 VS 2015は、代わりに「バージョン14」と呼ばれます。この機能のサポートは、「Visual Studio 2017バージョン15.3」で正式に導入されたようです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top