Getting CMake to build shared library for MSVC [duplicate] - visual-c++

This question already has answers here:
CMake link shared library on Windows
(3 answers)
Closed 6 years ago.
I've been building C and C++ projects in unix environments using CMake. However, I want to also start compiling in MSVC and I'm trying to get my head around the cmake documentation but I'm getting stuck.
I keep getting the following message when I try to build.
LINK : fatal error LNK1104: cannot open file 'Debug\MyLibrary.lib' [C:\sandbox\projects\cpp\DummyChelloWorld\build\ma
inProgram.vcxproj]
Can you tell me what I'm doing wrong?
CMakeLists.txt
cmake_minimum_required(VERSION 3.4)
project(helloWorld)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include(GenerateExportHeader)
ADD_LIBRARY(MyLibrary SHARED myShared.cpp)
set(SOURCE_FILES main.cpp)
GENERATE_EXPORT_HEADER( MyLibrary
BASE_NAME MyLibrary
EXPORT_MACRO_NAME MyLibrary_EXPORT
EXPORT_FILE_NAME ${CMAKE_BINARY_DIR}/MyLibrary_Export.h
STATIC_DEFINE MyLibrary_BUILT_AS_STATIC
)
add_executable(mainProgram ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(mainProgram MyLibrary)
TARGET_INCLUDE_DIRECTORIES(mainProgram PUBLIC exports)
main.cpp
#include "myShared.h"
int main() {
sayHI();
return 0;
}
myShared.cpp
#include <iostream>
#include "myShared.h"
using namespace std;
void sayHI() {
cout << "Hello World lib" << endl;
}
myShared.h
#ifndef HELLOWORLD_HELLO_H
#define HELLOWORLD_HELLO_H
void sayHI();
#endif //HELLOWORLD_HELLO_H

Turning my comment into an answer
For CMake Version >= 3.4
Just use CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS:
cmake_minimum_required(VERSION 3.4)
project(helloWorld)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1)
add_library(MyLibrary SHARED myShared.cpp)
set(SOURCE_FILES main.cpp)
add_executable(mainProgram ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(mainProgram MyLibrary)
For CMake Version < 3.4
You need to declare your functions/symbols as exported. So in your case, you have to modify the following files:
myShared.h
#ifndef HELLOWORLD_HELLO_H
#define HELLOWORLD_HELLO_H
#include "MyLibrary_Export.h"
void MyLibrary_EXPORT sayHI();
#endif //HELLOWORLD_HELLO_H
CMakeLists.txt
cmake_minimum_required(VERSION 3.4)
project(helloWorld)
set(CMAKE_CXX_STANDARD 11)
include(GenerateExportHeader)
add_library(
MyLibrary
SHARED
myShared.cpp
myShared.h
MyLibrary_Export.h
)
GENERATE_EXPORT_HEADER(
MyLibrary
BASE_NAME MyLibrary
EXPORT_MACRO_NAME MyLibrary_EXPORT
EXPORT_FILE_NAME MyLibrary_Export.h
STATIC_DEFINE MyLibrary_BUILT_AS_STATIC
)
target_include_directories(MyLibrary PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
set(SOURCE_FILES main.cpp)
add_executable(mainProgram ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(mainProgram MyLibrary)
I've
added MyLibrary_EXPORT to your function declaration
added the CMAKE_CURRENT_BINARY_DIR to the shared libraries include paths (to point to the generated export definitions header)
made use of the more cross-platform CMAKE_CXX_STANDARD definition.
Alternative
References
cmake link shared library on Windows
Export all symbols when creating a DLL

Related

Pytorch Tensor::data_ptr<long long>() not working on Linux

I cannot link my program to pytorch under Linux, get the following error:
/tmp/ccbgkLx2.o: In function `long long* at::Tensor::data<long long>() const':
test.cpp:(.text._ZNK2at6Tensor4dataIxEEPT_v[_ZNK2at6Tensor4dataIxEEPT_v]+0x14): undefined reference to `long long* at::Tensor::data_ptr<long long>() const'
I am building a very simple minimal example:
#include "torch/script.h"
#include <iostream>
int main() {
auto options = torch::TensorOptions().dtype(torch::kInt64);
torch::NoGradGuard no_grad;
auto T = torch::zeros(20, options).view({ 10, 2 });
long long *data = (long long *)T.data<long long>();
data[0] = 1;
return 0;
}
The command used to build it:
g++ -w -std=c++17 -o test-torch test.cpp -D_GLIBCXX_USE_CXX11_ABI=1 -Wl,--whole-archive -ldl -lpthread -Wl,--no-whole-archive -I../libtorch/include -L../libtorch/lib -ltorch -ltorch_cpu -lc10 -Wl,-rpath,../libtorch/lib
Pytorch has been downloaded from the link https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.7.0%2Bcpu.zip and unzipped (so I have the libtorch folder next to the folder with test.cpp).
Any ideas how to solve this problem? Same program works just fine under Visual C++.
P.S. I know pytorch is kind of designed for cmake, but I have zero experience with cmake and no desire to write a cmake-based build system for my app. Also, the examples they give are seemingly supposed to only work if pytorch is "installed" in the system. So I cannot just download the .zip with libs? And if I "install" it (e.g. from sources or in whatever other way) on an AVX512 system, will the binary I link to it and distribute to end-users work on non-AVX512? The documentation is completely incomprehensible for newbies.
UPDATE: I tried to do this via CMake following the tutorial https://pytorch.org/cppdocs/installing.html and got exactly the same error. Specifically, I renamed my directory to example-app and the source file to example-app.cpp. Then I created CMakeLists.txt in this directory with the following contents:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(example-app)
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
add_executable(example-app example-app.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}")
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
Then
mkdir build
cd build
cmake -DCMAKE_PREFIX_PATH=../../libtorch ..
cmake --build . --config Release
And here's the output:
CMakeFiles/example-app.dir/example-app.cpp.o: In function `long long* at::Tensor::data<long long>() const':
example-app.cpp:(.text._ZNK2at6Tensor4dataIxEEPT_v[_ZNK2at6Tensor4dataIxEEPT_v]+0x14): undefined reference to `long long* at::Tensor::data_ptr<long long>() const'
Makes me think, maybe I forgot to include some header or define some variable?
Oh, this is all on Mint 19.2 (equivalent to Ubuntu 18.04), g++ version is 7.5.0, glibc is 2.27. Compiling with g++-8 gives the same result.
This is not a cmake-related error, it's just how the library was implemented. I do not know why, but it appears that the specialization of T* at::Tensor::data<T> const with T = long long was forgotten/omitted.
If you want to get your signed 64-bits pointer, you can still get it with int64_t:
auto data = T.data<int64_t>();
It's good practice to use these types for which the size is explicit in general, in order to avoid compatibility issues.

Linker error compiling c-source using wininet with Mingw-w64

I have a problem compiling c-source on windows. I use functions of wininet and got a linker error.
I use this version g++.exe (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 8.1.0
sample code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wininet.h>
int main (int argc, char **argv)
{
InternetOpen("WebReader", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
return 0;
}
the compile statement wirh error:
"C:\Program Files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin\g++.exe" -lwininet -g test.c -o test.exe
C:\Users\peter\AppData\Local\Temp\ccfXocKI.o: In function `main':
D:\source\mingw\ShellHost/test.c:9: undefined reference to `_imp__InternetOpenA#20'
collect2.exe: error: ld returned 1 exit status
Can anyone help?
You should link with Wininet.lib as InternetOpenA documentation says (see Requirements part).
I realize this was posted almost two years ago, but I wanted to expand on nevilad's answer to help someone in the future:
As nevilad said, adding the Wininet library as an additional dependency should fix this issue.
In Visual Studios IDE... Project > Properties > Configuration Properties > Linker > Input > Additional Dependencies > add "Wininet.lib" to the list

linking mongocxx using cmakelists file in Linux

i am new to cmake and also to mongocxx. I have installed the mongocxx using the instructions given on the site http://mongocxx.org/mongocxx-v3/. My installatio is fine. Now I am trying to connect with mongodb using cmake in my project. When i write the following cmakelists.txt file
cmake_minimum_required(VERSION 3.15)
project(PROJECT_NAME)
set(CMAKE_CXX_STANDARD 14)
add_executable(PROJECT_NAME main.cpp)
find_package(libmongocxx REQUIRED)
find_package(libbsoncxx REQUIRED)
include_directories(${LIBMONGOCXX_INCLUDE_DIR})
include_directories(${LIBBSONCXX_INCLUDE_DIR})
include_directories("/usr/local/include/mongocxx/v_noabi")
include_directories("/usr/local/include/bsoncxx/v_noabi")
include_directories("/usr/local/include/libmongoc-1.0")
include_directories("/usr/local/include/libbson-1.0")
include_directories("/usr/local/lib")
target_link_libraries(PROJECT_NAME ${LIBMONGOCXX_LIBRARIES})
target_link_libraries(PROJECT_NAME ${LIBBSONCXX_LIBRARIES})
it gives me following error :
CMake Error at CMakeLists.txt:8 (find_package):
By not providing "Findlibmongocxx.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"libmongocxx", but CMake did not find one.
Could not find a package configuration file provided by "libmongocxx" with
any of the following names:
libmongocxxConfig.cmake
libmongocxx-config.cmake
Add the installation prefix of "libmongocxx" to CMAKE_PREFIX_PATH or set
"libmongocxx_DIR" to a directory containing one of the above files. If
"libmongocxx" provides a separate development package or SDK, be sure it
has been installed.
-- Configuring incomplete, errors occurred!
See also "/home/fedora/testmongo/build/CMakeFiles/CMakeOutput.log".
I also tried to run my cpp file with this method given on above website.
code of my cpp file is
#include <cstdint>
#include <iostream>
#include <vector>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/stdx.hpp>
#include <mongocxx/uri.hpp>
#include <mongocxx/instance.hpp>
#include <bsoncxx/builder/stream/helpers.hpp>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/builder/stream/array.hpp>
using bsoncxx::builder::stream::close_array;
using bsoncxx::builder::stream::close_document;
using bsoncxx::builder::stream::document;
using bsoncxx::builder::stream::finalize;
using bsoncxx::builder::stream::open_array;
using bsoncxx::builder::stream::open_document;
mongocxx::instance instance{}; // This should be done only once.
int main() {
std::cout << "Hello, World!" << std::endl;
mongocxx::client conn{ mongocxx::uri{ "mongodb://localhost:27017" } };
auto coll = conn["test"]["coll"];
std::vector<bsoncxx::document::value> documents;
for(int i = 0; i < 100; i++) {
documents.push_back(bsoncxx::builder::stream::document{} << "i" << i
<< finalize);
}
coll.insert_many(documents);
return 0;
}
and im trying to compile it with this command. its not giving any error
c++ --std=c++11 .cpp
-I/usr/local/include/mongocxx/v_noabi -I/usr/local/include/libmongoc-1.0
-I/usr/local/include/bsoncxx/v_noabi -I/usr/local/include/libbson-1.0
-L/usr/local/lib -lmongocxx -lbsoncxx
It complies without any errors and also generate output file a.out, but i don't know how to run that output file. its not running with
./a.out
gives following error
./a.out: error while loading shared libraries:
libmongocxx.so._noabi: cannot open shared object file: No such file
or directory """" This is the exact error i got
what should i do to correct this error or run the below executable file?
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/mongo-cxx-driver/lib64
These step resolved my problem
Use this as your CMakeLists.txt. Change $YOUR_PROJECT_NAME with your project's name.
cmake_minimum_required(VERSION 3.5)
if(POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif()
project($YOUR_PROJECT_NAME CXX)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror")
endif()
find_package(mongocxx REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
# Visual Studio pre 2017 requires boost polyfill.
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_STANDARD LESS 17)
find_package(Boost 1.56.0 REQUIRED)
if (CMAKE_VERSION VERSION_LESS 3.15.0)
target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
else()
target_link_libraries(${PROJECT_NAME} PRIVATE Boost::boost)
endif()
endif()
target_link_libraries(${PROJECT_NAME}
PRIVATE mongo::mongocxx_shared
)
add_custom_target(run
COMMAND ${PROJECT_NAME}
DEPENDS ${PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
)
get_target_property(LIBMONGOCXX_DEFINITIONS mongo::mongocxx_shared INTERFACE_COMPILE_DEFINITIONS)
list(FIND LIBMONGOCXX_DEFINITIONS "BSONCXX_STATIC" LIST_IDX)
if (${LIST_IDX} GREATER -1)
message(FATAL_ERROR "Expected BSONCXX_STATIC to not be defined")
endif()
list(FIND LIBMONGOCXX_DEFINITIONS "MONGOCXX_STATIC" LIST_IDX)
if (${LIST_IDX} GREATER -1)
message(FATAL_ERROR "Expected MONGOCXX_STATIC to not be defined")
endif()

How do I write the cmake script for clion to include glfw?

cmake_minimum_required(VERSION 3.15)
project(hello)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
set(CMAKE_CXX_STANDARD 11)
add_executable(hello main.cpp)
INCLUDE_DIRECTORIES(${GLFW_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(hello ${GLFW_STATIC_LIBRARIES})
It tells me
CMake Error at /home/user/.local/share/JetBrains/Toolbox/apps/CLion/ch-0/193.5233.144/bin/cmake/linux/share/cmake-3.15/Modules/FindPkgConfig.cmake:696 (message):
None of the required 'glfw3' found
when I try to build it. My glfw folder is located at /usr/local/include/GLFW.
AFAIK, glfw3 is using CMake as the build system,
(src: packages.debian.org/fr/sid/amd64/libglfw3-dev/filelist)
which uses modern CMake, so you don't need GLFW_INCLUDE_DIRS etc...
Inside this file /usr/lib/cmake/glfw3/glfw3Targets.cmake (loaded by /usr/lib/cmake/glfw3/glfw3Config.cmake), you'll see:
...
# Create imported target glfw
add_library(glfw SHARED IMPORTED)
set_target_properties(glfw PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "GLFW_DLL"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include"
)
...
So you can simply use:
find_package(glfw3 REQUIRED)
...
target_link_libraries(Foo glfw)
ps: same as my previous comment

Getting load library or linking error for XCB plugin of statically linked Qt5

Trying to create C++ Qt5.6.1 application and start it on Debian.
Getting either link error or load library error.
Qt build to a static libs, used configuration
configure -release -confirm-license -opensource -static -no-dbus -no-openssl -no-qml-debug -no-opengl -qt-freetype -qt-xcb -nomake tools -nomake tests -nomake examples -no-sql-db2 -no-sql-oci -no-sql-tds -no-sql-sqlite2 -no-sql-odbc -no-sql-ibase -no-sql-psql -skip doc -skip imageformats -skip webchannel -skip webengine -skip webview -skip sensors -skip serialport -skip script -skip multimedia
Project created with Cmake, libs are specified in this way:
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${QT5_LIB_ROOT}/cmake")
FIND_PACKAGE(Qt5Core REQUIRED)
FIND_PACKAGE(Qt5Gui REQUIRED)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Network REQUIRED)
FIND_PACKAGE( PNG REQUIRED )
FIND_PACKAGE( ZLIB REQUIRED)
FIND_PACKAGE( Threads REQUIRED )
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(QT_LIBS
libqtharfbuzzng_debug.a
libqtpcre_debug.a
libQt5PlatformSupport_debug.a
libxcb-static_debug.a
)
ELSE()
SET(QT_LIBS
libqtharfbuzzng.a
libqtpcre.a
libQt5PlatformSupport.a
libxcb-static.a
)
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(OS_SPECIFIC_LIBS
dl
Qt5::QXcbIntegrationPlugin
${CMAKE_THREAD_LIBS_INIT}
${ZLIB_LIBRARIES}
${PNG_LIBRARY} )
FOREACH(lib_name ${QT_LIBS})
IF(NOT EXISTS ${QT5_LIB_ROOT}/${lib_name})
MESSAGE(FATAL_ERROR "Could not locate required Qt lib ${QT5_LIB_ROOT}/${lib_name}")
ENDIF()
LIST(APPEND OS_SPECIFIC_LIBS ${QT5_LIB_ROOT}/${lib_name})
ENDFOREACH(lib_name)
And if I'm importing XCB plugin in the code ( Q_IMPORT_PLUGIN(QXcbIntegrationPlugin) it gives me link error:
/Qt5/plugins/platforms/libqxcb.a(qxcbmain.o): In function `QXcbIntegrationPlugin::create(QString const&, QStringList const&, int&, char**)':
qxcbmain.cpp:(.text+0x67): undefined reference to `QXcbIntegration::QXcbIntegration(QStringList const&, int&, char**)'
Anf if I don't import plugin - it just not start with error:
This application failed to start because it could not find or load the Qt platform plugin "xcb"
Any help? advice?
Thanks.
Solution was simple - just link with proper system libs:
fixed with adding
FIND_PACKAGE( X11 REQUIRED )
SET(OS_SPECIFIC_LIBS
...
xcb
X11-xcb
${X11_LIBRARIES}
)
(nvm the comment above, I found the problem)
To add to Ation answer, the "future proof" way I found to debug this is to use qmake for a minimal sample.
testcase.pro:
QT += core gui
QTPLUGIN.platforms = qminimal qxcb
CONFIG -= import_plugins
CONFIG += static
SOURCES += main.cpp
main.cpp:
#include <QCoreApplication>
#include <QDebug>
#include <QtPlugin>
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
qDebug() << "Does something!";
return app.exec();
}
Once this exist, run qmake and make. The make output will contain all -l**** you need to put in the CMake project CMAKE_CXX_LINK_EXECUTABLE variable. I can be automated.
The solution isn't simple. Maybe you doing something wrong if you are here. But you need to link res/archdatadir/plugins/platforms/libqxcb.a and lib/libQt{$Qt_MAJOR_VERSION}XcbQpa.a
Dirty example for cmake is here https://github.com/Jihadist/StaticQtPlugin/blob/master/CMakeLists.txt#L56 and dont't forget Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
Thanx to https://stackoverflow.com/users/1672598/emmanuel-lepage-vallee

Resources