Add executable from parent directory cmake - cmake

I'm trying to compile executable files in a subdirectory project/model/tests for testing and need to link my model files which reside at project/model. However, I can't get it to work. I've successfully added the parent directory but cmake keeps telling me no source file found for foo.cpp, which is in the parent directory, while bar.cpp, which is in the current directory, is added correctly.
cmake_minimum_required(VERSION 2.6)
# get parent directory
get_filename_component(MODEL_DIR ${CMAKE_CURRENT_SOURCE_DIR} PATH)
# Locate GTest
find_package(GTest REQUIRED)
# Add parent directory
include_directories(${GTEST_INCLUDE_DIRS} ${MODEL_DIR})
link_directories(${MODEL_DIR})
# all included directories are printed out correctly
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
message(STATUS "dir='${dir}'")
endforeach()
# foo.cpp, which is in the parent directory is not found
add_executable(runTests foo.cpp bar.cpp)
target_link_libraries(runTests ${GTEST_LIBRARIES} pthread)
Thank you.

When files listed in add_executable() and add_library() are given as relative paths (which they almost always are), they are interpretedd relative to CMAKE_CURRENT_SOURCE_DIR. In other words, you have to do one of these:
add_executable(runTests ../foo.cpp bar.cpp)
Or:
add_executable(runTests ${MODEL_DIR}/foo.cpp bar.cpp)
Side note: it's almost never a good idea to use link_directories(); that command is genrally more trouble than it's worth. The preferred alternative is to provide full paths to target_link_libraries() where necessary.

Related

CMake: Modifying library output directory of a target from a sub-project

I have a top-level CMakeLists.txt which includes another third party project from a subdirectory, like
add_subdirectory(ext/third_party/cmake)
third_party contains a library target which I want to build, but I want to modify some properties and want to avoid to modify the original CMake file. I do not want to link some of my own targets to that library, I'd rather want that third party library to be build with some modified properties and then put it into a custom output directory. So I do
set_target_properties(libthird_party PROPERTIES
# some properties that successfully get applied here
LIBRARY_OUTPUT_DIRECTORY "/my/output/dir")
I can see that other properties are successfully applied and the build is modified to my needs correctly, but the generated output library is not put into the directory I set. What could be the reason for that?
If this is a totally wrong or bad approach please also feel free to propose a better approach for my goal.
Figured it out myself with help from the comments. I was trying to modify a static library target, which is not affected by LIBRARY_OUTPUT_DIRECTORY (which only applies to dynamic libraries) but which needs the setting ARCHIVE_OUTPUT_DIRECTORY. So the corrected call is
set_target_properties(libthird_party PROPERTIES
# some properties that successfully get applied here
ARCHIVE_OUTPUT_DIRECTORY "/my/output/dir")
You have to deal with [LIBRARY, ARCHIVE, EXECUTABLE] x [Single, Multi]config generator x [Unix, Windows]way.
note: On Windows everything (.dll, .exe) is on the same directory while on Unix you generally have a bin and a lib directories.
include(GNUInstallDirs)
# Single config (e.g. makefile, ninja)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
if(UNIX)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
else()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
endif()
# For multi-config build system (e.g. xcode, msvc, ninja-multiconfig)
foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
if(UNIX)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_LIBDIR})
else()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG}
${CMAKE_BINARY_DIR}/${OUTPUTCONFIG}/${CMAKE_INSTALL_BINDIR})
endif()
endforeach()

CMake INCLUDE_DIRS variable doesn't contain the right path

I have a project that I'm trying to compile on a Linux-based HPC system using CMake. The project relies on the Eigen3 package, so I specified the path to the Eigen3 config file in the CMAKE_PREFIX_PATH variable as below (an excerpt from my CMakeLists.txt file).
set(CMAKE_PREFIX_PATH "/gpfs/loomis/apps/avx/software/Eigen/3.3.7")
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
message(STATUS ${EIGEN3_INCLUDE_DIR})
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
Note: the directory # CMAKE_PREFIX_PATH contains the installation tree /share/eigen3/cmake, where the config file is located. The CMAKE_PREFIX_PATH also contains an /include directory. So find_package shouldn't have any difficulty retrieving Eigen3's location, from my understanding.
However, the result of the message command is:
-- /gpfs/loomis/apps/avx/software/Eigen/3.3.7//gpfs/loomis/apps/avx/software/Eigen/3.3.7/include
not /gpfs/loomis/apps/avx/software/Eigen/3.3.7/include as desired. So include_directories isn't actually passing the correct package path. How do I fix this?
Thank you in advance!

CMake: write executables to multiple subdirectories

I have a source and build tree that looks something like this:
+-build/
+-bin/
+-modules/
+-src/
+-tests/
+-test1/
+-test2/
I have also configured CMake to write the executables into the build/bindirectory. That all works fine.
What I would like is to have most of my executables written into the build/bin directory, while those built from sources under the test directories be written into a build/bin/tests directory.
Is this possible? Can someone point me in the right direction?
I've tried setting the RUNTIME_OUTPUT_DIRECTORY variable directly and I've tried using set_target_properties, but without success.
Ideally, I like to be able to set something in the CMakeLists.txt file in the tests directory and have it trickle down into the subdirectories.
You may set CMAKE_RUNTIME_OUTPUT_DIRECTORY variable as many times as you want. Each setting will affect only on the executables created since that setting until the next one.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Futher executables will be placed under 'bin/'
add_executable(my_program <sources>...)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/tests)
# Futher executables will be placed under 'bin/tests/' instead
add_executable(test1 <sources>...)
add_executable(test2 <sources>...)
If you are creating the tests in the separate CMakeLists.txt, the settings can be made modular:
CMakeLists.txt:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Futher executables will be placed under 'bin/'
add_executable(my_program <sources>...)
add_subdirectory(tests)
tests/CMakeLists.txt:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/tests)
# Executables created below will be placed under 'bin/tests/' instead
add_executable(test1 <sources>...)
add_executable(test2 <sources>...)
Actually, when you call add_executable, it just uses the current value of the CMAKE_RUNTIME_OUTPUT_DIRECTORY variable. This fact can be found in the documentation about RUNTIME_OUTPUT_DIRECTORY target property, which is affected by the variable.

cmake include directories issue with cygwin

I want to add include directories to my project, which are defined in some environment variable SOME_DIR. SOME_DIR is set to 'D:\some_dir'.
Here's how I've added it in CMakeLists.txt:
include_directories($ENV{SOME_DIR}/include)
After generating Unix Makefiles via cygwin, compiler can't find header files from this directory. So, I've added some debug outputs to check list of included directories like this:
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
foreach(dir ${dirs})
message(STATUS "dir='${dir}'")
endforeach()
Output is:
dir='/cygdrive/d/myproject/D:/some_dir/include'
My question is: What should I do so that cmake include correct path, i.e. 'D:/some_dir/include'?

Simple CMakeLists.txt that reflects typical directory structure (/src, /inc, /bin subdirectories)

I am struggling to make a CMakeList.txt file to reflect a simple, typical makefile. The original is here http://pastebin.com/S9Czr1pt .
I tried many things (like SET(SOURCE ... and SET(HEADERS... ) to add /src, /lib and /third-party//include ), but I have no luck.
Can anyone either help me out or point to a tutorial that does this thing?
This is just an out of the blue skeleton - please see the CMake documentation for details of each function:
cmake_minimum_required(VERSION 2.6)
# Project name, can be used as target name too
project(Example)
# Search all .cpp files within src - recursive!
# You can add all source files by hand here too
file(GLOB_RECURSE SRCS "src/*.cpp")
# Add include path (you can also add it's sub directories
include_directories("include")
# Search for packages -- PLEASE NOTE: many libraries provide alternative's to this
# which often provide more functionality
find_package(PkgConfig REQUIRED)
# TODO: add proper pkg modul search info's and change the variable's name
pkg_search_module(PACKAGE_NO1 ...)
# Show some messages (optional)
if( (PACKAGE_NO1 )
include_directories(${(PACKAGE_NO1_INCLUDE_DIRS})
message(STATUS "Using OpenSSL ${(PACKAGE_NO1_VERSION}")
else()
# do error handling
endif()
# Add compiler flags
add_definitions(-std=c++11 -Wall) # -g O3 etc are added according to Release / Debug compilation
# Build a executable target (1st param: Target name; 2nd: source files)
add_executable(${PROJECT_NAME} ${SRCS})