Question
Why .dlls are not copied to the build/Release/ directory as .exe is built?
Description
I create a new CMake file with this simple setup:
cmake_minimum_required(VERSION 3.21)
project(use_sort)
find_package(sortdemo REQUIRED)
add_executable(example main.cpp)
target_link_libraries(example PRIVATE sortdemo::my_sort_lib sortdemo::my_print_lib)
The project gets configured and installed as x64 Release linked to SHARED libs.
But in Release folder I can only see the .exe, without .dlls.
The libraries my_sort_lib and my_print_lib are my libraries that were installed before in C:\Program Files:
I do not know if it is necessary, but I also add a link to the CMakeLists of these libraries: https://github.com/petrasvestartas/CMAKE/tree/main/install_export
The full project is here:
https://github.com/petrasvestartas/CMAKE/tree/main/find_package
What I tried:
This does not copy any dlls
include(GNUInstallDirs )
install(
TARGETS "example"
RUNTIME_DEPENDENCIES
)
This gives me error
include(GNUInstallDirs )
install(
TARGETS "example"
RUNTIME_DEPENDENCIES "sortdemo::my_sort_lib"
)
Error:
CMake Error at CMakeLists.txt:28 (install):
install TARGETS given unknown argument "sortdemo::my_sort_lib".
This gives me error too and not understandable (use this answer from another stackoverflow post)
MACRO(INSTALL_ADD_IMPORTED_DLLS target_list target_component destination_folder)
foreach(one_trg ${target_list})
get_target_property(one_trg_type ${one_trg} TYPE)
if (NOT one_trg_type STREQUAL "INTERFACE_LIBRARY")
get_target_property(one_trg_dll_location ${one_trg} IMPORTED_LOCATION_RELEASE)
if( one_trg_dll_location MATCHES ".dll$")
install(FILES ${one_trg_dll_location} DESTINATION ${destination_folder} CONFIGURATIONS Release COMPONENT ${target_component})
endif()
get_target_property(one_trg_dll_location ${one_trg} IMPORTED_LOCATION_DEBUG)
if( one_trg_dll_location MATCHES ".dll$")
install(FILES ${one_trg_dll_location} DESTINATION ${destination_folder} CONFIGURATIONS Debug COMPONENT ${target_component})
endif()
endif()
endforeach()
ENDMACRO()
set(THIRDPARTY_TARGETS "sortdemo::my_sort_lib" "sortdemo::my_print_lib")
if(MSVC)
INSTALL_ADD_IMPORTED_DLLS("${THIRDPARTY_TARGETS}" bin bin)
endif()
Error
Make Error at CMakeLists.txt:28 (get_target_property):
get_target_property() called with non-existent target "my_sort_lib".
Call Stack (most recent call first):
CMakeLists.txt:44 (INSTALL_ADD_IMPORTED_DLLS)
Related
I'm trying to build and link-to apache-arrow v9.0.0 inside my cmake project using the following section in my CMakeLists.txt file.
ExternalProject_Add(arrow
URL "https://www.apache.org/dist/arrow/arrow-9.0.0/apache-arrow-9.0.0.tar.gz"
SOURCE_SUBDIR cpp)
message(STATUS "arrow source dir: ${arrow_SOURCE_DIR}")
include_directories(${arrow_SOURCE_DIR}/cpp/src)
The compilation complains that the apache-arrow headers are missing
fatal error: 'arrow/array.h' file not found
#include <arrow/array.h>
^~~~~~~~~~~~~~~
1 error generated.
supported by the fact that the output of message(STATUS "arrow source dir: ${arrow_SOURCE_DIR}") is empty
-- arrow source dir:
Another error seemingly related to the apache-arrow installation reported by cmake is that
CMake Error at cmake_modules/ThirdpartyToolchain.cmake:267 (find_package):
Could not find a configuration file for package "xsimd" that is compatible
with requested version "8.1.0".
The following configuration files were considered but not accepted:
/opt/homebrew/lib/cmake/xsimd/xsimdConfig.cmake, version: 9.0.1
Call Stack (most recent call first):
cmake_modules/ThirdpartyToolchain.cmake:2245 (resolve_dependency)
CMakeLists.txt:575 (include)
Of course, the traditional approach of installing apache-arrow externally with say brew install apache-arrow and using find_package works well enough, but I'd like something more cross-platform. One of the arrow devs had provided a link on how to properly use include_directories with ExternalProject_Add for an earlier question, but I guess that example is now outdated.
What's the recommended way of installing and then linking-to apache-arrow inside a cmake project using ExternalProject_Add?
Edit: Minimal Example
CMakeLists.txt
cmake_minimum_required(VERSION 3.24)
project(arrow_cmake)
set(CMAKE_CXX_STANDARD 23)
include(ExternalProject)
ExternalProject_Add(Arrow
URL "https://www.apache.org/dist/arrow/arrow-9.0.0/apache-arrow-9.0.0.tar.gz"
SOURCE_SUBDIR cpp
CMAKE_ARGS "-Dxsimd_SOURCE=BUNDLED"
)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} arrow_shared)
main.cpp
#include <iostream>
#include <arrow/array.h> // not found!
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
Could you try forcing Arrow build system to download and use the bundled xsimd? I've been able to reproduce and been able to build locally.
ExternalProject_Add(Arrow
URL "https://www.apache.org/dist/arrow/arrow-9.0.0/apache-arrow-9.0.0.tar.gz"
SOURCE_SUBDIR cpp
CMAKE_ARGS "-Dxsimd_SOURCE=BUNDLED"
)
I don't think we have documentation for it at the moment and we assume find_package to be used on the documentation: https://arrow.apache.org/docs/dev/cpp/build_system.html. Maybe we could open a ticket to improve the documentation in order to use it with CMake's ExternalProject or FetchContent.
Building arrow from sources in cmake took quite some doing. It's heavily influenced by this link.
cmake/arrow.cmake
# Build the Arrow C++ libraries.
function(build_arrow)
set(one_value_args)
set(multi_value_args)
cmake_parse_arguments(ARG
"${options}"
"${one_value_args}"
"${multi_value_args}"
${ARGN})
if (ARG_UNPARSED_ARGUMENTS)
message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
endif ()
# If Arrow needs to be built, the default location will be within the build tree.
set(ARROW_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/arrow_ep-prefix")
set(ARROW_SHARED_LIBRARY_DIR "${ARROW_PREFIX}/lib")
set(ARROW_SHARED_LIB_FILENAME
"${CMAKE_SHARED_LIBRARY_PREFIX}arrow${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(ARROW_SHARED_LIB "${ARROW_SHARED_LIBRARY_DIR}/${ARROW_SHARED_LIB_FILENAME}")
set(PARQUET_SHARED_LIB_FILENAME
"${CMAKE_SHARED_LIBRARY_PREFIX}parquet${CMAKE_SHARED_LIBRARY_SUFFIX}")
set(PARQUET_SHARED_LIB "${ARROW_SHARED_LIBRARY_DIR}/${PARQUET_SHARED_LIB_FILENAME}")
set(ARROW_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/arrow_ep-build")
set(ARROW_CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${ARROW_PREFIX}"
"-DCMAKE_INSTALL_LIBDIR=lib" "-Dxsimd_SOURCE=BUNDLED"
"-DARROW_BUILD_STATIC=OFF" "-DARROW_PARQUET=ON"
"-DARROW_WITH_UTF8PROC=OFF" "-DARROW_WITH_RE2=OFF"
"-DARROW_FILESYSTEM=ON" "-DARROW_CSV=ON" "-DARROW_PYTHON=ON")
set(ARROW_INCLUDE_DIR "${ARROW_PREFIX}/include")
set(ARROW_BUILD_BYPRODUCTS "${ARROW_SHARED_LIB}" "${PARQUET_SHARED_LIB}")
include(ExternalProject)
externalproject_add(arrow_ep
URL https://github.com/apache/arrow/archive/refs/tags/apache-arrow-9.0.0.tar.gz
SOURCE_SUBDIR cpp
BINARY_DIR "${ARROW_BINARY_DIR}"
CMAKE_ARGS "${ARROW_CMAKE_ARGS}"
BUILD_BYPRODUCTS "${ARROW_BUILD_BYPRODUCTS}")
set(ARROW_LIBRARY_TARGET arrow_shared)
set(PARQUET_LIBRARY_TARGET parquet_shared)
file(MAKE_DIRECTORY "${ARROW_INCLUDE_DIR}")
add_library(${ARROW_LIBRARY_TARGET} SHARED IMPORTED)
add_library(${PARQUET_LIBRARY_TARGET} SHARED IMPORTED)
set_target_properties(${ARROW_LIBRARY_TARGET}
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${ARROW_INCLUDE_DIR}
IMPORTED_LOCATION ${ARROW_SHARED_LIB})
set_target_properties(${PARQUET_LIBRARY_TARGET}
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${ARROW_INCLUDE_DIR}
IMPORTED_LOCATION ${PARQUET_SHARED_LIB})
add_dependencies(${ARROW_LIBRARY_TARGET} arrow_ep)
endfunction()
Use it in your CMakeLists.txt file as
...
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(arrow)
build_arrow()
I want to build an application that depends on the OpenCV (version 3.4.6) viz module. This module has the VTK library (version 7.1.1) as dependency. I want to use ExternalProject to build both, the vtk library and the opencv viz module and subsequently want to build the main application, all in one cmake run.
.
├── CMakeLists.txt
├── deps
│ └── CMakeLists.txt
└── main.cpp
I am using the cmake ExternalProject module to build both opencv and vtk inside a subdirectory like this:
deps/CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(dependencies)
include(ExternalProject)
ExternalProject_add(
vtklib
GIT_REPOSITORY https://github.com/Kitware/vtk
GIT_TAG v7.1.1
GIT_PROGRESS TRUE
UPDATE_COMMAND ""
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DBUILD_TESTING=OFF
-DBUILD_EXAMPLES=OFF
-DVTK_DATA_EXCLUDE_FROM_ALL=ON
-DVTK_USE_CXX11_FEATURES=ON
-Wno-dev
)
add_library(vtk INTERFACE IMPORTED GLOBAL)
add_dependencies(vtk vtklib)
ExternalProject_add(
ocv
GIT_REPOSITORY https://github.com/opencv/opencv
GIT_TAG 3.4.6
GIT_PROGRESS TRUE
UPDATE_COMMAND ""
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DWITH_VTK=ON
-Wno-dev
)
# ExternalProject_Get_Property(ocv install_dir)
# include_directories(${install_dir}/src/ocv/include)
include_directories(${CMAKE_INSTALL_PREFIX}/include)
set(ocv_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_VS_PLATFORM_NAME}/vc15)
set(OCV_VERSION 346)
add_dependencies(ocv vtklib)
add_library(opencv_core SHARED IMPORTED)
set_target_properties(opencv_core PROPERTIES
IMPORTED_IMPLIB "${ocv_libdir}/lib/opencv_core${OCV_VERSION}.lib"
IMPORTED_LOCATION "${ocv_libdir}/bin/opencv_core${OCV_VERSION}.dll"
)
add_library(opencv_viz SHARED IMPORTED)
set_target_properties(opencv_viz PROPERTIES
IMPORTED_IMPLIB "${ocv_libdir}/lib/opencv_viz${OCV_VERSION}.lib"
IMPORTED_LOCATION "${ocv_libdir}/bin/opencv_viz${OCV_VERSION}.dll"
)
the main CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.14)
project(cmaketest VERSION 0.1 DESCRIPTION "" LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_Flags "${CMAKE_CXX_FLAGS} -std=c++17")
# include_directories(${CMAKE_INSTALL_PREFIX}/include)
add_subdirectory(deps)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} opencv_core opencv_viz)
install(
TARGETS ${PROJECT_NAME}
EXPORT "${PROJECT_NAME}-targets"
LIBRARY DESTINATION lib/
ARCHIVE DESTINATION lib/${CMAKE_PROJECT_NAME}
RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include/${CMAKE_PROJECT_NAME}/${PROJECT_NAME}
)
the main.cpp for completeness:
#include <opencv2/viz.hpp>
int main(){}
but it seems that the include_directories and add_library calls inside deps/CMakeLists.txt do not work on the correct scope as i am getting the following error messages:
error C1083: File (Include) can not be opened: "opencv2/viz.hpp"
if i uncomment the include_directories inside the main CMakeLists.txt then i get a linker error (this is not what i want, included directories should be specified inside deps/CMakeLists.txt):
LNK1181: opencv_core.lib can not be opened
If i just copy the contents of deps/CMakeLists.txt in the main CMakeLists.txt in place of the add_subdirectory call everything works fine.
So, how do i get the include directories and the created targets from the subdirectory in my main CMakeLists?
edit:
call to cmake configure:
cmake.exe -B build -S . -G "Visual Studio 17 2022" -A x64 -T v141 -DCMAKE_INSTALL_PREFIX=D:/test
call to cmake build:
cmake.exe --build build --config Release --target install
Unlike to normal targets, which are global, an IMPORTED target by default is local to the directory where it is created.
For extend visibility of the IMPORTED target, use GLOBAL keyword:
add_library(opencv_core SHARED IMPORTED GLOBAL)
This is written in the documentation for add_library(IMPORTED):
The target name has scope in the directory in which it is created and below, but the GLOBAL option extends visibility.
cmake has couple steps:
configuration
generation (depends on configuration)
build (depends on generation)
test (depends on build)
install (depends on build)
Now problem is that your build step depends on result of install step. This happens here:
set(ocv_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_VS_PLATFORM_NAME}/vc15)
and when this variable is used.
This is causing that to be able to complete build step you need success in install step. And cmake will do install step after successful build. So you have dependency cycle.
Instead importing opencv as shared library:
add_library(opencv_viz SHARED IMPORTED)
Link your target with targets created by imported project of opnecv.
I am trying to use mFast for FastFix protocol on my windows machine but not able to install using cmake-gui.exe I am using Visual studio 2010 on Windows Server 2003.
cmake-gui tool.exe image with configurations
CMAKE-LISTS.txt
file (GLOB headers "*.h") ## retrieve all header files in current directory
file (GLOB sources "*.cpp") ## retrieve all source files in current directory I had added Executable path and Library path.
file (GLOB instruction_headers "instructions/*.h") ## retrieve all header files in instructions directory
file (GLOB instruction_sources "instructions/*.cpp") ## retrieve all source files in instructions directory
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
set(mfast_SRCS ${sources} ${instruction_sources} ${headers} ${instruction_headers})
add_library(mfast_static STATIC ${mfast_SRCS})
target_include_directories(mfast_static PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
if (UNIX)
set_target_properties(mfast_static PROPERTIES OUTPUT_NAME mfast)
endif()
set_target_properties(mfast_static PROPERTIES COMPILE_FLAGS -DMFAST_STATIC_DEFINE)
install(TARGETS mfast_static
EXPORT mFASTTargets
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" COMPONENT lib)
set(MFAST_STATIC_LIBRARIES ${MFAST_STATIC_LIBRARIES} mfast_static CACHE INTERNAL "")
if (BUILD_SHARED_LIBS)
add_library(mfast SHARED ${mfast_SRCS})
if (NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.12")
target_compile_definitions(mfast INTERFACE "-DMFAST_DYN_LINK")
endif (NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.12")
if (CMAKE_COMPILER_IS_GNUCXX OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"))
set_target_properties(mfast PROPERTIES COMPILE_FLAGS -fvisibility=hidden)
endif()
set_target_properties(mfast PROPERTIES
VERSION "${MFAST_VERSION}"
SOVERSION "${MFAST_SOVERSION}")
install(TARGETS mfast
EXPORT mFASTTargets
RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT lib)
set(MFAST_SHARED_LIBRARIES ${MFAST_SHARED_LIBRARIES} mfast CACHE INTERNAL "")
endif (BUILD_SHARED_LIBS)
add_subdirectory (coder)
add_subdirectory (xml_parser)
add_subdirectory (json)
if (BUILD_SQLITE3)
add_subdirectory (sqlite3)
endif(BUILD_SQLITE3)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
DESTINATION "${INSTALL_INCLUDE_DIR}"
FILES_MATCHING PATTERN "*.h")
Error Log file
CMake Error at mfast/CMakeLists.txt:20 (install):
install TARGETS given no ARCHIVE DESTINATION for static library target
"mfast_static".
CMake Error at mfast/coder/CMakeLists.txt:28 (install):
install TARGETS given no ARCHIVE DESTINATION for static library target
"mfast_coder_static".
CMake Error at mfast/xml_parser/CMakeLists.txt:22 (install):
install TARGETS given no ARCHIVE DESTINATION for static library target
"mfast_xml_parser_static".
CMake Error at mfast/json/CMakeLists.txt:19 (install):
install TARGETS given no ARCHIVE DESTINATION for static library target
"mfast_json_static".
CMake Error at fast_type_gen/CMakeLists.txt:18 (install):
install TARGETS given no RUNTIME DESTINATION for executable target
"fast_type_gen".
CMake Warning (dev) at CMakeLists.txt:5 (set):
Cannot set "FAST_TYPE_GEN_INSTALL_LOCATION": current scope has no parent.
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Error at CMakeLists.txt:7 (install):
install FILES given no DESTINATION!
CMake Warning (dev) in CMakeLists.txt:
No cmake_minimum_required command is present. A line of code such as
cmake_minimum_required(VERSION 3.12)
should be added at the top of the file. The version specified may be lower
if you wish to support older CMake versions for this project. For more
information run "cmake --help-policy CMP0000".
This warning is for project developers. Use -Wno-dev to suppress it.
Configuring incomplete, errors occurred!
See also "D:/Mihir/mFastVisualStudioProject/CMakeFiles/CMakeOutput.log".
what I have tried:
Added Executable Path and Library
Installed Boost-library 1.63 and added in Path,But found no luck whatsoever as you can see i am getting static library file error. Thanking in Advance
I'm creating a native library under Android Studio, and I'm hurting the following problem.
In my AndroidStudio project CMakeLists.txt, I have this:
cmake_minimum_required(VERSION 3.7.0)
add_library(native-lib
SHARED
src/main/cpp/native-lib.cpp )
IF(USE_EXTERNAL)
include(ExternalProject)
ExternalProject_Add(
project_mylib
DOWNLOAD_COMMAND ""
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/mylib/"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}
)
add_dependencies(native-lib project_mylib)
ELSE()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/mylib/)
ENDIF()
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries(native-lib
${log-lib}
mylib
)
A self-made library is located in src/main/cpp/mylib/, with a CMakeLists.txt:
cmake_minimum_required(VERSION 3.7.0)
project(lib)
add_library(mylib SHARED lib.cpp)
INSTALL(TARGETS mylib
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
)
When I use the "traditional" add_subdirectory(...) everything goes well. But, if I use the ExternalProject_Add(...) version, linker is skipping the compiled libmylib.so library and so cannot link mylib to native-lib.
I have the following message: skipping incompatible /home/.../app/.externalNativeBuild/cmake/debug/arm64-v8a/lib/libmylib.so when searching for -lmylib
My guess is that all the flags set by AndroidStudio for the root CMakeLists.txt are not set when the ExternalProject is compile leading to an incompatible shared library.
So, I wonder if there is a way to compile a cmake ExternalProject like it was part of the root project (sharing the same compile flags etc) ?
Thanks for any advice
I'm using a pre-compiled third party library that has multiple DLLs (one for the actual third party, and some more as its own dependencies)
My Directory structure is as follows
MyApp
CMakeLists.txt // Root CMake file
src
MyCode.cpp
thirdpartydep // Precompiled thirdparty dependency
FindThirdPartyDep.cmake
bin/
thirdparty.dll
thirdparty_dep1.dll
thirdparty_dep2.dll
include/
thirdparty.h
lib/
thirdparty.lib // this is the importlibrary that loads thirdparty.dll
Until now, we've been copying over all the DLLs in the thirdpartydep/bin directory using copy_if_different and manually listing the paths to the DLLs. I'm trying to set up the install target correctly to copy the dlls in thirdpartydep/bin to CMAKE_INSTALL_PREFIX/bin but I can't figure out how to tell cmake about the extra binary files belonging to thirdpartydep.
If you use modern CMake with correctly build CONFIG thirdparty packages (* -config.cmake) instead of MODULES (Find*.cmake), then this will work:
MACRO(INSTALL_ADD_IMPORTED_DLLS target_list target_component destination_folder)
foreach(one_trg ${target_list})
get_target_property(one_trg_type ${one_trg} TYPE)
if (NOT one_trg_type STREQUAL "INTERFACE_LIBRARY")
get_target_property(one_trg_dll_location ${one_trg} IMPORTED_LOCATION_RELEASE)
if( one_trg_dll_location MATCHES ".dll$")
install(FILES ${one_trg_dll_location} DESTINATION ${destination_folder} CONFIGURATIONS Release COMPONENT ${target_component})
endif()
get_target_property(one_trg_dll_location ${one_trg} IMPORTED_LOCATION_DEBUG)
if( one_trg_dll_location MATCHES ".dll$")
install(FILES ${one_trg_dll_location} DESTINATION ${destination_folder} CONFIGURATIONS Debug COMPONENT ${target_component})
endif()
endif()
endforeach()
ENDMACRO()
it is used like this:
set(THIRDPARTY_TARGETS "example_target1 example_target2 opencv_core")
if(MSVC)
INSTALL_ADD_IMPORTED_DLLS("${THIRDPARTY_TARGETS}" bin bin)
endif()
You can simply use the install() command like that:
install(FILES ${DLL_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX}/dll
CONFIGURATIONS Release COMPONENT ${LIBRARY_NAME})