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

查看:1411
本文介绍了父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特定的库,所有的libs放置在/ lib文件夹,并且python的lib被放置到/ 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)

-Child 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)


推荐答案

将我的评论变成答案

Turning my comments into an answer

我使用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 http://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.

我更改/删除的内容:

  • 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`文件)。

strong>替代方法

Alternatives

与所有语言/框架如 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:

  • see Cmake: use add_custom_command to copy binary to specific location failed when location doesn't exist
  • and - a little more up-to-date utilizing "generator expressions" - CMake: how to specify different steps for different build configurations for Visual Studio?

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

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