On my host system (Ubuntu, 64Bit) I use gcc/g++ compilers to crosscompile my library for my Android app (arm64-v8a). On calling functions from my App I receive messages that libraries like libc.so.6 or libstdc++.so.6 cannot be found.
Within my /usr directory I have an aarch64-linux-gnu folder containing bin, include and lib folders.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.6.0)
set(CMAKE_TOOLCHAIN_FILE android.toolchain.cmake)
project(testlibrary)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STYANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# find header & source
file(GLOB_RECURSE SOURCE_CPP "src/*.cpp")
file(GLOB_RECURSE HEADER "src/*.h")
add_library(${PROJECT_NAME} SHARED
${SOURCE_CPP}
${HEADER}
)
source_group("Header include" FILES ${HEADER})
source_group("Source src" FILES ${SOURCE_CPP})
android.toolchain.cmake:
cmake_minimum_required(VERSION 3.6.0)
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")
set(CMAKE_ANDROID_NDK /home/ubuntu/Android/Sdk/ndk/21.4.7075529)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
The error messages are the following:
dlopen failed: library "libc.so.6" not found: needed by /my/lib/path/testlib.so in namespace classloader-namespace
or
dlopen failed: library "libstdc++.so.6" not found: needed by /my/lib/path/testlib.so in namespace classloader-namespace
Do I have to set a Sysroot or other paths so my libraries are found within my toolchain file and which path(s) do I use?
EDIT1: Adding the aarch64-linux-gnu folder to my build directory and explicitly including
target_link_libraries($PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/aarch64-linux-gnu/lib/libstdc++.so.6)
# also any other lib, e.g. libstdc++.so, libc.so and libc.so.6 don't work
still results in the mentioned error message.
I made a minimal example of the error using the .cpp and .hpp files below which results in this case in libc.so.6 not found. Removing the malloc line also removes the error messages. Calling the testFunc also return the correct value to my App which I can display.
src_file.cpp
#include "header_file.hpp"
#include <stdlib.h> // for malloc
int testFunc_(){
char* buffer;
buffer = (char *) malloc (10);
return 42;
}
header_file.hpp
extern "C" int testFunc_();
I also added the following lines to my android.toolchain.cmake file (I copied the folder from /usr/aarch64/linux-gnu/ to my build dir)
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(LDFLAGS="-Wl,-rpath,../aarch64-linux-gnu/lib")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} ${LDFLAGS}" CACHE INTERNAL "" FORCE)
EDIT2:
On running readelf -d 'path/to/lib' I get the following (necessary I suppose) entries
Tag Type Name/Value
0x000...1 (NEEDED) Shared library: [libc.so.6]
0x000..1d (RUNPATH) Library runpath: [/home/username/Desktop/projectfolder/aarch64-linux-gnu/lib]
Adding the following line to my CMakeLists.txt (after removing the RPATH related stuff from my toolchain file or changing them also to ./) should allow me to add the libraries right next to my library.so in the build folder (arm64-v8a).
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
There is no RPATH tag. The RUNPATH entry is the location of my .so.6 and .so files I copied from the /usr/aarch64-linux-gnu folder. I think my main problem is bundling the necessary libraries correctly within my application as David Grayson implicated.
EDIT3:
Running file libc.so.6 also shows its an ELF 64-bit LSB shared object with ARM aarch64 architecture dynamically linked for GNU/Linux 3.7.0, interpreter /lib/ld-linux-aarch64.so.1, stripped
EDIT4:
Within my app/build.gradle I have the following lines
if(isNewArchitectureEnabled()) {
externalNativeBuild {
ndkBuild {
arguments "APP_PLATFORM=android-12",
"APP_STL=c_++shared",
"NDK_TOOLCHAIN_VERSION=gcc", // was clang before
"GENERATED_SRC_DIR=$buildDir/generated/source",
"PROJECT_BUILD_DIR=$buildDir",
"REACT_ANDROID_DIR=${reactNativeRoot}/ReactAndroid",
"REACT_ANDROID_BUILD_DIR=${reactNativeRoot}/ReactAndroid/build",
"NODE_MODULES_DIR=$rootDir/../node_modules"
cflags "-Wall", "-Werror", "-fexceptions", "-frtti", "-DWITH_INSPECTOR=1"
cppFlags "-std=c++17", //maybe 11 here(?) tried out both my App and .so to 11 but also no success
targets "myapp_appmodules"
}
}
}
and also
packagingOptions {
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libm.so'
pickFirst 'lib/arm64-v8a/libm.so.6'
pickFirst 'lib/arm64-v8a/libstdc++.so'
pickFirst 'lib/arm64-v8a/libstdc++.so.6'
pickFirst 'lib/arm64-v8a/libc.so'
pickFirst 'lib/arm64-v8a/libc.so.6'
}
Am I probably using a wrong compiler/give the standalone toolchain within my ndk folder a try!
You either need to link those libraries statically into your executable (-static at link time might work) or you need to ship them with your executable and put them somewhere the executable will find them, like in the same directory.
I'm not very familiar with Android but there might also be a way to have the target Android system provide those libraries at run time, since they are very common and used widely.
I solved it changing my compilers (CMAKE_C_COMPILER and CMAKE_CXX_COMPILER ) within the toolchain file and leaving my CMakeLists.txt as it was in the first place.
cmake_minimum_required(VERSION 3.6.0)
set(CMAKE_SYSTEM_NAME Android)
set(CMAKE_SYSTEM_VERSION 21)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_ANDROID_ARCH_ABI arm64-v8a)
set(CMAKE_C_COMPILER /home/username/path/to/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang)
set(CMAKE_CXX_COMPILER /home/username/path/to/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++)
set(CMAKE_ANDROID_NDK /home/username/path/to/ndk)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
using Android API level 21.
Related
I'm trying to compile my program for Windows, on Linux, so I installed the w64-mingw32 compiler via the Debian package manager. I made a separate cmakelists file where I chose x86_64-w64-mingw32-g++ as the compiler. When I try to run my build script, I get errors where it can't find the libraries that I use in my project. This is my cmake file:
cmake_minimum_required (VERSION 3.5)
if (POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
else (NOT POLICY CMP0072)
message(STATUS "Could not use CMP0072 policy")
endif(POLICY CMP0072)
project(opengl-test LANGUAGES CXX)
set(CMAKE_CXX_COMPILER "/usr/bin/x86_64-w64-mingw32-g++")
set(CMAKE_C_COMPILER "/usr/bin/x86_64-w64-mingw32-gcc")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(GNUInstallDirs)
set(CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set (source_dir "${PROJECT_SOURCE_DIR}/src/")
set (base_dir "${source_dir}/base/")
set (IMGUI_DIR "/usr/include/imgui")
set(GCC_COVERAGE_LINK_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
file(GLOB source_files "${source_dir}/*.cpp")
file(GLOB_RECURSE base_files "${base_dir}/*.cpp")
file(GLOB imgui_files "${IMGUI_DIR}/*.cpp")
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_executable(${PROJECT_NAME} ${source_files} ${imgui_files} ${base_files})
#target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
message(STATUS ${OPENGL_LIBRARIES})
target_link_libraries(${PROJECT_NAME} PUBLIC ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES})
A lot of the code in the cmakelists file doesn't do anything because I was trying to make it work but nothing was working. I left it in so you can see what I've tried and doesn't work.
I can run this and it compiles, but I get a linker error.
CMake Warning:
No source or binary directory provided. Both will be assumed to be the
same as the current working directory, but note that this warning will
become a fatal error in future CMake releases.
-- /usr/lib/x86_64-linux-gnu/libOpenGL.so/usr/lib/x86_64-linux-gnu/libGLX.so/usr/lib/x86_64-linux-gnu/libGLU.so
-- Configuring done
CMake Warning at CMakeLists.txt:38 (add_executable):
Cannot generate a safe runtime search path for target opengl-test because
files in some directories may conflict with libraries in implicit
directories:
runtime library [libGLEW.so.2.1] in /usr/lib64 may be hidden by files in:
/usr/lib/x86_64-linux-gnu
Some of these libraries may not be found correctly.
-- Generating done
-- Build files have been written to: /home/user/Documents/CPP-Stuff/Scrap-Framework
[29/29] Linking CXX executable opengl-test
FAILED: opengl-test
: && /usr/bin/x86_64-w64-mingw32-g++ -g CMakeFiles/opengl-test.dir/src/main.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_demo.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_draw.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_impl_glfw.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_impl_opengl3.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_tables.cpp.o CMakeFiles/opengl-test.dir/usr/include/imgui/imgui_widgets.cpp.o CMakeFiles/opengl-test.dir/src/base/Application/Application.cpp.o CMakeFiles/opengl-test.dir/src/base/Application/Window.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/Cubemap.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/Texture.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/UniformBuffer.cpp.o CMakeFiles/opengl-test.dir/src/base/GL/VertexBuffer.cpp.o CMakeFiles/opengl-test.dir/src/base/Input/Input.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/Material.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/Mesh.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/Model.cpp.o CMakeFiles/opengl-test.dir/src/base/Model/ModelLoader.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/FPSCamera.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/MaterialManager.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/Renderbuffer.cpp.o CMakeFiles/opengl-test.dir/src/base/Renderer/Renderer.cpp.o CMakeFiles/opengl-test.dir/src/base/Scene/Lights.cpp.o CMakeFiles/opengl-test.dir/src/base/Scene/Scene.cpp.o CMakeFiles/opengl-test.dir/src/base/Scene/Skybox.cpp.o CMakeFiles/opengl-test.dir/src/base/Shader/Shader.cpp.o CMakeFiles/opengl-test.dir/src/base/Shader/ShaderManager.cpp.o -o opengl-test -Wl,-rpath,/usr/lib/x86_64-linux-gnu -lglfw /usr/lib/x86_64-linux-gnu/libOpenGL.so /usr/lib/x86_64-linux-gnu/libGLX.so /usr/lib/x86_64-linux-gnu/libGLU.so /usr/lib64/libGLEW.so && :
/usr/bin/x86_64-w64-mingw32-ld: cannot find -lglfw
/usr/bin/x86_64-w64-mingw32-ld: /usr/lib/x86_64-linux-gnu/libOpenGL.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
The include files are located in /usr/include/, but I also put them in /usr/x86_64-w64-mingw32/include/.
Does anyone know how I can fix this, or a better way to compile for Windows on Linux?
You need to build the libraries you're using for Windows, or find prebuilt ones, e.g. in MSYS2 repositories. You also need to point CMake to those libraries.
I've made Quasi-MSYS2 to automate both.
Example usage:
# Install Clang, LLD, Wine. Then:
git clone https://github.com/holyblackcat/quasi-msys2
cd quasi-msys2/
make install _gcc _glfw _glew
env/shell.sh
# Build
cd your/project/location
mkdir build
cd build
cmake ..
make
# Run with Wine
./a.exe
Here is CMakeLists.txt I've used. I removed the cross-compilation stuff (which is handled automatically).
cmake_minimum_required (VERSION 3.5)
if (POLICY CMP0072)
cmake_policy(SET CMP0072 NEW)
else (NOT POLICY CMP0072)
message(STATUS "Could not use CMP0072 policy")
endif(POLICY CMP0072)
project(opengl-test LANGUAGES CXX)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
add_executable(a 1.cpp)
message(STATUS ${OPENGL_LIBRARIES})
target_link_libraries(a PUBLIC ${GLFW_LIBRARIES} ${OPENGL_LIBRARIES} GLEW::GLEW)
I also put them in /usr/x86_64-w64-mingw32/include/
You shouldn't modify system include directories manually. Leave them to your package manager.
I'm trying to cross compile to an ARM with linux from my x86 with a linux.
The issue appears to be that when including some standard library headers like iostream or string, even if those are included from the path where the cross compiler is, and its standard library, some of the dependencies of those headers seems to be included from my local standard library.
The headers from my local standard library have some x86 specific type definitions which do not exist on ARM hence the compilation fails.
The error shown is:
[01m[K/usr/include/bits/floatn.h:87:9:[m[K [01;31m[Kerror: [m[K?[01m[K__float128[m[K? does not name a type; did you mean ?[01m[K__cfloat128[m[K??
87 | typedef [01;31m[K__float128[m[K _Float128;
| [01;31m[K^~~~~~~~~~[m[K
| [32m[K__cfloat128[m[K
In file included from [01m[K/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/usr/include/c++/9.3.0/cwchar:44[m[K,
from [01m[K/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/usr/include/c++/9.3.0/bits/postypes.h:40[m[K,
from [01m[K/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/usr/include/c++/9.3.0/iosfwd:40[m[K,
from [01m[K/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/usr/include/c++/9.3.0/ios:38[m[K,
from [01m[K/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/usr/include/c++/9.3.0/ostream:38[m[K,
from [01m[K/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/usr/include/c++/9.3.0/iostream:39[m[K,
from [01m[K/home/lorandpetok/cross_ws/src/rvc_robot/rvc_ui/include/ConsoleMenu.h:5[m[K,
from [01m[K/home/lorandpetok/cross_ws/src/rvc_robot/rvc_ui/src/ConsoleMenu.cpp:1[m[K:<
Here you can see that I include iostream, the includes cascade down to cwchar which in turn includes floatn.h from my local x86 library.
The compiler used for cross compilation is gcc 9.3.0
My cmake toolchain file used:
set(ARTHERO_SYSROOTS "/opt/fslc-wayland/3.1/sysroots")
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR armv8-a)
set(TOOLCHAIN_PREFIX ${ARTHERO_SYSROOTS}/x86_64-fslcsdk-linux/usr/bin/aarch64-fslc-linux/aarch64-fslc-linux-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_SYSROOT ${ARTHERO_SYSROOTS}/aarch64-fslc-linux)
set(CMAKE_PREFIX_PATH ${CMAKE_SYSROOT}/usr/lib/cmake ${CMAKE_SYSROOT}/opt/ros/melodic/share)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT} ${CATKIN_DEVEL_PREFIX})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_MODULE_PATH ${CMAKE_SYSROOT}/opt/ros/melodic/share)
set(LD_LIBRARY_PATH ${CMAKE_SYSROOT}/opt/ros/melodic/lib)
set(COMPILER_FLAGS " -march=armv8-a -mtune=cortex-a53")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMPILER_FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_FLAGS}" CACHE STRING "" FORCE)
include_directories(/opt/fslc-wayland/3.1/sysroots/aarch64-fslc-linux/opt/ros/melodic/include/)
What could make the compiler or cmake to include the header from my local standard library and how should i tell it to look in the correct path?
I'm trying to specify to the compiler to ignore all messages + warnings originating from the libs folder, where I keep my external libraries used in my project.
The LLVM library is the main cause of the problem, since the warnings produced fill up the entire screen making it very difficult for me to efficiently identify compile-time errors, etc.
I'm using CMake and have my LLVM 9.0.0 library under the libs folder. I would like to instruct the compiler (using CMake) to ignore all warnings and messages originating from the libs folder.
This is my CMakeLists.txt file:
# General project settings.
cmake_minimum_required(VERSION 3.12.4)
project(ionir)
# Setup compiler flags.
set(CMAKE_CXX_STANDARD 17)
# General project information.
set(PROJECT_URL "https://github.com/ionlang/ir-c")
# Setup source and build directories.
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
option(USE_MD "Use MD instead of MTd" OFF)
if (USE_MD)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MD")
#set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
endif(USE_MD)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
# Setup versioning.
set(VERSION_MAJOR "1")
set(VERSION_MINOR "0")
set(VERSION_PATCH "0")
set(VERSION "$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)")
# Configure and use LLVM. Also ensures LLVM 9.0.0 is installed.
find_package(LLVM 9.0.0 EXACT REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
# Include LLVM source directories (for syntax support, etc.). The SYSTEM symbol supposedly marks the directory to supress warnings.
include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) #---> COMMENTED TO SOLVE CIRCULAR DEPS. PROBLEM.
add_definitions(${LLVM_DEFINITIONS})
# Disable warnings from includes.
#add_library(llvm INTERFACE)
#target_sources(llvm INTERFACE)
#target_include_directories(llvm PRIVATE include/ SYSTEM INTERFACE include/)
# Set source file(s).
file(GLOB_RECURSE SOURCES
"src/*.h"
"src/*.cpp"
)
# Specify that this project is a library.
add_library(${PROJECT_NAME} ${SOURCES})
# Provide include directories to be used in the build command. Position in file matters.
#target_include_directories(${PROJECT_NAME} PRIVATE "src")
include_directories("src")
# Find the libraries that correspond to the LLVM components
# that we wish to use
# llvm_map_components_to_libnames(llvm_libs support core irreader)
# Link against LLVM libraries.
target_link_libraries(${PROJECT_NAME} ${llvm_libs})
# Setup unit testing using Google Test (GTest) if applicable. This binds the CMakeLists.txt on the test project.
option(BUILD_TESTS "Build tests" ON)
if (BUILD_TESTS)
add_subdirectory(libs/googletest)
add_subdirectory(test)
endif()
And below is some of the warnings/messages I'm receiving that are filling up the console.
How can I accomplish this?
So I've been trying to learn CMake and use it with C++. I'd like to have a go at creating a portable game engine which uses Direct3D 12 on Windows.
Currently, I have the following CMakeLists.txt for my project:
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(PsychoEngineCore)
set(SRCS_CXX ${CMAKE_CURRENT_LIST_DIR})
include(${CMAKE_CURRENT_SOURCE_DIR}/src/dir_src.cmake)
set(LIB_TYPE "STATIC" CACHE STRING "Static or Dynamic Linking")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU OR
${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
set(warnings "-Wall -Wextra -Werror")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
set(warnings "/W4 /WX /EHsc")
endif()
if(NOT CONFIGURED_ONCE)
set(CMAKE_CXX_FLAGS "${warnings}"
CACHE STRING "Flags used by the compiler during all build types." FORCE)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Do we want static libraries?
# When STATIC_LINKING is TRUE, then cmake looks for binaries ending in ".a".
# THIS IS FOR LINUX ONLY!
if(LIB_TYPE EQUAL STATIC)
if (UNIX AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES(".a"))
endif(UNIX AND NOT APPLE)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set_target_properties(surface PROPERTIES LINK_SEARCH_END_STATIC 1)
endif(LIB_TYPE EQUAL STATIC)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include(GenerateExportHeader)
add_library(${PROJECT_NAME} ${LIB_TYPE} ${SRCS_CXX})
GENERATE_EXPORT_HEADER(
${PROJECT_NAME}
EXPORT_MACRO_NAME PE_API
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/Engine/API/${PROJECT_NAME}Export.hpp
DEPRECATED_MACRO_NAME PE_API_DEP
STATIC_DEFINE PE_STATIC
)
Currently I have my d3d12.lib file in the following location:
C:\Program Files (x86)\Windows Kits\10\Libs\10.0.16299.0\um\x64
Is there a way to keep the path dynamic and preferably "update" if a newer version is available on said system?
Thanks!
Turning my comment into an answer
Generally speaking, just add a
target_link_libraries((${PROJECT_NAME} d3d12.lib)
The Windows SDK (where the Direct3D SDK is now part of) is in the standard search paths e.g. of the linker for libraries. So it's found automatically by the MSVC compiler and linker.
And I don't think that upgrading to a newer (yet unknown) API version automatically is a good idea. You're writing your program for a specific API version.
Working Example
Here is a minimal working example (Tested VS2017 15.5.5, CMake 3.9.0):
cmake_minimum_required(VERSION 3.0)
project(Direct3DExample)
find_package(Git REQUIRED)
set(_path "${CMAKE_BINARY_DIR}/DirectX-Graphics-Samples/Samples/Desktop/D3D12HelloWorld/src/HelloTriangle")
if (NOT EXISTS "${_path}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" clone https://github.com/Microsoft/DirectX-Graphics-Samples.git
)
endif()
file(GLOB _files "${_path}/*")
list(APPEND _shader ${_files})
list(FILTER _files EXCLUDE REGEX "\\.vcxproj|\\.hlsl")
list(FILTER _shader INCLUDE REGEX "\\.hlsl")
get_filename_component(_name "${_path}" NAME)
add_executable(${_name} WIN32 ${_files})
target_compile_definitions(${_name} PRIVATE "UNICODE" "_UNICODE")
target_link_libraries(${_name} PRIVATE "d3d12.lib" "dxgi.lib" "d3dcompiler.lib")
add_custom_command(
TARGET ${_name}
POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy ${_shader} $<TARGET_FILE_DIR:${_name}>
)
If you need more (compilers/linkers that are not finding the Windows SDK automatically), you may want to look the following find_package() config code:
https://github.com/Microsoft/DirectXShaderCompiler/blob/master/cmake/modules/FindD3D12.cmake
I already read and searched a lot (e.g. 1 2 3, several docs for CMake, similar projects, etc. to find a solution but I have not been able to solve my problem. I am relatively new to Cmake and Linux (Ubuntu 14.04).
I want to use libsbp (https://github.com/swift-nav/libsbp) to write a program in C++ to communicate with a GPS module. I cloned the repository and installed the C-Library. So now in /usr/local/lib there are two files: libsbp.so and libsbp-static.a and the headers are in /usr/local/include/libsbp
In my own project I include the headers with #include "libsbp/sbp.h" which also works.
Now the Problem: if I want to use a method from libsbp e.g. sbp_state_init(&s); I get undefined reference to "sbp_state_init(sbp_state_t*)"
The relevant part of my Cmake for my own project:
link_directories(/usr/local/lib)
add_executable(main ${QT_SOURCES} ${QT_HEADER_HPP})
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)
As I said before, I tried some things:
find_library(SBP_LIB sbp /usr/local/lib) -> same error
same goes for using libsbp in target_link_libraries or searching for it
link_directory(/usr/local/lib)
trying different paths, even moveing libsbp.so into the project directory and "finding" it with ${CMAKE_CURRENT_SOURCE_DIR}
Maybe you can help me!
edit:
this is the CMakeList.txt from the libsbp/c/src directory
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif (NOT DEFINED BUILD_SHARED_LIBS)
file(GLOB libsbp_HEADERS "${PROJECT_SOURCE_DIR}/include/libsbp/*.h")
include_directories("${PROJECT_SOURCE_DIR}/CBLAS/include")
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
include_directories("${PROJECT_SOURCE_DIR}/lapacke/include")
include_directories("${PROJECT_SOURCE_DIR}/include/libsbp")
set(libsbp_SRCS
edc.c
sbp.c
)
add_library(sbp-static STATIC ${libsbp_SRCS})
install(TARGETS sbp-static DESTINATION lib${LIB_SUFFIX})
if(BUILD_SHARED_LIBS)
add_library(sbp SHARED ${libsbp_SRCS})
install(TARGETS sbp DESTINATION lib${LIB_SUFFIX})
else(BUILD_SHARED_LIBS)
message(STATUS "Not building shared libraries")
endif(BUILD_SHARED_LIBS)
install(FILES ${libsbp_HEADERS} DESTINATION include/libsbp)
this is the CMakeList.txt from /libsbp/c/
cmake_minimum_required(VERSION 2.8.9)
project(libsbp)
# Setup flags for Code Coverage build mode
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C++ compiler for building with code coverage."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C compiler for building with code coverage."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used for linking binaries with code coverage."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the shared libraries linker during builds with code coverage."
FORCE )
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
# Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE )
# Set project version using Git tag and hash.
execute_process(
COMMAND git describe --dirty --tags --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_VERSION_FOUND
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)
# Set project version explicitly for release tarballs.
#set(VERSION foo)
message(STATUS "libsbp version: ${VERSION}")
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Some compiler options used globally
set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}")
add_subdirectory(src)
add_subdirectory(docs)
add_subdirectory(test)
It seems that your program uses C++ and the library is written in C.
Symbols in C and C++ are encoded differently (mangled). When including C headers from C++ you need to tell the compiler. This can be done by declaring the symbols extern "C".
extern "C" {
#include <libsbp/sbp.h>
}
Some libraries already include this in their headers, but not sbp.
You have (at least) two possibilities:
Installing the library (this is what you did)
Integrating the library in your CMake project
When installing the library, the target_link_libraries command needs to be modified slightly:
find_library(SBP_LIB sbp /usr/local/lib)
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} ${SBP_LIB})
When you integrate the library in your CMake project, you can directly use the following command without using find_library. This works, because the library is known to CMake since it is built within the current project.
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)