2017-02-19 18 views
-1

(Платформа: C++ 14, Clang 3.8, Ubuntu 16.04, CMake 3.5.1)Уплотненный Static Linked Библиотеки и Spooky Bug

У меня есть два статических библиотек (PawLIB, CalikoCat) и исполняемый файл, который полагается на OtherLibrary. В CalkoCat есть один класс, Dummy. (Я просто убедился, что все ссылки находятся прямо перед тем, как мы начнем серьезное развитие в этой библиотеке.)

Класс Dummy в настоящее время использует функцию PawLIB для тестирования.

calikocat-source/include/calikocat/dummy.hpp

#include "pawlib/iochannel.hpp" 

class Dummy 
{ 
    public: 
     Dummy(){} 
     static void speak(); 
     ~Dummy(){} 
}; 

calikocat-source/src/dummy.cpp

#include "otherlibrary/dummy.hpp" 

void Dummy::speak() 
{ 
    pawlib::ioc << "Hello, world!" << pawlib::io_end; 
} 

Нет проблем. Он правильно компилирует и правильно связывает CMake.

ПРИМЕЧАНИЕ. Вы можете смело предположить, что все переменные в обоих файлах CMakeLists.txt в этом вопросе тщательно протестированы и работают. Я проверял каждую тройку.

calikocat-source/CMakeLists.txt (фрагмент)

include_directories(include) 

# Include headers of dependencies. 
include_directories(${PAWLIB_DIR}/include) 

add_library(${TARGET_NAME} STATIC 
    include/calikocat/dummy.hpp 
    src/dummy.cpp 
) 

# Link against dependencies. 
target_link_libraries(${TARGET_NAME} ${PAWLIB_DIR}/lib/libpawlib.a) 

Теперь, мне нравится, включая тестер приложений с моими библиотеками, и это не является исключением. В репо я разделяю код библиотеки и тестера на calikocat-source и calikocat-tester каталогов. Я использую CMake для тестера, а ...

calikocat-tester/CMakeLists.txt (фрагмент)

include_directories(include) 

# Include headers of dependencies. 
include_directories(${PAWLIB_DIR}/include) 
include_directories(../calikocat-source/include) 

add_executable(calikocat-tester 
    main.cpp 
) 

# Link against dependencies. 
target_link_libraries(${TARGET_NAME} ${CPGF_DIR}/lib/libcpgf.a) 
target_link_libraries(${TARGET_NAME} ${PAWLIB_DIR}/lib/libpawlib.a) 
target_link_libraries(${TARGET_NAME} ${CMAKE_HOME_DIRECTORY}/../calikocat-source/lib/$<CONFIG>/libcalikocat.a) 

ли это правильно строит целиком и полностью зависит от наличия одной линии на main.cpp! Прочтите ниже ТЩАТЕЛЬНО.

calikocat-tester/main.cpp, РАБОЧАЯ ВЕРСИЯ

#include <calikocat/dummy.hpp> 
#include <pawlib/iochannel.hpp> 

int main() 
{ 
    pawlib::ioc << "Hello, world!" << pawlib::io_end; 
    Dummy::speak(); 

    return 0; 
} 

Компиляция и запуск этой версии работает, как ожидалось, печать Hello, world! на терминале дважды.

calikocat-tester/main.cpp, нерабочая версия

#include <calikocat/dummy.hpp> 
#include <pawlib/iochannel.hpp> 

int main() 
{ 
    //pawlib::ioc << "Hello, world!" << pawlib::io_end; 
    Dummy::speak(); 

    return 0; 
} 

Этой версия файла, где я закомментировать линию, используя PawLIB непосредственно, не компилируется. Вот ошибка ...

[100%] Linking CXX executable ../../bin/Debug/calikocat-tester 
../../../calikocat-source/lib/Debug/libcalikocat.a(dummy.cpp.o): In function `Dummy::speak()': 
/home/jason/Code/Repositories/calikocat/calikocat-source/src/dummy.cpp:4: undefined reference to `pawlib::ioc' 
/home/jason/Code/Repositories/calikocat/calikocat-source/src/dummy.cpp:5: undefined reference to `pawlib::iochannel::operator<<(pawlib::ioformat::IOControl const&)' 
../../../calikocat-source/lib/Debug/libcalikocat.a(dummy.cpp.o): In function `pawlib::iochannel::operator<<(char const*)': 
/home/jason/Code/Repositories/calikocat/calikocat-source/../../pawlib/pawlib/include/pawlib/iochannel.hpp:521: undefined reference to `pawlib::iochannel::resolve_pointer(char const*)' 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 
CMakeFiles/calikocat-tester.dir/build.make:99: recipe for target '../../bin/Debug/calikocat-tester' failed 

Я ожидал его компилировать, и при запуске, просто распечатать Hello, world! на терминал один раз.

Что здесь происходит, а что мне не хватает?

ответ

1

Вы должны попытаться обратить вспять эти две строки:

target_link_libraries(${TARGET_NAME} ${PAWLIB_DIR}/lib/libpawlib.a) 
target_link_libraries(${TARGET_NAME} ${CMAKE_HOME_DIRECTORY}/../calikocat-source/lib/$<CONFIG>/libcalikocat.a) 

Поскольку libcalikocat.a использует символы из libpawlib.a, он должен появиться первый в командной строке.

+0

Работал как очарование, спасибо. Иными словами, если 'D' полагается на' C', 'C' на' B' и 'B' на' A', тогда 'D' должен ссылаться в порядке' C B A'. Это достаточно легко. – CodeMouse92