I have a project structure like this which I wish to build using CMake.
root\
|
|--crystal\
| |
| |--include\ Math.h, Window.h
| |--src\ Math.cpp, Window.cpp
| |--lib\
| |--CMakeLists.txt // the CHILD cmake
|
|--game\ main.cpp
|--CMakeLists.txt // the PARENT cmake
The crystal sub-project is supposed to produce a static library (libcrystal.a) in the lib/ folder (using the contents of include/ and src/) and the root project will produce an executable out of game/main.cpp linking the libcrystal.a static library.
The Parent CMAKE is as follows:
cmake_minimum_required(VERSION 2.8.1)
project(thegame)
set(CRYSTAL_LIB_DIR lib)
set(CRYSTAL_LIB_NAME crystal)
add_subdirectory(${CRYSTAL_LIB_NAME})
set(LINK_DIR ${CRYSTAL_LIB_NAME}/${CRYSTAL_LIB_DIR})
set(SRCS game/main.cpp)
link_directories(${LINK_DIR})
include_directories(${CRYSTAL_LIB_NAME}/include)
add_executable(thegame ${SRCS})
target_link_libraries(thegame lib${CRYSTAL_LIB_NAME}.a)
The child CMAKE is as follows:
cmake_minimum_required(VERSION 2.8.1)
project(crystal)
include_directories( include )
file(GLOB_RECURSE SRC "src/*.cpp")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CRYSTAL_LIB_DIR})
add_library(${CRYSTAL_LIB_NAME} STATIC ${SRC})
What isn't working:
When I executed cmake . and sudo make in the root/ directory I expected both parent and child cmake to run sequentially. But it seems like the child cmake is not getting invoked and thus not producing the .a file. Its showing some error like:
Scanning dependencies of target thegame
[ 20%] Building CXX object CMakeFiles/thegame.dir/game/main.cpp.o
[ 40%] Linking CXX executable thegame
/usr/bin/ld: cannot find -lcrystal
collect2: error: ld returned 1 exit status
CMakeFiles/thegame.dir/build.make:94: recipe for target 'thegame' failed
make[2]: *** [thegame] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/thegame.dir/all' failed
make[1]: *** [CMakeFiles/thegame.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
What is working:
I went ahead the did this
executed cmake . in root/
navigate into the crystal folder and manually invoked the Makefile by sudo make
came to the root/ again and invoked the outer Makefile by sudo make
and this perfectly worked.
Question:
Why the child CMake is not getting invoked as I mentioned in the What isn't working section ???
Use target_link_libraries(thegame ${CRYSTAL_LIB_NAME}) in the root CMakeLists.txt and remove link_directories call. CMake will recognize that you are linking to crystal target and set makefile dependencies and compiler flags accordingly.
Related
I have a library compiled as a single file that I'm trying to link with cmake but haven't been able to cobble together something that works using existing examples that should be related, eg.
CMake link an external library
Cmake linking external libraries
What I have so far:
cmake_minimum_required(VERSION 3.17)
project(atem)
set(CMAKE_CXX_STANDARD 14)
set(BMD_API_LIB "BMDSwitcherAPI")
set(BMD_API_PATH "/Library/Application Support/Blackmagic Design/Switchers/BMDSwitcherAPI.bundle/Contents/MacOS/")
find_library(BMDSwitcherAPI ${BMD_API_LIB} PATHS ${BMD_API_PATH})
add_executable(atem main.cpp BMDSwitcherAPIDispatch.cpp)
target_link_libraries(atem ${BMDSwitcherAPI})
The files main.cpp and BMDSwitcherAPIDispatch.cpp exist in the same directory. Building says that the file for the library can't be found, but the binary for the library file for ${BMD_API_LIB} cannot be found, but it is definitely at the path given in ${BMD_API_PATH}.
I'm not sure where to go from here.
Edit: added entire error message
====================[ Build | atem | Debug ]====================================
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake --build /Users/user/Code/atem/cmake-build-debug --target atem -- -j 9
[ 33%] Linking CXX executable atem
ld: library not found for -lBMDSwitcherAPI
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [atem] Error 1
make[2]: *** [CMakeFiles/atem.dir/all] Error 2
make[1]: *** [CMakeFiles/atem.dir/rule] Error 2
make: *** [atem] Error 2
This may not be helpful to anyone else because it was so specific to the one library I was using, but here it is anyway.
cmake_minimum_required(VERSION 3.17)
project(atem)
set(CMAKE_CXX_STANDARD 14)
find_library(CoreFoundation_Library CoreFoundation)
mark_as_advanced(CoreFoundation_Library)
set(
SWITCHERS_SDK_INCLUDE_DIR
/Applications/Blackmagic\ ATEM\ Switchers/Developer\ SDK/Mac\ OS\ X/include/
)
add_executable(
atem
atem/main.cpp
${SWITCHERS_SDK_INCLUDE_DIR}/BMDSwitcherAPIDispatch.cpp
)
target_include_directories(atem PRIVATE ${SWITCHERS_SDK_INCLUDE_DIR})
target_link_libraries(atem ${CoreFoundation_Library})
Recently I have started to learn CMake. To practice, I am trying to link SDL2 manually. I know that there is another way around using find_file which is easy. But I want to do it myself for practice.
I get an error when I try to link the libSDL2main.a file (running the Makefile using cmd mingw32-make)
[ 50%] Linking CXX executable exe0.exe
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: cannot find -llibSDL2main
collect2.exe: error: ld returned 1 exit status
CMakeFiles\exe0.dir\build.make:105: recipe for target 'exe0.exe' failed
mingw32-make[2]: *** [exe0.exe] Error 1
CMakeFiles\Makefile2:94: recipe for target 'CMakeFiles/exe0.dir/all' failed
mingw32-make[1]: *** [CMakeFiles/exe0.dir/all] Error 2
Makefile:102: recipe for target 'all' failed
mingw32-make: *** [all] Error 2
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(SDL_Test_Project)
include_directories(include)
add_executable(exe0 main.cpp)
target_link_libraries(exe0 libSDL2main.a)
Here main.cpp is only a source file. I have put SDL2.dll and libSDL2main.a into the root of the project directory. (I used the CMake GUI to generate the Makefile in Windows 10).
If you want to link to the SDL2 libraries directly in target_link_libraries() (without defining IMPORTED targets, or using find_library()), use the full path to each library. The CMAKE_SOURCE_DIR variable provides the full path to the root directory of the CMake project:
target_link_libraries(exe0 PRIVATE
mingw32
${CMAKE_SOURCE_DIR}/libSDL2main.a
${CMAKE_SOURCE_DIR}/SDL2.dll
)
Note, for SLD2, you may also have to add the mingw32 to this command when using MinGW for compilation.
I'm using external files for work with my library, so but I do not want using the relative path inside my file C++ but I want using this convention
I read that with CMake is possible to create this if using the target_include_directories
I'm new with Cmake and I have a problem with configuring this target on my project
This is my directory configuration
This is my CMake configuration
cmake_minimum_required(VERSION 2.6)
project(decompile-bitcoin-script)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES
main.cpp
#Bitcoin Lib
bitcoinlib/script.cpp
bitcoinlib/script_error.cpp
bitcoinlib/key_io.cpp
bitcoinlib/pubkey.cpp
bitcoinlib/sign.cpp
bitcoinlib/standard.cpp
)
add_executable(Decompiler ${SOURCE_FILES})
target_include_directories(Decompiler PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/bitcoinlib)
This is the compiler error
[ 12%] Building CXX object CMakeFiles/Decompiler.dir/main.cpp.o
[ 25%] Building CXX object CMakeFiles/Decompiler.dir/bitcoinlib/script.cpp.o
/home/vincenzo/Github/decompiler-bitcoin-script/bitcoinlib/script.cpp:6:10: fatal error: bitcoinlib/script.h: No such file or directory
#include <bitcoinlib/script.h>
^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
CMakeFiles/Decompiler.dir/build.make:86: recipe for target 'CMakeFiles/Decompiler.dir/bitcoinlib/script.cpp.o' failed
make[2]: *** [CMakeFiles/Decompiler.dir/bitcoinlib/script.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/Decompiler.dir/all' failed
make[1]: *** [CMakeFiles/Decompiler.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Inside the main not have code but I have only main with a cout<<"foo";
What I'm doing wrong?
target_include_directories(Decompiler PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/bitcoinlib)
This line is telling the compiler that ./bitcoinlib is the root of the include path.
So #include <bitcoinlib/script.h> is looking for ./bitcoinlib/bitcoinlib/script.h.
You seem to have set up your project directory with CMakeLists.txt inside your source/headers directory, so you can change the target_include_directories setting like this:
target_include_directories(Decompiler PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
Or, you can change ./bitcoinlib/script.cpp to #include <script.h> since that header is in the same directory as the .cpp file anyways.
I would recommend that you restructure your project a bit though:
<Project Directory>
CMakeLists.txt
include
bitcoinlib
< your bitcoinlib headers here >
src
bitcoinlib
< your bitcoinlib sources here >
main.cpp
target_include_directories(Decompiler PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
I am currently trying to setup my C++ project using CMake, I successfully included dependencies like OpenMPI, but when going to Swiften, this became complex. This is not delivered in the form a package, but as shown in the git repository linked up there. Building that wasn't an issue, but I searched quite a lot of time, without finding any way to include libraries that don't provide a .so, and no main headers.
Here's my current CMakeLists.txt, made for testing only.
cmake_minimum_required (VERSION 3.0.0)
#set the executable
project (mtest)
set(EXECUTABLE_OUTPUT_PATH .)
add_executable (mtest main.cpp)
#defines libs
find_package(MPI REQUIRED)
set(CMAKE_CXX_COMPILE_FLAGS ${CMAKE_CXX_COMPILE_FLAGS} ${MPI_COMPILE_FLAGS})
set(CMAKE_CXX_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS} ${MPI_LINK_FLAGS})
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
include_directories(SYSTEM Swiften)
target_link_libraries(mtest ${MPI_LIBRARIES})
add_library(swiften SHARED IMPORTED)
set_target_properties(swiften PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/Swiften/libSwiften.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/Swiften"
)
target_link_libraries(mtest swiften)
And when trying to run make, here's the error :
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/Documents/CTests/build
[ 50%] Building CXX object CMakeFiles/mtest.dir/main.cpp.o
/home/user/Documents/CTests/main.cpp:12:10: fatal error: Swiften/Client/Client.h: No such file or directory
#include <Swiften/Client/Client.h>
^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
CMakeFiles/mtest.dir/build.make:62: recipe for target 'CMakeFiles/mtest.dir/main.cpp.o' failed
make[2]: *** [CMakeFiles/mtest.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/mtest.dir/all' failed
make[1]: *** [CMakeFiles/mtest.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
By the way, if the directory structure may help you, here's a tree output : https://pastebin.com/giPb9229
I try to use cmake with an external library but i can't. I use minGW and g++ compiler.
My project is organised as follow:
project/
CMakeLists.txt
src
main.cpp
lib
win
x86
SDL2-2.0.3 (contains SDL2.dll, SDL2.lib, SDL2main.lib and SDL2test.lib
include
SDL2 (contains all header)
bin
The cmake generator works `cmake -G"Eclipse CDT4 - Unix Makefiles"
My cmake file:
`
#
# File generated by CMakeBuilder
#
#
cmake_minimum_required(VERSION 2.6)
PROJECT ( project CXX )
################ INCLUDE Libs ####################
SET (CMAKE_INCLUDE_PATH "${PROJECT_SOURCE_DIR}/include/")
SET (CMAKE_LINKER_PATH "${PROJECT_SOURCE_DIR}/lib/win/x86/SDL2-2.0.3/")
message(STATUS "INCLUDE_PATH: ${CMAKE_INCLUDE_PATH}" )
message(STATUS "LINKER_PATH: ${CMAKE_LINKER_PATH}" )
INCLUDE_DIRECTORIES(${CMAKE_INCLUDE_PATH})
LINK_DIRECTORIES(${CMAKE_LINKER_PATH})
set (CMAKE_CXX_FLAGS "-lSDL2main -lSDL2 -lmingw32 ")
#Generate file source
file( GLOB_RECURSE source_files src/*)
ADD_EXECUTABLE(project ${source_files})
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
But when i launch make, i obtain this error:
`
CMakeFiles/project.dir/objects.a(main.cpp.obj):main.cpp:(.text+0x0): multiple
definition of main
C:/Users/Gege/workspaces/workspaceCPP/project/lib/win/x86/SDL2-2.0.3/SDL2m
ain.lib(./Release/SDL_windows_main.obj):(.text[_main]+0x0): first defined here
Warning: corrupt .drectve at end of def file
C:/Users/Gege/workspaces/workspaceCPP/project/lib/win/x86/SDL2-2.0.3/SDL2m
ain.lib(./Release/SDL_windows_main.obj):(.text[_main]+0x12): undefined reference
to SDL_main'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:/Users/Gege/workspaces/workspaceCPP/project/lib/win/x86/SDL2- 2.0.3/SDL2main.lib(./
Release/SDL_windows_main.obj): bad reloc address 0x8 in section .text[_WinMain#
16]'
collect2.exe: error: ld returned 1 exit status
CMakeFiles/project.dir/build.make:87: recipe for target 'bin/project.exe'
failed
make[2]: *** [bin/project.exe] Error 1
CMakeFiles/Makefile2:60: recipe for target 'CMakeFiles/project.dir/all' faile
d
make[1]: *** [CMakeFiles/arduinoGeo.dir/all] Error 2
Makefile:75: recipe for target 'all' failed
make: *** [all] Error 2
`
Actually i don't want to put my lib in minGW folder to keep the build easy for the others.
Thanks for you help