父 CMakeLists.txt 覆盖子 CMakeLists.txt 输出目录选项 [英] Parent CMakeLists.txt overwriting child CMakeLists.txt output directory options
问题描述
我试图将项目中的库放入构建输出中的某个目录中,但父 CMakeLists.txt 正在覆盖输出设置.父 CMakeLists.txt 将所有库设置为放置在/lib 目录中.
I am trying to place a library from a project into a certain directory in my build output, but the parent CMakeLists.txt is overwriting the output settings. The parent CMakeLists.txt sets all libraries to be placed in a /lib directory.
但是,我的一个库需要放入/python 库中.我在 Windows 上的设置.意思是,除了我的 python 特定库之外的所有库都放在/lib 文件夹中,而 python 库放在/python 文件夹中.
One of my libraries, however, needs to be placed into a /python library. The settings I have work on Windows. Meaning, all libs excluding my python specific library get placed in a /lib folder, and the python lib gets placed into the /python folder.
当我在 Linux 上构建时出现问题.所有的库,包括 python 特定的库,都放在/lib 文件夹中.FORCE 选项什么也不做.
The problem appears when I build on Linux. All of the libraries, including the python specific library, get placed into the /lib folder. The FORCE option does nothing.
如果我只为一个平台构建,我可以处理任一目录布局.但我真的很想跨平台保留相同的布局.
If I were only building for one platform, I could deal with either directory layout. But I really want to preserve the same layout across platforms.
CMakeLists.txt 如下:
CMakeLists.txt as follows:
-父 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)
-子 CMakeLists.txt
-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)
推荐答案
将我的评论变成答案
我成功地使用 MinGW 和 CMake 3.3.0 测试了以下内容(我将您的示例减少了一点以专注于输出目录):
I successfully tested the following with MinGW and CMake 3.3.0 (I reduced your example a little to concentrate on the output directories):
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://stackoverflow.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
子目录中创建.
Now python_shape.pyd
is created in python
subdirectory.
我更改/删除的内容:
- 在子
CMakeLists.txt
中设置..._OUTPUT_DIRECTORY
全局变量不是必需的和/或不起作用 - 添加了
LIBRARY_OUTPUT_DIRECTORY
覆盖python_shape
MODULE
库目标的输出目录(另见例如 CMake 库输出的自定义目录) - 删除了by config"设置,因为我认为这是一项功能,即像 Visual Studio 这样的多配置生成环境将不同的配置二进制文件放入同名的子文件夹中.
- 在
-std=c++11
周围添加了一些if
语句.它也只需在主CMakeLists.txt
中设置一次 - 您不需要手动"创建输出目录,它们是由 make 环境自动创建的
- Setting the
..._OUTPUT_DIRECTORY
global variables in the childCMakeLists.txt
is not necessary and/or won't work - Added
LIBRARY_OUTPUT_DIRECTORY
to overwrite the output directory forpython_shape
MODULE
library target (see also e.g. Custom Directory for CMake Library Output) - Removed the "by config" settings, because I think it's a feature that multi-configuration make environments like Visual Studio put different configuration binaries into equally named sub-folders.
- Added some
if
statements around-std=c++11
. It has also only to be set once in the mainCMakeLists.txt
- You don't need to create the output directories "manually", they are created automatically by the make environments
有关您的第一种方法不起作用的原因,请参阅我上面的评论.
For the reasoning why your first approach didn't work, see my comments above.
而且我不推荐使用 file(GLOB ...)
收集源文件(参见例如 为什么 cmake 文件 GLOB 是邪恶的? 或 CMake/Ninja 试图编译已删除的 `.cpp` 文件).
And I wouldn't recommend the use of file(GLOB ...)
to collect source files (see e.g. Why is cmake file GLOB evil? or CMake/Ninja attempting to compile deleted `.cpp` file).
替代方案
与像 CMake
这样的所有语言/框架一样,有不止一种方法可以做事.
As with all languages/frameworks like CMake
there is more then one way to do things.
例如您还可以使用 POST_BUILD
步骤将二进制文件复制到公共输出目录:
E.g. you could also use POST_BUILD
steps to copy your binaries to a common output directory:
- 见Cmake:当位置不存在时,使用 add_custom_command 将二进制文件复制到特定位置失败
- 和 - 使用生成器表达式"更新一点 - CMake:如何为 Visual Studio 的不同构建配置指定不同的步骤?
这篇关于父 CMakeLists.txt 覆盖子 CMakeLists.txt 输出目录选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!