2016-10-11 6 views
1

foo.c bar.cとbaz.cに加えて、他のファイルのコードとデータを使用する関数myfn()を定義するラッパーコードmyfn.cがあります。静的アーカイブにおけるCのシンボルの可視性

オブジェクトファイルやアーカイブmyfn.oやlibmyfn.aのようなものを作成したいので、myfn()を他のプロジェクトで利用できるようにするには{foo、bar、 baz} .oも同様です。

Linux/gccでこれを行う正しい方法は何ですか?ありがとう。


更新:私はそれを行う方法を見つけました。もともと、これはDSOではなく静的アーカイブに関するものであることを強調しておきました。とにかく、レシピ:

  1. #define PUBLIC __attribute__ ((visibility("default")))は、myfn.cPUBLICとしてmyfn()をマーク。何も記さないでくださいPUBLIC

  2. gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hiddenでオブジェクトをコンパイルします。このオブジェクトは、myfn()以外のすべてを隠しとしてマークします。

  3. ldの部分連動するスイッチ使用して便利なアーカイブを作成しますので、同じようPUBLICませんでしたすべてのものをローカライズld -r foo.o bar.o baz.o myfn.o -o libmyfn.a

  4. を:今objcopy --localize-hidden libmyfn.a

  5. nmmyfnがで唯一のグローバル・シンボルであると言いますlibmyfn.a以降の他のプログラムへのリンクは、gcc -o main main.c -L. -lmyfn(ここではプログラムはmyfn()を呼び出し、foo()を呼び出そうとするとコンパイルは失敗します)。

私はステップ3でar代わりのld -rを使用する場合は、コンパイルは、ステップ5で失敗した:私はarmyfnfooなどをリンクされておらず、もはやかつてそれらの機能がローカライズされていないことができますね、ld -rが解決に対し、ローカライズされる前にリンクしてください。

「正しい」方法であることを確認するか、より巧妙な方法で実現することを歓迎します。

+0

正しい方法は、図書館の作成に関する文献やチュートリアルを見つけることです。 –

+1

私は答えとしてユージンを投稿することに賛成しますので、私はそれをダウン投票することができます。ありがとう。 – PythonAteMyHamster

答えて

0

残念なことに、すべてのモジュールのグローバルがlibmyfn.aの最終的な外部シンボルのリストで利用できるという意味で、グローバル用のCリンケージはすべて、または全くありません。

gccツールチェーンは、あなたのライブラリ内の他の翻訳単位にそれらを利用できるようにしているときに、外部のユーザからのシンボルを非表示にすることができます拡張機能を提供しています:

がfoo.h:

void foo(); 

foo.cを:

void foo() __attribute__ ((visibility ("hidden"))); 

myfn.h:

void myfn(); 

myfn.c:ポータビリティのために

#include <stdio.h> 
#include "foo.h" 

void myfn() { 
    printf("calling foo...\n"); 
    foo(); 
    printf("calling foo again...\n"); 
    foo(); 
} 

、あなたはおそらく__attribute__ ((visibility ("hidden")))のためのマクロを作成し、gccを条件条件付きコンパイルブロックに置くの恩恵を受けるだろう。

さらに、Linuxはutility called stripを提供しています。これにより、コンパイル済みオブジェクトファイルからシンボルの一部を削除できます。オプション-Nおよび-Kを使用して、保持または削除する個々のシンボルを識別できます。

+0

これは私のオリジナルに最も近い応答です私はそれを編集して、提案された解決策についてあなたが何を考えているかを教えてくれるでしょうか? – PythonAteMyHamster

+1

@PythonAteMyHamsterいくつかの関数をパブリックにする新しいアプローチ他のすべてを取り除くことは正しいようです。 – dasblinkenlight

+0

私はそれを1時間与えるでしょうが、誰も何かより良い投稿をしていない場合は、正しい答えを得ることができます。 – PythonAteMyHamster

-1

と仮定myfn.cは、あなたが他の三つのファイルのfoo.cの中で使用したい機能でmyfun()、bar.cに& baz.c

は今myfn.cすなわち、コードから共有ライブラリを作成しましたlibmyf.a

この関数は、他の3つのファイルでmyfun()を呼び出します。これらのファイルのexternとして関数を宣言します。これらのファイルのオブジェクトコードを作成し、リンクフェーズでlibmyf.aをリンクすることができます。

共有ライブラリを使用するには、次のリンクを参照してください。

http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html

+0

ありがとうPankaj、しかし私は基本的にライブラリを構築する方法を知っています。私が知らなかったのは、シンボルの可視性を制御する方法でした。私は今それを持っていると思う。 – PythonAteMyHamster

+0

https://gcc.gnu.org/wiki/Visibility 上記のページでは、ソリューションを確認し、#pragmasを使用して別の方法を提供しています。 –

0

この静的ライブラリを構築するための

gcc -c -O2 foo.c bar.c baz.c myfn.c 
ar av libmyfunctions.a foo.o bar.o baz.o myfn.o 

コンパイルでスタートなどの他のプログラムとのリンク:今すぐ

gcc -O2 program.c -lmyfunctions -o myprogram 

あなたlibmyfunctions.aが、最終的にはソースから余分なものを持っていますこれはmyfn.cのコードでは必要ではありませんが、リンカーは最終的なprograを作成するときにこれを削除するという合理的な仕事をするべきですm。

+0

ありがとうございました。しかし、「余分なもの」は私が質問したときに削除しようとしていた問題でした! – PythonAteMyHamster

+0

リンカーは、未使用のオブジェクトコードを削除します。しかし、.libファイルのサイズを最小限にしようとするなら、カスタムビルドが必要です。 (例: '#define LIBRARY_BUILD 1'、ビルドのために意図されていないコードは#ifndef' LIBRARY_BUILD'セクションの下にあります。 – selbie

+0

これはリンカがどんなオブジェクトコードを引き出すのかに関するものではありませんでした。 libmyfn.a内のシンボルだけをAPIを表すもの(APIを実装する他のすべての関数ではない)に変更することができます。 – PythonAteMyHamster

関連する問題