unix - guia - Parent CMakeLists.txt sobrescribe las opciones de directorio de salida de CMakeLists.txt hijo
qgis español (1)
Estoy tratando de colocar una biblioteca de un proyecto en un determinado directorio en mi salida de compilación, pero el padre CMakeLists.txt sobrescribe la configuración de salida. El padre CMakeLists.txt establece todas las bibliotecas que se colocarán en un directorio / lib.
Sin embargo, una de mis bibliotecas debe colocarse en una biblioteca / python. La configuración que tengo funciona en Windows. Es decir, todas las librerías excluyendo mi biblioteca específica de python se colocan en una carpeta / lib, y la lib de python se coloca en la carpeta / python.
El problema aparece cuando construyo en Linux. Todas las bibliotecas, incluida la biblioteca específica de Python, se colocan en la carpeta / lib. La opción FORCE no hace nada.
Si solo estuviera construyendo para una plataforma, podría tratar con cualquier diseño de directorio. Pero realmente quiero preservar el mismo diseño en todas las plataformas.
CMakeLists.txt de la siguiente manera:
-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)
Convertir mis comentarios en una respuesta
Probé con éxito lo siguiente con MinGW y CMake 3.3.0 (reduje un poco tu ejemplo para concentrarme en los directorios de salida):
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://.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()
Ahora python_shape.pyd
se crea en el subdirectorio python
.
Lo que he cambiado / eliminado:
- Establecer las variables globales__
..._OUTPUT_DIRECTORY
en el niñoCMakeLists.txt
no es necesario y / o no funcionará - Se agregó
LIBRARY_OUTPUT_DIRECTORY
para sobrescribir el directorio de salida parapython_shape
MODULE
library target (ver también p. Ej. Custom Directory para CMake Library Output ) - Se eliminó la configuración "por configuración", porque creo que es una característica que los entornos de configuración multiconfiguración como Visual Studio pongan diferentes binarios de configuración en subcarpetas igualmente nombradas.
- Se agregaron algunas sentencias
if
alrededor de-std=c++11
. También solo debe establecerse una vez en el principalCMakeLists.txt
- No es necesario que cree los directorios de salida "manualmente", sino que los crea automáticamente
Por el razonamiento de por qué su primer enfoque no funcionó, vea mis comentarios arriba.
Y no recomendaría el uso de file(GLOB ...)
para recopilar archivos fuente (consulte, por ejemplo, ¿Por qué el archivo cmake GLOB está mal? O CMake / Ninja intentando compilar el archivo `.cpp` eliminado ).
Alternativas
Al igual que con todos los lenguajes / marcos como CMake
hay más de una forma de hacer las cosas.
Por ejemplo, también podría usar los pasos de POST_BUILD
para copiar sus binarios en un directorio de salida común:
- vea Cmake: use add_custom_command para copiar el binario a la ubicación específica que falló cuando la ubicación no existe
- y - un poco más actualizado utilizando "expresiones de generador" - CMake: cómo especificar diferentes pasos para diferentes configuraciones de compilación para Visual Studio?