【问题标题】:Using CMake to build a platform agnostic directory structure使用 CMake 构建与平台无关的目录结构
【发布时间】:2015-08-23 18:59:36
【问题描述】:

我正在尝试为我的跨平台项目创建目录结构,但遇到了一些问题。我让 CMake 确定放置我的库和可执行文件的适当位置,但该结构仅适用于 Windows。

我的结构如下所示:

  • 项目目录
      • 可执行文件
    • 蟒蛇
      • 升压模块
      • python 脚本

这在 Windows 上运行良好,我将我的模块编译为 .pyd 并将其放在 python 文件夹中。不过,问题出现在我的 Linux 版本上。它没有将 boost-module.so 放入我的 python 文件夹,而是将其放入我的 lib 文件夹和测试库中。

我目前有 3 个 CMakeLists.txt 文件。一个在我的可执行文件的根项目中。第二个是在我写的一个小型测试库中。第三个是我构建的一个测试 boost::python 模块,它从第二个导出一个类。它们如下,按上面列出的顺序。

基地:

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)

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

#install target
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)

测试库:

cmake_minimum_required(VERSION 2.8)

#set the project name and type
project(shape CXX)

#test for windows
if(WIN32)
#build DLL
    include(GenerateExportHeader)
endif(WIN32)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

#set file variables
file(GLOB SOURCE src/*.cpp)
file(GLOB HEADERS inc/*.hpp)

#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
#test for Windows again
if(WIN32)
    #generate the export header for the .dll
    #generate_export_header(shape
    #                       BASE_NAME shape
    #                       EXPORT_MACRO_NAME shape_EXPORT
    #                       EXPORT_FILE_NAME shape_Export.h
    #                       STATIC_DEFINE shape_BUILT_AS_STATIC)
    add_library(shape STATIC ${SOURCE})
elseif(UNIX)
    add_library(shape SHARED ${SOURCE})
endif(WIN32)

#Enable C++11 if it is available
target_compile_features(shape PRIVATE cxx_range_for)
#link library
target_link_libraries(shape ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${SFML_LIBRARIES})
#drop "lib" from the library name
set_target_properties(shape PROPERTIES PREFIX "")

Boost Python 模块:

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 ${CMAKE_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()

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

非常感谢任何帮助或指导。

【问题讨论】:

    标签: python c++ cmake cross-platform boost-python


    【解决方案1】:

    LIBRARY_OUTPUT_DIRECTORY 的 CMake 文档说:

    可以构建三种目标文件:存档、库和运行时。可执行文件始终被视为运行时目标。静态库始终被视为归档目标。模块库始终被视为库目标。对于非 DLL 平台,共享库被视为库目标。对于 DLL 平台,共享库的 DLL 部分被视为运行时目标,相应的导入库被视为存档目标。包括 Cygwin 在内的所有基于 Windows 的系统都是 DLL 平台。

    所以你需要改变:

    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)
    

    进入:

    SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY  ${OUTPUT_BINDIR} CACHE PATH "build directory")
    

    在你的 boost python CMakeLists.txt 中。 ${CONF} 变体也一样。

    【讨论】:

    • 不幸的是,这并不能解决问题。我的 boost 模块 (.so) 仍然放在 Linux 上的 /lib 目录中。它在 Windows 上没有改变,仍然放置在正确的位置。还有其他想法吗?至少,您帮助简化了我的 CMakeLists.txt,这很棒。
    • 我认为没有任何改变,因为您使用了CACHE。所有路径都已在“Base”CMakeLists.txt 中设置并缓存,因此不会在“boost python”CMakeLists.txt 中进行修改。您可以尝试在“boost python”CMakeLists.txt 中使用FORCE,或者不要全局缓存/设置路径等。请参阅CMake 文档以获取SET
    猜你喜欢
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2011-11-08
    • 2012-04-18
    • 2014-10-06
    • 1970-01-01
    相关资源
    最近更新 更多