cmake: add_dependencies does not work with external projects - c++

Consider the following CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(xyz)
include(ExternalProject)
set(EXTSRC ${CMAKE_SOURCE_DIR}/external)
ExternalProject_Add(q
GIT_REPOSITORY
"https://github.com/sftrabbit/CppSamples-Samples.git"
SOURCE_DIR ${EXTSRC}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND "")
add_executable(xyzbin
${EXTSRC}/1-common-tasks/ranges/range-iteration.cpp)
add_dependencies(xyzbin q)
I would expect that the external project files was downloaded first and then my executable target starts to be configured. However, this is not the case.
When I run "cmake .." in a build directory inside the source directory, it yields:
(usual configure stuff above ....)
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
CMake Error at CMakeLists.txt:16 (add_executable):
Cannot find source file:
/home/janberq/Desktop/cmake_problem/external/1-common-tasks/ranges/range-iteration.cpp
Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
.hxx .in .txx
CMake Error: CMake can not determine linker language for target: xyzbin
CMake Error: Cannot determine link language for target "xyzbin".
-- Generating done
-- Build files have been written to: /home/janberq/Desktop/cmake_problem/build
It seems like, cmake first tries to acquire linker language, which isn't possible in that case as I don't have source files.
I tried adding,
set_target_properties(xyzbin PROPERTIES LINKER_LANGUAGE CXX)
But it didn't work at all, unfortunately. What can I do to fix that error?
P.S. my cmake version is 3.5.2, os: ubuntu 16.10.

ExternalProject_Add adds a target. It won't do anything until you do a make.
To download the repository before configuring, you have to explicitly tell CMake to do so. Or you could create a setup.sh script downloading dependencies and (possibly) running cmake right after.

Related

Cmake can't find compiler without editing PATH

so what i am doing is that i am having 2 targets in a project, one is program for embedded device that i am crosscompiling, and the second are tests. I need to build them with 2 different compilers.
To main project i am passing arm compiler path by file toolchain.cmake and its working fine.
But right now i would like to build also the tests without having to add path to mingw64/bin to my environment variables (yes its working if i do that).
Test project is added as:
ExternalProject_Add(${UNIT_TEST_TARGET}
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test/
PREFIX ${UNIT_TEST_TARGET}
CMAKE_ARGS ${GTEST_ARGS}
BUILD_ALWAYS TRUE
INSTALL_COMMAND cmake -E echo "Skipping install step."
EXCLUDE_FROM_ALL TRUE)
So right now i would like to pass to this external project file toolchaintests.cmake which looks like :
set(CMAKE_C_COMPILER <my_path_here>/mingw64/bin/gcc.exe)
set(CMAKE_CXX_COMPILER <my_path_here>/mingw64/bin/g++.exe)
with:
list(APPEND GTEST_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/toolchaintests.cmake")
and if i do this cmake can't recognize the compilers:
-- The C compiler identification is unknown
-- The CXX compiler identification is unknown
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - failed
-- Check for working C compiler: <my_path_here>/mingw64/bin/gcc.exe
-- Check for working C compiler: <my_path_here>/mingw64/bin/gcc.exe - broken
CMake Error at C:/Program Files/CMake/share/cmake-3.24/Modules/CMakeTestCCompiler.cmake:69 (message):
The C compiler
" <my_path_here>/mingw64/bin/gcc.exe"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: <my_path_here>/out/build/tests/src/tests-build/CMakeFiles/CMakeTmp
Run Build Command(s):C:/Ninja/ninja-win/ninja.exe cmTC_a1c48 && [1/2] Building C object CMakeFiles\cmTC_a1c48.dir\testCCompiler.c.obj
FAILED: CMakeFiles/cmTC_a1c48.dir/testCCompiler.c.obj
<my_path_here>\mingw64\bin\gcc.exe -o CMakeFiles\cmTC_a1c48.dir\testCCompiler.c.obj -c <my_path_here>\out\build\tests\src\tests-build\CMakeFiles\CMakeTmp\testCCompiler.c
ninja: build stopped: subcommand failed.
Can i do this somehow else?

How do I get CMake to find my test in my C library project?

I have a project here:
https://github.com/edhartnett/ncglm
It is a small C library for reading netCDF data files from the Geostationary Lightning Mapper. I have an autotools build which works fine, and I'm trying to add a CMake build.
The directory structure is simple, there is a main directory, a src directory, and a test directory.
In the main directory I have:
# This is the main cmake file for ncglm, a library to help read the
# netCDF data files from the Global Lightning Mapper (GLM) instrument
# on GOES-16 and GOES-17.
#
# Ed Hartnett 11/10/19
# This will use any cmake between 3.1 and 3.15, preferint later
# versions with updated policies.
cmake_minimum_required(VERSION 3.1...3.15)
if (${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
# set the project name
project(ncglm VERSION 1.0)
#Add custom CMake Module
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/"
CACHE INTERNAL "Location of our custom CMake modules.")
# Find netCDF.
include(FindNetCDF)
include_directories("${NETCDF_INCLUDES}")
# Create a config.h.
configure_file(config.h.cmake.in config.h)
# Turn on testing.
enable_testing()
include(CTest)
# Build in this subdirectory.
add_subdirectory(src test)
In the src subdirectory I have:
# This is the cmake file for the src directory of the ncglm library.
# Ed Hartnett 11/10/19
# Build the ncglm library.
add_library(ncglm glm_read.c goes_glm.h glm_data.h)
In the test directory I have:
# This is the cmake build file for the test directory of the ncglm library.
#
# Ed Hartnett 11/10/19
enable_testing()
add_test(NAME tst_glm_read COMMAND tst_glm_read)
build_test(tst_glm_read)
add_sh_test(nc_test4 run_glm_tests)
When I build, I get:
ed#mikado:~/ncglm/build$ cmake -DNETCDF_INCLUDES=/usr/local/netcdf-c-4.7.2_hdf5-1.10.5/include -DNETCDF_LIBRARIES=/usr/local/netcdf-c-4.7.2_hdf5-1.10.5/lib .. && make test
-- The C compiler identification is GNU 7.4.0
-- The CXX compiler identification is GNU 7.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found NetCDF: /usr/local/netcdf-c-4.7.2_hdf5-1.10.5/lib
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ed/ncglm/build
Running tests...
Test project /home/ed/ncglm/build
No tests were found!!!
How come cmake is not trying to build or run my test?
add_subdirectory(src test)
This is invalid / it doesn't do what you think it does. What you want to do is:
add_subdirectory(src)
add_subdirectory(test)
The cmake website is down right now, I can't link to it. From memory the add_subdirectory(src test) reads CMakeLists.txt in the src source directory, but builds the sources in the test build directory, the test is created inside the build directory inside CMAKE_CURRENT_BUILD_DIR. To add two source directories, you have to use two add_subdirectory().

How to make cmake output to the "build" directory?

I'm using cmake to compile a C++ project, and I want cmake to generate all the output files(metafiles like Makefile used to create binaries) in the build folder. I've checked all the answers in How do I make cmake output into a 'bin' dir?, none of them worked for me(suprisingly!). Files are generated in the root folder instead of in the build folder, what's wrong here? I guess I must have missed something.
Code Structure
➜ cmake-test tree .
.
├── CMakeLists.txt
└── hello.cpp
0 directories, 2 files
CMakeLists.txt
# Specify the minimum version for CMake
cmake_minimum_required(VERSION 3.11)
# Project's name
project(hello)
# Set the output folder where your program will be created
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# The following folder will be included
include_directories("${PROJECT_SOURCE_DIR}")
add_executable(hello ${PROJECT_SOURCE_DIR}/hello.cpp)
Build Commands and Outputs
➜ cmake-test cmake .
-- The C compiler identification is GNU 8.2.0
-- The CXX compiler identification is GNU 8.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/searene/CLionProjects/cmake-test
➜ cmake-test ls
bin CMakeCache.txt CMakeFiles cmake_install.cmake CMakeLists.txt hello.cpp Makefile
cmake version
➜ cmake-test cmake --version
cmake version 3.11.4
CMake suite maintained and supported by Kitware (kitware.com/cmake).
OS
Linux
The usual way to do this, rather than changing variables to set the path, is simply to create the output directory, change to it, and run cmake from there. So instead of cmake . you usually have cmake .. or similar.
I understand the initial impulse to say "But I expect my build system to write output somewhere else." But CMake is not usually used in the way you were initially expecting, and other people who run your CMake build won't expect what you were expecting, so it's probably best to just use the built-in, default behavior, which is to put the output wherever cmake was run.
Put another way: You are fighting against the tool. Don't do that.
Disclaimer: I recommend going with #john-zwinck's answer.
By default, cmake uses the current working directory as build directory and whatever path you provide as source directory. So the normal way of achieving your goal is
create the build directory (mkdir build)
go there (cd build)
call cmake with the source dir as argument (cmake path/to/source)
BUT there is another way, as far as I know not documented in the cmake docs and only kept for compatibility reasons or internal usage, that some people are using. The -B and -H flags
cmake -Hpath/to/source -Bpath/to/build
or even from the source dir
cmake . -Bbuild
Important: no space after -B.
CMake 3.19.1 (not sure how about older ones) has following option (from docs):
cmake [<options>] -S <path-to-source> -B <path-to-build>
Uses as the build tree and as the
source tree. The specified paths may be absolute or relative to the
current working directory. The source tree must contain a
CMakeLists.txt file. The build tree will be created automatically if
it does not already exist. For example:
cmake -S src -B build

Issue with CMake and find_package

I'm very new to CMake, and I try to write a CMake file for my project.
My project consists of .h and .cpp files, generating an executable, and using the SFML library.
I've installed the findSFML script, I use the find_package function of CMake:
cmake_minimum_required(VERSION 2.6)
# Projet name
project("Witch_Blast")
file(
GLOB_RECURSE
source_files
src/*
)
add_executable(
"Witch_Blast"
${source_files}
)
# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2.1 REQUIRED system window graphics audio)
target_link_libraries(Witch_Blast ${SFML_LIBRARIES})
I try to generate a Windows Code::Blocks project.
It finds the library and generate projects files.
My problem:
It won't compile because it won't find the SFML header files, and I cannot modify the project setting...
What have I done wrong ?
Thanks !
EDIT:
CMake generation output:
-- The C compiler identification is GNU 4.7.1
-- The CXX compiler identification is GNU 4.7.1
-- Check for working C compiler: C:/Program Files (x86)/CodeBlocks/MinGW/bin/gcc.exe
-- Check for working C compiler: C:/Program Files (x86)/CodeBlocks/MinGW/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/CodeBlocks/MinGW/bin/g++.exe
-- Check for working CXX compiler: C:/Program Files (x86)/CodeBlocks/MinGW/bin/g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found SFML 2.1 in C:/Lib/SFML-2.1_TDM/include
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/Seb/Dev/Witch Blast/cmakedir
message(SFML_LIBRARIES):
debugC:/Lib/SFML-2.1_TDM/lib/libsfml-system-d.aoptimizedC:/Lib/SFML-2.1_TDM/lib/
libsfml-system.adebugC:/Lib/SFML-2.1_TDM/lib/libsfml-window-d.aoptimizedC:/Lib/S
FML-2.1_TDM/lib/libsfml-window.adebugC:/Lib/SFML-2.1_TDM/lib/libsfml-graphics-d.
aoptimizedC:/Lib/SFML-2.1_TDM/lib/libsfml-graphics.adebugC:/Lib/SFML-2.1_TDM/lib
/libsfml-audio-d.aoptimizedC:/Lib/SFML-2.1_TDM/lib/libsfml-audio.a
(But it's not a linker error, it's an include path error)
You need to add the header directory to you compiler's path.
include_directories(${SFML_INCLUDE_DIR})
All variables find_package(SFML) sets can be found here.

Error building program with MySQL Connector C++

I have the following compile time error I cannot find the reason of:
fatal error: mysql_connection.h: No such file or directory
I am using cmake, and these are the CMakeLists.txt files:
# Top level CMakeLists.txt - MyProg
cmake_minimum_required (VERSION 2.6)
set (PROJECT_NAME "MyProg")
### Out-of-tree directories
set (UTILITIES_DIR "~/utilities")
### Configure header file to pass CMake's settings to the source code
configure_file (
"Config.h.in"
"${PROJECT_SOURCE_DIR}/Config.h"
)
add_subdirectory (src "${CMAKE_CURRENT_BINARY_DIR}/obj")
add_subdirectory (${UTILITIES_DIR} "${CMAKE_CURRENT_BINARY_DIR}/obj/external/utilities")
and
# Source level CMakeLists.txt - MyProg/src
### MySQL Connector/C++ ###
set (MYSQLCONNECTORCPP_ROOT_DIR "~/3rdParty/mysql-connector-c++-1.1.0")
### Include paths ###
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
include_directories (${UTILITIES_DIR})
include_directories (${MYSQLCONNECTORCPP_ROOT_DIR})
include_directories (/usr/local/include)
link_directories (/usr/local/lib)
link_directories (${MYSQLCONNECTORCPP_ROOT_DIR}/driver)
link_directories (/usr/lib64/mysql/)
link_directories (/usr/lib64/)
link_directories (/usr/local/mysql/lib/)
add_executable (myprog
entrypoint.cpp
MyProg.cpp
MyProg_test.cpp
${UTILITIES_DIR}/DBInterface.cpp
)
target_link_libraries (myprog mysqlcppconn-static mysqlclient)
This is the output from cmake (out of source build):
> cmake ../MyProg/
-- The C compiler identification is GNU 4.7.1
-- The CXX compiler identification is GNU 4.7.1
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: ~/MyProg_prj/Debug
And this is the fatal error I get from make:
> make
Scanning dependencies of target myprog
[ 8%] Building CXX object obj/CMakeFiles/myprog.dir/entrypoint.cpp.o
In file included from ~/MyProg_prj/MyProg/src/entrypoint.cpp:18:0:
~/utilities/DBInterface.hpp:18:30: fatal error: mysql_connection.h: No such file or directory
compilation terminated.
make[2]: *** [obj/CMakeFiles/myprog.dir/entrypoint.cpp.o] Error 1
make[1]: *** [obj/CMakeFiles/myprog.dir/all] Error 2
make: *** [all] Error 2
The mysql_connection.h file is in the directory specified in the CMakeLists.txt file.
This problem happened after I upgraded Linux (before it worked correctly), but this should not be the reason. The PATH should contain everything needed.
Thank you.
Platform: Linux (OpenSuse), GCC 4.7.1, cmake, MySQL Connector C++ 1.1.0
You are most likely missing the 'libmysqlcppconn-dev' library. Once installed, you shouldn't be seeing this error.
Before updating the system, in the source code I included the MySQL header like this:
#include <mysql_connection.h>
Now I have to specify the subdirectory:
#include <driver/mysql_connection.h>
Something must have changed in how the paths are set...