说明
最近在学习C++,顺带学些了一下CMake,但是当链接(link)的时候,总是出现类似于下面的错误。注:所有关于protobuf的调用链上的函数都显示这个问题,这里只粘贴了其中的一条。
c++ undefined reference to google::protobuf::internal::VerifyVersion(int, int, char const*)
解决方法
- 由于是链接时出现了问题,因此查看build/CMakeFiles/test_server/link.txt文件,发现该文件中指示的protobuf链接库的.a文件是存在的。将link.txt改为link.sh再次执行,发现还是出现同样的错误。
- 查看之前直接用命令行(g++ -std=c++11)编译的.o文件,与执行CMake之后的.o文件不一样,因此考虑可能是编译的问题。
- 查看build/CMakeFiles/test_server/flags.cmake文件,发现里边的CXX_FLAG设置的编译器为(-std=gnu++11),因此确定是CMakeLists.txt文件中的某些标志位没设置好。
原本的CMakeLists.txt文件如下:
set(CMAKE_CXX_STANDARD 11)
改为如下即可编译链接成功:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
函数说明
- 变量
CXX_STATNARD_REQUIRED
的官方解释为:
If this property is set to ON, then the value of the CXX_STANDARD target property is treated as a requirement. If this property is OFF or unset, the CXX_STANDARD target property is treated as optional and may “decay” to a previous standard if the requested is not available. For compilers that have no notion of a standard level, such as MSVC, this has no effect.
意思是,如果不设置的话,则之前设置的STANDARD 11标准可能会失效。因此,下面两条语句一般是连用的。
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- 变量
CXX_EXTENSIONS
的解释为:
This property specifies whether compiler specific extensions should be used. For some compilers, this results in adding a flag such as -std=gnu++11 instead of -std=c++11 to the compile line. This property is ON by default. The basic C++ standard level is controlled by the CXX_STANDARD target property.
也就是说,该值默认使用gnu++11编译,我们的protobuf编译的时候是使用c++11编译的,因此,应该把该变量关了。