정적 라이브러리를 다른 정적 라이브러리에 링크


138

많은 정적 라이브러리 (a_1-a_n)에 의존하는 작은 코드 조각이 있습니다. 해당 코드를 정적 라이브러리에 패키지하고 다른 사람들이 사용할 수 있도록 만들고 싶습니다.

내 정적 라이브러리는 X라고하고 잘 컴파일합니다.

X의 함수를 사용하는 간단한 샘플 프로그램을 만들었지 만 X에 연결하려고하면 라이브러리 a_1-a_n에서 누락 된 기호에 대한 많은 오류가 발생합니다.

X를 포함하는 새로운 정적 라이브러리 인 Y와 X에 필요한 모든 기능 (a_1-a_n에서 선택된 비트)을 만들어 사람들이 자신의 프로그램을 연결할 수 있도록 Y 만 배포 할 수있는 방법이 있습니까?


최신 정보:

나는 ar로 모든 것을 버리고 하나의 mega-lib를 만드는 것을 보았습니다 . 그러나 필요하지 않은 많은 기호를 포함합니다 (모든 .o 파일은 약 700MB이지만 정적으로 링크 된 실행 파일은 7입니다) MB). 실제로 필요한 것만 포함시키는 좋은 방법이 있습니까?


이것은 여러 C / C ++ 라이브러리를 하나로 결합하는 방법 과 밀접한 관련이 있습니다 . .

답변:


76

정적 라이브러리는 다른 정적 라이브러리와 연결되지 않습니다. 이를 수행하는 유일한 방법은 라이브러리 / 리버 도구 (예 : Linux의 경우 ar )를 사용하여 여러 라이브러리를 연결하여 하나의 새 정적 라이브러리를 작성하는 것입니다.

편집 : 업데이트에 응답하여 필요한 기호 만 선택하는 유일한 방법은 해당 기호가 포함 된 .o 파일의 하위 집합에서 라이브러리를 수동으로 만드는 것입니다. 어렵고 시간이 많이 걸리며 오류가 발생하기 쉽습니다. 나는이 작업을 수행하는 데 도움이되는 도구를 알지 못하지만 (존재하지 않는다는 말은 아니지만) 제작하는 데 매우 흥미로운 프로젝트가 될 것입니다.


안녕하세요 닐, 질문을 업데이트했습니다. 필요한 .o 파일 만 포함하는 방법을 알고 있습니까?
Jason Sundram

업데이트-이 작업을 수행하려는 경우, 물러서서 다른 작업을 수행하십시오 (John Knoeller가 지적하지 않는 한 Visual Studio를 사용하는 경우). 나는이 접근법에 많은 시간을 보냈고 유용한 것을 얻지 못했습니다.
Jason Sundram

GNU ld 도구는 -r출력을 ld의 입력으로 사용할 수 있는 옵션 을 제공합니다 . 한 번 연결하면 재배치 가능해야 라이브러리를 대리 할 수 ​​있습니다. (그것을 시도했다).
harper

49

Visual Studio를 사용하고 있다면 가능합니다.

Visual Studio와 함께 제공되는 라이브러리 작성 도구를 사용하면 명령 줄에서 라이브러리를 함께 연결할 수 있습니다. 그래도 비주얼 편집기 에서이 작업을 수행하는 방법을 모르겠습니다.

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib

5
VS2008에서 Librarian / General 아래의 compositelib 프로젝트 속성에서 [x] 링크 라이브러리 종속성을 확인하면 lib1 및 lib2가 compositelib의 종속성 인 경우이를 수행합니다. 약간 버그가있는 것 같습니다. '모든 구성'에서 한 번이 아니라 각 빌드 구성에서 확인란을 개별적으로 설정합니다.
Spike0xff

2
VS2015 IDE-Librarian / General의 "Additional Dependencies"를 사용하여 프로젝트가 빌드하는 라이브러리에 추가 라이브러리를 직접 연결하지 않습니까?
davidbak

@ davidbak 나는 지난 며칠 동안 이것을 알아 내려고 노력하고 있으며 분명히이 옵션은 더 이상 사용되지 않으며 아무것도하지 않습니까?
Montaldo

20

GNU 툴체인이있는 Linux 또는 MingW :

ar -M <<EOM
    CREATE libab.a
    ADDLIB liba.a
    ADDLIB libb.a
    SAVE
    END
EOM
ranlib libab.a

삭제하지 않는 경우 중 liba.alibb.a, 당신은 "얇은 아카이브를"할 수 있습니다 :

ar crsT libab.a liba.a libb.a

Windows에서 MSVC 툴체인 사용 :

lib.exe /OUT:libab.lib liba.lib libb.lib

libb.a에서 joint lib까지 모든 것을 포함하고 있기 때문에 OP의 문제를 실제로 해결하지는 못하지만 libb에서 몇 개의 모듈 만 있으면 매우 커질 수 있습니다.
Elmar Zander

1
@ElmarZander 그러나 ar crsT복사 대신 " 심 볼링 ( symlinking)"과 같은 작업을 수행 할 수 있습니다 . 데이터 사본 하나만 배송하면됩니다.
Star Brilliant

씬 아카이브는 Linux 커널 v4.19에서 특히 사용됩니다 : unix.stackexchange.com/questions/5518/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

10

정적 라이브러리는 .o객체 파일 의 아카이브 일뿐 입니다. ar(유닉스 가정)으로 추출하고 하나의 큰 라이브러리에 다시 넣습니다.


6

Link Library Dependencies프로젝트 속성 대신 Visual Studio에서 라이브러리를 연결하는 다른 방법이 있습니다.

  1. 다른 라이브러리와 결합하려는 라이브러리 (X)의 프로젝트를여십시오.
  2. X와 결합하려는 다른 라이브러리를 추가하십시오 (오른쪽 클릭, Add Existing Item...).
  3. 자신의 특성에 가서 확인 Item Type하다Library

이것은 마치 마치 마치 X의 다른 라이브러리를 포함합니다.

lib /out:X.lib X.lib other1.lib other2.lib

안녕하세요, 저는 Intel IPP를 사용하고 있으며 하나의 (정적) 라이브러리에 래핑되기를 원하는 자체 기능을 만들었습니다. 그러나 lib를 만든 다음 프로젝트를 다른 컴퓨터로 보내서 만든 lib 만 사용하여 프로젝트를 컴파일 할 수있게하려면 Intel IPP 라이브러리의 .h 파일이 필요하다는 오류가 발생합니다. 어떤 생각?
Royi

lib 파일로는 충분하지 않습니다. 사용하려면 헤더 파일도 포함해야합니다. 그러나이 스레드가 링크에 대해 이야기하고 문제가 컴파일 단계에 있기 때문에 여기서는 주제가 아닙니다.
evpo

확인. 당신을 돕기 위해 더 많은 정보가 필요합니다. 빌드 출력 또는 로그를보고 누락 된 .h 파일에 대한 문제점을 확인하십시오. 나는 그것이 cl.exe라고 생각합니다. 이 경우 헤더를 사용하는 컴파일 된 .cpp / .cc / .c 파일의 이름이 표시됩니다. 해당 .cpp 파일의 이름은 무엇이며 어떤 프로젝트에 속해 있습니까?
evpo

나 진짜 혼란 스럽다. 이 글을 읽기 전에는 작동하지 않은 것 같습니다 (이것은 내 프로젝트가 이미 구성된 방식입니다). 그러나 이제 이것을 읽고 프로젝트를 재설정 했으므로 분명히 작동합니다. 그림을 이동! :(
Mordachai

1
@Mordachai이 하이쿠 아래 완벽하게 당신의 경험을 설명 : 어제는 Windows가 그처럼 작동하지 않는 오늘 일
evpo

5

나머지를 읽기 전에 참고하십시오 : 여기에 표시된 쉘 스크립트는 사용하기에 안전하지 않으며 테스트를 거쳤습니다. 자신의 책임하에 사용하십시오!

해당 작업을 수행하기 위해 bash 스크립트를 작성했습니다. 라이브러리가 lib1이고 일부 기호를 포함해야하는 라이브러리가 lib2라고 가정하십시오. 스크립트는 이제 루프에서 실행되며, 여기서 lib1에서 정의되지 않은 기호가 lib2에 있는지 확인할 수 있습니다. 그런 다음로로 lib2에서 해당 객체 파일을 추출하고 ar이름을 약간 바꾼 다음 lib1에 넣습니다. lib2에 포함 된 내용은 아직 포함되지 않은 lib2의 다른 내용이 필요하므로 루프가 다시 실행되어야하므로 누락 된 기호가 더있을 수 있습니다. 루프의 일부 패스 후에 더 이상 변경 사항이없는 경우, 즉 lib2에서 lib1에 추가 된 오브젝트 파일이 없으면 루프가 중지 될 수 있습니다.

포함 된 기호는 여전히에 의해 정의되지 않은 것으로보고 nm되므로 루프를 중지 할 수 있는지 여부를 결정하기 위해 lib1에 추가 된 객체 파일을 추적하고 있습니다.

#! /bin/bash

lib1="$1"
lib2="$2"

if [ ! -e $lib1.backup ]; then
    echo backing up
    cp $lib1 $lib1.backup
fi

remove_later=""

new_tmp_file() {
    file=$(mktemp)
    remove_later="$remove_later $file"
    eval $1=$file
}
remove_tmp_files() {
    rm $remove_later
}
trap remove_tmp_files EXIT

find_symbols() {
    nm $1 $2 | cut -c20- | sort | uniq 
}

new_tmp_file lib2symbols
new_tmp_file currsymbols

nm $lib2 -s --defined-only > $lib2symbols

prefix="xyz_import_"
pass=0
while true; do
    ((pass++))
    echo "Starting pass #$pass"
    curr=$lib1
    find_symbols $curr "--undefined-only" > $currsymbols
    changed=0
    for sym in $(cat $currsymbols); do
        for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
            echo "  Found $sym in $obj."
            if [ -e "$prefix$obj" ]; then continue; fi
            echo "    -> Adding $obj to $lib1"
            ar x $lib2 $obj
            mv $obj "$prefix$obj"
            ar -r -s $lib1 "$prefix$obj"
            remove_later="$remove_later $prefix$obj"
            ((changed=changed+1))
        done
    done
    echo "Found $changed changes in pass #$pass"

    if [[ $changed == 0 ]]; then break; fi
done

나는 그 스크립트의 이름을 지정 libcomp했으므로 다음과 같이 호출 할 수 있습니다.

./libcomp libmylib.a libwhatever.a

libwhatever는 기호를 포함 할 위치입니다. 그러나 모든 것을 먼저 별도의 디렉토리에 복사하는 것이 가장 안전하다고 생각합니다. 나는 내 스크립트를 그렇게 믿지 않을 것입니다 (그러나 그것은 나를 위해 일했습니다 .libgsl.a를 숫자 라이브러리에 포함시키고 -lgsl 컴파일러 스위치를 생략 할 수 있습니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.