How to Build/Debug Android Studio External Source Library? - c++

I've been attempting to build and debug an external Java/C++ source library inside Android Studio 2.2 but I am unable to figure out how to do this or if it is possible.
In specific, I am attempting to use the https://github.com/mapbox/mapbox-gl-native library, but I suspect the solution may be similar for any Java/C++ library. In this case the library contains a Makefile and a CMakeLists.txt file.
I have not seen how the CMakeLists.txt is used, but I have built the Mapbox library from source using the command:
BUILDTYPE=Debug make android
I have created a project using the Android Studio wizard and chose the C++ option which creates a sample .cpp that successfully builds and debugs:
// native-lib.cpp
#include <jni.h>
#include <string>
extern "C"
jstring
Java_com_example_kea_mapboxtest_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
It also create an app/CMakeLists.txt file.
I am looking for anyway I can build and debug a 3rd party C++ source library. My best guess is that there is some way to modify the app/CMakeLists.txt file generated by the wizard to do this, but I'm guessing this is what to do and I can't figure out how.
The reason I think this might be the correct road to take is that the wizard generated app/CMakeLists.txt contains:
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/native-lib.cpp
which seems to work. I was thinking it might be possible to reference the library CMakeLists.txt or the Makefile found in the Mapbox source inside the wizard generated CMakeLists.txt. The hope is the library it builds will be debuggable. Alternatively having it statically linked would also be acceptable, so long as I could debug into the C++ source in the library.
Thanks.

Ordinarily, I'd suggest using add_subdirectory() to first bring map box into your build and then target_link_libraries() to link your native-lib target to it, something like this:
add_subdirectory(path/to/mapbox/src mapbox)
add_library(native-lib SHARED src/main/cop/native-lib.cpp)
target_link_libraries(native-lib PUBLIC mbgl-core)
Unfortunately, the mapbox project's CMakeLists.txt file assumes it is the top level of the build, so that approach won't work without some hackery on your part (the problem is its use of CMAKE_SOURCE_DIR in its top level CMakeLists.txt file). An alternative might be to use ExternalProject instead. This is less convenient but more flexible in that it allows you to bring in builds from just about any sort of external project, building such projects in their own sandbox which your main build then uses for linking, etc. It also has the advantage that it can take care of downloading the source for mapbox for you too, so you don't have to add it directly to your own project's sources. Rather than repeat it all here, I'll refer you to the following links for existing questions and answers which should point you in the right direction for using ExternalProject.
A fairly simple example with some useful comments
Kitware's blog post on how to use ExternalProject (credit to this answer for the link).
A range of answers relating to use of GoogleTest which might inspire some ideas and highlight some things to be careful of (check all the answers, not just the top rated).
If that's still not clear enough, let me know in the comments or start a chat and I'll try to clarify this answer further for you.

Related

clarify on CMAKE library installation

The odd is that I can understand CMAKE documents, but I still can not figure out how to use it in a little more complicated scenario.
I want to install a SHARED LIB, to let someone else use it.
I know I can install it with CMAKE install command, but my first question is that my code still works without installing the library. The library is built and put under cmake_build_debug dir.
All I did is:
FILE(GLOB SHAREAD_SRC
${CMAKE_CURRENT_SOURCE_DIR}/Interface/*.cpp
)
set(MY_LIB mylib)
add_library(${MY_LIB} SHARED ${SHAREAD_SRC})
add_executable(run_src src/my_src.cpp ${HEADERS})
target_link_libraries(run_src ${MY_LIB})
I can now include the library's header in my source code and start to use it.
My question is,
in add library command, should I also include my library's header files? Currently i only include the source files to build the library, since whenever I use the library, I know where physically the library headers are(since i made this library), and for those others who also want to use this lib, i would provide them the header and the built lib target, so whereever they want to put them, no problem.
some answers talk about the install command saying that without the header files included in add_library, Why add header files into ADD_LIBRARY/ADD_EXECUTABLE command in CMake, otherwise you won't see headers in IDE-generated project. My headers are in this project, so I don't understand this issue. Why do I need to install this library? What is the purpose of install if the user downloaded my header file and have the built binary?
Thanks for helping! Appreciation in advance.
Except for the mentioned reason that specified files gonna be "visible" in IDE there is one more: explicit better than implicit (yeah Pythonish statement) -- meaning that you give a hint to the reader of your CMakeLists.txt of what exact files your library consists of. And yes, using GLOB for sources is the known bad practice for many reasons -- IRL it's not really hard to maintain the list of sources explicitly and makes your build system less error-prone. In some circumstances, you can gain some more benefits of having headers mentioned explicitly (e.g. using install(TARGET ... PUBLIC_HEADERS ...) but this is the other subject :)
You didn't specify your workflow (how do you build and distribute your project/library). However, the primary goal of install is to form the built image of your project -- i.e. what targets/files/directories gonna be installed and into what directory layout. It's needed to build other projects dependent on yours or produce packages (w/ CPack) to distribute or deploy 'em somewhere.
Also, to let others use your built library in CMake way please read how to make a package section in the manual. So, others can just do find_package(YourProject) and use it (link w/ it via target_link_libraries) -- easy peasy!

How to 'install' and use in-house dependencies for other projects with CMake

clarification: If the below setup is a reasaonable way to do it, then my question is mainly, how do I best add the public headers with the .lib when I run ninja install as my solution does not do this currently.
There is a myriad of examples of how to do stuff in different ways, and many seem to contradict eachother to just confuse me even more.
I'm trying to change out a in-house build system and replace it with CMake. The codebase consists of many different components/libraries, like OS/Platform abstraction, networking, functionality etc. Before this was always compiled together as one big codebase, so running clean would remove everything and rebuild all dependencies.
Now it comes to the part where I have trouble understanding on how a modern smart way to do it in CMake is.
Ignoring the fact that a dependency-chain tool on top is needed, my idea was to build the components/libraries in order of libraries with no dependency to the topmost as isolated build runs.
Then each isolated build run would be built with its dependencies, like only the windows API for the OS abstraction library, and then run install and export on it.
Is this the general prefered way, to compile a library to a .lib on windows or .a on linux and export it to a known shared location?
Im guessing it would be required then to copy all public header files for this library to the same location? If so, how is this most correctly done?
If I have my OS abstraction folder structure
OSabstraction/
includes/
OSabstraction/
abstraction.h
src/
abstraction.cpp
CMakeLists.txt
and my CMakeLists is
cmake_minimum_required(VERSION 3.12)
project(OSabstraction LANGUAGES CXX)
add_library(abstraction)
target_sources(abstraction
PRIVATE
src/abstraction.cpp
)
target_include_directories(abstraction
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes/>
$<INSTALL_INTERFACE:include>
)
install(
TARGETS abstraction
EXPORT abstraction-export
ARCHIVE DESTINATION lib
)
How would I best go around to use this library in many other inhouse projects? This library is in practice many times larger, so what would be the correct way to do it for a large project?
edit: I tried to follow Pablo Arias' guide on how to do CMake Right, but I am not sure how the build_interface and install_interface generators work in regards to getting my header files with the export of the .lib file.
Recommended solution is to use a package manager together with CMake.
The link below is a full C++ project setup template which can use the package manager https://conan.io/ to support splitting up dependencies into individual libraries.
https://github.com/trondhe/cmake_template

Add external library into current c++ project

I'm trying to use the xgboost library to basically translate a model I developed in R to C++.
I've not used an external library and other sources online did not help me much so decided to ask the question here to hopefully find the way to do it.
Here's the library I need to use in my C++ code: https://github.com/dmlc/xgboost
I'm using Visual Studio Ultimate 2013. I have a make file that I use to define my project.
I am looking for the proper way to use this library in my C++ code.
If you have ever used this library before, I really appreciate your help. Any hint will be appreciated.
To use the library, one needs to first build it. I could not manage to build the master branch. So, I decided to use the V0.4 instead. I built the solution in that branch using Visual Studio and it produced the dll and lib files. One can then import the .dll file by using Add_library to add it via Cmake. After Add_library, the include directories need to be added by include_directories command.
I need to generate .a and .so files in the end. I'm working in windows and could not find a way to generate these files, yet!
So I found the way to resolve this issue. I shared it in another answer
Add an external library (e.g., Eigen) via CMake
Hope this helps people who are looking!

Writing a makefile for a C++ program

Can someone help me write my first makefile?
I have a helloworld.cpp code in /path/to/main/code/helloworld.cpp.
And then I have just included a .h file #include "SFML/network.hpp".
Now SFML library is saved in /path/to/SFML/Library
It would be great if someone can help me getting started in this. In the mean time, I am trying to read thru the literature but its very overwhelming.
Although you may need to learn the traditional GNU Makefile syntax in order to work with other projects, I recommend using CMake for your own projects because it is simpler and more intuitive.
A CMake file for your example would go in a file called CMakeLists.txt in the root directory of your project (same as the source in this case) and look like this:
project(HelloWorld) # Name your project.
add_executable(helloworld helloworld.cpp) # Specify an executable to build.
link_directories(/path/to/SFML) # Tell it where your libraries are.
target_link_libraries(helloworld Library) # Tell it which library to link.
If you want to be able to #include headers from SFML without including the directory name every time, then you can also write:
include_directories(SFML) # Tell it where your headers are.
Further documentation on writing CMake files and running CMake is available on the website.
Lastly, CMake often gives a noisy but harmless message requesting that you put a line like this at the top of your CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8) # Quell warnings.
Cheers.
It is probably simple on its own, but just wanted to recommend genmake.pl, I used this to great effect for my school project. It is quite easy to use, it generates a skeleton Makefile for you and you need to fill in things like the path to SFML.
If you're using ACE (Adaptive Communication Environment), it comes with a very powerful makefile creation utility called MPC (Makefile Project Creator)
To compile a simple program, and auto-generate GNU makefiles, a minimal example could be:
project(*my_project) : baseWorkspace {
exename = my_project
exeout = ./
Source_Files {
main.cpp
}
}
I've found that the beauty of using this tool is that it can inherit "base" workspaces, almost like polymorphism in C++. The libraries defined in the "base" are used in the current project, allowing the programmer to utilize various building blocks to easily manipulate and create projects rapidly.
I'm confident only the MPC portion of ACE can be downloaded and used via an RPM, I'll search around and see if I can find an appropriate example for you.

Good practices when adding downloaded c++ source code to my project

I am trying to use gnuplot++, but this is really a more general question about downloaded source code. I have downloaded the gnuplot++ source code and it consists of multiple .h and .cc files. I would like to use it in othercopy projects in the future so I am reluctant to add all the files into my project directory.
From what I understand gcc will look in /usr/local/include for header files, so I have put the code there for now. But what is the best way to compile and link the code?
Should I use the makefile to include the directory of the source code?
Should I keep it somewhere easy to find like /usr/local/include?
How do I know the best way to compile the code in gnuplot++?
Typically, if the project itself doesn't come with install instructions, I usually add it somewhere "public", e.g. /usr/local/project/{lib,include,src,...} where "project" in this case would be gnuplot++.
In this case, there doesn't appear to be any support for building this into a library, which makes it a little more awkward, as you need the sources included in your project itself. I'd still keep those sources separate, but you may prefer to just put them into a separate directory within the project [or spend an hour or three making a library of it].
For general practice, yes, keep the source for gnuplot++ (or any other similar 3rd-party project) separate from your own application source code. This makes it much easier to manage updates to the 3rd party projects, etc.
Yes, I would use the makefile for your application to also include the path to the headers for gnuplot++ and I would not copy those files directly into /usr/local/include. Instead, I would consider a couple options: do nothing and point your include path in your makefile to the gnuplot++ directory, or put symbolic links in /usr/local/include to point to the gnuplot++ files.
As for the best way to compile gnuplot++, I would have to look at gnuplot++ myself and see what it has to say, perhaps in a README file or similar.
In general, when using third-party libraries, you build and install those libraries according to the installation description that comes with the downloaded source.
If there is no installation guideline, it is typically a set of steps like
./configure
make
make install
Then it is the responsibility of the library to ensure the relevant headers and library files are easily locatable for use in your project.
gnuplot++ is an exception here, because it does not seem to come with its own build structure.
The best advice in cases such as this is to put the source from gnuplot++ in a directory within your project (possibly parallel to your own sources) and include the files in your own build setup.