2016-06-20 29 views
6

Mam bardzo podobny problem do jednego described na liście mailingowej cmake, gdzie mamy projekt zależny od wielu bibliotek statycznych (wszystkie zbudowane ze źródła w poszczególnych submodułach, każdy z własnym CMakeLists. txt opisujący proces kompilacji dla każdej biblioteki), który chciałbym połączyć w jedną statyczną bibliotekę do wydania dla konsumentów. Zależności mojej biblioteki mogą ulec zmianie i nie chcę obciążać deweloperów w dalszym ciągu tymi zmianami. Schludnym rozwiązaniem byłoby połączenie wszystkich bibliotek w jedną bibliotekę.Łącząc kilka bibliotek statycznych w jedną przy użyciu CMake

Co ciekawe, polecenie target_link_libraries nie łączy wszystkich statyki podczas ustawiania celu na mylib i używania go w ten sposób. .

target_link_libraries(mylib a b c d) 

jednak dziwnie, jeśli robię projekt mylib to moduł podrzędny od projektu wykonywalnego, a tylko połączyć przeciwko mylib w górnym poziomie wykonywalny CMakeLists.txt biblioteka wydaje się być łączone. To znaczy. mylib ma 27 MB, zamiast 3 MB, gdy ustawiam cel, aby budował tylko mylib.

Istnieją rozwiązania opisują rozpakowywanie bibliotekami do plików obiektów i rekombinacyjnego (here i here), ale wydaje się znacznie niezgrabne gdy CUpewnij wydaje się w pełni zdolny do automatycznego łączenia z bibliotekami w sposób opisany w powyższym przykładzie. Jest tam magiczne polecenie, którego mi brakuje lub zalecany elegancki sposób tworzenia biblioteki wydań?

+0

Ale co zrobisz z tymi wszystkimi to pliki i katalogi? – Drop

+0

@Drop one są spłaszczone lub ukryte za publicznym interfejsem 'mylib'. Deps powinien być niewidoczny dla użytkowników. – learnvst

+0

Jeśli używasz gcc i nie potrzebujesz, aby twój makefile był niezależny od kompilatora, możesz wypróbować ['--whole-archive'] (http://stackoverflow.com/questions Opcja/805555/ld-linker-question-the-whole-archive-option). –

Odpowiedz

2

Biorąc pod uwagę najbardziej prosty przykład pracę mogę myśleć: 2 klas, a i b, gdzie a zależy od b. .

A.H

#ifndef A_H 
#define A_H 

class aclass 
{ 
public: 
    int method(int x, int y); 
}; 

#endif 

a.cpp

#include "a.h" 
#include "b.h" 

int aclass::method(int x, int y) { 
    bclass b; 
    return x * b.method(x,y); 
} 

B.H.

#ifndef B_H 
#define B_H 

class bclass 
{ 
public: 
    int method(int x, int y); 
}; 

#endif 

b.cpp

#include "b.h" 

int bclass::method(int x, int y) { 
    return x+y; 
} 

main.cpp

#include "a.h" 
#include <iostream> 

int main() 
{ 
    aclass a; 
    std::cout << a.method(3,4) << std::endl; 

    return 0; 
} 

Jest możliwe skompilować je w oddzielnych bibliotekami statycznych, a następnie połączyć się za pomocą statycznych bibliotekami cel niestandardowy.

cmake_minimum_required(VERSION 2.8.7) 

add_library(b b.cpp b.h) 
add_library(a a.cpp a.h) 
add_executable(main main.cpp) 

set(C_LIB ${CMAKE_BINARY_DIR}/libcombi.a) 

add_custom_target(combined 
     COMMAND ar -x $<TARGET_FILE:a> 
     COMMAND ar -x $<TARGET_FILE:b> 
     COMMAND ar -qcs ${C_LIB} *.o 
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 
     DEPENDS a b 
     ) 

add_library(c STATIC IMPORTED GLOBAL) 
add_dependencies(c combined) 

set_target_properties(c 
     PROPERTIES 
     IMPORTED_LOCATION ${C_LIB} 
     ) 

target_link_libraries(main c) 

Działa również dobrze przy użyciu Apple libtool wersji docelowej niestandardowej. . .

add_custom_target(combined 
     COMMAND libtool -static -o ${C_LIB} $<TARGET_FILE:a> $<TARGET_FILE:b> 
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 
     DEPENDS a b 
     ) 

Ciągle szwy, jak gdyby należało zachować lepszy styl. .

+0

To nie odpowiada na pytanie. Ta odpowiedź dotyczy łączenia kilku plików obiektów, podczas gdy pytanie dotyczy łączenia kilku bibliotek. –

+0

@ctcchen: Cóż, wygląda na to, że 'CMakeLists.txt' spowoduje połączenie biblioteki,' libcombi.a'. Ale moje pytanie do learnvst brzmi: czy to naprawdę wymaga niestandardowego celu? Czy nie ma bardziej standardowego mechanizmu? – einpoklum