简体   繁体   English

在Windows上使用Python脚本中的g ++编译C ++代码

[英]Compiling C++ code with g++ from Python script on Windows

I'm trying to write a Python script that calls g++.exe via subprocess.Popen() and uses it to compile a .cpp file into an .exe. 我正在尝试编写一个Python脚本,通过subprocess.Popen()调用g ++。exe并使用它将.cpp文件编译成.exe文件。 The problem is that no matter how I try to pass the path to the source file, I get the following error: 问题是,无论我如何尝试将路径传递给源文件,我都会收到以下错误:

g++.exe: error: CreateProcess: No such file or directory g ++。exe:错误:CreateProcess:没有这样的文件或目录

My directory structure is as follows: 我的目录结构如下:

D:/Test/test.py
D:/Test/external/mingw64/g++.exe
D:/Test/c/client/client.cpp

And my code is: 我的代码是:

import os, subprocess

class builder():
    def __init__(self):
        self.gccPath = os.path.abspath("external/mingw64/g++.exe")
        self.sourceDir = os.path.abspath("c/client")
        self.fileName = "client.cpp"
        self.sourceFile = os.path.join(self.sourceDir, self.fileName)

    def run(self):
        command = [self.gccPath, self.sourceFile , "-o", "client.exe"]
        print command
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        n=1
        while True:
            nextLine = process.stdout.readline()
            if nextLine == '' and process.poll() != None:
                break
            if nextLine != "" and nextLine != None:
                print n, nextLine
            n=n+1

builder = builder()
builder.run()

Just some of the ways I've tried to pass the path: 只是我试图通过这条道路的一些方法:

Command: ["D:\\Test\\external\\mingw64\\g++.exe", "c/client/client.cpp", "-o", "client.exe"]
Command: ["D:\\Test\\external\\mingw64\\g++.exe", "c\\client\\client.cpp", "-o", "client.exe"]
Command: ["D:\\Test\\external\\mingw64\\g++.exe", "D:\\Test\\c\\client\\client.cpp", "-o", "client.exe"]

I also tried passing cwd to Popen: 我也尝试过将cwd传递给Popen:

command = [self.gccPath, "client.cpp", "-o", "client.exe"]
process = subprocess.Popen(command, shell=True, cwd=self.sourceDir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Always the same error. 总是一样的错误。 I've used Popen plenty of times before and it's usually a trivial matter, so I'm pretty stumped right now as to what I'm doing wrong. 我以前曾经多次使用过Popen而且这通常是一件小事,所以我现在对于我做错了什么很难过。

It is not the client.cpp file that is not found, but the g++.exe . 它不是找不到的client.cpp文件,而是g++.exe You can know that because it is CreateProcess that generates the error. 您可以知道,因为CreateProcess是生成错误的。 If it was the cpp file, CreateProcess would succeed, and only then would the compiler return with an error. 如果它是cpp文件, CreateProcess将成功,只有这样编译器才会返回错误。

os.path.abspath("external/mingw64/g++.exe")

This builds an absolute path from the relative path you give. 这将根据您给出的相对路径构建绝对路径。 Relative means relative to current directory, not to the directory of the python file. 相对意味着相对于当前目录,而不是相对于python文件的目录。

If your g++ is in a fixed tree, a better way should be to construct the path from the script name, like this: 如果你的g ++在一个固定的树中,更好的方法应该是从脚本名称构造路径,如下所示:

os.path.join(os.path.dirname(__file__), "external/mingw64/g++.exe")

Holds true for other places where you use abspath for something not relative to current working directory. 对于使用abspath而不是与当前工作目录相关的其他地方,保持为true。

I was able to solve my own problem and get a working .exe with the following code: 我能够解决自己的问题,并使用以下代码获得一个有效的.exe:

import os, subprocess, json, glob

class client():
    def __init__(self):
        self.gccDir = os.path.abspath("external/mingw64")
        self.sourceDir = "c/client"
        self.fileName = "client.cpp"
        self.sourceFile = os.path.join(self.sourceDir, self.fileName)
        self.destFile = self.sourceFile.replace(".cpp", ".exe")

    def run(self):
        srcFiles = glob.glob(os.path.join(self.sourceDir+"/*.cpp"))
        srcFiles.remove(self.sourceFile)
        myEnv = os.environ.copy()
        myEnv["PATH"] = myEnv["PATH"]+";"+self.gccDir
        command = ["g++.exe", self.sourceFile, " ".join([x for x in srcFiles]), "-std=c++11", "-Os", "-o", self.destFile]
        process = subprocess.Popen(command, shell=True, env=myEnv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        n=1
        while True:
            nextLine = process.stdout.readline()
            if nextLine == '' and process.poll() != None:
                break
            if nextLine != "" and nextLine != None:
                print n, nextLine
            n=n+1

The command ends up being: 该命令最终成为:

['g++.exe', 'c/client\\client.cpp', 'c/client\\utils.cpp', '-std=c++11', '-Os', '-o', 'c/\\client.exe']

Paths look ugly but work. 路径看起来很难看但很有效。 The manual removing of sourceFile from srcFiles is a bit clumsy, but it seems necessary that the main file is the first to be referenced in the command. 手动从srcFiles中删除sourceFile有点笨拙,但似乎必须首先在命令中引用主文件。

This answer was very useful and allowed me to temporarily set the PATH environment variable to whatever directory I had g++.exe in. Thanks to everyone for trying to help. 这个答案非常有用,允许我暂时将PATH环境变量设置为我有g ++。exe的目录。感谢大家试图提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM