Родительский CMakeLists.txt перезаписывает дочерние параметры выходного каталога CMakeLists.txt
Я пытаюсь поместить библиотеку из проекта в определенный каталог в выводе моей сборки, но родительский CMakeLists.txt перезаписывает настройки вывода. Родительский CMakeLists.txt устанавливает все библиотеки для размещения в каталоге /lib.
Однако одну из моих библиотек нужно поместить в библиотеку /python. Настройки у меня работают на Windows. Это означает, что все библиотеки, кроме моей специфичной для Python библиотеки, помещаются в папку /lib, а библиотека python помещается в папку /python.
Проблема появляется, когда я собираюсь на Linux. Все библиотеки, включая библиотеку, специфичную для python, помещаются в папку /lib. Опция FORCE ничего не делает.
Если бы я строил только для одной платформы, я мог бы иметь дело с любым макетом каталога. Но я действительно хочу сохранить один и тот же макет на разных платформах.
CMakeLists.txt следующим образом:
-Parent CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(renderer2d)
#enable debug symbols by default
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
#(you can also set on cl: -D CMAKE_BUILD_TYPE=Release)
#place outside of Debug/Release folders
SET(OUTPUT_BINDIR ${PROJECT_BINARY_DIR}/bin)
MAKE_DIRECTORY(${OUTPUT_BINDIR})
SET(OUTPUT_LIBDIR ${PROJECT_BINARY_DIR}/lib)
MAKE_DIRECTORY(${OUTPUT_LIBDIR})
SET (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_LIBDIR} CACHE PATH "build directory")
SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_BINDIR} CACHE PATH "build directory")
IF(WIN32)
SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_BINDIR} CACHE PATH "build directory")
ELSE(WIN32)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_LIBDIR} CACHE PATH "build directory")
ENDIF(WIN32)
# For each configuration (Debug, Release, MinSizeRel... and/or anything the user chooses)
FOREACH(CONF ${CMAKE_CONFIGURATION_TYPES})
# Go uppercase (DEBUG, RELEASE...)
STRING(TOUPPER "${CONF}" CONF)
SET("CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_LIBDIR}")
SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_BINDIR}")
IF(WIN32)
SET("CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_BINDIR}")
ELSE()
SET("CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_LIBDIR}")
ENDIF()
ENDFOREACH()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
#set the source directory
file(GLOB SOURCES src/*.cpp)
add_subdirectory(shape)
add_subdirectory(py_shape)
add_subdirectory(scripts)
#define sources and executable
set(EXECUTABLE_NAME "renderer2d")
add_executable(${EXECUTABLE_NAME} ${SOURCES})
#find python
find_package(PythonInterp)
find_package(PythonLibs 2.7 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
#detect and add SFML
#this line checks a cmake file for hints on where to find cmake
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
#find any version 2.x of SFML
#see the FindSFML.cmake file for additional details and instructions
find_package(SFML 2 REQUIRED system window graphics network audio)
include_directories(${SFML_INCLUDE_DIR})
#find and include Boost python libraries
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost COMPONENTS python system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
#link all found libraries to the executable
if(WIN32)
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE $<$<BOOL:${MSVC}>:BOOST_ALL_NO_LIB>)
endif(WIN32)
target_link_libraries(${EXECUTABLE_NAME} ${PYTHON_LIBRARIES} ${SFML_LIBRARIES} ${Boost_LIBRARIES} shape)
-Child CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(py_shape CXX)
#set file variables
file(GLOB SOURCE src/*.cpp)
file(GLOB HEADERS inc/*.hpp)
#place outside of Debug/Release folders
SET(OUTPUT_BINDIR ${CMAKE_BINARY_DIR}/python)
MAKE_DIRECTORY(${OUTPUT_BINDIR})
set(OUTPUT_LIBDIR ${CMAKEK_BINARY_DIR}/python)
MAKE_DIRECTORY(${OUTPUT_LIBDIR})
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${OUTPUT_LIBDIR} CACHE PATH "build directory")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_BINDIR} CACHE PATH "build directory")
IF(WIN32)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_BINDIR} CACHE PATH "build directory")
ELSE(WIN32)
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_LIBDIR} CACHE PATH "build directory")
ENDIF(WIN32)
#for each configuration
FOREACH(CONF ${CMAKE_CONFIGURATION_TYPES})
#Go uppercase {DEBUG, RELEASE...)
SET("CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_LIBDIR}")
SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_BINDIR}")
IF(WIN32)
SET("CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_BINDIR}")
ELSE()
SET("CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONF}" "${OUTPUT_LIBDIR}")
ENDIF()
ENDFOREACH()
#find packages
find_package(PythonInterp)
find_package(PythonLibs 2.7 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
find_package(Boost COMPONENTS python REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2 REQUIRED system window graphics network audio)
include_directories(${SFML_INCLUDE_DIR})
#build the library
add_library(python_shape MODULE ${SOURCE})
#enable C++11 if available
target_compile_features(python_shape PRIVATE cxx_range_for)
#link library
target_link_libraries(python_shape shape ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${SFML_LIBRARIES})
#drop "lib" from the library name
set_target_properties(python_shape PROPERTIES PREFIX "")
if(WIN32)
#set extension to ".pyd"
set_target_properties(python_shape PROPERTIES SUFFIX ".pyd")
endif(WIN32)
1 ответ
Превращаю мои комментарии в ответ
Я успешно протестировал следующее с MinGW и CMake 3.3.0 (я немного сократил ваш пример, чтобы сконцентрироваться на выходных каталогах):
CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(renderer2d C CXX)
# TODO: Remove, this is just for testing
file(WRITE "src/renderer2d.cpp" "int main(void) {}")
file(WRITE "py_shape/src/py_shape.cpp" "")
#enable debug symbols by default
if(CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
#(you can also set on cl: -D CMAKE_BUILD_TYPE=Release)
#place outside of Debug/Release folders
#see http://www.cmake.org/Wiki/CMake_Useful_Variables
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin")
if(WIN32)
set(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}")
else()
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
endif()
#see https://stackru.com/questions/10851247/how-to-activate-c-11-in-cmake
if (CMAKE_VERSION VERSION_LESS "3.1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}")
endif()
else()
set(CMAKE_CXX_STANDARD 11)
endif()
#set the source directory
file(GLOB SOURCES src/*.cpp)
add_subdirectory(py_shape)
#define sources and executable
add_executable(${PROJECT_NAME} ${SOURCES})
add_dependencies(${PROJECT_NAME} python_shape)
py_shape / CMakeLists.txt
#set file variables
file(GLOB SOURCE src/*.cpp)
file(GLOB HEADERS inc/*.hpp)
#build the library
add_library(python_shape MODULE ${SOURCE})
set_target_properties(python_shape PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/python")
#drop "lib" from the library name
set_target_properties(python_shape PROPERTIES PREFIX "")
if(WIN32)
#set extension to ".pyd"
set_target_properties(python_shape PROPERTIES SUFFIX ".pyd")
endif()
Сейчас python_shape.pyd
создан в python
подкаталог.
Что я изменил / удалил:
- Настройка
..._OUTPUT_DIRECTORY
глобальные переменные у ребенкаCMakeLists.txt
не нужно и / или не будет работать - добавленной
LIBRARY_OUTPUT_DIRECTORY
перезаписать выходной каталог дляpython_shape
MODULE
цель библиотеки (см. также, например, пользовательский каталог для вывода библиотеки CMake) - Удалены настройки "by config", потому что я думаю, что это функция, которая позволяет мультиконфигурации создавать среды, такие как Visual Studio, помещая различные двоичные файлы конфигурации в папки с одинаковыми именами.
- Добавили некоторые
if
заявления вокруг-std=c++11
, Он также должен быть установлен только один раз в главномCMakeLists.txt
- Вам не нужно создавать выходные каталоги "вручную", они создаются автоматически средами make
По причинам, почему ваш первый подход не сработал, смотрите мои комментарии выше.
И я бы не рекомендовал использовать file(GLOB ...)
собирать исходные файлы (см., например, Почему cmake файл GLOB злой? или CMake/Ninja пытается скомпилировать удаленный файл `.cpp`).
альтернативы
Как и во всех языках / фреймворках, таких как CMake
есть больше чем один способ сделать вещи.
Например, вы также можете использовать POST_BUILD
шаги, чтобы скопировать ваши двоичные файлы в общий выходной каталог:
- см. Cmake: используйте add_custom_command, чтобы скопировать двоичный файл в конкретное местоположение, если местоположение не существует
- и - немного более современное использование "выражений генератора" - CMake: как задать разные шаги для разных конфигураций сборки для Visual Studio?