2017-03-17 590 views
1

我试图将C++和Python结合起来,为此我使用了CMake。在CMakeLists.txt中,我试图找到一个程序:从Cmake的find_program保存可执行文件,以便它可以由Python运行

# Check for Gmsh executable 
find_program (GMSH gmsh [/Applications/Gmsh.app/Contents/MacOS/ /usr/bin/ /usr/local/bin/]) 

if(GMSH) 
    message(STATUS "Found Gmsh in: ${GMSH}") 
    set(HAVE_GMSH YES) 
else() 
    set(HAVE_GMSH NO) 
endif() 
message(STATUS "Setting HAVE_GMSH to: ${HAVE_GMSH}") 

因此,这是能够找到没有问题的可执行文件。但不知何故,我必须将它保存到某处,以便稍后可以从Python中调用它。这应该在配置文件中完成吗?什么是正确的方法来做到这一点?

UPDATE

我创建了包含以下内容的文件ProjectConfig.cmake.in:

# Compute paths 
get_filename_component(PROJECT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) 
set(PROJECT_INCLUDE_DIRS "@[email protected]") 

# Our library dependencies (contains definitions for IMPORTED targets) 
include("${PROJECT_CMAKE_DIR}/ProjectTargets.cmake") 

# These are IMPORTED targets created by ProjectTargets.cmake 
set(PROJECT_LIBRARIES core) 
set(PROJECT_EXECUTABLE bar) 

#cmakedefine HAVE_GMSH @[email protected] 
#cmakedefine GMSH @[email protected] 

而且的CMakeLists.txt文件看起来像这样:

cmake_minimum_required(VERSION 3.1) 
project(TestProject) 
enable_language(CXX) 


# Options 

# Offer the user the choice of overriding the installation directories 
set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") 
set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") 
set(INSTALL_INCLUDE_DIR include CACHE PATH 
    "Installation directory for header files") 
if(WIN32 AND NOT CYGWIN) 
    set(DEF_INSTALL_CMAKE_DIR CMake) 
else() 
    set(DEF_INSTALL_CMAKE_DIR lib/CMake/Project) 
endif() 
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH 
    "Installation directory for CMake files") 

# Make relative paths absolute (needed later on) 
foreach(p LIB BIN INCLUDE CMAKE) 
    set(var INSTALL_${p}_DIR) 
    if(NOT IS_ABSOLUTE "${${var}}") 
    set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") 
    endif() 
endforeach() 

# Check for Gmsh executable 
find_program (GMSH gmsh [/Applications/Gmsh.app/Contents/MacOS/ /usr/bin/ /usr/local/bin/]) 

if(GMSH) 
    message(STATUS "Found Gmsh in: ${GMSH}") 
    set(HAVE_GMSH YES) 
else() 
    set(HAVE_GMSH NO) 
endif() 
message(STATUS "Setting HAVE_GMSH to: ${HAVE_GMSH}") 

# Python support 
# 

# find Python 
find_package(PythonInterp) 

# find SWIG 
find_package(SWIG REQUIRED) 
include(${SWIG_USE_FILE}) 

find_package(PythonLibs) 
include_directories(${PYTHON_INCLUDE_PATH}) 

message(STATUS "PYTHON_INCLUDE_PATH: ${PYTHON_INCLUDE_PATH}") 
message(STATUS "PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}") 

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/core) 
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/core/fem) 

#set(CMAKE_SWIG_OUTDIR ${PROJECT_BINARY_DIR}/../lib/project) 

SET_SOURCE_FILES_PROPERTIES(swig/core.i PROPERTIES CPLUSPLUS ON) 
set_source_files_properties(swig/core.i SWIG_FLAGS "-includeall;-c++;-shadow") 
swig_add_module(core python swig/core.i core/foo.cpp) 
swig_link_libraries(core project_core ${PYTHON_LIBRARIES}) 

################################################################################ 
# Directories 
# 

# set up include-directories 
include_directories(
    "${PROJECT_SOURCE_DIR}" # to find core/foo.hpp 
    "${PROJECT_BINARY_DIR}") # to find core/config.hpp 

# Add sub-directories 
add_subdirectory(core) 
add_subdirectory(bar) 

# The interesting stuff goes here 
# =============================== 

# Add all targets to the build-tree export set 
export(TARGETS project_core bar 
    FILE "${PROJECT_BINARY_DIR}/ProjectTargets.cmake") 

# Export the package for use from the build-tree 
# (this registers the build-tree with a global CMake-registry) 
export(PACKAGE Project) 

# Create the ProjectConfig.cmake and ProjectConfigVersion files 
file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}" 
    "${INSTALL_INCLUDE_DIR}") 
# ... for the build tree 
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}") 
configure_file(ProjectConfig.cmake.in 
    "${PROJECT_BINARY_DIR}/ProjectConfig.cmake" @ONLY) 
# ... for the install treew 
set(CONF_INCLUDE_DIRS "\${PROJECT_CMAKE_DIR}/${REL_INCLUDE_DIR}") 
configure_file(ProjectConfig.cmake.in 
    "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/ProjectConfig.cmake" @ONLY) 
# ... for both 
configure_file(ProjectConfigVersion.cmake.in 
    "${PROJECT_BINARY_DIR}/ProjectConfigVersion.cmake" @ONLY) 

# Install the ProjectConfig.cmake and ProjectConfigVersion.cmake 
install(FILES 
    "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/ProjectConfig.cmake" 
    "${PROJECT_BINARY_DIR}/ProjectConfigVersion.cmake" 
    DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) 

# Install the export set for use with the install-tree 
install(EXPORT ProjectTargets DESTINATION 
    "${INSTALL_CMAKE_DIR}" COMPONENT dev) 

现在我不确定结果配置文件的位置(在$ {PROJECT_BINARY_DIR}中)是否是放置它的正确位置。我应该把它放在整个层次结构的根部吗?这是一个大项目,其结构是这样的:

├── AUTHORS.rst 
├── CHANGELOG.rst 
├── CONTRIBUTING.rst 
├── LICENSE 
├── MANIFEST.in 
├── Makefile 
├── README.rst 
├── core 
│   ├── CMakeLists.txt 
│   ├── ProjectConfig.cmake.in 
│   ├── ProjectConfigVersion.cmake.in 
│   ├── Makefile 
│   ├── bar 
│   ├── core 
│   └── swig 
├── setup.cfg 
├── setup.py 
├── src 
│   └── project 
├── tests 
│   └── unit 
└── tox.ini 

回答

0

的常用方法是使用configure_file搜索和替换其中的CMake变量。例如,假设你有一个头文件名为foo.h.in

#define HAVE_GMSH ${HAVE_GMSH} 

然后在CMake的调用

configure_file(foo.h.in ${CMAKE_BINARY_DIR}/foo.h) 

然后它会替换该文件的所有CMake的变量。通常表示法是将0用于“否”,而1用于“是”。所以,如果你set(HAVE_GMSH 1),这将扩大到

#define HAVE_GMSH 1 

然后,您必须确保包含目录的输出文件中,例如target_include_directories(mytarget ${CMAKE_BINARY_DIR})(当然,这是把产生的良好做法包括子目录中的文件但是不要将输出文件放在源目录中)。

CMake文档提到您也可以使用特殊的@[email protected]进行展开。在这种情况下,请使用@ONLYconfigure_file。它还提供#cmakedefine

您可以对Python文件使用相同的方法。许多项目在CMake变量中定义作者,版本等,然后提供一个setup.py.in文件,该文件被搜索并替换为configure_file

+0

我用你的建议更新了我的答案。我仍然不清楚如何使用Python调用可执行文件。 – aaragon

相关问题