Library's CMake generates DLL. Application's CMake wants LIB - windows

My library has minimal, straightforward CMake code with the pertinent lines
add_library(MyLib <sources>)
install(
TARGETS MyLib
LIBRARY DESTINATION ${destination}/lib
RUNTIME DESTINATION ${destination}/lib
COMPONENT Libraries)
install(
FILES mylib.h
DESTINATION ${destination}/include
COMPONENT Headers)
When executed under Windows, the system generates mylib.dll in ...\build\Release, and mylib.lib and mylib.exp (what's that?) in ...\build\lib\Release. It only installs mylib.dll.
My application has minimal, straightforward CMake code to search for my library:
find_path(MyLib_INCLUDE_DIR mylib.h)
find_library(MyLib_LIBRARIES NAMES MyLib)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MyLib DEFAULT_MSG MyLib_LIBRARIES MyLib_INCLUDE_DIR)
Which works under Linux, but under Windows results in
-- Could NOT find MyLib (missing: MyLib_LIBRARIES)
From experimentation I know that this error occurs whenever there is only a .DLL file, and no associated .LIB import library.
Shall I correct MyLib to install mylib.lib? How?
Or is it possible to modify my application so that it is satisfied with mylib.dll only? How?
Research done so far
This is not about static vs dynamic linking (DLL and LIB files - what and why?, cmake link against dll/lib): I want dynamic linking; if a .LIB file is required, it has nothing to do with static linking.
This link cmake : shared library : how to get the .lib name instead of .dll name? may be pertinent, but is not explicit enough. Two other questions CMake generated VS project expecting lib instead of dll, Linking dll/lib to a cmake project seem related, but have no answer.

Command install classifies .lib file for a shared library as ARCHIVE. This is explicitly stated in the documentation:
For DLL platforms (all Windows-based systems including Cygwin), the DLL import library is treated as an ARCHIVE target.
So you need to add ARCHIVE clause to install() for install .lib file as well:
install(
TARGETS MyLib
ARCHIVE DESTINATION ${destination}/lib
LIBRARY DESTINATION ${destination}/lib
RUNTIME DESTINATION ${destination}/bin
COMPONENT Libraries)
Not also, that RUNTIME DESTINATION is usually specified as bin, the same as destination for executables. This helps the executables on Windows to locate the shared libraries (.dll).

Related

How to create ".dll.a" and ".a' file

I am currently compiling a program involved reference to fftw3 library. I intend to compile it with Mingw-w64. I understand that I should put the fftw3.h in the /include folder and "fftw3.a" and "fftw3.ddl.a" files into the /lib folder for compilation by gcc.
However from the online available source, I can only find the source code for fftw3 library or the "dll" file to the best. I am wondering how I can find or make the "fftw3.a" and "fftw3.ddl.a" files.

How to specify the output directory of a given DLL?

I'm using the following src/CMakeLists.txt:
cmake_minimum_required(VERSION 3.1.0)
project(foo)
add_library(foo SHARED foo.cpp)
set_target_properties(foo
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/subdir
)
And on Windows, I'm building the library using:
mkdir build
cd build
cmake ../src
cmake --build .
Output File: ~/build/Debug/foo.dll
Expected Output File: ~/build/Debug/subdir/foo.dll
What am I doing wrong?
It works fine on platforms other than Windows, and it seems like it should work according to the following documentation:
add_library
set_target_properties
LIBRARY_OUTPUT_DIRECTORY
cmake-generator-expressions.
Short answer
On Windows, unlike other platforms, you should use RUNTIME_OUTPUT_DIRECTORY instead of LIBRARY_OUTPUT_DIRECTORY to specify the output directory of a shared library.
Long answer
This is documented on the CMake documentation about Output Artifacts:
Runtime Output Artifacts
A runtime output artifact of a buildsystem
target may be:
The executable file (e.g. .exe) of an executable target created by the
add_executable() command.
On DLL platforms: the executable file (e.g.
.dll) of a shared library target created by the add_library() command
with the SHARED option. The RUNTIME_OUTPUT_DIRECTORY and
RUNTIME_OUTPUT_NAME target properties may be used to control runtime
output artifact locations and names in the build tree.
Library Output Artifacts
A library output artifact of a buildsystem
target may be:
The loadable module file (e.g. .dll or .so) of a module library target
created by the add_library() command with the MODULE option.
On
non-DLL platforms: the shared library file (e.g. .so or .dylib) of a
shared library target created by the add_library() command with
the SHARED option. The LIBRARY_OUTPUT_DIRECTORY and
LIBRARY_OUTPUT_NAME target properties may be used to control library
output artifact locations and names in the build tree.
But why would CMake make such a difference between DLL platforms (Windows) and non-DLL platforms (macOS, Linux, etc.)?
I couldn't find a source documenting this design decision, but I believe the rationale is that Windows does not support the concept of rpath, that is, .exe files can't store internally the location of their dependent .dll files. Therefore, on Windows, .dll files are often stored in the same folder as .exe files to make sure that the DLLs are found at runtime. Instead, on Unix systems, shared library files are often stored in a separate lib folder, while application binaries are stored in a bin folder, which is not a problem because binaries can store the location of their dependencies using rpath.
In conclusion, it makes sense for cross-platform development to define both LIBRARY_OUTPUT_DIRECTORY and RUNTIME_OUTPUT_DIRECTORY, like so:
cmake_minimum_required(VERSION 3.1.0)
project(foo)
add_library(foo SHARED foo.cpp)
set_target_properties(foo
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/lib
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/bin
)

boost library 1.47.1 build 'lib' prefix causing LNK1104 error

I'm having difficulties generating the correct boost .lib file to compile with a VS project I've been given. It appears that after performing the complete build installation using 'b2.exe' from VS2010 command prompt I'm only able to generate the boost library files that contain the 'lib' prefix.
When I come to compile my project I'm getting the following error message:
"error LNK1104: cannot open file 'boost_signals-vc90-mt-1_47.lib'"
After going through the lib folder I can see that my boost build has only generated 'libboost_signals-vc90-mt-1_47.lib'
The boost documentation gives the following information about the lib prefix:
lib
Prefix: except on Microsoft Windows, every Boost library name begins with this string. On Windows, only ordinary static libraries use the lib prefix; import libraries and DLLs do not.
So far I've attempted the following build options for the msvc-9.0 toolset:
'build-type=complete'
'link=static,shared'
Any advice on how I may be able to generate the required .lib file would be greatly appreciated.
Many Thanks.
link=static should be used whenever you're linking to static version of boost library.
link=shared - should be used whenever you're linking dynamically to boost. It will add extra dependencies on boost dll's.
You can also use link=static,shared to build both versions - static and dynamic.
Define 'BOOST_ALL_DYN_LINK' in project controls how you link to boost.
If it's defined - it's dynamic linking, if not defined - it's static linking.

Linking a static boost build into a static library under VS2012 & Win32/64

I'm trying to build a static library to be released as an API for a network device. I can successfully compile and link the library to produce .lib output files, and I relocate them into a directory structure as follows:
EyeLib
L-Include
| L-PublicInterface.h
L-Lib
| L-debug
| | L-MyLib.lib
| | L-MyLib.pdb
| L-release
| L-MyLib.lib
L-MyLibConfig.cmake
Where the MyLibConfig.cmake file is extremely simple, and contains:
# the header file is relative to this cmake file, so get the path.
GET_FILENAME_COMPONENT( MyLib_TOPLEVEL_DIR ${CMAKE_CURRENT_LIST_FILE} PATH )
SET( MyLib_INCLUDE_DIR ${MyLib_TOPLEVEL_DIR}/include )
IF( WIN32 )
FIND_LIBRARY( MyLib_DEBUG_LIBRARY MyLib ${MyLib_TOPLEVEL_DIR}/lib/debug )
FIND_LIBRARY( MyLib_RELEASE_LIBRARY MyLib ${MyLib_TOPLEVEL_DIR}/lib/release )
SET( MyLib_LIBRARIES optimized ${MyLib_RELEASE_LIBRARY} debug ${MyLib_DEBUG_LIBRARY} )
ENDIF( WIN32 )
IF( UNIX )
FIND_LIBRARY( MyLib_LIBRARY MyLib ${MyLib_TOPLEVEL_DIR}/lib )
SET( MyLib_LIBRARIES "${MyLib_LIBRARY}" )
MARK_AS_ADVANCED( MyLib_LIBRARY )
ENDIF( UNIX )
# handle the QUIETLY and REQUIRED arguments
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MyLib DEFAULT_MSG MyLib_LIBRARIES MyLib_INCLUDE_DIR)
MARK_AS_ADVANCED( MyLib_INCLUDE_DIR )
This build structure has worked for some test libraries I've built in the past, but I'm getting a link error when I try and use it to build a simple test app saying "error LNK1104: cannot open file 'libboost_thread-vc110-mt-s-1_54.lib'"
I can get the test app to build and run successfully if I add it to the same project as the library build. I assume this is because the library build is finding the boost libs to link against, so it propagates through to the executables in the project.
I built boost 1.54 with b2 link=static runtime-link=static threading=multi variant=debug,release --layout=tagged and linked both the library build and the test app build to the static MSVC runtime (/MT).
Can anyone offer some help/advice/further tests with this one? I need to make sure that all the boost stuff is compiled-in to the API library, so our clients don't have to install boost themselves.
Additional Info
In-case it's helpful, here's the cmakelists.txt file from the library build:
set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}/lib")
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost REQUIRED COMPONENTS system date_time regex thread chrono)
if(NOT WIN32)
list(APPEND Boost_LIBRARIES pthread)
endif()
include_directories(${Boost_INCLUDE_DIRS})
FILE(GLOB srcs *.cpp)
FILE(GLOB headers *.h)
set(libname MyLib)
set(deps ${Boost_LIBRARIES})
#To allow compilation. std=c++0x is for accepting the access to enums, which usually is just accepted with Visual Studio
IF( NOT WIN32 )
set (CMAKE_CXX_FLAGS "-fpermissive -std=c++0x")
ENDIF( NOT WIN32 )
SOURCE_GROUP( ${libname} FILES ${srcs} )
SOURCE_GROUP( "${libname}\\Hdr" FILES ${headers} )
add_library(${libname} ${srcs} ${headers})
target_link_libraries( ${libname} ${deps} )
This is by design.
When building a static library, any dependencies to that library will not get linked into the library directly. Instead when building an executable all library dependencies (direct and indirect) will be linked directly to that executable.
This is also the way most compiler handle static libraries. While VS does offer a special option to link dependencies into static libs, this is not possible on e.g. gcc without resorting to dirty file hacks. Since CMake only supports features that can be used on all supported generators, CMake will not allow to do this even on VS builds.
You have a couple of options now:
Use a dll instead of a static library (add_library(${libname} SHARED ...)). While a static library is basically a bunch of object files wrapped together, a dll is more or less the same as an executable. In particular, all static library dependencies get linked directly into the dll. The disadvantage here is that you have to deal with the usual dll mess: You have to specify which functions to export and the usual issues with passing stuff across dll boundaries apply.
Have your find script also search for all the dependencies. You should be able to restructure your library's dependency handling in a way that the amount of code duplication is minimal. The disadvantage is that configuring a third-party application becomes more difficult (especially on Windows) since you now not only need to find the library itself, but also all of its dependencies.
Use exported targets. This approach makes most sense if the library is built on the same machine as the final executable. Upon building the library, CMake auto-generates the config files for using that library. Your application then just needs to find an include that script and you're good to go. Disadvantage is that the export mechanism is not the most straight-forward feature of CMake, so you will have to spend some time to familiarize yourself with it.
Pull in the library sources directly into each executable. Basically each executable does an add_subdirectory on the library source dir. You still have to configure the dependencies for each executable and on top of that you also have to build the library seperately for each executable. You probably don't want to do this.

dev cpp win32 the program can't start because sqlite3.dll is missing

I am using dev c++ IDE which used ming gcc(i am not sure of it)
I wanted to use sqlite3 in my win32 c application
I downloaded sqlite3.dll and sqlite3.dev and used dlltool to create a .a file like libsqlite3.a and pasted in the lib folder of dev cpp and added this path in the project options -> parameters
i copied the header file sqlite3.h into the include folder(which i got from another website - http://www.opensource.apple.com/source/SQLite/SQLite-74/derived_source/sqlite3.h)
i executed the program and got the message 'the program can't start because sqlite3.dll is missing in your computer'
so i copied the sqlite3.dll into my working directory and then it worked
BUT
How to make the sqlite.* static while compiling?
I mean i thought by including the libsqlite3.a, the final exe will not be dependent of any external dll's.
So i want to know how to compile in a way that i will not be needing a dll and by doing so it makes my windows program standalone.
do i have a create a .lib file instead of .a file?
EDIT after answers and comments:
Besides, the devpak is working fine... yet i wanted to know how to include files to project or to create .a files so i am trying this way because if some components do not provide devpak then this will be the way we need to compile.. isn't it?
EDIT to show what i have done after the answer by CL and the two comments
This is how i have added the sqlite.c to project list
Here is the compile log
Compiler: Default compiler
Building Makefile:
"C:\Users\jayapalc\Documents\test-sqlite\Makefile.win"
Executing make...
make.exe -f "C:\Users\jayapalc\Documents\test-sqlite\Makefile.win" all
g++.exe -c sqlite3.c -o sqlite3.o -I"lib/gcc/mingw32/3.4.2/include"
-I"include/c++/3.4.2/backward" -I"include/c++/3.4.2/mingw32" -I"include/c++/3.4.2" -I"include"
sqlite3.c: In function `void strftimeFunc(sqlite3_context*, int,
sqlite3_value**)':
sqlite3.c:14727: error: invalid conversion from void*' tochar*'
The files i got in sqlite.org/sqlite-amalgamation-3071502.zip are
shell.c, sqlite3.h, sqlite3.c, sqlite3ext.h and i saw in other discussions that shell.c is not needed...
Besides, people were talking about gcc and g++... .
Apart from updating Dev-C++ itself, try this to compile sqlite.c as a C file:
Go to Project >> Project Options >> Files.
Find the C file we're talking about. Untick "Compile file as C++".
This should inform Dev-C++ that it should invoke gcc.exe, and not g++.exe.
If you don't want to compile sqlite yourself by adding it to your project, you can try passing the -static flag to GCC/G++ to force it to link libsqlite.a statically.
Just include the sqlite3.c file in your project.
You need only this filed, and it must be compiled as C, not C++.
Apparently, Dev-C++ does not allow mixing C and C++ source files in one project.
Instead, you could try to compile sqlite3.c as C and then include the generated .o file into the C++ project (on the Linker page).

Resources