父 CMakeLists.txt 覆盖子 CMakeLists.txt 输出目录选项 [英] Parent CMakeLists.txt overwriting child CMakeLists.txt output directory options

查看:36
本文介绍了父 CMakeLists.txt 覆盖子 CMakeLists.txt 输出目录选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将项目中的库放入构建输出中的某个目录中,但父 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.pydpython 子目录中创建.

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 child CMakeLists.txt is not necessary and/or won't work
  • Added LIBRARY_OUTPUT_DIRECTORY to overwrite the output directory for python_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 main CMakeLists.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:

这篇关于父 CMakeLists.txt 覆盖子 CMakeLists.txt 输出目录选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆