我如何链接包含基于CMAKE定义的全局变量定义的条件类型/变量定义的库?
简介
我正在尝试使用 toulbar2 作为我的CMAKE项目中的C ++库,但是我有很多麻烦将其链接到我的主要可执行文件。
我在此处和其他类似网站上都发现了许多有关此主题的类似问题,但是它们都没有帮助我解决我的具体问题。我实际上尝试了所有事情,但我没有让它起作用,我希望你们中的一些人可以帮助我。
我正在运行Ubuntu 18.04,CMAKE版本3.23,在我的项目中,我正在使用标准C ++ 11。我是一名熟练的程序员,但我只是C ++和CMAKE的初学者/中级用户。
我已经尝试做的事情
我无法列出我的所有尝试,所以我只会提及我认为是我最好的尝试,以使您了解我可能做错了什么。
1)在我的第一次尝试中,我尝试使用与我导入的任何非标准库相同的方法,即使用find_package()
在cmakelists.txt中链接找到的库,并包含找到的include_dirs。但是,我很快意识到Toulbar2均未提供A find< tokage> .cmake
或< name> config.cmake
file。因此,这种方法无法正常工作。
2)我的第二次尝试是我认为使我最接近解决方案的尝试。您可以使用命令来轻松地将Toulbar2作为动态库来编译:cmake -dlibtb2 = on ..
在您先前创建的假设 build> build> build>中。使用构造
后,您的.so
文件中的build> build/lib/linux
。安装后,您可以使用命令find_library
本身使Cmake本身找到此库。因此,我的cmakelists.txt最终看起来像这样:
[...]
find_library(TB2_LIBRARIES tb2)
if(TB2_LIBRARIES)
set(all_depends ${all_depends} ${TB2_LIBRARIES})
else(TB2_LIBRARIES)
add_compile_definitions("-DNO_TB2")
message("Compiling without Toulbar2, if you want to use it, please install it first")
endif(TB2_LIBRARIES)
[...]
target_link_libraries(main ${all_depends})
[...]
此代码在某种程度上起作用,这意味着cmake正确地找到了库并运行链接命令,但是,如果我尝试#include #include< toulbar2lib.hpp> 找不到标题。因此,我发现我应该告诉CMAKE在哪里可以找到该标头,所以我最终添加了一个
include_directories(/path/to/header/file's/directory)
,但是我还有另一个问题。找到标头,但是在编译时找不到许多标题中使用的名称。原因是在Toulbar2中,通过使用#IFDEF或#IFNDEF等预处理指令来有条件地定义某些变量/类型,并且依次通过在编译时通过CMAKE定义了这些条件中使用的全局变量。如果您对一个示例感兴趣,我可以提及提到的标头文件中使用的COPT
类型。我看到这里的难题中缺少一块,但我无法弄清楚哪一个。由于我预先编译了库,这些定义在包含标头文件时应该存在,因为我正确地链接了包含这些定义的通讯库。
3)我的第三次尝试不如我提到的其他两个尝试优雅,但我拼命地试图找到解决方案。因此,我在项目中复制了整个Toulbar2克隆文件夹,并尝试将其添加为子目录,这意味着我的主cmakelists.txt
包含该行:
add_subdirectory(toulbar2)
它提供cmakelists.txt < /code>也是如此,这样做应该没有问题。然后,我包括包含我需要的标头文件的Toulbar2的SRC目录,我应该没事。正确的?错误的。我遇到了与以前相同的问题(2),即当我尝试编译项目时,实际上并未定义一些有条件定义的变量/类型,即使副标题Toulbar2正确(无错误)。
我只想提到任何答案是欢迎的,但是,如果您可以帮助我找出一个优雅的解决方案(请参阅1或2),这将会更好,因为此代码将很快或以后发布。预先感谢您的帮助。
Introduction
I am trying to use Toulbar2 as a C++ library in my CMake project, however I am having much trouble linking it to my main executable.
I found many similar questions on this topic, both here and on other similar website, but none of them helped me with my specific issue. I tried literally everything and I did not menage to make it work, I was hoping that some of you may help me with that.
I am running Ubuntu 18.04, CMake version 3.23 and in my project I am using the standard C++11. I am a proficient programmer, but I am just an beginner/intermediate user of both C++ and CMake.
What I've already tried to do
I cannot list all my attempts, so I will only mention those I think are my best ones, to give you an idea of what I may be doing wrong.
1) In my first attempt, I tried to use the same approach I used for any non-standard library I imported, i.e. using find_package()
in CMakeLists.txt to then link the found LIBRARIES and include the found INCLUDE_DIRS. However, I soon realised that Toulbar2 provides neither a Find<package>.cmake
or <name>Config.cmake
file. So, this approach could not work.
2) My second attempt is the one that in my opinion brought me the closest to the solution I hoped for. You can easily compile Toulbar2 as a dynamic library using the command: cmake -DLIBTB2=ON ..
in an hypothetical build
directory you previously created. After compiling with make
you have your .so
file in build/lib/Linux
. After installation, you can make CMake find this library by itself using the command find_library
. So, my CMakeLists.txt ended up looking like this:
[...]
find_library(TB2_LIBRARIES tb2)
if(TB2_LIBRARIES)
set(all_depends ${all_depends} ${TB2_LIBRARIES})
else(TB2_LIBRARIES)
add_compile_definitions("-DNO_TB2")
message("Compiling without Toulbar2, if you want to use it, please install it first")
endif(TB2_LIBRARIES)
[...]
target_link_libraries(main ${all_depends})
[...]
This code works to some extent, meaning that CMake correctly finds the library and runs the linking command, however if I try to #include <toulbar2lib.hpp>
the header is not found. So I figured out I should have told CMake where to find that header, so I ended up adding a
include_directories(/path/to/header/file's/directory)
However, I still have another problem. The header is found, but a lot of names used in the header are not found at compilation time. The reason is that in Toulbar2 some variables/types are defined conditionally by using preprocessing directives like #ifdef or #ifndef, and in turn the global variables used in these conditions are defined through CMake at compilation time. If you are interested in an example, I can mention the Cost
type that is used in the mentioned header file. I see that there's a piece missing in the puzzle here, but I cannot figure out which one. Since I pre-compiled the library those definitions should exist when I include the header file, because I am correctly linking the correspondent library that contains those definitions.
3) My third attempt is less elegant than the the other two I mentioned, but I was desperately trying to find a solution. So, I copied the whole toulbar2 cloned folder inside my project and I tried to add it as a subdirectory, meaning that my main CMakeLists.txt
contains the line:
add_subdirectory(toulbar2)
It provides a CMakeLists.txt
too, there should be no problem in doing it. Then I include the src directory of toulbar2, that contains the header file I need, and I should be okay. Right? Wrong. I got the same problem that I had before with (2), i.e. some variables/types conditionally defined were not actually defined when I tried to compile my project, even though the subproject toulbar2 was correctly (no errors) compiled.
I just wanted to mention that any answer is welcome, however if you could help me figure out an elegant solution (see 1 or 2) for this problem it would be way better, as this code is intended to be published soon or later. Thank you in advance for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
解决方案2)看起来不错。您只需要添加以下汇编标志-dndebug -dboost -dlongdouble_prob -dlong_cost使用toulbar2lib.hpp编译项目时。请参阅github/toulbar2 readme.md如何在没有cmake的情况下编译这些标志(除了在这种情况下不应通过使用的wcspformatly)。
Solution 2) looks fine. You just need to add the following compilation flags -DNDEBUG -DBOOST -DLONGDOUBLE_PROB -DLONGLONG_COST when compiling your project with toulbar2lib.hpp. See github/toulbar2 README.md how to compile without cmake for those flags (except WCSPFORMATONLY that should not by used in this context).