我有一个项目,它曾经是一组巨大的源文件,所有这些源文件都经过编译然后链接为一个可执行文件。作为使项目更加模块化的第一步,我将构建分解为几个更小的块,并使它们成为静态库。有一个层次结构,因此Exe1将链接到静态库Lib2A和Lib2B. Lib2A将取决于 static Lib3A、lib3B、lib3C等。此处的数字显示了它们在层次结构中的层。
问题是我需要--whole-archive在链接时使用,否则找不到底层库中的某些符号。
当我添加以下链接时Exe1:
target_link_libraries(Exe1 -Wl,--whole-archive Lib2A Lib2B -Wl,--no-whole-archive)
Run Code Online (Sandbox Code Playgroud)
我最终得到了一个实际的链接阶段命令,例如:
g++ -o Exe1 -Wl,--whole-archive libLib2A.a libLib2B.a -Wl,--no-whole-archive libLib3A.a libLib3B.a libLib3C.a
Run Code Online (Sandbox Code Playgroud)
不可避免地,某些第 3 层静态库中的符号会丢失,并且会出现丢失符号错误。
我期望因为Lib2A有Lib3*库作为依赖项,所以它们也会--whole-archive在链接器命令的“内部”部分,但它们出现在外部。
我尝试了许多不同的组合(例如将--whole-archive东西放在较低层),但还没有遇到使用 CMake 的方法。我究竟做错了什么?
谢谢
我正在努力使用正确的命令来执行以下操作:
找到包含特定符号的所有共享库(*.so).
这就是我尝试过的:
find -iname '*.so*' -exec nm {} \; | grep -H _ZN6QDebugD1Ev
Run Code Online (Sandbox Code Playgroud)
上面给出了一些带有符号的输出,但没有找到符号出现的文件名.我给grep告诉它打印文件名的任何标志都会丢失,因为grep是从stdin提供的.
(standard input): U _ZN6QDebugD1Ev
(standard input): U _ZN6QDebugD1Ev
(standard input): U _ZN6QDebugD1Ev
(standard input): U _ZN6QDebugD1Ev
(standard input):0015e928 T _ZN6QDebugD1Ev
(standard input): U _ZN6QDebugD1Ev
(standard input): U _ZN6QDebugD1Ev
(standard input): U _ZN6QDebugD1Ev
Run Code Online (Sandbox Code Playgroud)
另一种尝试:
find -iname '*.so*' -exec nm {} \; -exec grep _ZN6QDebugD1Ev {} \;
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为两个高管完全独立.
我该怎么办?
我试图理解为什么 CMake 在特定情况下会抱怨。
我的模块 A 取决于模块 B,而模块 B 又取决于模块 C。
模块C是模块B的子目录,每个模块的CMakeLists.txt相关部分如下所示:
模块 A 执行以下操作:
add_library(A STATIC "")
target_include_directories(A PRIVATE
$<TARGET_PROPERTY:B,INCLUDE_DIRECTORIES>
)
Run Code Online (Sandbox Code Playgroud)
模块 B 执行以下操作:
add_library(B static "")
set(some_dirs
C
)
foreach(DIR ${some_dirs})
add_subdirectory(${DIR})
target_link_libraries(B PUBLIC ${DIR})
endforeach(DIR)
Run Code Online (Sandbox Code Playgroud)
模块 C 执行以下操作:
add_library(C STATIC "")
target_include_directories(C
PUBLIC
$<TARGET_PROPERTY:OtherLib,INCLUDE_DIRECTORIES>
PRIVATE
)
Run Code Online (Sandbox Code Playgroud)
有一个可执行文件链接到模块 A。
使用 TARGET_PROPERTY:INCLUDE_DIRECTORIES 的原因是我正在将一个具有大量循环依赖项的大型项目从单一的可执行文件转移到具有不同库的可执行文件。我最初的努力只是创建模块,然后打破循环依赖。因此,在此示例中,target_link_libraries我不使用依赖项,而是target_include_directories将属性 INCLUDE_DIRECTORIES 用于依赖项。我希望这是有道理的。
我收到上述情况的错误,其中包括:
Configuring done
Failed to parse JSON from CMake server.
Failed to parse JSON from CMake server.
CMake Error in A/CMakeLists.txt: …Run Code Online (Sandbox Code Playgroud) 我读过这篇文章 [1],但就我而言,CMake 说它找不到 glew。
我在 Windows 上,我的 CMake 模块文件夹中有一个 FindGLEW.cmake 文件,大概是在我安装 CMake-3.6 时放在那里的。我在 sourceforge 上找到了 GLEW 并下载了适用于 Windows 的 zip 文件。我解压并安装在C:\Program Files\glew。当我创建自己的库并使用 CMake 构建和安装它们时,这是它们安装的默认位置,所以我非常有信心我在这里没问题。
我的 CMakeLists.txt 中的片段是:
find_package(GLEW REQUIRED)
include_directories(${GLEW_INCLUDE_DIRS})
link_libraries(${GLEW_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)
来自 CMake 的实际错误消息是:
CMake Error at C:/Program Files/CMake/share/cmake-3.6/Modules/FindPackageHandleStandardArgs.cmake:148 (message):
Could NOT find GLEW (missing: GLEW_INCLUDE_DIR GLEW_LIBRARY)
Call Stack (most recent call first):
C:/Program Files/CMake/share/cmake-3.6/Modules/FindPackageHandleStandardArgs.cmake:388 (_FPHSA_FAILURE_MESSAGE)
C:/Program Files/CMake/share/cmake-3.6/Modules/FindGLEW.cmake:44 (find_package_handle_standard_args)
source/CMakeLists.txt:5 (find_package)
Run Code Online (Sandbox Code Playgroud)
FindGLEW.cmake 是否有可能损坏?我查看了其他几个 FindXXXXX.cmake 文件,它们就像雪花,每个都非常独特。所以我很难肯定地说它遵循惯例。
add_custom_command()在构建 elf 文件目标后,我在 CMake 构建中有一些东西可以做一些事情:将其转换为 srec,用 0xFF 填充各个区域并创建一个二进制图像,生成一个 CRC 并获取图像的大小。 add_custom_command()可以有DEPENDS,让它只在elf文件重新生成时才运行,很棒。
我还想做的是使用 FILE() 创建一个新文件,其中包含二进制文件名、crc 和大小(可能是简单的 JSON 格式),但文档暗示我不能在事情之后做这个文件活动我上面提到的已经发生了。
# This command creates the FF-filled binary file. It uses objcopy to create the srec
# file to operate on.
add_custom_command(
OUTPUT ThreadingApp.bin filled.srec
MAIN_DEPENDENCY ThreadingApp.elf
COMMAND ${CMAKE_OBJCOPY} ARGS -O srec ThreadingApp.elf ThreadingApp.srec
COMMAND srec_cat.exe ThreadingApp.srec -offset - -minimum-addr ThreadingApp.srec
?fill 0xFF -over ThreadingApp.srec -o filled.srec
COMMAND srec_cat.exe filled.srec -o ThreadingApp.bin -binary
)
# This command creates the CRC …Run Code Online (Sandbox Code Playgroud)