I am working through learning CMake's install commands. I have it pretty much figured out for executables. For libraries there are few additional steps to build and install the required CMake scripts so the library can be used in the following scenarios.
Find and link the library from the local build generated by the current CMake project.
Find and link the library from a common installation location. This is required by 3rd party CMake projects that don't build the library.
I want to build a library called FooBar. FooBar is linked to an executable called App, that is defined in the same CMake project as FooBar.
Here are my CMake files and project structure.
<project-root>
|-app
| |-src
| | |-main.cpp
| |
| |-CMakeLists.txt
|
|-lib
| |-include
| | |-FooBar.h
| |
| |-src
| | |-FooBar.cpp
| |
| |-CMakeLists.txt
|
|-CMakeLists.txt
# File: <project-root>/CMakeLists.txt
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(SampleProject VERSION 0.0.1 LANGUAGES CXX)
add_subdirectory(lib)
add_subdirectory(app)
# File: <project-root>/app/CMakeLists.txt
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
set(TARGET_NAME "App")
find_package(FooBar REQUIRED)
set(IMPL_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
)
add_executable(
${TARGET_NAME}
${IMPL_FILES}
)
target_link_libraries(
${TARGET_NAME}
PRIVATE
FooBar
)
install(
TARGETS
${TARGET_NAME}
DESTINATION
bin
)
# File: <project-root>/lib/CMakeLists.txt
set(LIB_NAME FooBar)
set(CMAKE_CXX_VERSION 11)
set(IMPL_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/Lib.cpp
)
set(PUBLIC_DEFI_FILES
${CMAKE_CURRENT_SOURCE_DIR}/include/Lib.h
)
add_library(
${LIB_NAME}
STATIC
${IMPL_FILES}
)
target_include_directories(
${LIB_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
set_target_properties(
${LIB_NAME}
PROPERTIES
PUBLIC_HEADER
${PUBLIC_DEFI_FILES}
)
install(
TARGETS
${LIB_NAME}
EXPORT
${LIB_NAME}Targets
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
)
install(
EXPORT
${LIB_NAME}Targets
FILE
${LIB_NAME}Config.cmake
DESTINATION
lib/cmake/${LIB_NAME}
)
# I am under the impression these are needed for other targets in the
# current project to be able to use "find_package(FooBar)". I also
# think that "CMAKE_EXPORT_NO_PACKAGE_REGISTRY" needs to not be set.
message(STATUS "CMAKE_EXPORT_NO_PACKAGE_REGISTRY: ${CMAKE_EXPORT_NO_PACKAGE_REGISTRY}")
export(
EXPORT
${LIB_NAME}Targets
FILE
${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}Config.cmake
)
export(PACKAGE ${LIB_NAME})
To generate build files I run
# Clean project directory.
mkdir _build
cd _build
cmake .. -DCMAKE_INSTALL_PREFIX=<project-root>/_dist
and I get the following error.
-- CMAKE_EXPORT_NO_PACKAGE_REGISTRY:
CMake Error at app/CMakeLists.txt:5 (find_package):
By not providing "FindFooBar.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "FooBar", but
CMake did not find one.
Could not find a package configuration file provided by "FooBar" with any
of the following names:
FooBarConfig.cmake
foobar-config.cmake
Add the installation prefix of "FooBar" to CMAKE_PREFIX_PATH or set
"FooBar_DIR" to a directory containing one of the above files. If "FooBar"
provides a separate development package or SDK, be sure it has been
installed.
-- Configuring incomplete, errors occurred!
Running the above command a second time yields the same error message. I should not see that message because these two lines
export(
EXPORT
${LIB_NAME}Targets
FILE
${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}Config.cmake
)
export(PACKAGE ${LIB_NAME})
should generate _build/FooBar/FooBarConfig.cmake and add it to the search path for packages seen by App.
If I remove the app sub-directory, build and install FooBar to _dist, and then re-add app, I do not get the error. Even if I clear out _build and generate build files from scratch, I don't get the error. How is CMake finding my local install config script, but not the one in the build directory? Am I doing something wrong or does anyone have any idea why this might not work?
Related
I have been working on this all day, but I think I finally have my base case figured out. I am using a GitHub repo DBCPPP in my application. This repo relies on LibXml2, to ensure it is available LibXml2 is included as a submodule and build with dbcppp through a series of CMakeLists.txt. I am trying to resolve an issue with my build in which the Linux kernel and the DBCPPP recipe are both attempting to install /usr/lib/libxml2.so.2.9.10. I have an open question about it here.
My potential solution is to prevent DBCPPP from creating the libxml2.so.2.9.10 file, and instead build using the libxml2.so.2.9.10 file created by Yocto.
So far my CMakeLists.txt contains:
cmake_minimum_required(VERSION 3.12)
project("libdbcppp" VERSION 0.1.0)
set(LIBXML2_INCLUDE_DIR /mnt/WorkDrive/Documents/EVCC_Application/build-fb/tmp/work/cortexa7t2hf-neon-poky-linux-gnueabi/libxml2/2.9.10-r0/libxml2-2.9.10/include)
set(LIBXML2_LIBRARIES /mnt/WorkDrive/Documents/EVCC_Application/build-fb/tmp/work/cortexa7t2hf-neon-poky-linux-gnueabi/libxml2/2.9.10-r0/image/usr/lib)
#include(FindPkgConfig)
#include(FindLibXml2 REQUIRED)
find_package(LibXml2 REQUIRED)
option(build_tests "Build tests" ON)
option(build_examples "Build examples" ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_STATIC_LIBRARY_PREFIX "")
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_definitions("/bigobj")
endif()
include_directories("include")
include_directories("third-party/libxmlmm/libxmlmm")
include_directories("/mnt/WorkDrive/Documents/EVCC_Application/build-fb/tmp/work/cortexa7t2hf-neon-poky-linux-gnueabi/boost")
include_directories("/mnt/WorkDrive/Documents/EVCC_Application/build-fb/tmp/work/cortexa7t2hf-neon-poky-linux-gnueabi/libxml2/2.9.10-r0/libxml2-2.9.10/include")
include_directories("third-party/cxxopts/include")
file(GLOB libxmlmm_header
"third-party/libxmlmm/libxmlmm/*.h"
)
file(GLOB libxmlmm_src
"third-party/libxmlmm/libxmlmm/*.cpp"
)
add_library(libxmlmm SHARED "")
target_link_libraries(libxmlmm LibXml2::LibXml2)
target_sources("libxmlmm"
PRIVATE ${libxmlmm_header}
PRIVATE ${libxmlmm_src}
)
install(TARGETS "libxmlmm" EXPORT ${PROJECT_NAME}Targets DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(
DIRECTORY "libxmlmm"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libxmlmm
FILES_MATCHING PATTERN "*.h")
set(CMAKE_STATIC_LIBRARY_PREFIX "")
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE #ONLY
)
ADD_CUSTOM_TARGET(uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
)
Edit: I am updating my question with my latest CMakeLists.txt. I am integrating this with a Yocto project. This appears to work within Ubuntu but when I added it to the Yocto build I get the error.
error: /mnt/WorkDrive/Documents/MAIN_Application/build-fb/tmp/work/cortexa7t2hf-neon-poky-linux-gnueabi/libxml2/2.9.10-r0/image/usr/lib: read: Is a directory
| collect2: error: ld returned 1 exit status
| ninja: build stopped: subcommand failed.
| WARNING: exit code 1 from a shell command.
I am trying to get better on CMake. Currently I try to build a toy example that is using OpenCV that I have built from source and installed in a directory called thirdparty.
I can run build
cmake ..
cmake --build .
cmake --install . --prefix ../tmp
In build I can run ./app/TestOpenCV and get a 3x4 zero matrix as output.
If I run ../tmp/bin/TestOpenCV I get
Reason: tried: '/usr/local/lib/libopencv_gapi.406.dylib' (no such file), '/usr/lib/libopencv_gapi.406.dylib' (no such file)
It appears that the linking is not working appropriately when I install the binary. I.e. it searching for the libraries in the wrong location. How can I make this work?
I have the following structure
TestCMake
CMakeLists.txt
app
TestOpenCV.cpp
CMakeLists.txt
thirdparty
installdir
opencv_mac
bin
include
lib
share
TopLevel CMakeLists.txt
cmake_minimum_required(VERSION 3.24)
project(Tutorial VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(OpenCV REQUIRED PATHS "thirdparty/installdir/opencv_mac/lib/cmake/opencv4/" NO_DEFAULT_PATH)
include_directories(SYSTEM ${OpenCV_INCLUDE_DIRS})
add_subdirectory(app)
App level CMakeLists
add_executable(TestOpenCV TestOpenCV.cpp)
target_link_libraries(TestOpenCV ${OpenCV_LIBS})
install(TARGETS TestOpenCV
DESTINATION bin)
How can I make the binary work after installing it?
I'm building a test project to learn libraries zeromq with cppmq, and I want to include both libraries as subdirectories. I currently have the following structure:
|-- CMakeLists.txt
|-- deps
| |-- cppzmq-4.3.0
| | |-- CMakeLists.txt
| | `-- rest of files
| |-- zeromq-4.3.1
| | |-- CMakeLists.txt
| | `-- rest of files
`-- main.cpp
I've tried with the following CMakeLists:
cmake_minimum_required(VERSION 3.14)
project(PruebaZeroMQ)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(deps/zeromq-4.3.1)
add_subdirectory(deps/cppzmq-4.3.0)
add_executable(PruebaZeroMQ main.cpp)
target_link_libraries(PruebaZeroMQ
libzmq
cppzmq)
When I run cmake, I get the following error:
-- Detected CPPZMQ Version - 4.3.0
-- CMake libzmq package not found, trying again with pkg-config (normal install of zeromq)
CMake Error at deps/cppzmq-4.3.0/CMakeLists.txt:20 (message):
ZeroMQ was not found, neither as a CMake package nor via pkg-config
cppmq depends on zeromq, and looks like it tries to load it using find_package, so I tried to modify CMAKE_MODULE_PATH so it could find the ZeroMQConfig.cmake file, but it fails too, with the same error:
add_subdirectory(deps/zeromq-4.3.1)
list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_BINARY_DIR}/deps/zeromq-4.3.1 ")
add_subdirectory(deps/cppzmq-4.3.0)
Is there a way of achieving this? I'd rather not install the libraries system-wide.
After trying to manually find_package, CMake showed the following error message:
Add the installation prefix of "ZeroMQ" to CMAKE_PREFIX_PATH or set
"ZeroMQ_DIR" to a directory containing one of the above files.
So I tried that, using:
set(ZeroMQ_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/zeromq-4.3.1)
And it worked.
I am currently working on implementing a ROS library into our company software stack. Because the library is based on ROS and thus uses catkin I am rewriting the library to use cmake exclusively and try to apply the modern CMake approach. The library is structured as follows:
.
|-- CMakeLists.txt
|-- LICENSE
|-- README.md
|-- grid_map_core
| |-- CHANGELOG.rst
| |-- CMakeLists.txt
| |-- cmake
| | `-- grid_map_core-extras.cmake
| |-- grid_map_coreConfig.cmake
| |-- include
| | `-- grid_map_core
| | `-- iterators
| |-- src
| | `-- iterators
| `-- test
If I install the library and try to add the library in a simple test_project to the target I get an error displaying the Eigen3 dependency cannot be found:
CMake Error at CMakeLists.txt:6 (find_package):
Found package configuration file:
/usr/local/lib/cmake/grid_map_core/grid_map_coreConfig.cmake
but it set grid_map_core_FOUND to FALSE so package "grid_map_core" is
considered to be NOT FOUND. Reason given by package:
grid_map_core could not be found because dependency Eigen3 could not be
found.
Unfortunately the Eigen version I have to use does not provide the Eigen3Config.cmake option and I am forced to use the cmake provided FindEigen3.cmake alternative.
(I suppose compiling a newer Eigen3 version manually would be a valid alternative, nevertheless I try to completely understand the modern cmake approach which looks very promising for exactly avoiding such issues)
From all the resources online I am not quite sure how the transitive dependency is handled in this case.
To my understanding the grid_map_coreConfig.cmake should forward the imported Eigen3 dependency.
In the grid_map_core CMakeLists the eigen is found by the command find_package(Eigen3 3.2 REQUIRED) and the find_dependency macro just wraps this exact same command.
Resources
The main CmakeLists.txt looks as follows:
# Set cmake version
cmake_minimum_required(VERSION 3.0.2)
# Set project name
project(grid_map)
# Must use GNUInstallDirs to install libraries into correct
# locations on all platforms.
include(GNUInstallDirs)
add_compile_options(-std=c++11)
# Add subdirectories
add_subdirectory(grid_map_core)
The grid_map_core CMakeLists as follows:
# Set cmake version
cmake_minimum_required(VERSION 3.0.2)
# Set project name
project(grid_map_core)
add_compile_options(-std=c++11)
# import Eigen3
find_package(Eigen3 3.2.2 REQUIRED)
## Define Eigen addons.
include(cmake/${PROJECT_NAME}-extras.cmake)
#########
# Build #
#########
# Add the library target
add_library(${PROJECT_NAME}
src/BufferRegion.cpp
src/GridMap.cpp
src/GridMapMath.cpp
src/Polygon.cpp
src/SubmapGeometry.cpp
src/iterators/CircleIterator.cpp
src/iterators/EllipseIterator.cpp
src/iterators/GridMapIterator.cpp
src/iterators/LineIterator.cpp
src/iterators/PolygonIterator.cpp
src/iterators/SlidingWindowIterator.cpp
src/iterators/SubmapIterator.cpp
)
# set target include directories
target_include_directories(${PROJECT_NAME}
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
${EIGEN3_INCLUDE_DIR}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# add an alias
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
# set target compile options
target_compile_options(${PROJECT_NAME}
PRIVATE
$<$<CONFIG:Debug>:-Werror>
)
###########
# Install #
###########
# 'make install' to the right locations
install(TARGETS ${PROJECT_NAME}
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION include
)
# This makes the project importable from the install directory
# Put config file in per-project dir.
install(EXPORT "${PROJECT_NAME}Targets"
FILE "${PROJECT_NAME}Targets.cmake"
NAMESPACE "${PROJECT_NAME}::"
DESTINATION lib/cmake/${PROJECT_NAME})
# generate config.cmake
include(CMakePackageConfigHelpers)
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
VERSION "${PROJECT_NAME}_VERSION"
COMPATIBILITY SameMajorVersion
)
# install config.cmake files
install(FILES "${PROJECT_NAME}Config.cmake"
DESTINATION "lib/cmake/${PROJECT_NAME}")
###########
# Testing #
###########
and the grid_map_coreConfig.cmake as follows:
include(CMakeFindDependencyMacro)
find_dependency(Eigen3 REQUIRED)
include("${CMAKE_CURRENT_LIST_DIR}/grid_map_coreTargets.cmake")
and the test_project's CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(test_project)
set(CMAKE_MODULE_PATH /usr/share/cmake-3.0/Modules)
add_compile_options(-std=c++11)
find_package(grid_map_core REQUIRED CONFIG)
add_executable(test_project main.cpp)
target_link_libraries(test_project
PRIVATE
grid_map_core::grid_map_core
)
For completeness I'm adding the FindEigen3.cmake file:
# - Try to find Eigen3 lib
#
# This module supports requiring a minimum version, e.g. you can do
# find_package(Eigen3 3.1.2)
# to require version 3.1.2 or newer of Eigen3.
#
# Once done this will define
#
# EIGEN3_FOUND - system has eigen lib with correct version
# EIGEN3_INCLUDE_DIR - the eigen include directory
# EIGEN3_VERSION - eigen version
# Copyright (c) 2006, 2007 Montel Laurent, <montel#kde.org>
# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael#free.fr>
# Copyright (c) 2009 Benoit Jacob <jacob.benoit.1#gmail.com>
# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
if(NOT Eigen3_FIND_VERSION)
if(NOT Eigen3_FIND_VERSION_MAJOR)
set(Eigen3_FIND_VERSION_MAJOR 2)
endif(NOT Eigen3_FIND_VERSION_MAJOR)
if(NOT Eigen3_FIND_VERSION_MINOR)
set(Eigen3_FIND_VERSION_MINOR 91)
endif(NOT Eigen3_FIND_VERSION_MINOR)
if(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION_PATCH 0)
endif(NOT Eigen3_FIND_VERSION_PATCH)
set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
endif(NOT Eigen3_FIND_VERSION)
macro(_eigen3_check_version)
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK FALSE)
else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
set(EIGEN3_VERSION_OK TRUE)
endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
if(NOT EIGEN3_VERSION_OK)
message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
"but at least version ${Eigen3_FIND_VERSION} is required")
endif(NOT EIGEN3_VERSION_OK)
endmacro(_eigen3_check_version)
if (EIGEN3_INCLUDE_DIR)
# in cache already
_eigen3_check_version()
set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
else (EIGEN3_INCLUDE_DIR)
find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
PATHS
${CMAKE_INSTALL_PREFIX}/include
${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen3 eigen
)
if(EIGEN3_INCLUDE_DIR)
_eigen3_check_version()
endif(EIGEN3_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
mark_as_advanced(EIGEN3_INCLUDE_DIR)
endif(EIGEN3_INCLUDE_DIR)
The error message you got is generated by find_dependency macro, but not by find_package command, which is called internally by that macro. Because you call find_dependency with REQUIRED keyword (and this keyword is passed to inner find_package), the only possible scenario of your error is follow:
Call to find_package(Eigen3 REQUIRED) interprets Eigen3 to be found.
But when find_dependency checks find_package results, it interprets Eigen3 to be not found.
Rather strange, isn't it?
Actually, your FindEigen3.cmake script is one of the old ones, which sets upper case flow of "FOUND" variable, which denotes success of the script:
# EIGEN3_FOUND - system has eigen lib with correct version
but the correct name of such variable should be Eigen3_FOUND (the package name should be exactly the same as in find_package(Eigen3) call and in the name of the script FindEigen3.cmake).
Command find_package checks both spelling of the "FOUND" variable: correct one and upper-case one. Such way, when FindEigen3.cmake script sets EIGEN3_FOUND variable with intention "I have found the package", find_package understands that intention, marking the package as found.
But macro find_dependency checks only correct name of the variable, Eigen3_FOUND. Because this variable isn't set by the FindEigen3.cmake script, the package is treated as not found.
As a fast fix, you may replace in the FindEigen3.cmake script EIGEN3_FOUND with Eigen3_FOUND, and everything should work. (Well, the same replacement should be done on the user machine. Or you should ship corrected FindEigen3.cmake script with your library).
I am trying to use CMake and CPack to build and package a Mac OS X application, but I can't figure out the correct way to include resources.
This is what my CMakeLists.txt looks like:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(foo)
ADD_EXECUTABLE(foo foo.c foo.txt)
SET_TARGET_PROPERTIES(foo PROPERTIES MACOSX_BUNDLE TRUE)
SET_TARGET_PROPERTIES(foo PROPERTIES RESOURCE foo.txt)
INSTALL(TARGETS foo DESTINATION ".")
SET(CPACK_GENERATOR TGZ)
INCLUDE(CPack)
However, when I use it to build a package, foo.txt gets included twice: in the Resources directory of the bundle as expected, but also at the root:
$ cd build
$ cmake ..
$ make package
$ tar -xvzf foo-0.1.1-Darwin.tar.gz
x foo-0.1.1-Darwin/foo.app/Contents/Info.plist
x foo-0.1.1-Darwin/foo.app/Contents/MacOS/foo
x foo-0.1.1-Darwin/foo.app/Contents/Resources/foo.txt
x foo-0.1.1-Darwin/foo.txt
What am I doing wrong?
EDIT
For easier reading, here is what the final, working, CMakeLists.txt looks like (as per Josh's answer and my comment on it):
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(foo)
ADD_EXECUTABLE(foo foo.c foo.txt)
SET_TARGET_PROPERTIES(foo PROPERTIES MACOSX_BUNDLE TRUE)
SET_SOURCE_FILES_PROPERTIES(foo.txt PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
INSTALL(TARGETS foo DESTINATION ".")
SET(CPACK_GENERATOR TGZ)
INCLUDE(CPack)
Removing the line * PROPERTIES RESOURCE foo.txt) should solve the problem.
Since you have included cpack in your cmake file, the generated TGZ will contain all of the files which would be installed with make install. In this case, you have
SET_TARGET_PROPERTIES(foo PROPERTIES MACOSX_BUNDLE TRUE)
which will build foo as an OS X application bundle (doc), and
SET_TARGET_PROPERTIES(foo PROPERTIES RESOURCE TRUE)
specifies foo.txt as a resource files (doc). With both of those PROPERTIES set, make install will create two versions of foo.txt. One in the bundle, foo.app/Contents/Resources/foot.txt, and one in the top level directory, foo.txt. Therefore, CPack will also generate those two versions of foo.txt.