choose to build library or executable in cmake - c++

I'm building a library in c++ for which I generate project with CMake.
However, I don't know how to write a good CMakeLists.txt at the top directory of the library.
In fact, actually it works if I want to simply include the library in another project (adding library, linking sources, etc...), but I want that if I generate the library itself without other project, it generate a demo project provided by the library.
So I would like a CMakeLists that
link the library in the case of an inclusion in a project
build a demo in the case of the CmakeLists is used as the top cmakelists.
My first idea is to search if "project(xxx)" has already been called, but I don't know if this is a good idea. As I don't really know what is the good practice about this I have real difficulties to find information in the documentation.

A quick way to detect if your current project is also the top-level project is by inspecting PROJECT_SOURCE_DIR and CMAKE_SOURCE_DIR:
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
message("You are building stand-alone!")
endif()
But note that this might not be the best solution to your problem. Allowing libraries to be pulled into third-party builds like this requires explicit support from both your library and the enclosing build.
Alternatively, you can build both projects separately, but provide proper packaging for your library to make it easy to integrate. This approach is usually more flexible, as it gives your clients the freedom to choose when and how they want to build your library before pulling it into their build.

Related

How to add an existing lib need to be built to my own project

I'm currently working on a project in C++. I use autotools, I'm new for it BTW, to make the building system. An existing library with a makefile must be used in my project. Because it's a rarely used library, for the sake of portability I need to copy the entire sources in the my project directory and ask makefile to build the library with its own makefile before building my codes. What should I do? I have no clue how to add code in Makefile.am or somewhere like it. Any helpful answers are appreciated.
Two parts:
Build the library as recommended by the library's README or instructions. You might have to choose options to produce an acceptable flavor of shareable library.
To your project, add the output shareable library as a library for inclusion. You probably will also have to add a declarations file (.h) to it somewhere too.
It might be expedient to include the library directly into your project in (IMHO) rare cases. However, resist that urge: It usually causes trouble with symbols (namespace pollution and namimg conflicts) and messes up assumptions about how the interfaces are supposed to work. It also makes source code control more difficult.
With the recommended separation of projects (yours v. library), usually some degree of smarts are needed to conditionally rebuild the project if the library has changed. That can be done with a encapsulating makefile which first calls make the_library then calls make myproject. Or you can manually invoke the proper makefiles which would be more convenient since the library—once it is working satisfactorily—probably won't need any work.

How to use separate CMake targets for host application and any of the used libraries?

When I'm using CMake and library which also uses CMake, I add the library directory in my CMake project to allow building the library alongside my project. For example:
# add SFML library dependencies
add_subdirectory("third_party/lib/SFML")
include_directories("third_party/lib/SFML/include")
target_link_libraries(${CMAKE_PROJECT_NAME} sfml-system sfml-window sfml-graphics)
Then CMake automatically matches project Debug builds to use library Debug build, and project Release builds to use library Release build. In some cases it is useful build targets to be controlled separately for the main project and every one of the libraries used by it. For example, if I'm not interested in debugging inside the library code I will want to build in Debug mode only my code and to link it against Release version of the library, because I don't want to sacrifice additional performance. In other cases maybe I want to debug only inside one of the used libraries, if I have suspicious for bug inside it, but again for performance reasons I want to link release versions for all other libraries. Is it possible and what is the best way to achieve this behavior?
With both imported targets and dependent targets from the same build tree, you will always get the behavior you described, that each configuration uses its own matching build of the library. Messing with this means fiddling with CMake's internals, so I'd advise against it.
If you want to link against a specific version of the library, the most robust way is to use find_library. Note that this will only work if the library dependency is already available in its binary form at configure time. That is, you can no longer build the dependency as part of the dependent project.
If that is not an option, consider using ExternalProject_Add to build the dependency and specify the location of the dependency binary manually.
All in all, your current approach is the most convenient one, so only change this if performance of the dependency's debug build is a real problem. Also note that while mixing debug and release builds is mostly fine for C libraries, it can easily break for C++ libraries, especially if you have standard library types on the interfaces.

The dependencies between opencv libraries

When we build the opencv library, either in a dynamic way or in a static way, we will produce several separated libraries. Take the 2.48 version for example, we will have
opencv_core248 opencv_imgproc248 zlib IlmImf comctl32 opencv_highgui248 libpng
and so on. So my question here is clearly there are some dependencies between these libraries, for example, if I want to invoke opencv_core248 and opencv_imgproc24 library in a project, I have link errors. Then, if I add zlib library, the compilation error will be solved.
Question: I want to ask a very general question: how can I know the dependencies between all the libraries insider opencv? Are there some documents I can follow? Thanks.
I don't think there is a document listing all the dependencies between the OpenCV libraries.
However I can suggest two methods to find out these dependencies:
Using Dependency Walker, a free tool allowing to analyze executables and DLLs. For instance, if you open opencv_calib3dXXX.DLL (where XXX represents your OpenCV version), you'll see that it requires opencv_coreXXX.dll, opencv_flannXXX.dll, opencv_imgprocXXX.dll and opencv_features2dXXX.dll and some system DLLs.
Using the project structure generated by CMake, a free tool for cross-platform compilation which is used for compliing OpenCV from sources. For instance, if I generate the project structure for VS2010 and open it, I can right-click on the project associated to opencv_calib3d and view the project dependencies.
I mentionned the tools I know and use for Windows, but equivalent tools must also exist for other platforms.

External library dependencies in a c++ project

I am currently trying to setup a project in C++, b that uses the luabind library. Unfortunately on my distro, namely Arch, this library isn't in the official repos and the one in the AUR is out of date and fails to compile.
Considering that I need the library only for this project I thought that I could make a sandboxed environment similar to python's virtualenv by building the library then installing(copying) the include files and resulting binaries in 2 sub-directories of my project called include and lib, respectively which I'll add to the linking and include paths when building. I understand why distributing the libraries with your project is bad: security and bug fixes in the meantime for example. However distributing DLLs is almost universally done on Windows(which I might do if I cross-compile) and many projects such as games on Linux tend to package their libraries to avoid inconsistencies between disrtos. Moreover if ever need a patched or forked version of a lib I doubt I'll ever find it in any official repo.
So my question is:
Is what I described above a common practice? Should I do it like this?
If not, what is the most commonly-agreed-upon solution to this problem?
NOTE: I use Cmake for build automation, if it matters
EDIT: This question slightly overlaps with mine.
Your approach is interesting, but it is not necessary for you to devise a working system because it has already been done, and luckily, you are only one step away from the solution !
Using CMake, it is easy to automate the building and linking of external source code, using the ExternalProject module.
See http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html for useful information.
This approach has several advantages:
you do not have to include the library's source code in your repository
you can point to the specific version/git tag of the library that you know works with your software OR the latest release if you are certain it will not break compatibility
you do not have to write a complete CMakeLists.txt file to build a possibly complex code base
you can eventually configure the external project to build as a static library so you will not have to distribute shared libraries
you can even completely bypass this if not necessary, by trying to detect a working version of the library on your system with the usual find_package call, and only fall back to building it as an external project if not found

Boost C++ libraries installation

I have just downloaded the boost libraries from the boost website and extracted them to my desktop. I was hoping to just have a quick look at them and have them installed on my machine and perhaps use them in the future when I am more accustomed to C++.
When I extracted it, I was confused with all of the extracted files. There is all of the headers in the boost directory but tutorials mention running bootstrap.bat (I'm using Windows).
So I am asking this: do I simply extract the headers to my compilers include directory like normal to get boost up and running or do I need to do something else?
As I understand it from searching about, apparently "most" of boost is just templates and can be used simply by including the headers, but what about the rest?
Am I totally barking up the wrong tree?
Thanks for any help
Since you mentioned you run Windows, take a look at this automated installer:
► http://www.boostpro.com/download/
Also, some general advice:
do I simply extract the headers to my compilers include directory
No! Do not pollute your compiler's includes with third-party includes; make a separate directory specifically for a particular library. You'll then need to tell your specific IDE in what directory it can find the library headers.
I usually use boostpro's installer, it is less work. I vaguely remember having to set up the BOOST_ROOT environment variable on one of my systems to use it.
The libraries that contained compiled source should be included in the installer.
If you don't use the installer (or don't set up your build correctly), and try to use the libraries that need it you will likely get some linker errors when you try and compile your program. Usually if you take those linker errors and plop them in google it tells you pretty quick which libraries you need to include in your build system. I use CMake for that and have been very happy..
Just add the root boost directory to include paths of your compiler/IDE (so if you have Boost extracted to C:\Boost, the compiler will use that path, not C:\Boost\boost).
Don't do any copying of the boost folder to your compiler's include directory, because it may make upgrading Boost harder in the future.
Also if you plan to use any of boost's compiled libraries, add Boost's lib directory to compiler's library search paths. Configuring the compiling step is a matter of putting the right toolset parameter to boost's build tool. If you have your command line environment configured properly, bootstrap should run and compile the builder without any problems, and the Boost builder should properly detect your toolset, so no parameters will be necessary.
As you do such configuration only once every time you do a clean install of your favorite compiler, it's not as hard or daunting as it seems.