I want to create a .dll library with all its dependencies packed inside the .dll.
However, there seems to be no easy way to achieve that with Cmake. My setup:
cmake_minimum_required(VERSION 3.0.0)
project(Main VERSION 0.1.0)
add_library(Main SHARED Main.cpp)
find_package(libzippp REQUIRED)
target_link_libraries(Main PRIVATE libzippp::libzippp)
This will produce both Main.dll but also libzippp.dll.
I would like to have libzippp.dll packed (statically linked) into Main.dll.
Of course you can't pack one DLL into another. You have to make libzippp a static library in the first place. To do this, build libzippp with BUILD_SHARED_LIBS set to NO at the CMake command line. Then libzippp::libzippp will be a static library when you go to find_package it.
This is easy enough to show steps for:
$ git clone git#github.com:ctabin/libzippp.git
$ cmake -S libzippp -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=NO -DCMAKE_INSTALL_PREFIX=$PWD/local -DLIBZIPPP_BUILD_TESTS=NO
$ cmake --build build --target install
$ tree local
local/
├── include
│ └── libzippp
│ └── libzippp.h
├── lib
│ └── libzippp_static.a
└── share
└── libzippp
├── FindLIBZIP.cmake
├── libzipppConfig.cmake
├── libzipppConfigVersion.cmake
├── libzipppTargets.cmake
└── libzipppTargets-release.cmake
This question already has answers here:
Understanding "requests linking to directory" cmake warning
(1 answer)
CMake link to external library
(6 answers)
Closed 10 months ago.
I am making an anpr algorithm that requires tesseract to decode the image to text. When running cmake .. inside my build dir, I get a warning saying:
┌──(user㉿MacBookArch)-[~/dev/anpr/build]
└─$ cmake ..
-- Configuring done
CMake Warning at CMakeLists.txt:15 (target_link_libraries):
Target "main" requests linking to directory
"/home/user/dev/anpr/build/libs/leptonica". Targets may link only to
libraries. CMake is dropping the item.
CMake Warning at CMakeLists.txt:16 (target_link_libraries):
Target "main" requests linking to directory
"/home/user/dev/anpr/build/libs/tesseract". Targets may link only to
libraries. CMake is dropping the item.
-- Generating done
-- Build files have been written to: /home/user/dev/anpr/build
This leads me into the thoughts that I have made something wrong. I have copied the repos for leptonica and tesseract into the libs directory for portability.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.2.2)
project( ANPR )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include )
include_directories(${PROJECT_SOURCE_DIR}/libs/tesseract/include)
include_directories(${PROJECT_SOURCE_DIR}/libs/leptonica/include)
link_directories(${PROJECT_SOURCE_DIR}/libs/tesseract)
link_directories(${PROJECT_SOURCE_DIR}/libs/leptonica)
add_executable( main src/main.cpp )
target_link_libraries( main ${OpenCV_LIBS} )
target_link_libraries( main ${CMAKE_CURRENT_BINARY_DIR}/libs/leptonica)
target_link_libraries( main ${CMAKE_CURRENT_BINARY_DIR}/libs/tesseract)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/samples/001.jpg
${CMAKE_CURRENT_BINARY_DIR}/samples/001.jpg
COPYONLY
)
and this is my project structure:
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── LeptonicaTargets.cmake
│ ├── libs
│ ├── main
│ ├── Makefile
│ └── samples
├── CMakeLists.txt
...
├── include
│ └── main.hpp
├── libs
│ ├── leptonica
│ └── tesseract
...
├── samples
│ └── 001.jpg
└── src
└── main.cpp
The contents of the build dir is auto generated with cmake.
make command inside the build dir goes fine without errors even after make clean:
┌──(user㉿MacBookArch)-[~/dev/anpr/build]
└─$ make
[ 50%] Building CXX object CMakeFiles/main.dir/src/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
How can I resolve this warning? I am open to all improvements, thank you!
I have a simple c++ project which includes eigen. I'm able to compile the project on my own machine but having trouble to compile it to webassembly with emscripten.
Project structure:
.
├── CMakeLists.txt
├── include
│ └── HelloWasm
│ └── my_lib.h
└── src
├── main.cpp
└── my_lib.cpp
File contents:
CMakeLists.txt
cmake_minimum_required( VERSION 3.0 )
project( HelloWasm )
# flags
# include files
include_directories( ./include .include/HelloWasm ./src )
# target
add_executable( HelloWasm ./src/main.cpp ./src/my_lib.cpp )
# 3rd party libs
find_package(Eigen3 REQUIRED NO_MODULE)
include_directories(${EIGEN3_INCLUDE_DIR})
include/HelloWasm/my_lib.h
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using Eigen::MatrixXd;
class MyLib
{
private:
protected:
public:
MyLib()
{
}
~MyLib()
{
}
void eigen_test();
};
src/main.cpp
#include <iostream>
#include "HelloWasm/my_lib.h"
using namespace std;
int main()
{
MyLib my_lib;
my_lib.eigen_test();
}
src/my_lib.cpp
#include "HelloWasm/my_lib.h"
void MyLib::eigen_test()
{
MatrixXd m(2, 2);
m(0, 0) = 3;
m(1, 0) = 2.5;
m(0, 1) = -1;
m(1, 1) = m(1, 0) + m(0, 1);
cout << '\n'
<< m << endl;
}
Compiling the project successfully locally:
mkdir build && cd build
cmake ..
make
➜ ./HelloWasm
3 -1
2.5 1.5
Errors when trying to compile to webassemply
(I tried following the steps provided in the emscripten docs)
mkdir build && cd build
cmake ..
emcmake cmake ..
output:
configure: cmake .. -DCMAKE_TOOLCHAIN_FILE=/Users/me/programming/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_CROSSCOMPILING_EMULATOR="/Users/me/programming/emsdk/node/12.9.1_64bit/bin/node"
-- Configuring done
-- Generating done
CMake Warning:
Manually-specified variables were not used by the project:
CMAKE_TOOLCHAIN_FILE
-- Build files have been written to: /Users/me/programming/sandbox/cpp_sandbox/so_question_project/build
Now running make:
➜ emmake make
make: make
Scanning dependencies of target HelloWasm
[ 33%] Building CXX object CMakeFiles/HelloWasm.dir/src/main.cpp.o
[ 66%] Building CXX object CMakeFiles/HelloWasm.dir/src/my_lib.cpp.o
[100%] Linking CXX executable HelloWasm
[100%] Built target HelloWasm
Obviously that did not create a .wasm file...
Doing the following:
em++ CMakeFiles/HelloWasm.dir/src/main.cpp.o CMakeFiles/HelloWasm.dir/src/my_lib.cpp.o -o helloWasm.js
output:
em++: warning: CMakeFiles/HelloWasm.dir/src/main.cpp.o is not a valid input file [-Winvalid-input]
em++: warning: CMakeFiles/HelloWasm.dir/src/my_lib.cpp.o is not a valid input file [-Winvalid-input]
em++: error: no input files
note that input files without a known suffix are ignored, make sure your input files end with one of: ('.c', '.i', '.cpp', '.cxx', '.cc', '.c++', '.CPP', '.CXX', '.C', '.CC', '.C++', '.ii', '.m', '.mi', '.mm', '.mii', '/dev/null', '.bc', '.o', '.obj', '.lo', '.dylib', '.so', '.a', '.ll', '.h', '.hxx', '.hpp', '.hh', '.H', '.HXX', '.HPP', '.HH')
What am I missing here...?
Change:
em++ CMakeFiles/HelloWasm.dir/src/main.cpp.o CMakeFiles/HelloWasm.dir/src/my_lib.cpp.o -o helloWasm.js
To:
em++ CMakeFiles/HelloWasm.dir/src/main.cpp.o CMakeFiles/HelloWasm.dir/src/my_lib.cpp -o helloWasm.js
Emscripten can't compile my_lib.cpp.o because it's already compiled to machine code (it's an object file). You have to use a .cpp file, not .cpp.o.
I have a suggestion for you.
First, you can put your lib files (my_lib.h and my_lib.cpp) on same directory.
Second, you can create a folder for your applications (HelloWasm) and put your executable codes (main.cpp) in this folder.
Finally, you can create CMakeLists.txt file for each folder.
This is your new directory tree:
.
├── CMakeLists.txt
├── Applications
│ └── HelloWasm
│ ├── CMakeLists.txt
│ └── main.cpp
└── Libraries
├── CMakeLists.txt
├── my_lib.h
└── my_lib.cpp
CMakeLists.txt (the first one) :
cmake_minimum_required(VERSION 3.0)
project(LIBRARYANDAPPS)
#This function is starting build and looking all folders.
function( start_build )
file( GLOB_RECURSE components "${CMAKE_SOURCE_DIR}/*/CMakeLists.txt" )
foreach( component ${components} )
get_filename_component( path ${component} PATH )
add_subdirectory( ${path} )
endforeach( )
endfunction( )
start_build()
CMakeLists.txt (for HelloWasm):
#You can add Emscripten flags like this.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
-std=c++11 --bind \
-s USE_WEBGL2=1 -s FULL_ES3=1 --memory-init-file 0")
find_package(Eigen3 REQUIRED NO_MODULE)
include_directories(${EIGEN3_INCLUDE_DIR})
include_directories("${CMAKE_SOURCE_DIR}/Libraries")
ADD_EXECUTABLE(HelloWasm main.cpp)
TARGET_LINK_LIBRARIES(HelloWasm MyLib Eigen)
CMakeLists.txt (for Library):
find_package(Eigen3 REQUIRED NO_MODULE)
include_directories(${EIGEN3_INCLUDE_DIR})
ADD_LIBRARY(MyLib STATIC my_lib.cpp my_lib.h)
TARGET_LINK_LIBRARIES(MyLib Eigen)
With these edits, you can create bigger projects, libraries. And I think more useful like this.
I am trying to test mongodb c++ driver on Ubuntu 16.04.
The driver is installed in ${Devfolder}/sdk/mongodb/
and the test is in ${Devfolder}/testMongoDb/.
The code was compliled and tested using:
export PKG_CONFIG_PATH=${Devfolder}/sdk/mongodb/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${Devfolder}/sdk/mongodb/lib
c++ --std=c++11 test.cpp -o test $(pkg-config --cflags --libs libmongocxx)
Then I want to use mongodb driver in my CMake project.
ugitho#ugitho:projects$ tree -L 3
.
├── sdk
│ └── mongodb
│ ├── bin
│ ├── include
│ ├── lib
│ └── share
├── testMongo
│ ├── a.out
│ ├── build
│ │ ├── CMakeCache.txt
│ │ ├── CMakeFiles
│ │ ├── cmake_install.cmake
│ │ ├── cmongodb
│ │ └── Makefile
│ ├── CMakeLists.txt
│ ├── test
│ └── test.cpp
But I got the following error:
ugitho#ugitho:build$ cmake ..
LIBMONGOCXX_INCLUDE_DIRS = /home/ugitho/NGUYENKHAC/projects/sdk/mongodb/include/mongocxx/v_noabi;/home/ugitho/NGUYENKHAC/projects/sdk/mongodb/include/bsoncxx/v_noabi
LIBMONGOCXX_LIBRARIES = LIBMONGOCXX_LIBRARY_PATH-NOTFOUND;LIBBSONCXX_LIBRARY_PATH-NOTFOUND
LIBBSONCXX_INCLUDE_DIRS = /home/ugitho/NGUYENKHAC/projects/sdk/mongodb/include/bsoncxx/v_noabi
LIBBSONCXX_LIBRARIES = LIBBSONCXX_LIBRARY_PATH-NOTFOUND
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
LIBBSONCXX_LIBRARY_PATH
linked by target "cmongodb" in directory
/home/ugitho/NGUYENKHAC/projects/testMongoDb
linked by target "cmongodb" in directory
/home/ugitho/NGUYENKHAC/projects/testMongoDb
LIBMONGOCXX_LIBRARY_PATH
linked by target "cmongodb" in directory
/home/ugitho/NGUYENKHAC/projects/testMongoDb
-- Configuring incomplete, errors occurred!
See also "/home/ugitho/NGUYENKHAC/projects/testMongoDb/build/CMakeFiles/CMakeOutput.log".
edited*:
Here are CMakeLists.txt and test.cpp.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(cmongodb)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_PREFIX_PATH /home/ugitho/NGUYENKHAC/projects/sdk/mongodb)
#find_package(libmongocxx REQUIRED)
#find_package(libbsoncxx REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBMONGOCXX REQUIRED libmongocxx)
pkg_check_modules(LIBBSONCXX REQUIRED libbsoncxx)
message("LIBMONGOCXX_INCLUDE_DIRS = ${LIBMONGOCXX_INCLUDE_DIRS}")
message("LIBMONGOCXX_LIBRARIES = ${LIBMONGOCXX_LIBRARIES}")
message("LIBBSONCXX_INCLUDE_DIRS = ${LIBBSONCXX_INCLUDE_DIRS}")
message("LIBBSONCXX_LIBRARIES = ${LIBBSONCXX_LIBRARIES}")
set(COMMON_LIBRARIES ${LIBMONGOCXX_LIBRARIES} ${LIBBSONCXX_LIBRARIES})
set(SOURCE_FILES test.cpp)
add_executable(cmongodb ${SOURCE_FILES})
target_include_directories(cmongodb PUBLIC ${LIBMONGOCXX_INCLUDE_DIRS})
target_include_directories(cmongodb PUBLIC ${LIBBSONCXX_INCLUDE_DIRS})
target_link_libraries(cmongodb ${COMMON_LIBRARIES})
test.cpp:
#include <iostream>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
int main(int, char **) {
std::cout << "1" << std::endl;
mongocxx::instance inst{};
mongocxx::client conn{mongocxx::uri{}};
bsoncxx::builder::stream::document document{};
auto collection = conn["testdb"]["testcollection"];
document << "hello"
<< "world";
collection.insert_one(document.view());
auto cursor = collection.find({});
for (auto &&doc : cursor) {
std::cout << bsoncxx::to_json(doc) << std::endl;
}
return 0;
}
Do you have any idea about what I missed here?
Updates:
with the new CMakeLists.txt, there are no more cmake errors.
ugitho#ugitho:build$ cmake ..
-- Checking for module 'libmongocxx'
-- Found libmongocxx, version 3.4.0
-- Checking for module 'libbsoncxx'
-- Found libbsoncxx, version 3.4.0
CMAKE_PREFIX_PATH = /home/ugitho/NGUYENKHAC/projects/sdk/mongodb/shared
LIBMONGOCXX_INCLUDE_DIRS = /home/ugitho/NGUYENKHAC/projects/sdk/mongodb/include/mongocxx/v_noabi;/home/ugitho/NGUYENKHAC/projects/sdk/mongodb/include/bsoncxx/v_noabi
LIBMONGOCXX_LIBRARIES = mongocxx;bsoncxx
LIBBSONCXX_INCLUDE_DIRS = /home/ugitho/NGUYENKHAC/projects/sdk/mongodb/include/bsoncxx/v_noabi
LIBBSONCXX_LIBRARIES = bsoncxx
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ugitho/NGUYENKHAC/projects/testMongoDb/build
[1]+ Done gedit /home/ugitho/NGUYENKHAC/projects/testMongoDb/build/CMakeFiles/CMakeOutput.log
The errors are now on make level:
ugitho#ugitho:build$ make
Scanning dependencies of target cmongodb
[ 50%] Building CXX object CMakeFiles/cmongodb.dir/test.cpp.o
[100%] Linking CXX executable cmongodb
/opt/llvm/x86_64/6.0.0.g631a/bin/ld: error: unable to find library -lmongocxx
/opt/llvm/x86_64/6.0.0.g631a/bin/ld: error: unable to find library -lbsoncxx
/opt/llvm/x86_64/6.0.0.g631a/bin/ld: error: unable to find library -lbsoncxx
collect2: error: ld returned 1 exit status
make[2]: *** [cmongodb] Error 1
make[1]: *** [CMakeFiles/cmongodb.dir/all] Error 2
make: *** [all] Error 2
UPDATE *** 27/12/2018
cmake_minimum_required(VERSION 3.2)
project(cmongodb)
set(CMAKE_CXX_STANDARD 14)
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
set(CMAKE_PREFIX_PATH ${PARENT_DIR}/sdk/mongodb)
message("CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
find_package(libmongocxx REQUIRED)
find_package(libbsoncxx REQUIRED)
set(MongoDb_INCLUDE_DIR ${PARENT_DIR}/sdk/mongodb/include)
include_directories(${MongoDb_INCLUDE_DIR}/mongocxx/v_noabi
${MongoDb_INCLUDE_DIR}/bsoncxx/v_noabi)
set(SOURCE_FILES test.cpp)
add_executable(cmongodb ${SOURCE_FILES})
target_link_libraries(cmongodb ${LIBMONGOCXX_LIBRARIES}
${LIBBSONCXX_LIBRARIES})
I managed to compile using this CMakeLists.txt.
new project config will be coming soon.
{GTest & Boost & MongoDb C++ Driver}
Thank you!!
Would anyone be able to post a simple example of how to compile code which uses libfreenect2? After installing the library, the following structure is created in my home directory:
→ tree freenect2
freenect2
├── include
│ └── libfreenect2
│ ├── config.h
│ ├── export.h
│ ├── frame_listener.hpp
│ ├── frame_listener_impl.h
│ ├── libfreenect2.hpp
│ ├── logger.h
│ ├── packet_pipeline.h
│ └── registration.h
└── lib
├── cmake
│ └── freenect2
│ └── freenect2Config.cmake
├── libfreenect2.so -> libfreenect2.so.0.2
├── libfreenect2.so.0.2 -> libfreenect2.so.0.2.0
├── libfreenect2.so.0.2.0
└── pkgconfig
└── freenect2.pc
I attempted to compile with the .pc file using a line similar to this found on the pkg-config wikipedia page:
gcc -o test test.c $(pkg-config --libs --cflags libpng)
But came with up with this error:
./test: error while loading shared libraries: libfreenect2.so.0.2: cannot open shared object file: No such file or directory
Obviously, I messed up the compilation process somewhere, but I'm not sure where to look since this is error occurs on runtime and not at compile time. There's also a .cmake file created with the library install, which I'm sure would lead to a more robust and proper solution, but I'm not entirely sure how to use that and haven't been able to find a simple guide showing how to do so. Any links to beginner-friendly documentation are also appreciated. In the documentation for libfreenect2, it says to use this line when compiling cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2 -- is this something that I'd have to use when making the library or when making my application?
Another tangentially related question, would it be better to move the /include and /lib directories to /usr/local/include and /usr/local/lib respectively? I believe that would "install" the library system-wide, but I imagine there's some reason that libfreenect2 doesn't do it automatically and I'm not sure what that is.
Well, I just use cmake with a CMakeLists.txt file that I create. Do like this:
Create a CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("My Project")
set(CMAKE_CXX_FLAGS "-std=c++11")
find_package(freenect2 REQUIRED)
include_directories("/usr/include/libusb-1.0/")
INCLUDE_DIRECTORIES(
${freenect2_INCLUDE_DIR}
)
add_executable(main ./main.cpp)
target_link_libraries(main ${freenect2_LIBRARIES})
In this file, I assume we want to compile the main.cpp file that uses libfreenect2. So, in your local directory create a build folder, using the terminal:
mkdir build && cd build
Then, run the command in the terminal:
cmake -Dfreenect2_DIR=$HOME/freenect2/lib/cmake/freenect2 .. && make
this should create main executable in the build folder. Please, note that this cmake command specifies the freenect2 directory. In this case I assume it was placed in the /home directory.
However, I understand that having to type that long cmake command or search for it on the terminal history may be boring for some people. So, it is possible to embed the command like this:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("My Project")
set(CMAKE_CXX_FLAGS "-std=c++11")
# Set cmake prefix path to enable cmake to find freenect2
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} $ENV{HOME}/freenect2/lib/cmake/freenect2)
find_package(freenect2 REQUIRED)
include_directories("/usr/include/libusb-1.0/")
INCLUDE_DIRECTORIES(
${freenect2_INCLUDE_DIR}
)
add_executable(main ./main.cpp)
target_link_libraries(main ${freenect2_LIBRARIES})
After, just run this in the terminal:
mkdir build && cd build && cmake .. & make
This answer was my source for this second way of compiling the code.
Hope this helps!