【发布时间】:2017-10-30 07:22:55
【问题描述】:
我正在尝试使用 CMake(Windows 上的 CLion)构建我的 C++ 应用程序。应用程序使用 Thrift 库,并且这些库已成功(至少我希望如此)使用 Microsoft Visual 2015 构建。我可以使用 SCons 构建应用程序:
import os
from os import path, listdir
gen_cpp = [path.join('gen-cpp', f) for f in listdir('gen-cpp') if f.endswith('.cpp')]
client_source = [path.join('logic', folder, f) for folder in ['', 'parser', 'mars', 'view']
for f in listdir(path.join('logic', folder)) if f.endswith('.cpp')]
server_source = [path.join('server', 'server.cpp')]
tests_source = [path.join('test_cases', f) for f in listdir('test_cases') if f.endswith('.cpp')]
cpppath = ['.','c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src\\','c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src\\thrift\\server',
'c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\']
libpath = ['C:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release\\', 'c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\stage\\x64\\lib\\',
'C:\\OpenSSL-Win64\\lib']
libs = ['libthrift','libssl','openssl','libcrypto']
env = Environment(CPPPATH = cpppath,
LIBS = libs,
LIBPATH = libpath,
MSVC_VERSION='14.0',
CPPFLAGS='/EHsc',
)
gen_cpp_o = env.Object(gen_cpp)
client_o = env.Object(client_source)
tests_o = env.Object(tests_source)
tests_files = gen_cpp_o + [f for f in client_o if str(f) != path.join('logic', 'main.obj')] + tests_o
env.Program('CoreWars', gen_cpp_o + client_o)
env.Program('Server', gen_cpp_o + server_source)
env.Program('tests', tests_files)
.exe 文件,由 'scons' 命令创建,运行良好。但是,当我尝试使用 CMake 构建应用程序时,就像这样:
cmake_minimum_required(VERSION 3.7)
project(client)
SET (THRIFT_ROOT "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0")
SET (THRIFT_INCLUDEDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src")
SET (THRIFT_LIBRARYDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release")
include_directories(${THRIFT_INCLUDEDIR})
MESSAGE("Thrift_LIBRARIES: ${THRIFT_LIBRARYDIR}")
MESSAGE("Thrift_INCLUDES: ${THRIFT_INCLUDEDIR}")
#find_package(Thrift REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET (BOOST_ROOT "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_INCLUDEDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_LIBRARYDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\libs")
find_package(Boost 1.64.0 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
set(SOURCE_FILES ../gen-cpp/MARS.cpp ../gen-cpp/mars_constants.cpp ../gen-cpp/mars_types.cpp main.cpp
parser/InstructionFactory.cpp parser/RedcodeParser.cpp parser/InstructionData.cpp ServerConnector.cpp
mars/Instruction.cpp mars/InstructionOperator.cpp parser/ParserException.cpp MainController.cpp
mars/MarsSimulator.cpp Initializer.cpp Player.cpp Player.h PlayerInfo.cpp PlayerInfo.h Warrior.cpp
Warrior.h PlayerCreator.cpp PlayerCreator.h view/ViewInput.cpp view/ViewInput.h MarsResult.cpp MarsResult.h
mars/DatInstruction.cpp mars/DatInstruction.h mars/MovInstruction.cpp mars/MovInstruction.h)
add_executable(CoreWars ${SOURCE_FILES})
target_link_libraries(CoreWars ${Boost_LIBRARIES} $(THRIFT_LIBRARYDIR))
CMake 报错:
[ 4%] Linking CXX executable CoreWars.exe
G__~1.EXE: error: $(THRIFT_LIBRARYDIR): No such file or directory
mingw32-make.exe[3]: *** [logic/CoreWars.exe] Error 1
如果我尝试使用 find_package(Thrift REQUIRED) 命令查找 thrift 库,则会收到以下错误:
CMake Error at logic/CMakeLists.txt:13 (find_package):
By not providing "FindThrift.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Thrift", but
CMake did not find one.
Could not find a package configuration file provided by "Thrift" with any
of the following names:
ThriftConfig.cmake
thrift-config.cmake
如果有任何帮助,我将不胜感激。
EDIT1:
我试图在这个问题的帮助下解决我的问题:CMake link to external library,但不幸的是,它对我不起作用。 我已经编辑了我的 CMakeList.txt:
cmake_minimum_required(VERSION 3.7)
project(client)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET (THRIFT_ROOT "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0")
SET (THRIFT_INCLUDEDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src")
SET (THRIFT_LIBRARYDIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release")
MESSAGE("Thrift_LIBRARIES: ${THRIFT_LIBRARYDIR}")
MESSAGE("Thrift_INCLUDES: ${THRIFT_INCLUDEDIR}")
find_library(THRIFT_FOUND_LIB thrift PATHS ${THRIFT_LIBRARYDIR})
MESSAGE("Thrift found lib: ${THRIFT_FOUND_LIB}")
link_libraries(thrift "${THRIFT_FOUND_LIB}")
link_directories(${THRIFT_LIBRARYDIR})
include_directories(${THRIFT_INCLUDEDIR})
SET (BOOST_ROOT "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_INCLUDEDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
SET (BOOST_LIBRARYDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\libs")
find_package(Boost 1.64.0 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
set(SOURCE_FILES ../gen-cpp/MARS.cpp ../gen-cpp/mars_constants.cpp ../gen-cpp/mars_types.cpp main.cpp
parser/InstructionFactory.cpp parser/RedcodeParser.cpp parser/InstructionData.cpp ServerConnector.cpp
mars/Instruction.cpp mars/InstructionOperator.cpp parser/ParserException.cpp MainController.cpp
mars/MarsSimulator.cpp Initializer.cpp Player.cpp Player.h PlayerInfo.cpp PlayerInfo.h Warrior.cpp
Warrior.h PlayerCreator.cpp PlayerCreator.h view/ViewInput.cpp view/ViewInput.h MarsResult.cpp MarsResult.h
mars/DatInstruction.cpp mars/DatInstruction.h mars/MovInstruction.cpp mars/MovInstruction.h)
add_executable(CoreWars ${SOURCE_FILES})
MESSAGE("Cmake prefix path: ${CMAKE_PREFIX_PATH}")
LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
target_link_libraries(CoreWars ${Boost_LIBRARIES} thrift)
Cmake commnad find_library 成功找到了我的thrift。这是 CMake 输出:
C:\Users\Antek\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\171.4073.41\bin\cmake\bin\cmake.exe -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" C:\Users\Antek\Documents\MEGAsync\_STUDIA\ZPR\proj1\Core-Wars-ZPR
Thrift_LIBRARIES: c:\Users\Antek\libs\thrift-0.10.0\thrift-0.10.0\lib\cpp\x64\Release
Thrift_INCLUDES: c:\Users\Antek\libs\thrift-0.10.0\thrift-0.10.0\lib\cpp\src
Thrift found lib: C:/Users/Antek/libs/thrift-0.10.0/thrift-0.10.0/lib/cpp/x64/Release/libthrift.lib
-- Boost version: 1.64.0
Cmake prefix path:
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Antek/Documents/MEGAsync/_STUDIA/ZPR/proj1/Core-Wars-ZPR/cmake-build-release
但是,当我尝试链接我的项目时,出现错误:
[ 4%] Linking CXX executable CoreWars.exe
C:/PROGRA~1/MINGW-~1/X86_64~1.2-P/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4.9.2/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lthrift
我错过了什么吗?请注意,thrift 已在 x64/Release 模式下构建,我在 CLion 中使用 x64 mingw,CMake 也处于发布模式。 谢谢。
EDIT2:
经过几次改进,链接器似乎能够找到节俭的地方。但是,现在,我得到 undefined reference to... 错误。对于节俭和一些提升库。例如:
CMakeFiles\CoreWars.dir/objects.a(MARS.cpp.obj):MARS.cpp:(.text+0x454): undefined reference to `apache::thrift::TApplicationException::write(apache::thrift::protocol::TProtocol*) const'
和
CMakeFiles\CoreWars.dir/objects.a(MARS.cpp.obj):MARS.cpp:(.text.startup+0x11): undefined reference to `boost::system::generic_category()'
此错误的原因可能是什么? ${Boost_LIBRARIES} 不应该还包括 Boost.System 库路径吗?在这种情况下,谷歌搜索的解决方案似乎不合适。
更新 CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(client)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
SET (THRIFT_ROOT "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0")
SET (THRIFT_INCLUDE_DIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\src")
SET (THRIFT_LIB_DIR "c:\\Users\\Antek\\libs\\thrift-0.10.0\\thrift-0.10.0\\lib\\cpp\\x64\\Release")
find_library(THRIFT_FOUND_LIB thrift PATHS ${THRIFT_LIB_DIR})
MESSAGE("Found Thrift lib: ${THRIFT_FOUND_LIB}")
find_path(THRIFT_FOUND_HEADERS thrift PATHS ${THRIFT_INCLUDE_DIR})
MESSAGE("Found Thrift headers: ${THRIFT_FOUND_HEADERS}")
include_directories(${THRIFT_FOUND_HEADERS})
link_directories(${THRIFT_FOUND_HEADERS})
link_directories(${THRIFT_FOUND_LIB})
SET (BOOST_ROOT "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
#SET (BOOST_INCLUDEDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost")
#SET (BOOST_LIBRARYDIR "c:\\Users\\Antek\\libs\\boost_1_64_0\\boost\\libs")
find_package(Boost 1.64.0 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARIES})
set(SOURCE_FILES ../gen-cpp/MARS.cpp ../gen-cpp/mars_constants.cpp ../gen-cpp/mars_types.cpp main.cpp
parser/InstructionFactory.cpp parser/RedcodeParser.cpp parser/InstructionData.cpp ServerConnector.cpp
mars/Instruction.cpp mars/InstructionOperator.cpp parser/ParserException.cpp MainController.cpp
mars/MarsSimulator.cpp Initializer.cpp Player.cpp Player.h PlayerInfo.cpp PlayerInfo.h Warrior.cpp
Warrior.h PlayerCreator.cpp PlayerCreator.h view/ViewInput.cpp view/ViewInput.h MarsResult.cpp MarsResult.h
mars/DatInstruction.cpp mars/DatInstruction.h mars/MovInstruction.cpp mars/MovInstruction.h)
add_executable(CoreWars ${SOURCE_FILES})
target_include_directories(CoreWars SYSTEM PUBLIC ${THRIFT_FOUND_HEADERS})
target_link_libraries(CoreWars LINK_PUBLIC ${THRIFT_FOUND_LIB} ${Boost_LIBRARIES} )
再次感谢您。
【问题讨论】:
-
看起来您传递的是要查找库的目录,而不是实际库的名称
libthrift.lib -
对于给定的错误消息,它会导致拼写错误:
$(THRIFT_LIBRARYDIR)应该替换为${THRIFT_LIBRARYDIR},因为在 CMake 中变量被引用为${}。 (但在修正错字后,您将收到错误couldn't open the file, it is directory。) -
@Tsyvarev - 你是对的,有一个错字。我更正了它,还查看了“可能重复”的帖子,但没有运气。我用新的 CMakeLists.txt 编辑了帖子
-
您的
find_library()调用将库的路径存储在变量 THRIFT_FOUND_LIB 中;您应该将此变量用于链接:target_link_libraries(CoreWars ${THRIFT_FOUND_LIB})。它在corresponded answer 中有描述。