区别是什么 : - lX11 选项对 CMake 中的目标_ link_ 图书馆
原标题:What difference: -lX11 option vs. target_link_libraries in CMake
I need to use OpenGL as a library in my project on my Ubuntu 15.04 64bit PC, which is built by CMake 3.0.2. I install packages: mesa-common-dev mesa-utils-extra libgl1-mesa-dev libglu1-mesa-dev libglapi-mesa libx11-dev libxi-dev libxinerama-dev libxcursor-dev libxrandr-dev
After run cmake and Makefile, I got these link error:
/usr/bin/ld: /home/user/CMU462/DrawSVG/asst1_drawsvg/lib/libglfw.a(x11_window.c.o): undefined reference to symbol XConvertSelection
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.so: error adding symbols: DSO missing from command line
I checked /usr/lib/x86_64-linux-gnu/libX11.so, it does exist.
I found a explanation, it seems I failed to link my project with X11 library. The answer says that add -lX11 option may fix this.
Alternatively I link X11 library in CMakeLists.txt according to FindX11.cmake:
find_package(X11 REQUIRED)
message(STATUS "X11_FOUND = ${X11_FOUND}")
message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}")
message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}")
include_directories(${X11_INCLUDE_DIR})
link_directories(${X11_LIBRARIES})
target_link_libraries(MyProj ... ${X11_LIBRARIES})
Run cmake I got these output:
-- X11_FOUND = 1
-- X11_INCLUDE_DIR = /usr/include
-- X11_LIBRARIES = /usr/lib/x86_64-linux-gnu/libX11.so;/usr/lib/x86_64-linux-gnu/libXext.so
But I still got the error aforementioned.
QUESTION: The X11 library can be linked by
using target_link_libraries in CMakeLists.txt, or
adding -lX11 option directly to compiling command
What s the difference between them? Does the link in CMakeLists.txt directly lead to a -lX11 option in Makefile generated?
If so, did I do something wrong in CMakeLists.txt?
UPDATE
Let s take this project as example, following is my build procedure.
Install required libraries: Install the OpenGL and other relative libraries (the GLEW and GLFW library is provided in this project): mesa-common-dev mesa-utils-extra libgl1-mesa-dev libglu1-mesa-dev libglapi-mesa libxi-dev libxinerama-dev libxcursor-dev libxrandr-dev
Run CMake: Then use the provided CMakeLists.txt, everything goes right.
Make: When make the project, this error occurred:
/usr/bin/ld: /home/user/CMU462/DrawSVG/asst1_drawsvg/lib/libglfw.a(x11_window.c.o): undefined reference to symbol XConvertSelection
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.so: error adding symbols: DSO missing from command line
I have searched for many times, all of the answers say that the incorrect link of glfw3 and x11 lead to the error:
missing the -X11 option. However in line 26 of CMakeLists.txt exists this option
the libraries show arranged in order. I check the dependencies with pkg-config --libs command, all libraries are arranged in order in line 17 to 29 of CMakeLists.txt.
The only potential reason for this is the order of the compile options of libraries (line 17 to 29) and the target_link_libraries (line 116) of CMakeLists.txt.
Otherwise, there must be another error omitted by me during my procedure.
问题回答
Here are a few huge differences between using CMake to find libraries and directly doing something like -lX11:
Is the Library Installed?
When looking for a library with cmake ... you can use the REQUIRED flag. This means if the library cannot be located on your development or build system, the process stops here in a much clearer manner than if you tried to compile and get errors for failing #include or linking against non-existing libraries.
For example:
find_package(Boost REQUIRED)
Where are the Library Headers?
The find_package() is expected to be provided by the author of a given package (CMake also provides some of .cmake files). This is very helpful as the author knows where they install the headers. This can change drastically between operating systems (even different versions of Linux).
As a results you get a variable set with the path to the library.
target_include_directories(${PROJECT_NAME}
PUBLIC
${Boost_INCLUDE_DIRS}
)
Again, you may not see that as super useful. After all, all includes are under /usr/include, right? In one of my projects, I have 30 contribs. Each one installs files under directory ${CMAKE_BINARY_DIR}/dist/include. For me to have those headers accessible by the other contribs and the main system, I have to have CMake find those files and give me the correct path. I definitely could hard code that path too. After all, that dist/include is the same thing as /usr/include... however, yet again, the user could decide to move that folder somewhere else. The CMake approach helps you dealing with many such situations.
How to Link against that Library?
The next step, as you asked about the -lX11 and whether the target_link_libraries() is of any help, is to determine how to link the library.
To link against all the Boost library you use the following:
target_link_libraries(${PROJECT_NAME}
${Boost_LIBRARIES}
)
If you only want to link against a specific Boost library, then you can use that specific component name:
target_link_libraries(${PROJECT_NAME}
${Boost_FILESYSTEM_LIBRARIES}
)
Note that the include may also require the special component name.
99% of the time, libraries can be linked using the -l option. Here we have several issues. The CMake search will find the library in a location which may not be /usr/lib. Actually, on Linux, we now have /usr/lib/x86_64-linux-gnu, although the linker knows about that one, there could be other sub-directories and other locations (/lib) that some OSes use. CMake is likely to find those automatically.
Actually, in many cases, the full path is used instead of the usual -l. Some CMake libraries may instead make use of the -L command line option. Further, some libraries have special command line option requirements. These will also be gathered by CMake and added to various variables that you can make use of (usually named after LDFLAGS).
Anything Else?
Yes.
The compile step may require special CFLAGS or CXXFLAGS. I think this is pretty rare these days, but I ve seen some libraries requiring really complicated compilation flags (i.e. -DNAME=...). These are added to a library specific set of flags that you can add to your CFLAGS and/or CXXFLAGS (in most cases, these are not made mandatory as they can have unwanted side effects).
So, as a conclusion, if -lX11 works for you and you don t want to spend any time on the corresponding CMake implementation, you can always use -lX11. If you want many people out there to be able to compile your project, though, you ll want to setup CMake properly and use all of those parameters in your project. Then a much larger number of people will be able to use your software.
Side Note
As mentioned by others, the link_directories() is to add directories to the linker. These are added using the -L command line option. This is rarely used manually. In most cases, the full path to the library is used by CMake allowing the library to be really anywhere (like in my case, my libraries end up under dist/lib).
相关问题
Where are the symbols etext, edata and end defined?
This is a code from Linux man page:
#include <stdio.h>
#include <stdlib.h>
extern char etext, edata, end;
int main() {
printf("First address past:
");
printf(" program text (...
Problem statically linking MFC libraries
I have a Visual Studio 6 workspace I m trying to convert to a Visual Studio 2008 solution. The output of said solution is a .dll. It has to be a .dll and it needs to statically link MFC as I can t ...
Create a shared lib using another shared lib
I have a shared library "libwiston.so". I am using this to create another shared library called "libAnimation.so", which will be used by another project. Now, the second library "libAnimation.so" can ...
[ linux, g++, linking]: library is in ldconf cache and Links Manually, but not by default
This appears similar to an earlier post: ld cannot find an existing library But to the best of my knowledge, it s not exactly the same situation. The following command works:
$g++ -I../../include/ -...
C++ linker - Lack of duplicate symbols
Why does the following code not give me a duplicate symbol linker error for Impl?
I ran across this problem in some code I inherited and I m recreating a shorter version here for simplicity.
I have ...
problem w/ linking static function g++
I am trying to build a small program and I have my own library libfoo. I have a camera class that is calling a static function from my Vector3 class (i.e. crossProduct). My camera class and Vector3 ...
Extract statically linked libraries from an executable
I m not sure if this is even possible, but given an executable file (foo.exe), with has many libraries which has been linked statically.
Is there any software that extract from this file the .lib ( ...
未界定的符号。 原件:无
除这一未界定的符号错误外,一切都在发挥作用: