-1

I'm trying to build my C++ app using CMake (CLion on Windows). Application uses Thrift libraries, and those have been successfully (at least I hope so) built with Microsoft Visual 2015. I can built app with 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 files, created as a result of the 'scons' command, work perfectly fine. But, when I try to do build app with CMake, like that:

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 reports an error:

[  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

If i try to find thrift library with find_package(Thrift REQUIRED) command, I get the following error:

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

I would be grateful for any help.


EDIT1:

I tried to solve my problem with the help of this question: CMake link to external library, but, unfortunately, it does not work for me. I have edited my 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 successfully finds my thrift. Here is CMake output:

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

But, when I try to link my project, there is an error:

[  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

Am I missing something? Note that thrift has been built in x64/Release mode, and I am using x64 mingw in CLion and CMake is also in release mode. Thanks.


EDIT2:

After fiew improvements, linker seems to be able to find thrift. But, now, I get undefined reference to... error. For the thrift and also some boost libs. For example:

CMakeFiles\CoreWars.dir/objects.a(MARS.cpp.obj):MARS.cpp:(.text+0x454): undefined reference to `apache::thrift::TApplicationException::write(apache::thrift::protocol::TProtocol*) const'

and

CMakeFiles\CoreWars.dir/objects.a(MARS.cpp.obj):MARS.cpp:(.text.startup+0x11): undefined reference to `boost::system::generic_category()'

What may be the cause of this error? Shouldn't ${Boost_LIBRARIES} include also Boost.System library path? Googled solutions seem to not be appropriate in this case.

Updated 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} )

Thank You again.

3voC
  • 647
  • 7
  • 19
  • 1
    It looks like you are passing the directory where to look for the library, but not the name of the actual library `libthrift.lib` – Darien Pardinas May 30 '17 at 01:56
  • Possible duplicate of [CMake link to external library](https://stackoverflow.com/questions/8774593/cmake-link-to-external-library) – Tsyvarev May 30 '17 at 07:08
  • 1
    As for given error message, it results in typo: `$(THRIFT_LIBRARYDIR)` should be replaced with `${THRIFT_LIBRARYDIR}`, as in CMake variables are referenced with `${}`. (But after fixing of the typo you will get the error `couldn't open the file, it is directory` instead.) – Tsyvarev May 30 '17 at 07:13
  • @Tsyvarev - You were right, there was a typo. I corrected it, also took a look at the 'possible duplicate' post, but with no luck. I have edited post with new CMakeLists.txt – 3voC May 30 '17 at 11:04
  • Your `find_library()` call stores path to the library in the variable *THRIFT_FOUND_LIB*; this variable you should use for link: `target_link_libraries(CoreWars ${THRIFT_FOUND_LIB})`. It is described in the [corresponded answer](https://stackoverflow.com/a/41909627/3440745). – Tsyvarev May 30 '17 at 12:22
  • @Tsyvarev i did as You suggested; now the error is 'undefined reference'. I put updated CMakeLists.txt in edited post. If You could look at it, I would be grateful. – 3voC May 30 '17 at 22:13
  • Visual Studio works with `.lib` *import* libraries, MinGW works with `.a`. You may create `.a` library from `.def` file as described in this question: https://stackoverflow.com/questions/6731100/link-to-python-with-mingw. – Tsyvarev May 30 '17 at 22:46

1 Answers1

1

It looks like you are passing the directory where to look for the library, but not the name of the actual library. Add this in your CMakelists.txt, it should work:

target_include_directories(${THRIFT_INCLUDEDIR})
target_link_libraries(CoreWars ${Boost_LIBRARIES} libthrift.lib) # Or may be just 'thrift'
Darien Pardinas
  • 5,910
  • 1
  • 41
  • 48
  • Yeah, you're right. But, after correcting this mistake, it still can't find thrift :(. See edit of my question please. – 3voC May 30 '17 at 11:00