Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building of executable and shared library with cmake, runtimelinker does not find dll

I am working with gcc(cygwin), gnu make, windows 7 and cmake.

my cmake testprojekt has the following structure

rootdir
|-- App
|   |-- app.cpp
|   +-- CMakeLists.txt
|-- Lib
|   |-- lib.cpp
|   |-- CMakeLists.txt
|-- MakeFileProject
+ CMakeLists.txt

rootdir/App/app.cpp:

#include<string>
void printThemMessageToScreen(std::string input);//prototype
int main(int argc,char **argv){
 printThemMessageToScreen("this will be displayed by our lib");
 return 0;
}

rootdir/Lib/lib.cpp:

#include<iostream>
#include<string>

void printThemMessageToScreen(std::string input){
 std::cout<<input;
}

rootdir/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)
project(TestProject)

add_subdirectory(App)
add_subdirectory(Lib)

rootdir/Lib/CMakeLists.txt:

add_library(Lib SHARED lib.cpp)

rootdir/App/CMakeLists.txt:

# Make sure the compiler can find include files from our Lib library. 
include_directories (${LIB_SOURCE_DIR}/Lib) 

# Make sure the linker can find the Lib library once it is built. 
link_directories (${LIB_BINARY_DIR}/Lib) 

# Add executable called "TestProjectExecutable" that is built from the source files 
add_executable (TestProjectExecutable app.cpp) 

# Link the executable to the lib library. 
target_link_libraries (TestProjectExecutable Lib) 

Now, when i run cmake and make, everything will get generated & built with no errors, but when i try to execute the binary, it will fail because the library which was generated could not be found.

BUT: when i copy the lib dll into the same directory like the app exe, it will get executed!

also: if i configure the library to be static, it will also execute.

how to tell the runtime linker where to look for my dll?

UPDATE:

Solution according to the Method proposed by User Vorren:

I opened up the registry editor, and navigated to the following Key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths

, here i created a new key with the name of my Applikation:

in this case : TestProjectExecutable.exe

after that, the (default) value was set to the full path of TestProjectExecutable.exe including the filename and extension. Then i created another String Value called "Path" and set the value to the folder where the dll was located:

enter image description here

like image 588
Daniel Jawna Avatar asked Apr 27 '14 12:04

Daniel Jawna


People also ask

Is it better to use CMake for libraries or applications?

The bar for clean CMake code is significantly higher for a library than for an application because the CMake code itself affects end users. For an application, some ugliness is tolerable because it doesn't propagate through the dependency tree (you don't typically link to executables).

Is it possible to create an executable without a link interface?

However, executables usually don’t need a link interface, so it would make more sense to use the PRIVATE keyword here. this creates a myexec that contains not just the code for main.cpp as hoped, but also the code from the shared library mylibA. This would mean that mylibA is a static library, not a shared one.

Is it illegal to link to multiple libraries in one directory?

Certainly for a single target, it is totally illegal to link to both at the same time. This means we don't need to support mixing both types in a single directory. The bar for clean CMake code is significantly higher for a library than for an application because the CMake code itself affects end users.

Where do I put CMake package config scripts?

Since various package management systems (like vcpkg, Nuget, APT, etc.) have different standards for where to place CMake package config scripts, we create a cache variable, SomeLib_INSTALL_CMAKEDIR, to allow our users to control where those scripts go. We pick a common, safe default. Now we'll add the logic to install our libraries and headers:


2 Answers

Your problem lies not with linker or compiler, but with the way Windows searches for DLL's.

The OS will use the following algorithm to locate the required DLL's:

Look in:

  1. The directories listed in the Application-specific Path registry key;
  2. The directory where the executable module for the current process is located;
  3. The current directory;
  4. The Windows system directory;
  5. The Windows directory;
  6. The directories listed in the PATH environment variable;

Thus you have two reasonable options if you don't want to clutter the OS directories with your app-specific dll:

  1. Create an app-specific Path registry entry (I would go with this option);
  2. Put your DLL in the same folder as your EXE;
  3. Modify the PATH variable (but why would you do that, if you can go with option 1?);
like image 199
mr.pd Avatar answered Oct 05 '22 23:10

mr.pd


A solution I prefer that hasn't really been mentioned, is build your shared-libs into the same directory as your executables. This tends to be a much simpler solution.

One way to do this with cmake is

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

Or you can also set output directories based on build flavours.

See how do I make cmake output into a 'bin' dir?

like image 39
amurray Avatar answered Oct 06 '22 00:10

amurray