I have 2 projects (prj1 and prj2). One (prj2) depends on the other (prj1) that is a static library. I arrive to compile them separately with CMake.
But I needed to integrate one (prj1) to the other one (prj2). So I would like CMake to compile the static library (prj1) before the other (prj2) and then link the static library. I tried things, but id did not work.
prj1 "core" is https://gitlab.com/RyDroid/PlanetWars2dRT-core
prj2 "SDL2" is https://gitlab.com/RyDroid/PlanetWars2dRT-SDL2/ (see branch adding-core)
In prj2, externals/core is a git submodule (for non git users, you can see this directory as a copy-paste of prj1).
I tried (without success) this CMakeLists.txt in prj2 "SDL2":
cmake_minimum_required(VERSION 2.8)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wformat=2 -Wpedantic -D_FORTIFY_SOURCE=2")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# TODO
endif()
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
# if (CMAKE_VERSION VERSION_LESS "3.1")
# if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
# CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# set (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
# endif()
# else()
# set(CMAKE_CXX_STANDARD 11)
# endif()
project(PlanetWars2dRT-SDL2)
# Version number
set(VERSION_MAJOR "0")
set(VERSION_MINOR "0")
set(VERSION_MICRO "0")
# Configure a header file to pass some of the CMake settings
# to the source code.
configure_file (
"src/compilation_config.h.in"
"${PROJECT_BINARY_DIR}/compilation_config.h"
)
# Add the binary tree to the search path for include files
# so that we will find compilation_config.h
include_directories("${PROJECT_BINARY_DIR}")
set(LIBRARY_OUTPUT_PATH lib/${CMAKE_BUILD_TYPE})
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
include_directories(src/)
file(
GLOB_RECURSE
source_files
src/*
)
add_executable(planet-wars-2d-rt-sdl2 ${source_files})
#include(ExternalProject)
#ExternalProject_Add(PlanetWars2dRT PREFIX externals/core/)
include_directories(externals/core/src/utils/ externals/core/src/specific/)
add_subdirectory(externals/core/)
#find_package(PlanetWars2dRT-core REQUIRED)
include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)
pkg_search_module(SDL2GFX REQUIRED SDL2_gfx)
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2IMAGE_INCLUDE_DIRS})
target_link_libraries(
planet-wars-2d-rt-sdl2
planet-wars-2d-rt-core
${SDL2_LIBRARIES} ${SDL2GFX_LIBRARIES}
)
That is a simplified version of the tree of prj2:
.
├── build (with CMake stuff generated with "cmake ..")
├── CMakeLists.txt
├── externals
│ └── core
│ ├── build (with CMake stuff generated with "cmake ..")
│ ├── CMakeLists.txt
│ ├── makefile
│ └── src
├── makefile
├── README.md
└── src
├── compilation_config.h.in
└── planet-wars-2d-rt-sdl2.cpp
How can I compile the library of prj1 "core" in prj2 "SDL2" with CMake, and then link the library of prj1 with prj2 (again with CMake)?
If your solution does not work with a non GNU/Linux OS, it is not a big problem. Note: my PC is running on Debian GNU/Linux 8 "Jessie".
Regards.
I cannot access your repo https://gitlab.com/RyDroid/PlanetWars2dRT-SDL2/, perhaps the servers are down for maintenance. If I understand your problem correctly, you may create a structure like that:
root/
CMakeLists.txt // 1
src/
CMakeLists.txt // 2
main.cpp
SDL2/
some sources
CMakeLists.txt // 3
core/
some sources
CMakeLists.txt // 4
In the CMakeLists.txt [1] you should declare your project name, required packages, common flags, include paths etc.:
cmake_minimum_required( VERSION 2.x )
project(name)
include_directories(inc inc/core inc/SDL2 inc/SthElse)
add_subdirectory(src)
In CMakeLists.txt [2] for subdir src you should declare your main executable and also add subdirs with your prj1 and prj2
add_subdirectory(core)
add_subdirectory(SDL2)
add_executable(main main.cpp)
target_link_libraries(main core SDL2 SomeOtherLib)
Finally, in your CMakeLists.txt [3] && [4] in your lib dirs you should declare static libraries:
add_library(core STATIC ${YourSourceFiles})
This approach always worked for me. If you used to compile and run "core" and "SDL2" as standalone binaries, perhaps you will have to reorganize them a little bit.
Both project have a file "compilation_config.h". At compilation time, the wrong was taken so compilation failed, because the code used was #include "compilation_config.h" that was ambigous.
So I created a "include/project-name" dir in both project and I changed the include path : "prj1/compilation_config.h" or "prj2/compilation_config.h". Thanks to that there was no ambiguity anymore, so it works now!
Related
I am trying to make a very simple regression model that (among other things), builds and compiles a GCC target for coverage, executes, and then publishes a standard Cobertura coverage report (all within Jenkins). The Jenkins part is somewhat irrelevant here, I'm only concerned with CMake syntax at the moment. This is my CMake file so far:
cmake_minimum_required( VERSION 3.15 )
# Project's name
project( my_project )
# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/test/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set( CMAKE_VERBOSE_MAKEFILE on )
# Generate coverage on GCC.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
set(LDFLAGS "${LDFLAGS} -lgcov -fprofile-arcs")
endif()
# Includes and Sources
include_directories(${PROJECT_SOURCE_DIR}/inc)
file(GLOB APP_SRC "./src/*.c")
file(GLOB TEST_DEPENDS_SRC "./test/src/*.c")
# Add executable to list.
add_executable( ${PROJECT_NAME}_Test ${APP_SRC} ${TEST_DEPENDS_SRC} )
This generates my *.gcno and *.gcda files in the directory /test/build/gcc/CMakeFiles/my_project.dir/*, but for ease of post-processing, I think I want these files placed alongside their source. Is that possible? If so, how? Is that best practice? I'm still pretty green when it comes to CMake.
I'm having a hard time opening the interactive resource editor in a MFC CMake project that otherwise compiles and runs just fine.
The project files are laid out as follows:
.
├── CMakeLists.txt
├── inc
│ ├── <...>
│ ├── resource.h
├── res
│ ├── MyApp.ico
│ ├── MyApp.rc
│ └── MyApp.rc2
└── src
├── CMakeLists.txt
└── <...>
Top CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(MyProject)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 14)
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we4715") # makes missing return as error
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") # parallel build
endif()
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/output)
# MFC
add_definitions(-D_AFXDLL)
set(CMAKE_MFC_FLAG 1)
add_subdirectory(src)
src CMakeLists.txt:
include_directories(${CMAKE_SOURCE_DIR}/inc)
include_directories(${CMAKE_SOURCE_DIR}/res)
include_directories(${CMAKE_SOURCE_DIR})
set(SOURCES
<...>
)
set(HEADERS
<...>
)
add_executable(
${PROJECT_NAME}
WIN32
${SOURCES}
${HEADERS}
${CMAKE_SOURCE_DIR}/res/MyApp.rc
${CMAKE_SOURCE_DIR}/res/MyApp.rc2
)
install(TARGETS MyApp
RUNTIME DESTINATION .)
In Visual Studio (Pro) the project loads just fine and compiles for every configuration I need, but if I try to open an .rc file I get errors on missing headers from MFC and ATL (afxres.h, winres.h, dde.rh, ...). The resource file won't open in the resource editor like it does on a VS solution.
The mssage happens when double-clicking on MyApp.rc, and I get
fatal error RC1015: cannot open include file 'afxres.h'.
I use the latest VS version available as of today which is 15.8.5, and this happens when opening the CMake project in Visual Studio.
I have already installed the ATL/MFC components in my Visual Studio installation. Like I said, it compiles just fine so dependencies are resolved correctly.
Am I missing something? Is this even possible?
I am new to Cmake and I am trying to create a CMakeLists.txt to build my project. I can build my project from command line using g++ compiler but when it comes to Cmake I am confused.
The directory structure is like this :
Project_folder
|--> Source
|--> main.cpp
|--> file1.cpp
|--> file2.cpp
|--> Header
|--> header1.h
|--> header2.h
|--> build (from where I run cmake .. and make)
CMakeLists.txt (this is under Project_folder)
Dependencies
|--> utils
|--> Utils.cpp
|--> include (has many folders in here)
|--> build (this path is in LD_LIBRARY_PATH as well)
|--> sharedlib1.so
|--> sharedlib2.so
Now from within the Project_Folder I can successfully run :
g++ ./Source/main.cpp ./Source/file1.cpp ./Source/file2.cpp ../Dependencies/utils/Utils.cpp -I ../Dependencies -I ../Dependencies/include/ -I ./Header/ -L ../Dependencies/build -std=c++11 -lsharedlib1 -lsharedlib2 -o ./build/main `pkg-config opencv --cflags --libs`
and generate the executable file.
Now I want to configure a CMakeLists.txt and try to replicate what the above compiler line is doing but with no success (I can cmake .., but I cannot make). CMakeLists.txt looks like this :
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
project(my_project)
#For the shared library:
set ( PROJECT_LINK_LIBS sharedlib1.so sharedlib2.so)
link_directories(${PROJECT_SOURCE_DIR}/../Dependencies/build/ )
include_directories(${PROJECT_SOURCE_DIR}/../Dependencies ${PROJECT_SOURCE_DIR}/../Dependencies/include ${PROJECT_SOURCE_DIR}/Header)
file(GLOB SOURCES "Source/*.cpp" )
set(CMAKE_CXX_FLAGS_RELEASE pkg-config opencv cflags libs)
## add_executable(name_of_output.o list_of_cpp_files)
add_executable(build ${SOURCES})
Running make after generating the makefile I get undefined reference to everything inside main.cpp. Is there anything obvious in the CMakeLists.txt that I should change?
Your call to g++ includes the ../Dependencies/utils/Utils.cpp file, but your call to add_executable is only using the files matched by Source/*.cpp. A quick solution would be to add ../Dependencies/Utils.cpp to the call to add_executable() making it
add_executable(build ${SOURCES} "${PROJECT_SOURCE_DIR}/../Dependencies/Utils.cpp")
On a related note: CMake discourages using file(GLOB ...) to get a list of source files, it's generally better to list the source files explicitly
You should use target_link_libraries after add_executable.
Please check the examples:
Executable with Static Library
Executable with Shared Library
While running the application you will also get some errors. Please be aware of RPATH.
Ok I managed to solve it ! :)
# set Cmake minimum version to use
cmake_minimum_required(VERSION 2.8.9)
# set the compiler
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# name your project
project(my_project)
set(CMAKE_BUILD_TYPE Release)
# Find and load the settings from the packages
find_package(PkgConfig REQUIRED)
find_package(OpenCV REQUIRED )
# set the extra flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -cflags -libs")
# set the shared libraries name (where the libraries are libsharedlib1.so and libsharedlib2.so + opencv runtime libraries)
set(PROJECT_LINK_LIBS sharedlib1 sharedlib2) ${OpenCV_LIBS}
# include the header files (.h)
include_directories(${PROJECT_SOURCE_DIR}/../Dependencies ${PROJECT_SOURCE_DIR}/../Dependencies/include ${PROJECT_SOURCE_DIR}/Header)
# add the source files (.cpp) using the set command as follow
set(SOURCES
Source/main.cpp
Source/file1.cpp
Source/file2.cpp
${PROJECT_SOURCE_DIR}/../Dependencies/utils/Utils.cpp)
# link the shared libraries (/build/libsharedlib1.so and /build/libsharedlib2.so)
link_directories(${PROJECT_SOURCE_DIR}/../Dependencies/build/)
# add_executable(name_of_output list_of_cpp_files)
add_executable(main ${SOURCES})
# link the executable with the shared libraries
target_link_libraries(main ${PROJECT_LINK_LIBS} )
and finally ./main will run the program !
When I try to link librubberband.a I get:
libavfilter/af_rubberband.c:236: error: undefined reference to 'rubberband_set_pitch_scale'
I compiled rubberband for armv7a, and created a static library (rubberband.a).
I checked the library, and It contained the needed symbols (using nm).
I verified that librubberband.a is in the libpath (-L)
I verified that extern C exists in the rubberband.c.h file.
Any ideas?
The error happened in the link stage. Make sure the link directory has been added to -L parameters of your compiler.
-L/directory/of/your/lib
And specify the library with -l option.
So make sure the option -L/directory/of/your/lib -lrubberband set for your compiler when you build ffmpeg with rubberband support.
If you didn't use pkg-config to add the library. You can use the option --extra-ldflags to add when configure ffmpeg before build.
./configure \
# some configure options
--extra-ldflags="-L/directory/of/your/lib -lrubberband" \
# more configure options
If you use pkg-config to find out the libraries. Just add the library.pc directory to PKG_CONFIG_PATH, and let the build system do the remaining.
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/directory/to/your/rubberband.pc
Updated
Finally make sure you link against to the same architecture of your library.
$ arm-linux-androideabi-readelf -h librubberband.a |grep 'Class\|Machine
For armeabi-v7a, it should be ELF32 and ARM.
Updated
I have cloned the source of rubberband from https://bitbucket.org/breakfastquay/rubberband
And found the function call rubberband_set_pitch_scale is defined at src/rubberband-c.cpp, this file is not include in Android.mk when build for Android (WHY?).
So you have to add this file to build.
RUBBERBAND_SRC_FILES = ... \
$(RUBBERBAND_SRC_PATH)/rubberband-c.cpp
After build done, you need to create directory structure like below
.
├── include
│ └── rubberband
│ ├── RubberBandStretcher.h
│ └── rubberband-c.h
└── lib
├── librubberband.a
└── pkgconfig
└── rubberband.pc
The file rubberband.pc was copied from rubberband.in.pc with some minor changes.
prefix=/path/to/rubberband/install/root
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: rubberband
Version: 1.8.1
Description:
Libs: -L${libdir} -lrubberband -L/path/to/android/ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a -lgnustl_static
Cflags: -I${includedir}
Then add
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/path/to/rubberband/install/root
before ./configure to tell ffmpeg find rubberband by pkg-config.
I have tried with the latest ffmpeg, it works.
I am learning CMake but I am struggling to understand how to link a binary file to a shared library and then install these files in a release folder.
These is the structure of my project:
├── CMakeLists.txt
├── build
├── main
│ ├── CMakeLists.txt
│ └── main.cpp
├── release
|_______bin
│ ├── include
│ │ └── math.h
│ └── lib
│ └── libmathLib.dylib
└── shared_lib
├── CMakeLists.txt
├── include
│ └── math.h
└── src
└── math.cpp
In the root CMakeLists.txt I've defined the project settings and the subdirectory.
Root CMakeLists.txt:
cmake_minimum_required(VERSION 3.1)
project (Math)
set(CMAKE_BUILD_TYPE Release)
set(MAKE_INCLUDE_CURRENT_DIR ON)
ADD_SUBDIRECTORY(shared_lib)
ADD_SUBDIRECTORY(main)
Main CMakeLists.txt:
add_executable(main main.cpp)
TARGET_LINK_LIBRARIES(main LINK_PUBLIC mathLib)
Math lib ( shared lib )
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(mathLib SHARED src/math.cpp)
install(TARGETS mathLib DESTINATION /Users/giuseppe/development/cmake/release/lib LIBRARY NAMELINK_ONLY)
install(FILES include/math.h DESTINATION /Users/giuseppe/development/cmake/release/include)
When I build the project with Make, it doesn't link main.o to the shared library. Error :
Scanning dependencies of target mathLib
[ 50%] Building CXX object shared_lib/CMakeFiles/mathLib.dir/src/math.cpp.o
Linking CXX shared library libmathLib.dylib
[ 50%] Built target mathLib
Scanning dependencies of target main
[100%] Building CXX object main/CMakeFiles/main.dir/main.cpp.o
/Users/giuseppe/development/cmake/main/main.cpp:8:12: error: use of undeclared identifier 'sum'
count << sum(5,6) << endl;
^
1 error generated.
make[2]: *** [main/CMakeFiles/main.dir/main.cpp.o] Error 1
make[1]: *** [main/CMakeFiles/main.dir/all] Error 2
make: *** [all] Error 2
Release phase:
How can I make sure that the builds in the bin folder within the release folder use the shared lib in 'path/release/lib'? Possibly using a relative path such as '../lib/' ?
You must add include directory for library to main/CMakeLists.txt. Adding it to shared_lib/CMakeLists.txt is not enough. Try this line:
include_directories("../shared_lib/include")