Some libraries have conditional builds enabled by preprocessor defines, say, #ifdef ENABLE_THIS_FEATURE. How do we enable features like this with Homebrew?
With vcpkg, we could tweak CMake through vcpkg facilities. It's unclear to me how to do so with Homebrew.
Related
I am trying to build the following project https://github.com/whoshuu/cpr#cmake into my project by following their instructions for CMake reproduced below:
include(FetchContent)
FetchContent_Declare(cpr GIT_REPOSITORY https://github.com/whoshuu/cpr.git GIT_TAG c8d33915dbd88ad6c92b258869b03aba06587ff9) # the commit hash for 1.5.0
FetchContent_MakeAvailable(cpr)
My project already had some other libraries linked with the main target so I included this new library as follows:
target_link_libraries(my_target PRIVATE cpr::cpr PUBLIC other_libraries)
The problem with this is that the warnings from building the cpr library are preventing the project from building. I would like to suppress these warnings. I have tried adding the SYSTEM keyword as recommended here: How to suppress GCC warnings from library headers? so the code would look as follows:
target_link_libraries(my_target PRIVATE SYSTEM cpr::cpr PUBLIC other_libraries)
but this did not help. Are there other methods to suppress warnings from external libraries in CMake? If it helps, I am using C++-17 g++-11 and Ninja.
The only way around I could find was to disable warnings using compiler pragmas within the code:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weverything"
#include <cpr/cpr.h>
#pragma GCC diagnostic pop
This is compiler dependent. If you use clang, simply replace "GCC" by "clang". On Visual Studio, use pragma warning... This can be made portable with macros, have a look at this article.
Our project builds with CMake on several platforms, including Windows, Linux and cross-compilation on some embedded OSes, described with custom CMake toolchain files.
In case of cross-compilation, we have to maintain sets of preprocessor macros.
It is reflected in CMakeLists.txt in the following fashion.
File embedded_os1.toolchain.cmake
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)
set(CMAKE_C_COMPILER /path/to/cross-compiler)
# blah-blah-blah
set(embedded_OS1 TRUE)
... and we have similar files for other embedded OSes.
File CMakeLists.txt
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
if(embedded_OS1)
add_definitions(-Dmacro1 -Dmacro2)
elseif(embedded_OS2)
add_definitions(-Dmacro3 -Dmacro4)
elseif(embedded_OS3)
add_definitions(-Dmacro1 -Dmacro4)
endif()
I'd like to perform some kind of automatic checking that all preprocessor macros are set correctly.
I can easily do it with unit-tests on Windows and Linux.
But there is no possibility to compile and run executable files on embedded OSes, I can compile only static libs, that are then signed, put in a firmware images, etc, etc. And all I have on PC besides library is the JSON file with compiler calls, generated by EXPORT_COMPILE_COMMANDS.
What could you suggest?
I'd do it with #warning macro and check the compilation output with bash of whatever. Then you can set Werror for these files and get compile-time check. Or simply use #error (thanks to KamilCuk)
Another way is to dig into check binaries that help to see if the toolchain has threading or something else.
Is it possible to specify the BOOST_LIB_BUILDID for an already built Boost C++ library with the CMake FindBoost module?
I am supposed to use a Boost library that is built for x86 and x64 in the same directory, whereas the x64 version has been built with the following b2 arguments:
-layout=versioned --buildid=x64
I couldn't find anything related to this in the official CMake documentation.
When using a library outside of the project, e.g. boost or Guidelines Support Library, how should we specify the paths related to that library?
add the paths to the LIBRARY_PATH and CPLUS_INCLUDE_PATH environment variables used by the compiler.
define a environment variable (e.g. GSL_PATH) and then
add -L and -isystem flags in the makefile of each project.
Is there a best practice for this? What are the advantages and disadvantages of each approach? Consider the need to compile and use the project on other systems.
For various reasons the libraries are installed in a custom path
You can use cmake for configuring your project
And find boost and gsl with cmake
https://cmake.org/cmake/help/v3.2/module/FindGSL.html
https://cmake.org/cmake/help/v3.0/module/FindBoost.html
Example for boost
Say I am creating a project that uses a certain library and I have to provide the path for that library while linking. In the command line or makefile I might have:
g++ ... -L/path/to/mylibrary
I'm also going to send this project to someone else who wants to use it. The path on their system might not necessarily be the same as mine. They could be using a different file path all together.
How do I make sure that the path to the library works for both my computer and the recipient of my project?
This is the role of a build system or build configuration tool. There are many of those around. The main one is probably CMake as it has a very extensive feature set, cross-platform, and widely adopted. There are others like Boost.Jam, autoconf, and others.
The way that these tools will be used is that they have automated scripts for looking into the file-system and finding the headers or libraries that you need, i.e., the dependencies required to compile your code. They can also be used to do all sorts of other fancy things, like checking what features the OS supports and reconfiguring the build as a consequence of that. But the point is, you don't hard-code any file-paths into the build configuration, everything is either relative to your source folder or it is found automatically by the build script.
Here is an example CMake file for a project that uses Boost:
cmake_minimum_required (VERSION 2.8)
project (ExampleWithBoost)
find_package(Boost 1.46 COMPONENTS thread program_options filesystem REQUIRED)
# Add the boost directory to the include paths:
include_directories(SYSTEM ${Boost_INCLUDE_DIR})
# Add the boost library directory to the link paths:
link_directories(${Boost_LIBRARY_DIRS})
# Add an executable target (for compilation):
add_executable(example_with_boost example_with_boost.cpp)
# Add boost libraries to the linking on the target:
target_link_libraries(example_with_boost ${Boost_LIBRARIES})
The find_package cmake function is simply a special script (specialized for Boost, and installed with CMake) that finds the latest version of boost (with some minimal version) installed on the system, and it does so based on the file-name patterns that the library uses. You can also write your own equivalents of find_package, or even your own package finders, using the functions that CMake provides for searching the file system for certain file-name patterns (e.g., regular expressions).
As you see, the build configuration file above only refer directly to your source files, like "example_with_boost.cpp", and it's only relative to the source folder. If you do things right, the configuration scripts will work on virtually any system and any OS that CMake supports (and that the libraries you depend on support). This is how most major cross-platform projects work, and when you understand how to work with these systems, it's very powerful and very easy to use (in general, far easier to use and trouble-free than build configurations that you do by point-and-click within IDE menus like in Visual Studio).
You can use premake that generates cross platform makefiles: Visual Studio, Gcc and others
http://industriousone.com/what-premake
CMake is another alternative
http://www.cmake.org/
I'm not sure if there's a single universal way of doing this, but people often provide different config files and let the main Makefile detect which one to include: linux.make, darwin.make, cygwin.make etc.
there are also various tools like CMake that allow to automate this, but all in all it's just scripting that hides the system-dependency from the developer.