I'm struggling to use a DLL generated using CMAKE and C++. I'm able to build the library, include it and build the target project, the problem is that when I run the target build it crashes immediately.
My code is super easy and I don't know what I'm missing.
The DLL is built using CMAKE in a separate project. Here's the code
DLL PROJECT:
CMakeLists
cmake_minimum_required(VERSION 3.5)
project(LibProj LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions("-DBUILD_LIB")
file(GLOB
INCLUDE_FILES
baselibraryclass.h
)
file(GLOB
SOURCE_FILES
baselibraryclass.cpp
)
add_library(yourlib SHARED ${INCLUDE_FILES} ${SOURCE_FILES} )
baselibraryclass.h
#ifndef BASELIBRARYCLASS_H
#define BASELIBRARYCLASS_H
#ifdef BUILD_LIB
#define EXT_DLL __declspec(dllexport)
#else
#define EXT_DLL __declspec(dllimport)
#endif
#include <string>
class EXT_DLL BaseLibraryClass
{
public:
BaseLibraryClass();
};
#endif // BASELIBRARYCLASS_H
baselibraryclass.cpp
#include "baselibraryclass.h"
#include <iostream>
EXT_DLL BaseLibraryClass::BaseLibraryClass()
{
std::cout << "Hi from the library Class Object " << std::endl;
}
Target project
CMakeLists
cmake_minimum_required(VERSION 3.5)
project(TargetProject LANGUAGES CXX)
#Including the path of the library header
include_directories(D:/TestingDLLNativeCpp/Library/include)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(TargetProject main.cpp)
#The path of the built library is D:/TestingDLLNativeCpp/Library/Debug/yourlib.lib
target_link_libraries(TargetProject PRIVATE D:/TestingDLLNativeCpp/Library/Debug/yourlib.lib)
Target project main.cpp
#include <iostream>
#include <baselibraryclass.h>
using namespace std;
int main()
{
BaseLibraryClass testObk;
return 0;
}
As I wrote above, cmake configures properly and the compiler is able to build for both projects, however the target executables crashes immediately.
What am I doing wrong o.O??
Thanks for the attention
The issue of the dll not being included in the build directory might be solved by setting the CMAKE_RUNTIME_OUTPUT_DIRECTORY. However, a better practice would be to set the output directory of the .dll on a target basis. This will ensure that you have no unwanted side-effects in the long run.
set_target_property(yourlib PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
Related
This question already has answers here:
How do I make CMake output into a 'bin' dir?
(9 answers)
Closed 2 years ago.
I've read a number of posts concerning similar issues but I still can't find the solution to the following problem.
I have two CLion (OS Windows) projects mylib and myexe which reside in separate directories at the same level. mylib consists of two files:
library.h
void hello();
and library.cpp
#include "library.h"
#include <iostream>
void hello() {
std::cout << "Hello, World!" << std::endl;
}
The CMakeLists.txt for mylib is the following:
cmake_minimum_required(VERSION 3.16)
project(mylib)
set(CMAKE_CXX_STANDARD 14)
add_library(mylib SHARED library.cpp library.h)
Next, the project myexe consists of one file main.cpp
#include "../mylib/library.h"
int main() {
hello();
return 0;
}
with the following CMakeLists.txt file
cmake_minimum_required(VERSION 3.16)
project(myexe)
set(CMAKE_CXX_STANDARD 14)
add_executable(myexe main.cpp)
find_library(RESULT mylib "d:/src/test/mylib/cmake-build-debug")
target_link_libraries(myexe "${RESULT}")
Both projects are built without errors. But when I run myexe, the "Hello, world" isn't printed, and I'm getting the following:
Process finished with exit code -1073741515 (0xC0000135)
Please help me, how to solve this issue and link DLL correctly.
As #Scheff suggested, looking at How do I make CMake output into a 'bin' dir?, I just added theses three lines to the CMakeLists.txt files of both projects myexe and mylib:
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "../../bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "../../bin")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../../bin")
where "../../bin" is the desired directory to store .dll and .exe.
I have simple program as follow:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR})
add_executable(test main.cpp)
target_include_directories(test PRIVATE ${PROJECT_SOURCE_DIR})
target_link_libraries(test PRIVATE power.dll)
main.cpp:
#include <iostream>
#include "power.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
power(4.);
return 0;
}
power.h:
#ifndef POWER_H
#define POWER_H
double power(double number) noexcept;
#endif // POWER_H
Implementation of power.h is in a .dll named power.dll.
If I compile this project with MinGW 7.3.0 X64 says:
error: undefined reference to `power(double)'
If I compile it with MSVC 2017 X64 says:
error: LNK1104: cannot open file 'power.lib'
both errors show that power.dll can't detect by the linker.
I did many searches but none of solutions worked for me!
Can anyone help about this?
Thanks in advance!
Your modelling of the dynamic library is incorrect, both on CMake and on the source level.
As a starting point, try building the dll as part of the same CMake project as the consuming executable:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GenerateExportHeader)
add_library(power SHARED power_sources.cpp power.h)
generate_export_header(power)
target_include_directories(power PUBLIC ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR})
add_executable(test main.cpp)
target_link_libraries(test PRIVATE power)
Note the use of the generate_export_header function, which instructs CMake to generate macros for exporting functions on shared library interfaces in a portable way. Since generated files go to the binary directory tree, we have to adjust the include directories for the library accordingly.
To make sure the function gets properly exported, change your header as follows:
#ifndef POWER_H
#define POWER_H
#include <power_export.h>
POWER_EXPORT double power(double number) noexcept;
#endif // POWER_H
Note that generare_export_header allows you to customize the generated export header extensively.
Be sure you get the project to build and run from this baseline.
If you want to build the dll externally (which is not strictly necessary, but since that's what your question is about...), we have to modify the CMake file to something like:
cmake_minimum_required(VERSION 3.5)
project(test LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(power)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE power)
With all the magic here happening in the find_package call. That call is now responsible for providing all the information that was previously handled by the lines for building the library:
Providing of an imported target power for consumption by the target_link_libraries call
Association of the library name of the import library (the power.lib file) via that imported target
Exposure of the public include directories for both power.h and power_export.h via that imported target
You can either construct such an imported target manually in the find script, or have CMake do it for you. In the first case, create a FindPower.cmake script file, make sure it's location is part of the CMAKE_MODULE_PATH and write the code for finding the library and header files and constructing the imported target in there. Note that getting this right in a portable way can be very tricky and goes far beyond the scope of a StackOverflow question. In the second case, have the CMake script that builds the power library perform an install step during which a config file package will get generated, which can then be consumed by your test project. Note that this approach is not viable if the power library is not itself being built with CMake, so in that case you will have to stick with the first option.
Dynamic linking in Windows requires that externally visible symbols are declared with the keyword __declspec. Your header "power.h" should be modified:
#ifndef POWER_H
#define POWER_H
#if defined(__WIN32__) && !defined(__CYGWIN__)
# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_DLL)
# define POWERAPI __declspec(dllexport)
# elif (defined(_MSC_VER) || defined(__MINGW32__))
# define POWERAPI __declspec(dllimport)
# endif
#endif
POWERAPI double power(double number) noexcept;
#endif // POWER_H
In the project building the DLL power.dll with CMake, you should define the symbol BUILD_DLL:
add_definitions(-DBUILD_DLL)
then it should generate a power.lib file when the MSVC compiler and a power.a when using MINGW. Don't define BUILD_DLL in the project using the DLL, and it should work.
I don't want to install sqlite globally in my system, so I have downloaded the sqlite3 files from https://www.sqlite.org/2018/sqlite-amalgamation-3240000.zip and have copied sqlite3.c and sqlite3.h into the project folder.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
project(learn_cpp)
set(CMAKE_CXX_STANDARD 11)
add_executable(learn_cpp main.cpp)
main.cpp :
#include <iostream>
#include "sqlite3.h"
int main() {
return 0;
}
I am not getting any of the functions from sqlite3.h as suggestion in the CLion IDE.
By default, CMake doesn't search headers files in the current directory. For enable this behaviour, set CMAKE_INCLUDE_CURRENT_DIR variable:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(learn_cpp main.cpp ...)
I have a project in Clion using CMake and C++14. The project compiles but all standard library includes are marked as:
"Cannot find string", "Cannot find stdexcept", etc.
Additionally the symbols from the dll I included are not being detected. So they are all marked as:
"Cannot resolve ..."
I've included the header and cmakelist.txt. This is only happening in this project and I have almost identical cmakelist.txt files for all my projects. I have tried restarting CLion's cache. I also tried moving all the files to a new project which worked momentarily but with an hour CLion was flagging these lines again.
cmakelists.txt
cmake_minimum_required(VERSION 3.6)
project(BCI)
set(CMAKE_CXX_STANDARD 14)
#create dlls and executables in the root directory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
include_directories(
${CMAKE_SOURCE_DIR}
)
set(SOURCE_FILES
NeuralInterface.hpp
)
add_library(BCI SHARED ${SOURCE_FILES})
set_target_properties(BCI PROPERTIES LINKER_LANGUAGE CXX)
NeuralInterface.hpp
#ifndef NEURALINTERFACE_HPP
#define NEURALINTERFACE_HPP
//c++ includes
#include <stdexcept> //these are the includes which cannnot be resolved
#include <string>
//project includes
#include "okFrontPanelDLL.h"
extern std::string IntanAcquire; //this says cannot resolve container std
...
#endif
What else can I do to CMake so it finds these headers?
I am trying to find the best way to link my project source code with my boost unit tests. I have a fairly basic project setup right now using CMake, however all examples of boost UTF that I have come across have shown very basic tests which do not touch source code in a project that is along side the tests.
As a minimal example I have the following:
CMakeLists.txt
cmake_minimum_required(version 2.8)
project(test-project)
find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework )
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_subdirectory(src)
enable_testing()
add_subdirectory(test)
src/CMakeLists.txt
add_executable(example main.cpp foo.cpp)
src/foo.h
#include <string>
std::string hello(std::string name);
src/foo.cpp
#include "foo.h"
std::string hello(std::string name) { return "Hello " + name; }
src/main.cpp - Uses foo in a simple way
test/CMakeLists.txt
include_directories (../src)
set(TEST_REQUIRED_SOURCES ../src/foo.cpp)
add_executable (test test.cpp ${TEST_REQUIRED_SOURCES})
target_link_libraries(test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_test(SimpleTest test)
test/test.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE SimpleTest
#include <boost/test/unit_test.hpp>
#include "foo.h"
BOOST_AUTO_TEST_CASE(ShouldPass) {
BOOST_CHECK_EQUAL(hello("fred"), "Hello fred")
}
While this works, I'd like to avoid the following:
Defining TEST_REQUIRED_SOURCES with a list of all of my files required to compile.
Avoiding the duplicate compilation of code.
Does my structure look correct for this sort of project? Would it make sense to compile my code under src into a library instead? Most of my experience with testing is from C# where this is much simpler.
You can have a look at how I did it there: https://github.com/NewbiZ/mengine/blob/master/CMakeLists.txt
Basically, I build an object file with my library, and reuse it in the main executable AND the tests. That way you only build once.
The interesting piece of CMake is:
# Just build the object files, so that we could reuse them
# apart from the main executable (e.g. in test)
ADD_LIBRARY(mengine_objects OBJECT ${MENGINE_SOURCES})
Then build the main executable:
ADD_EXECUTABLE(mengine $<TARGET_OBJECTS:mengine_objects>
src/main.cpp)
And the tests:
ADD_EXECUTABLE(test_tga $<TARGET_OBJECTS:mengine_objects>
test_tga.cpp)
Hope that helps!