Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:如何编写脚本来编译和运行C++;通过CMake的程序?_Python_C++_Cmake - Fatal编程技术网

Python:如何编写脚本来编译和运行C++;通过CMake的程序?

Python:如何编写脚本来编译和运行C++;通过CMake的程序?,python,c++,cmake,Python,C++,Cmake,假设我有以下项目结构 | CMakeLists.txt | run_experiments.py +---libs \---src main.cpp main.h 如何让运行\u experiments.py通过CMake编译程序,并使用不同的命令行参数多次运行?我所尝试的: # run_experiments.py import os os.system("mkdir bin build") os.chdir("bui

假设我有以下项目结构

|   CMakeLists.txt
|   run_experiments.py
+---libs
\---src
        main.cpp
        main.h
如何让
运行\u experiments.py
通过CMake编译程序,并使用不同的命令行参数多次运行?我所尝试的:

# run_experiments.py

import os

os.system("mkdir bin build")
os.chdir("build")
os.system('cmake -G"Unix Makefiles" ..')
os.system("make")
# and so on...
但它看起来已经很难看了,我正在寻找最优雅、跨平台的解决方案(例如,带有MinGW和Linux的Windows)

UPD:添加了我的
CMakeLists.txt
,这是CLion默认生成的:

cmake_minimum_required(VERSION 3.16)
project(test_tokenizing)

set(CMAKE_CXX_STANDARD 14)

add_executable(test_tokenizing src/main.cpp src/main.h)

如果C++代码不是动态生成的或是什么东西,我建议您在启动Python程序之前先将其构建,然后只从Python程序执行它。 如果您有充分的理由从python代码构建它,我在上为您创建了一个小示例。类似的内容适用于run_experiements.py:

import os
import subprocess


def main():
    os.makedirs('build', exist_ok=True)
    subprocess.check_call('cmake -B build -G "NMake Makefiles"', shell=True)
    subprocess.check_call('cmake --build .', shell=True, cwd='build')

    subprocess.check_call('experiments 1 2 3', shell=True, cwd='build')
    subprocess.check_call('experiments 2 3 4', shell=True, cwd='build')


if __name__ == '__main__':
    main()
我将以下内容用于
main.cpp

#include <iostream>

int main(int argc, char **argv) {
    for (auto i = 0; i < argc; i++)
        std::cout << argv[i] << std::endl;
    return 0;
}

要使其正常工作,您需要正确设置环境以找到所需的工具。在我的例子中,我对python使用Miniconda3,然后使用
“C:\Program Files(x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat”
在路径中获取编译器和cmake


我手边没有Linux机器,但是如果您将
-G
设置为有条件的,并使用
Unix Makefiles
,它可能也可以在Linux(和其他地方)上工作。请注意,您不必在Windows上使用
.exe
,因为shell足够智能,即使您没有指定它也可以启动该程序。

Python的
子进程
模块将使您能够运行外部程序,如CMake和使用它构建的二进制文件。但是,Windows和Linux上的可执行文件名称将不同(Windows具有.exe扩展名)。您应该能够指定
/test\u tokenizing
来运行您的程序,如果您指定当前工作目录
cwd
,系统应该可以找到它

试试这个:

import os
import platform
import subprocess
import sys


def main(*args):
    current_directory = os.getcwd()
    build_dir = os.path.join(current_directory, 'build')

    if not os.path.exists(build_dir):
        os.makedirs(build_dir)

    if platform.system() == 'Windows':
        exe = os.path.join(build_dir, 'test_tokenizing.exe')
    else:
        exe = os.path.join(build_dir, 'test_tokenizing')

    cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + build_dir]
    cmake_args += ['-G', 'Unix Makefiles']

    subprocess.run(['cmake', ".."] + cmake_args, cwd=build_dir, check=True)
    subprocess.run(['cmake', '--build', '.'], cwd=build_dir, check=True)
    p = subprocess.run([exe, *args], cwd=build_dir, capture_output=True, text=True)
    print(p.stdout)


if __name__ == '__main__':
    args = []
    if len(sys.argv) > 1:
        args += sys.argv[1:]
    main(*args)
(对于
子流程中的
捕获输出
文本
,需要Python 3.7+。运行

在这里,您可以向脚本传递命令行参数,如下所示:

python run_experiments.py hello world
并且参数被转发到函数主()/<代码>,这将调用C++的可执行文件。 编辑:


<> >如果<代码> ./Test-ToKeTieln> <代码>在一些异国操作系统上不起作用,或者您想包含一些特定于平台的编译器/构建标志,我已经对上面的平台进行了检查,并指定了C++可执行文件的完整路径。

可以帮助您避免一些特定于平台的二进制文件,如<代码>生成< /C>。您可以使用避免调用某些特定于操作系统的命令之类的方法。您可能仍然需要一个子进程来调用
cmake
,为此,我建议使用该模块,而不是
os.system
。跨哪个平台?@MarkSetchell Windows和Linux。除非项目中的
CMakeLists.txt
包含运行可执行文件的目标,否则您需要使用该可执行文件的名称来运行它。这个名字肯定是依赖于平台的(在Windows上有
.exe
扩展,在Linux上没有扩展)。从您对@jignatius的回答来看,我想您的问题是您和您的同事没有一个一致的构建环境,这就是为什么您不能假设CMake、NMake或Visual Studio在这条道路上。因此,也许这是一个可以解决的角度,例如,通过在docker容器中提供构建环境,或者使用像Conan这样的包管理器,不仅打包库依赖项,而且打包构建工具。关于CMake 3.19:如果这是让python调用CMake的唯一剩余原因,那么您可以从源代码构建它并将其安装到git repo中。“要使其正常工作,您需要正确设置环境以找到所需的工具”-这就是问题所在。脚本必须准备好使用“开箱即用”,除了用户必须向路径添加CMake和Make的时候,就像我在MinGW中所做的那样。这段代码适用于它,但它不适用于Linux,在Linux中,可执行文件必须以
/
作为前缀。无论如何,感谢您努力回答我的问题。升级。通过运行build/experiments而不更改到build文件夹,您可以避免在unix上使用./。。。这在Windows上会导致一个小问题,因为您需要在那里使用相反的斜杠。但是您可以使用路径分隔符的
os.path.sep
来构造正确的路径。。。会有类似的事情发生,不幸的是,它们会使解决方案变得越来越长。您希望在windows上支持什么构建系统?我担心总有一些预先设置,以便把他们的路径。。。MSVC?明格?Cygwin?谢谢,我已经用MinGW和WSL Ubuntu在Windows上测试过了,它运行得很好。但是为什么要使用
-DCMAKE\u LIBRARY\u OUTPUT\u DIRECTORY=
而不是
-B
?它与C/C++库有什么关系吗?我的项目是可执行的。使用绝对路径和相对路径有什么区别?我们不能只在可执行文件前面加上
/
,就删除系统检查吗?正如另一张海报所说,没有必要在Windows上添加
.exe
。@kenticent您使用前缀
/test\u标记化
是正确的。见我的更新上面。关于,
DCMAKE\u LIBRARY\u OUTPUT\u DIRECTORY=
,我把它放在那里,以防您正在构建一些库。这将为您将它们放在生成文件夹中。谢谢。我希望您使用
if
添加替代版本,因为它在您使用某些外来操作系统或编写依赖于平台的代码时非常有用。@kenticent请参见上面的编辑。
python run_experiments.py hello world