How to properly link libraries from vcpkg in a CMake project - cmake

I'm testing vcpkg (on macOS) with a CMake project.
Since not all vcpkg packages have CMake find modules, I'm trying with a package that doesn't have one: libuuid
This is the directory tree relative to libuuid I can see from the vcpkg root:
$ find packages/libuuid_x64-osx
packages/libuuid_x64-osx
packages/libuuid_x64-osx/include
packages/libuuid_x64-osx/include/uuid
packages/libuuid_x64-osx/include/uuid/uuid.h
packages/libuuid_x64-osx/BUILD_INFO
packages/libuuid_x64-osx/lib
packages/libuuid_x64-osx/lib/libuuid.a
packages/libuuid_x64-osx/CONTROL
packages/libuuid_x64-osx/debug
packages/libuuid_x64-osx/debug/lib
packages/libuuid_x64-osx/debug/lib/libuuid.a
packages/libuuid_x64-osx/share
packages/libuuid_x64-osx/share/libuuid
packages/libuuid_x64-osx/share/libuuid/copyright
Example program:
#include <iostream>
#include <uuid/uuid.h>
int main(int argc, char **argv)
{
std::cout << "Hello, world!" << std::endl;
return 0;
}
Example CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(vcpkg_example_project)
add_executable(app app.cpp)
target_link_libraries(app uuid)
If I understand correctly, vcpkg's philosophy is not to provide missing CMake find-modules, but to simply have #include <libfoo/foo.h> work out of the box. And in fact the example above compiles fine. But fails to find -luuid:
$ cmake -DCMAKE_TOOCHAIN_FILE=/Users/me/Dev/vcpkg/scripts/buildsystems/vcpkg.cmake ..
...
$ cmake --build .
Scanning dependencies of target app
[ 50%] Building CXX object CMakeFiles/app.dir/app.cpp.o
[100%] Linking CXX executable app
ld: library not found for -luuid
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [app] Error 1
make[1]: *** [CMakeFiles/app.dir/all] Error 2
make: *** [all] Error 2
What am I missing?
Also, I see there is a installed/x64-osx/lib/libuuid.a. Shouldn't installed/x64-osx/lib automatically added as lib path by the toolchain cmake script?

I'd make a target out of uuid. From what you describe, most probably an Interface Library called uuid. You can add_target_include_directories and target_link_libraries for the headers and any libraries, and then add it to the rest of your project.
So something like this:
add_library(uuid INTERFACE)
if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
find_library(LIBUUID uuid "${CMAKE_CURRENT_SOURCE_DIR}/packages/libuuid_x64-osx/lib/")
else()
find_library(LIBUUID uuid "${CMAKE_CURRENT_SOURCE_DIR}/packages/libuuid_x64-osx/debug/lib/")
endif()
target_link_libraries(uuid INTERFACE "${LIBUUID}")
target_include_directories(uuid SYSTEM INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/packages/libuuid_x64-osx/include")
I'd then do an add_subdirectory to the library's folder and link to uuid

Related

Problems building MRPT program with cmake

I hate cmake, as I always seem to spend more time trying to get cmake to compile and build a program than I do writing and debugging the program cmake is supposed to be building.
Anyway, the latest problem is this.
I have some code that starts ...
#include <mrpt/obs/CObservationBatteryState.h>
#include <mrpt/obs/CObservationComment.h>
#include <mrpt/obs/CObservation2DRangeScan.h>
#include <mrpt/maps/CSimplePointsMap.h>
#include <mrpt/comms/CSerialPort.h>
#include <mrpt/poses/CPose3D.h>
#include <mrpt/system/os.h>
a fairly simple CMakeLists.txt that looks like...
project(some_sort_of_name)
cmake_minimum_required(VERSION 3.8)
find_package(MRPT COMPONENTS obs maps comms )
if(CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_BUILD_TYPE MATCHES "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
add_executable(lidar lidar.c)
add_executable(lidar_obs lidar_obs.cpp)
target_link_libraries(lidar_obs mrpt::obs mrpt::maps)
And the compilation fails with...
[ 50%] Built target lidar
[ 75%] Building CXX object CMakeFiles/lidar_obs.dir/lidar_obs.cpp.o
/home/mike/work/minipupper/lidar/lidar_obs.cpp:5:10: fatal error: mrpt/comms/CSerialPort.h: No such file or directory
5 | #include <mrpt/comms/CSerialPort.h>
So it is happy with compiling & building "lidar" which is a simple 'C' program with no calls to MRPT, but when it comes to compiling lidar_obs, it is happy to find the include files for obs and maps but not comms.
The include files are there, i.e.
$ ls /usr/include/mrpt/comms/include/mrpt
comms comms.h
$ ls /usr/include/mrpt/comms/include/mrpt/comms
CClientTCPSocket.h CInterfaceFTDI.h CSerialPort.h CServerTCPSocket.h net_utils.h nodelets.h registerAllClasses.h
just like e.g. obs & maps
$ ls /usr/include/mrpt/obs
include
$ /usr/include/mrpt/obs/include
mrpt
$ ls /usr/include/mrpt/obs/include/mrpt
maps obs obs.h
$ ls /usr/include/mrpt/obs/include/mrpt/maps
CMetricMapEvents.h CMetricMap.h CSimpleMap.h metric_map_types.h TMetricMapInitializer.h TMetricMapTypesRegistry.h
What is going on with cmake ? How does it find some files and not others.
You were missing the link command to also include the mrpt-comms library:
target_link_libraries(lidar_obs mrpt::obs mrpt::maps mrpt::comms)
# ^^^^^^^^^^^
CMake with exported libraries work like that: "linking" an imported cmake target, also includes the "-I" flags (for #includes) apart of the link -l flags themselves.

CMake Cross Compilation secondary dependencies

I have a program that compiles on my target machine (NVIDIA Jetson). Now I am trying to cross compile the same program on my laptop. I have a cross compiler and cloned the Jetson to use as a sysroot. I was following this guide from NVIDIA. My program compiles, but fails at a linking step. I'm linking against a library (protobuf) and the linker can't find the dependencies of the library. I have produced a minimal example that demonstrates this.
main.cpp:
#include <google/protobuf/util/json_util.h>
int main(int argc, char* argv[])
{
google::protobuf::util::JsonPrintOptions jsonOptions;
jsonOptions.always_print_enums_as_ints = true;
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(Test)
find_package(Protobuf REQUIRED)
add_executable(Test main.cpp)
target_include_directories(Test PRIVATE ${PROTOBUF_INCLUDE_DIRS})
target_link_libraries(Test PRIVATE ${PROTOBUF_LIBRARIES})
On my target computer CMake generates and builds this fine, but when cross compiling on my laptop CMake generates the makefiles, and the build step fails with the error:
[ 50%] Building CXX object CMakeFiles/Test.dir/main.cpp.o
[100%] Linking CXX executable Test
/home/lhahn/Documents/CrossCompilation/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/../../../../aarch64-linux-gnu/bin/ld: warning: libz.so.1, needed by /home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so, not found (try using -rpath or -rpath-link)
/home/lhahn/Documents/CrossCompilation/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/../../../../aarch64-linux-gnu/bin/ld: warning: libm.so.6, needed by /home/lhahn/Documents/CrossCompilation/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/../lib/gcc/aarch64-linux-gnu/7.3.1/../../../../aarch64-linux-gnu/lib/../lib64/libstdc++.so, not found (try using -rpath or -rpath-link)
/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so: undefined reference to `deflateInit2_'
/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so: undefined reference to `deflate'
/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so: undefined reference to `deflateEnd'
/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so: undefined reference to `inflate'
/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so: undefined reference to `inflateInit2_'
/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/local/lib/libprotobuf.so: undefined reference to `inflateEnd'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/Test.dir/build.make:98: Test] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/Test.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
The required library (ZLIB) exists in my sysroot (/home/lhahn/Documents/CrossCompilation/Images/jetson/usr/lib/aarch64-linux-gnu/libz.so), but the linker can't find it.
My toolchain file is
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_SYSROOT /home/lhahn/Documents/CrossCompilation/Images/jetson)
set(CMAKE_C_COMPILER /home/lhahn/Documents/CrossCompilation/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /home/lhahn/Documents/CrossCompilation/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH /home/lhahn/Documents/CrossCompilation/Images/jetson)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
What do I need to tell CMake so that the linker can find these secondary dependencies?
I figured out my problem. When I cloned the image and mounted it on my laptop I broke all of the symlinks in the cloned image, such as libz.so which is why cmake couldn't find them. When I fixed the symlink cmake went on to complain about the next broken symlink in the same manner. I think there are too many symlinks to fix them manually, but at least now I know what went wrong.

How to import zeromq libraries in cmake?

I'm just starting to learn how to work with zeromq libraries and using them in different C++ projects.
The sample code that I wrote (actually copied from there tutorials)is this:
// file: main.cpp
// Hello World client in C++
// Connects REQ socket to tcp://localhost:5555
// Sends "Hello" to server, expects "World" back
//
#include <zmq.hpp>
#include <string>
#include <iostream>
int main ()
{
// Prepare our context and socket
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_REQ);
std::cout << "Connecting to hello world server…" << std::endl;
socket.connect ("tcp://localhost:5555");
// Do 10 requests, waiting each time for a response
for (int request_nbr = 0; request_nbr != 10; request_nbr++) {
zmq::message_t request (5);
memcpy (request.data (), "Hello", 5);
std::cout << "Sending Hello " << request_nbr << "…" << std::endl;
socket.send (request);
// Get the reply.
zmq::message_t reply;
socket.recv (&reply);
std::cout << "Received World " << request_nbr << std::endl;
}
return 0;
}
and by building the output of this file with the command below:
g++ main.cpp -o test -lzmq
the file will be generated with no problem.
The problem that I have is that I want to build the file using CMake.Thus, I've written a CMakeLists.txt file as below:
cmake_minimum_required(VERSION 3.6)
project(test2)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lzmq")
set(SOURCE_FILES main.cpp)
add_executable(test2 ${SOURCE_FILES})
The part that I thought will be enough to build the program is -lzmq but even with that piece included, I get the following error messages:
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::error_t::error_t()':
/usr/include/zmq.hpp:62: undefined reference to `zmq_errno'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::error_t::what() const':
/usr/include/zmq.hpp:66: undefined reference to `zmq_strerror'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::message_t()':
/usr/include/zmq.hpp:107: undefined reference to `zmq_msg_init'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::message_t(unsigned long)':
/usr/include/zmq.hpp:114: undefined reference to `zmq_msg_init_size'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::~message_t()':
/usr/include/zmq.hpp:129: undefined reference to `zmq_msg_close'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::message_t::data()':
/usr/include/zmq.hpp:180: undefined reference to `zmq_msg_data'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::context_t::context_t(int)':
/usr/include/zmq.hpp:204: undefined reference to `zmq_init'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::context_t::~context_t()':
/usr/include/zmq.hpp:225: undefined reference to `zmq_term'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::socket_t(zmq::context_t&, int)':
/usr/include/zmq.hpp:251: undefined reference to `zmq_socket'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::close()':
/usr/include/zmq.hpp:283: undefined reference to `zmq_close'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::connect(char const*)':
/usr/include/zmq.hpp:314: undefined reference to `zmq_connect'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::send(zmq::message_t&, int)':
/usr/include/zmq.hpp:321: undefined reference to `zmq_send'
/usr/include/zmq.hpp:324: undefined reference to `zmq_errno'
CMakeFiles/test2.dir/main.cpp.o: In function `zmq::socket_t::recv(zmq::message_t*, int)':
/usr/include/zmq.hpp:331: undefined reference to `zmq_recv'
/usr/include/zmq.hpp:334: undefined reference to `zmq_errno'
Should I set another kind of variable in the CMake file or have I installed the library in a wrong directory? or is there anything else that I should have mentioned?
and The system witch I'm working on is Ubuntu 14.04
CMake doesn't include direct support for 0mq and 0mq doesn't include direct support for CMake. But, 0mq does support pkg-config and we can use this to help us. Since you mentioned that you're on Ubuntu 14.04, make sure you've done sudo apt-get install libzmq3-dev to install the 0mq libraries, headers, and the pkg-config .pc file.
Then use the following CMakeLists.txt which I've modified from your version above. (I've commented all my changes inline.)
## i have cmake 3.5
cmake_minimum_required(VERSION 3.5)
project(test2)
## use this to globally use C++11 with in our project
set(CMAKE_CXX_STANDARD 11)
## load in pkg-config support
find_package(PkgConfig)
## use pkg-config to get hints for 0mq locations
pkg_check_modules(PC_ZeroMQ QUIET zmq)
## use the hint from above to find where 'zmq.hpp' is located
find_path(ZeroMQ_INCLUDE_DIR
NAMES zmq.hpp
PATHS ${PC_ZeroMQ_INCLUDE_DIRS}
)
## use the hint from above to find the location of libzmq
find_library(ZeroMQ_LIBRARY
NAMES zmq
PATHS ${PC_ZeroMQ_LIBRARY_DIRS}
)
set(SOURCE_FILES main.cpp)
add_executable(test2 ${SOURCE_FILES})
## add the include directory to our compile directives
target_include_directories(test2 PUBLIC ${ZeroMQ_INCLUDE_DIR})
## at the 0mq library to our link directive
target_link_libraries(test2 PUBLIC ${ZeroMQ_LIBRARY})
Now you can make your project.
❯ make
[ 50%] Building CXX object CMakeFiles/test2.dir/main.cpp.o
[100%] Linking CXX executable test2
[100%] Built target test2
If you want to see what's happening under the hood, do a verbose make.
❯ make VERBOSE=1
/usr/bin/cmake -H/home/nega/foo -B/home/nega/foo/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/nega/foo/build/CMakeFiles /home/nega/foo/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/nega/foo/build'
make -f CMakeFiles/test2.dir/build.make CMakeFiles/test2.dir/depend
make[2]: Entering directory '/home/nega/foo/build'
cd /home/nega/foo/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/nega/foo /home/nega/foo /home/nega/foo/build /home/nega/foo/build /home/nega/foo/build/CMakeFiles/test2.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/nega/foo/build'
make -f CMakeFiles/test2.dir/build.make CMakeFiles/test2.dir/build
make[2]: Entering directory '/home/nega/foo/build'
[ 50%] Building CXX object CMakeFiles/test2.dir/main.cpp.o
/usr/bin/c++ -std=gnu++11 -o CMakeFiles/test2.dir/main.cpp.o -c /home/nega/foo/main.cpp
[100%] Linking CXX executable test2
/usr/bin/cmake -E cmake_link_script CMakeFiles/test2.dir/link.txt --verbose=1
/usr/bin/c++ CMakeFiles/test2.dir/main.cpp.o -o test2 /usr/lib/x86_64-linux-gnu/libzmq.so
make[2]: Leaving directory '/home/nega/foo/build'
[100%] Built target test2
make[1]: Leaving directory '/home/nega/foo/build'
/usr/bin/cmake -E cmake_progress_start /home/nega/foo/build/CMakeFiles 0
If you look at the compile line, you'll notice that
C++11 support was added (with the -std=gnu++11 flag)
There's no -I/path/to/zmq flag. That's because Ubuntu dumps zmq.hpp in to /usr/include and CMake is smart enough to know that is a default path, so it does nothing
If you look at the link line, you'll notice that libzmq.so has been included via it's full path. Some people don't like that (myself included) and prefer -L/lib/dir -lmylib instead. Using the full path is "the CMake way", and you'll actually come to appreciate it as you grow with CMake and use it for larger and more complicated projects (you still might not like it though.)
Also note, that since you're on Ubuntu we could have cheated and used dpkg -L libzmq3-dev to find the locations of the files we're interested in then added them to your original CMAKE_CXX_FLAGS line, but that's cheating and more importantly, not portable.
A cmake config file has been added to libzmq github repository Jan 7, 2017 here.
This is not included in the latest release (4.2.1) yet, but I belive it should be in the next release.
I have installed the head version using cmake and then installed cppzmq, which uses find_package(ZeroMQ REQUIRED) to locate libzmq. All worked like a charm.
EDIT: The cmake config file is included in release 4.2.2 here. Then it was moved to directory builds/cmake at release 4.2.4. I didn't test it again but find_package(ZeroMQ REQUIRED) should just work since ibzmq 4.2.2.
This works as well
cmake_minimum_required(VERSION 3.6)
project(test)
add_executable(c main.cpp)
target_link_libraries(c zmq)

Unable to link against Boost.Python on OS X

I am trying to build a really trivial example with Boost.Python. I have installed boost and boost-python with homebrew. I am using python 3.4.3 and boost 1.59. My OS is El Capitan.
Boost.Python was installed with python3 like this:
brew install boost-python --with-python3
I have 3 files:
/* greet.hpp */
#ifndef BOOSTPYTHONHELLOWORLD_GREET_HPP
#define BOOSTPYTHONHELLOWORLD_GREET_HPP
char const* greet();
#endif //BOOSTPYTHONHELLOWORLD_GREET_HPP
/* greet.cpp */
#include "greet.hpp"
char const* greet()
{
return "Hello world";
}
/* greet_ext.cpp */
#include "greet.hpp"
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(greet_ext)
{
using namespace boost::python;
def("greet", greet);
}
My CMakeLists.txt file looks like this:
cmake_minimum_required(VERSION 3.3)
project(BoostPythonHelloWorld)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(PYTHON_LIBRARY "/usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/lib/libpython3.4m.dylib")
set(PYTHON_INCLUDE_DIR "/usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/include/python3.4m")
FIND_PACKAGE(PythonLibs 3.4 REQUIRED)
FIND_PACKAGE(Boost COMPONENTS python)
if(NOT WIN32)
add_definitions(-DBOOST_ALL_DYN_LINK=1)
add_definitions(-DBOOST_TEST_DYN_LINK)
endif()
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
add_library(greet SHARED greet.cpp)
add_library(greet_ext SHARED greet_ext.cpp)
target_link_libraries(greet_ext greet)
target_link_libraries(greet_ext ${PYTHON_LIBRARIES})
target_link_libraries(greet_ext ${Boost_LIBRARIES})
set_target_properties(greet_ext PROPERTIES PREFIX "")
When I run CMake it finds all the correct python libraries (because I specified them manually as you can see in the file above).
During build I get the following link error:
Scanning dependencies of target greet
[ 25%] Building CXX object CMakeFiles/greet.dir/greet.cpp.o
[ 50%] Linking CXX shared library libgreet.dylib
[ 50%] Built target greet
Scanning dependencies of target greet_ext
[ 75%] Building CXX object CMakeFiles/greet_ext.dir/greet_ext.cpp.o
[100%] Linking CXX shared library greet_ext.dylib
Undefined symbols for architecture x86_64:
"boost::python::detail::init_module(PyModuleDef&, void (*)())", referenced from:
_PyInit_greet_ext in greet_ext.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [greet_ext.dylib] Error 1
make[1]: *** [CMakeFiles/greet_ext.dir/all] Error 2
make: *** [all] Error 2
Anyone have any idea why this is happening?
EDIT
If I link against Python 2.7 it works, which means boost-python was built against python 2.7 instead of 3.4, even though I specified the --with-python3 options..
So, the questions is, how to build boost-python against python 3.4?
The solution I am currently using is to reinstall boost-python without python 2.7 support.
The steps I took were:
Uninstall boost-python if already installed: brew uninstall boost-python.
Install boost-python with python3 support but without python 2.7 support: brew install boost-python --with-python3 --without-python.
In order to use boost-python with python 3 you need to change this in your CMakeLists.txt:
FIND_PACKAGE(Boost COMPONENTS python)
to this:
FIND_PACKAGE(Boost COMPONENTS python3)
That way you can recompile boost with python 2 support and still use python 3.
I'd suggest installing boost-python3 via brew.
You still need to give the minor version number as well and possibly the library path. The following worked for me:
BOOST_LIBRARYDIR=/usr/local/Cellar/boost-python3/1.67.0/lib cmake ..
with CMakeLists.txt (located in ..) containing
FIND_PACKAGE(Boost COMPONENTS python36)
(for Boost 1.67.0 and Python 3.6, obviously).

How can I make build failure of a custom target stop the building of a dependent target in CMake?

I am using CMake to build an application and a collection of plugins.
ADD_LIBRARY (plugin_X ...)
ADD_LIBRARY (plugin_Y ...)
ADD_LIBRARY (plugin_Z ...)
ADD_CUSTOM_TARGET (all_plugins)
ADD_DEPENDENCIES (all_plugins plugin_X plugin_Y plugin_Z)
ADD_EXECUTABLE (application ...)
ADD_DEPENDENCIES (application all_plugins)
The idea is that by running make application the plugins will be built as well.
My build scripts rely on make returning an error code if the build fails, but if one of the plugins fails to build, make application will still succeed.
How can I make the build of application fail if its dependencies fail?
On my box, it works correctly.
main.c
#include <stdio.h>
int main()
{
printf("Hello world!");
}
a.c
int test(){errorhere}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
ADD_LIBRARY (plugin_X a.c)
ADD_LIBRARY (plugin_Y a.c)
ADD_LIBRARY (plugin_Z a.c)
ADD_CUSTOM_TARGET (all_plugins)
ADD_DEPENDENCIES (all_plugins plugin_X plugin_Y plugin_Z)
ADD_EXECUTABLE (application main.c)
ADD_DEPENDENCIES (application all_plugins)
Make command
cmake -G "Unix Makefiles" ..
make application; echo $?
a.c:1: error: expected ‘;’ before ‘}’ token
make[3]: *** [CMakeFiles/plugin_X.dir/a.c.o] Error 1
make[2]: *** [CMakeFiles/plugin_X.dir/all] Error 2
make[1]: *** [CMakeFiles/application.dir/rule] Error 2
make: *** [application] Error 2
2