8

組み込みCプロジェクトを「モジュール」と「コンポーネント」に整理するのに役立つ高レベルのビルドシステム/ツールを探しています。これらの2つの用語は非常に主観的であるため、私の定義を以下に示します。

  • モジュールは、cファイルとhファイルのまとまりのあるコレクションですが、他のモジュールから見えるパブリックhファイルは1つだけです。
  • 一方、コンポーネント(またはレイヤー)は、モジュールのコレクションです(たとえば、アプリケーションレイヤー、ライブラリレイヤー、ドライバーレイヤー、RTOSレイヤーなど)。

ビルドシステム/ツールは-

  • コンポーネントとモジュール間の循環依存を防止します(モジュール内の循環依存は問題ありません)
  • モジュールのプライベートバリアへのアクセスを防止します。他のモジュールがモジュール専用のヘッダーファイルをインクルードしようとすると、ビルドシステムはエラーをスローする必要があります。ただし、プライベートバリア内のファイルには、そのバリア内の他のファイルを含めることができる必要があります。
  • ホストでの単体テストの自動構築と実行をサポート(TDDの高速フィードバックループ)
  • ターゲットシミュレータで実行されるサポートユニットテスト
  • サポートコードの静的分析
  • サポートコード生成
  • コード重複検出をサポート(DRY原則を適用)
  • サポートコードの美化
  • 単体テストコードカバレッジメトリックの生成をサポート
  • コード品質メトリックの生成をサポート
  • プラットフォームに依存しない

独自のビルドツールを作成して、それに多くの時間を費やすことができました。ただし、それは私の専門分野ではなく、誰かがすでにそのようなツールを作成している場合は、車輪の再発明をしたくありません。

4

2 に答える 2

4

これを実現する従来の方法は、各モジュールのソースコードを別々のディレクトリに配置することです。各ディレクトリには、モジュールのすべてのソースファイルとヘッダーファイルを含めることができます。

各モジュールのパブリックヘッダーは、ヘッダーの個別の共通ディレクトリに配置できます。おそらく、各ヘッダーの共通ディレクトリから関連するモジュールディレクトリへのシンボリックリンクを使用します。

コンパイルルールは、共通ディレクトリ内のヘッダーを除いて、他のモジュールからのヘッダーをモジュールに含めることはできないと単純に述べています。これにより、パブリックヘッダーを除いて、別のモジュールのヘッダーをモジュールに含めることができないという結果が得られます(したがって、プライベートバリアが適用されます)。

循環依存を自動的に防ぐことは簡単ではありません。問題は、一度に複数のソースファイルを調べることによってのみ循環依存関係があることを確認でき、コンパイラーは一度に1つしか調べないことです。

モジュールのペアであるModuleAとModuleB、および両方のモジュールを使用するプログラムであるProgram1について考えてみます。

base/include
        ModuleA.h
        ModuleB.h
base/ModuleA
        ModuleA.h
        ModuleA1.c
        ModuleA2.c
base/ModuleB
        ModuleB.h
        ModuleB1.c
        ModuleB2.c
base/Program1
        Program1.c

Program1.cをコンパイルするとき、両方のモジュールのサービスを利用する場合、ModuleA.hとModuleB.hの両方を含めることは完全に合法です。したがって、ModuleB.hが同じ変換ユニット(TU)に含まれている場合、ModuleA.hは文句を言うことができません。また、ModuleA.hが同じTUに含まれている場合、ModuleB.hも文句を言うことはできません。

ModuleAがModuleBの機能を使用することは合法であると仮定しましょう。したがって、ModuleA1.cまたはModuleA2.cをコンパイルする場合、ModuleA.hとModuleB.hの両方が含まれていても問題はありません。

ただし、循環依存を防ぐには、ModuleB1.cおよびModuleB2.cのコードがModuleA.hを使用することを禁止できる必要があります。

私が見る限り、これを行う唯一の方法は、ModuleA.hが含まれる前に含まれているにもかかわらず、「ModuleAはすでに含まれている」というModuleBのプライベートヘッダーを必要とするいくつかの手法です。

ModuleA.hのスケルトンは標準形式になります(そしてModuleB.hも同様になります)。

#ifndef MODULEA_H_INCLUDED
#define MODULEA_H_INCLUDED
...contents of ModuleA.h...
#endif

ここで、ModuleB1.cのコードに次のものが含まれている場合:

#define MODULEA_H_INCLUDED
#include "ModuleB.h"
...if ModuleA.h is also included, it will declare nothing...
...so anything that depends on its contents will fail to compile...

これは自動にはほど遠いです。

含まれているファイルの分析を行うことができ、依存関係のループのないトポロジカルソートが存在する必要があります。以前はtsort、UNIXシステム上にプログラム(およびコンパニオンプログラム)があり、アーカイブの再スキャンを必要としない順序でオブジェクトファイルを含むlorder静的()ライブラリを作成できるように、必要なサービスを一緒に提供していました。.aプログラムはranlib、最終的には単一のライブラリの再スキャンを管理する役割arld引き受けたためlorder、特に冗長になりました。しかしtsort、より一般的な用途があります。一部のシステムで使用できます(たとえば、MacOS X、RHEL 5 Linuxも)。

したがって、GCC plusの依存関係追跡を使用するとtsort、モジュール間にサイクルがあるかどうかを確認できるはずです。しかし、それは注意して処理する必要があります。

このようなものを自動的に処理するIDEまたは他のツールセットがあるかもしれません。しかし、通常、プログラマーは、要件とモジュール間の依存関係が注意深く文書化されている限り、問題を回避するのに十分な訓練を受けることができます。

于 2011-09-30T07:08:33.030 に答える
2

一般的な解決策として、JonathanLefflerの解決策を使用することを強くお勧めします。ただし、モジュールが自己完結型で分離されているかどうかの自動テストがどうしても必要な場合は、Debianのビルドシステムを試してみてください。

各モジュールをDebianパッケージにパッケージ化し(すでにautoconfされている場合は非常に迅速に実行されます)、Build-Dependsを適切に宣言し、pbuilder環境内でパッケージをビルドします。これにより、各モジュールのパブリックヘッダーのみが使用可能になり(他のパッケージをビルドするためにpbuilderによってインストールされる.debパッケージに含まれているため)、Debianパッケージツリーを調べてサイクルであることを確認するための優れたツールがあります-自由。

ただし、これはおそらくやり過ぎです。完全を期すためにそれを述べるだけで、あなたが間違いなく自動化された解決策を必要とする場合。

于 2011-09-30T07:39:37.933 に答える