I am trying to setup myproj starting from a demo. I would like to keep the demo as it is in a subdir of myproj while still sourcing all its code and system dependencies in myproj, but I cannot attain a proper building environment with cmake.
In particular I have cloned this in myproj/subdir. I can cd subdir, cmake and make the executable with no issues.
I have copied the main file from from myproj/subdir to myproj/myprog.cpp and created a myproj/CMakeLists.txt file:
cmake_minimum_required(VERSION 3.10)
project( myproj )
include_directories(${CMAKE_SOURCE_DIR}/subdir)
add_subdirectory(${CMAKE_SOURCE_DIR}/subdir)
add_executable( myproj myproj.cpp )
In this case, even if cmake runs fine, all of the -isystem paths that myproj/subdir/CMakeLists.txt was adding to the gcc command line when called directly, are now missing. Therefore make fails. What am I doing wrong? How do I bring back all the necessary paths?
Related
I have one project that produces a library:
project (myCoolLibrary)
ADD_LIBRARY(my_cool_library SHARED ${mysources_SRC})
And another project that should be using this library:
find_package (myCoolLibrary REQUIRED)
INCLUDE_DIRECTORIES("${myCoolLibrary_INCLUDE_DIRS}" )
add_executable(myCoolExe ${my_sources_SRC} )
TARGET_LINK_LIBRARIES(myCoolExe ${myCoolLibrary_LIBRARIES} )
Is there a way that I can change the first file so that the second file works automatically? That by running CMake on the first file and then running make on the output, then running CMake on the second file, CMake is able to find the package?
An answer where I just give the address of where the first project is built to the second package is also acceptable.
Taking the code found in a blog post by #daniperez - Use CMake-enabled libraries in your CMake project (III) - I've come up with the following minimal solution:
myCoolLibrary/CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(myCoolLibrary)
function(my_export_target _target _include_dir)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
"
include(\"\$\{CMAKE_CURRENT_LIST_DIR\}/${_target}Targets.cmake\")
set_property(
TARGET ${_target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES \"${_include_dir}\"
)
"
)
export(TARGETS ${_target} FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake")
# NOTE: The following call can pollute your PC's CMake package registry
# See comments/alternatives below
export(PACKAGE ${_target})
endfunction(my_export_target)
...
add_library(${PROJECT_NAME} SHARED ${mysources_SRC})
my_export_target(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}")
myCoolExe/CMakeLists.txt
cmake_minimum_required(VERSION 3.3)
project(myCoolExe)
find_package(myCoolLibrary REQUIRED)
...
add_executable(${PROJECT_NAME} ${my_sources_SRC})
target_link_libraries(${PROJECT_NAME} myCoolLibrary)
To make it reusable I have packed everything into my_export_target(). And I'm friend of self-propagating properties like INTERFACE_INCLUDE_DIRECTORIES.
As commented by #ruslo, using export(PACKAGE ...) can pollute your package registry. So alternatively you can:
Write the target configuration files directly to some dedicated place specific for a certain toolchain
See e.g. How to install your custom CMake-Find module and 0003659: FIND_PACKAGE command improvements.
Set CMAKE_MODULE_PATH via the second project's CMake command line (injecting the search path(s) from the outside). If you are building the two projects anyway with a build script, then this is the most direct way to propagate the module search path(s).
Additional References
export()
CMake/Tutorials/Package Registry
Unable to find Eigen3 with CMake
How to instruct CMake to use the build architecture compiler
I have the following cmake setup:
colorizer_root
|
|-------colorizer_lib
|-------colorizer_template_project
The colorizer_root contains the top level CMakeLists.txt which is invoked when running cmake:
colorizer_root CMakeLists.txt
project(colorizer_root)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
add_subdirectory(colorizer_lib)
add_subdirectory(colorizer_template_project)
As you can see it contains 2 subdirectories each a project on its own. Basically what the colorizer_lib does is create a shared library named libcolorize.so (no executables here!), which then is to be used by the other project colorizer_template_project (the executable is created in this project). Here are the two CMakeLists.txt files for their respective projects:
colorizer_lib CMakeLists.txt
project(colorizer_lib)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
include_directories(. INCLUDES)
add_library(colorizer SHARED colorizer.cpp)
colorizer_template_project CMakeLists.txt
project(colorizer_template_project)
cmake_minimum_required(VERSION 2.8)
find_library(COLORIZER_LIB colorizer
PATHS ${CMAKE_BINARY_DIR}/colorizer_lib
)
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} ${COLORIZER_LIB})
I'm having trouble figuring out how the whole lookup thing works. The problem here is that when I run the top level CMakeLists.txt it goes through both (obviously) but during processing the colorizer_template_project it breaks with a complaint:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
COLORIZER_LIB
linked by target "colorizer_template_project" in directory /home/USER/Programming/C_Cpp/colorizer/colorizer_template_project
This is an expected behaviour since libcolorizer.so cannot be present at the time of running cmake because it is created after make has been invoked.
How do I tell cmake to first process the first project (including the build step!) and then go to the next one? I know that this works if I add an executable to the project that creates the library and then directly link it to the binary but in this case I want separate projects for the library and the executable that is using it.
PS: I haven't given any details about the sources because they are not important here. It is - I believe - a general question, which is not specific to whether I'm using C, C++ or something similar.
project command doesn't make subprojects independent, so colorizer target is actually accessible for colorizer_template_project, and you can directly link with it:
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} colorizer)
I have two projects using CMake.
The first is a shared library. It compiles and installs fine. Currently, it is still necessary to build 'debug' releases of it. So presently it is installed under ~/localdebug. That folder looks like the root of a filesystem with a 'include' and 'lib' directory. The same concept as '/usr/local'.
The second is a program. It needs to compile and link against my library in ~/localdebug. The CMakeLists.txt file for it looks like this:
cmake_minimum_required(VERSION 2.6)
set(CMAKE_C_FLAGS "-std=gnu99")
#add_definitions(-pg)
find_library(SANDGROUSE_LIB NAMES sandgrouse)
add_library(http_parser http_parser.c)
add_executable(rsva11001adapter main.c rsva11001.c)
target_link_libraries(rsva11001adapter http_parser ${SANDGROUSE_LIB})
I run the following to set up the make files:
cmake --debug-output -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH="/home/ericu/localdebug" ..
Based on the CMake wiki, setting DCMAKE_PREFIX_PATH does exactly what I want.
CMAKE_PREFIX_PATH
(since CMake 2.6.0) This is used when searching for include files, binaries, or libraries using either the FIND_PACKAGE(), FIND_PATH(), FIND_PROGRAM(), or FIND_LIBRARY() commands. For each path in the CMAKE_PREFIX_PATH list, CMake will check "PATH/include" and "PATH" when FIND_PATH() is called, "PATH/bin" and "PATH" when FIND_PROGRAM() is called, and "PATH/lib" and "PATH" when FIND_LIBRARY() is called. See the documentation for FIND_PACKAGE(), FIND_LIBRARY(), FIND_PATH(), and FIND_PROGRAM() for more details.
However, when I do a 'make VERBOSE=1' this is what I get:
cd /home/ericu/rsva11001adapter/build/src && /usr/bin/gcc -std=gnu99 -g -o CMakeFiles/rsva11001adapter.dir/main.c.o -c /home/ericu/rsva11001adapter/src/main.c
/home/ericu/rsva11001adapter/src/main.c:19:31: fatal error: sandgrouse/server.h: No such file or directory
compilation terminated.
So, it does not seem that CMake is finding things in CMAKE_PREFIX_PATH. It obviously is not adding -I variables to the compiler invocations either.
An inspection of CMakeCache.txt makes it seem as though it has no idea what the variable is:
// No help, variable specified on the command line.
CMAKE_PREFIX_PATH:UNINITIALIZED=/home/ericu/localdebug
I've been working on this for over an hour. I'm nearly at the point of giving up using CMake if it is this difficult to use a non-standard library with it.
You should instruct CMake to add -I flags when compiling your library:
find_path(SANDGROUSE_INCLUDE_DIR sandgrouse/server.h)
include_directories(${SANDGROUSE_INCLUDE_DIR}
Place these lines before add_library() invocation.
I have a very simple directory structure:
Project
Project/src
Project/build
Source files are in Project/src, and I do the out-of-src build in Project/build. After running cmake ../ ; make, I can run the executable thusly: Project/build$ src/Executable - that is, the Executable is created in the build/src directory.
How do I set the location of the executable in the CMakeLists.txt file? I've attempted to follow some of the examples found at cmake.org, but the links that work don't seem to show this behaviour.
My Project/src/CMakeLists.txt file is listed here.
include_directories(${SBSProject_SOURCE_DIR}/src)
link_directories(${SBSProject_BINARY_DIR}/src)
set ( SBSProject_SOURCES
main.cpp
)
add_executable( TIOBlobs ${SBSProject_SOURCES})
And the top-level Project/CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (SBSProject)
set (CMAKE_CXX_FLAGS "-g3 -Wall -O0")
add_subdirectory(src)
You have a couple of choices.
To change the default location of executables, set CMAKE_RUNTIME_OUTPUT_DIRECTORY to the desired location. For example, if you add
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
to your Project/CMakeLists.txt before the add_subdirectory command, your executable will end up in Project/build for Unix builds or build/<config type> for Win32 builds. For further details, run:
cmake --help-property RUNTIME_OUTPUT_DIRECTORY
Another option for a project of this size is to have just one CMakeLists.txt. You could more or less replace add_subdirectory(src) with the contents of Project/src/CMakeLists.txt to achieve the same output paths.
However, there are a couple of further issues.
You probably want to avoid using link_directories generally. For an explanation, run
cmake --help-command link_directories
Even if you do use link_directories, it's unlikely that any libraries will be found in ${SBSProject_BINARY_DIR}/src
Another issue is that the CMAKE_CXX_FLAGS apply to Unix builds, so should probably be wrapped in an if (UNIX) ... endif() block. Of course, if you're not planning on building on anything other than Unix, this is a non-issue.
Finally, I'd recommend requiring CMake 2.8 as a minimum unless you have to use 2.6 - CMake is an actively-developed project and the current version has many significant improvements over 2.6
So a single replacement for Project/CMakeLists.txt could look like:
cmake_minimum_required (VERSION 2.8)
project (SBSProject)
if (UNIX)
set (CMAKE_CXX_FLAGS "-g3 -Wall -O0")
endif ()
include_directories (${SBSProject_SOURCE_DIR}/src)
set (SBSProject_SOURCES
${SBSProject_SOURCE_DIR}/src/main.cpp
)
add_executable (TIOBlobs ${SBSProject_SOURCES})
Another way of relocating the executable file location is via set(EXECUTABLE_OUTPUT_PATH Dir_where_executable_program_is_located)
build/'config type' for Win32 builds.
For MSVC, to avoid the default "/Debug" created folder
set_target_properties(my_target
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR})
I have a CMake project where I am using a library and now I want to test my code with a different version of that library. I can set INCLUDE_DIRECTORIES (and possibly later also linking) in the below example. But because I only want to do this temporarily, I'd like to manually set this path with ccmake/cmake-gui.
How do I do this?
project(min_example)
cmake_minimum_required(VERSION 2.8)
find_package(OpenCV REQUIRED)
# Without the following line please:
INCLUDE_DIRECTORIES("/home/me/src/opencv/install/include")
add_executable(min_example main.cpp)
target_link_libraries(min_example ${OpenCV_LIBS})
This should be possible by setting the CMAKE_PREFIX_PATH variable upon configuring your build. In your project directory generate a test_build directory and run:
mkdir test_build
cd test_build
cmake -DCMAKE_PREFIX_PATH=/home/me/src/opencv/install ..
Setting the CMAKE_PREFIX_PATH variable will make the find_package(OpenCV REQUIRED) command pick your OpenCV installation in /home/me/src/opencv and set the OpenCV_LIBS and OpenCV_INCLUDE_DIR variables accordingly.
Alternatively you can edit a CMakeCache.txt file of an existing build directory with the CMake GUI editor and add the CMAKE_PREFIX_PATH definition there. You have to re-configure your project then.
Using config in find_package will restrict search path to OpenCV_DIR. This will use the cmake config that opencv generates at build time to setup paths to include and libs
set(OpenCV_DIR "<cusompath>" CACHE PATH '' ${SHOULD_FORCE_CACHE})
find_package(OpenCV REQUIRED CONFIG)