Statik kitaplıkları diğer statik kitaplıklara bağlama


138

Birçok statik kitaplık (a_1-a_n) bağlı küçük bir kod parçası var. Bu kodu statik bir kütüphanede paketlemek ve başkalarının kullanımına sunmak istiyorum.

Statik kitaplığım, ona X diyelim, iyi derler.

X'den bir işlev kullanan basit bir örnek program oluşturdum, ancak X'e bağlamaya çalıştığımda, a_1 - a_n kütüphanelerinden eksik semboller hakkında birçok hata alıyorum.

Yeni bir statik kütüphane, X'i ve X'in ihtiyaç duyduğu tüm işlevleri (a_1 - a_n'den seçilen bitler) içeren bir yol oluşturabilir miyim, böylece insanların programlarını bağlamaları için sadece Y'yi dağıtabilirim?


GÜNCELLEME:

Ben sadece ar ile her şeyi damping baktım ve bir mega-lib yapma, ancak, bu gerekli olmayan bir çok sembol dahil (tüm .o dosyaları yaklaşık 700 MB, ancak, statik olarak bağlantılı bir yürütülebilir 7 MB). Sadece gerçekten gerekli olanı eklemenin güzel bir yolu var mı?


Bu , birkaç C / C ++ kütüphanesini bir arada nasıl birleştirir? .

Yanıtlar:


76

Statik kütüphaneler diğer statik kütüphanelerle bağlantı oluşturmaz. Bunu yapmanın tek yolu , birden çok kütüphaneyi birleştirerek tek bir yeni statik kütüphane oluşturmak için kütüphaneci / arşivleyici aracınızı (örneğin Linux'ta ar ) kullanmaktır.

Düzenleme: Güncellemenize yanıt olarak, yalnızca gerekli simgeleri seçmenin tek yolu kitaplığı, bunları içeren .o dosyalarının alt kümesinden el ile oluşturmaktır. Bu zor, zaman alıcı ve hataya açıktır. Bunu yapmanıza yardımcı olacak herhangi bir aracın farkında değilim (var olmadığını söylemek için değil), ancak bir tane üretmek oldukça ilginç bir proje olur.


Merhaba Neil, soruyu güncelledim - yalnızca gerekli olan .o dosyalarını dahil etmenin herhangi bir yolunu biliyor musunuz?
Jason Sundram

Güncelleme - Bunu yapmak istediğinizi düşünüyorsanız, geri adım atın ve başka bir şey yapın (John Knoeller'ın belirttiği gibi, Visual Studio kullanmıyorsanız). Bu yaklaşıma çok zaman battım ve yararlı bir şey alamadım.
Jason Sundram

GNU ld aracı -r, çıktının ld için giriş olarak kullanılabileceği bir seçenek sunar . Bir kez bağlanırsanız, yeniden yerleştirilebilir olmanız gerekir, kitaplıklarınızı yedekleyebilirsiniz. (thogh denedim).
harper

49

Visual Studio kullanıyorsanız, Evet, bunu yapabilirsiniz.

Visual Studio ile birlikte gelen kütüphane oluşturucu aracı, komut satırında kütüphanelere birlikte katılmanıza olanak tanır. Bunu görsel düzenleyicide yapmanın hiçbir yolunu bilmiyorum.

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

5
VS2008'de, Kütüphaneci / Genel altındaki compositelib'in proje özelliklerinde, [x] Bağlantı Kitaplığı Bağımlılıkları'nı işaretlerseniz, lib1 ve lib2'nin compositelib bağımlılıkları olması bunu sizin için yapar. Biraz hatalı görünüyor, onay kutusunu her derleme yapılandırmasında ayrı ayrı ayarladım, bir kez 'Tüm Konfigürasyonlar'da değil.
Spike0xff

2
VS2015 IDE - projenizin oluşturduğu kütüphaneye doğrudan bağlı ek kütüphaneler almak için Kütüphaneci / Genel altında "Ek Bağımlılıklar" kullanmıyor musunuz?
davidbak

@davidbak Son birkaç gündür bunu anlamaya çalışıyorum ve görünüşe göre bu seçenek eski ve hiçbir şey yapmıyor mu?
Montaldo

20

Linux veya MingW'de, GNU araç zinciri ile:

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

Eğer silmez liba.ave libb.abir "ince arşiv" yapabilirsiniz:

ar crsT libab.a liba.a libb.a

Windows'ta, MSVC araç zinciri ile:

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

Bilmek güzel, ama OP'nin problemini gerçekten çözmüyor, çünkü libb.a'dan her şeyi ortak lib'e dahil ediyorsunuz, libb'den sadece birkaç modüle ihtiyacınız varsa çok büyük olabilir.
Elmar Zander

1
@ElmarZander Ama ar crsTkopyalamak yerine "symlinking" gibi bir şey yapan kullanabilirsiniz , o zaman sadece bir veri kopyası göndermeniz gerekir.
Star Brilliant

İnce arşivler özellikle Linux çekirdeği v4.19'da kullanılır: unix.stackexchange.com/questions/5518/…
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

10

Statik kütüphane sadece .onesne dosyalarının bir arşividir . Bunları arçıkartın (Unix varsayarak) ve büyük bir kütüphaneye geri koyun.


6

Alternatif olarak Link Library Dependencies, proje özelliklerinde Visual Studio'daki kitaplıkları bağlamanın başka bir yolu vardır.

  1. Diğer kütüphanelerle birleştirilmesini istediğiniz kütüphanenin (X) projesini açın.
  2. X ile birleştirmek istediğiniz diğer kitaplıkları ekleyin (Sağ Tıklama, Add Existing Item...).
  3. Özelliklerine gidin ve emin olun Item TypeolduğunuLibrary

Bu, X'teki diğer kütüphaneleri, sanki

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

Merhaba, Intel IPP kullanıyorum ve hepsinin bir (Statik) lib'e sarılmasını istediğim kendi işlevlerimi yaptım. Yine de lib'i oluşturup projeyi yalnızca oluşturduğum lib'i kullanarak derleyebileceğim başka bir bilgisayara gönderdiğimde Intel IPP Kütüphanesinin bir .h dosyasının gerekli olduğunu söyleyerek bir hata alıyorum. Herhangi bir fikir?
Royi

lib dosyası genellikle yeterli değildir. Kullanmak istiyorsanız, başlık dosyalarını da eklemeniz gerekir. Ama iş parçacığı burada bağlantıdan bahsediyor ve sorununuz derleme aşamasında.
evpo

tamam. Size yardımcı olmak için daha fazla bilgiye ihtiyacım olacak. Derleme çıktısına veya günlüğüne bakın ve eksik .h dosyasında neyin şikayet ettiğini görün. Ben cl.exe olduğunu düşünüyorum. Bu durumda, üstbilgiyi kullanan derlenmiş .cpp / .cc / .c dosyasının adını verir. Bu .cpp dosyasının adı ve hangi projeye ait?
evpo

Kafam çok karıştı. Bunu okumadan önce, daha önce hiç işe yaramadı (projelerim zaten bu şekilde yapılandırıldı). Ama şimdi bunu okuduğum ve projelerimi sıfırladığım için, görünüşe göre çalışıyor. Git şekil! :(
Mordachai

1
@Mordachai Aşağıdaki bu haiku deneyiminizi mükemmel bir şekilde anlatıyor: Dün işe yaradı Bugün çalışmıyor Windows böyle
evpo

5

Geri kalanını okumadan önce not: Burada gösterilen kabuk betiğinin kullanımı kesinlikle güvenli değildir ve iyi test edilmiştir. Kendi sorumluluğunuzdadır kullanın!

Bu görevi gerçekleştirmek için bir bash senaryosu yazdım. Kütüphanenizin lib1 olduğunu ve bazı sembolleri dahil etmeniz gereken lib2 olduğunu varsayalım. Komut dosyası şimdi bir döngüde çalışır ve burada lib1'den hangi tanımsız sembollerin lib2'de bulunabileceğini kontrol eder. Daha sonra, karşılık gelen nesne dosyalarını lib2'den ayıklar, aronları yeniden adlandırır ve lib1'e koyar. Şimdi daha eksik semboller olabilir, çünkü lib2'den eklediğiniz şeylerin henüz eklemediğimiz lib2'den başka şeylere ihtiyacı vardır, bu nedenle döngü tekrar çalıştırılmalıdır. Döngünün bazı geçişlerinden sonra artık değişiklik yoksa, yani lib1'e lib1'e hiçbir nesne dosyası eklenmezse, döngü durabilir.

Not, dahil sembolleri hala tarafından tanımsız olarak rapor nm, bu yüzden döngü durdurulabilir olup olmadığını belirlemek için lib1, kendilerine eklenmiş olan nesne dosyalarını izliyorum.

#! /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

Bu komut dosyasını adlandırdım libcomp, böylece daha sonra çağırabilirsiniz

./libcomp libmylib.a libwhatever.a

libwhatever, semboller eklemek istediğiniz yerdir. Ancak, her şeyi önce ayrı bir dizine kopyalamanın en güvenli yol olduğunu düşünüyorum. Senaryomuma o kadar çok güvenmezdim (ancak benim için çalıştı; libgsl.a'yı sayısal kütüphaneme ekleyebilir ve -lgsl derleyici anahtarını bırakabilirim).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.