嵌套静态链接库和一个可怕的错误
Nested Static Linked Libraries and a Spooky Bug
(平台:C++14、Clang 3.8、Ubuntu16.04、CMake 3.5.1)
我有两个静态库(PawLIB、CalikoCat)和一个依赖于 OtherLibrary 的可执行文件。在 CalkoCat 中只有一个 class,Dummy。 (在我们开始认真开发这个库之前,我只是确保一切都正确链接。)
The Dummy class 目前依赖 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)
现在,我喜欢在我的库中包含测试应用程序,这也不例外。在 repo 中,我将库和测试程序代码分成 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;
}
编译和 运行ning 此版本按预期工作,向终端打印 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!
。
这是怎么回事,我错过了什么?
你应该尝试颠倒这两行:
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 的符号,它应该首先出现在命令行中。
(平台:C++14、Clang 3.8、Ubuntu16.04、CMake 3.5.1)
我有两个静态库(PawLIB、CalikoCat)和一个依赖于 OtherLibrary 的可执行文件。在 CalkoCat 中只有一个 class,Dummy。 (在我们开始认真开发这个库之前,我只是确保一切都正确链接。)
The Dummy class 目前依赖 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)
现在,我喜欢在我的库中包含测试应用程序,这也不例外。在 repo 中,我将库和测试程序代码分成 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;
}
编译和 运行ning 此版本按预期工作,向终端打印 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!
。
这是怎么回事,我错过了什么?
你应该尝试颠倒这两行:
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 的符号,它应该首先出现在命令行中。