【问题标题】:Compiling C++ code with g++ from Python script on Windows在 Windows 上使用 Python 脚本中的 g++ 编译 C++ 代码
【发布时间】:2016-06-12 13:35:48
【问题描述】:

我正在尝试编写一个 Python 脚本,该脚本通过 subprocess.Popen() 调用 g++.exe 并使用它将 .cpp 文件编译为 .exe。问题是,无论我如何尝试将路径传递给源文件,都会出现以下错误:

g++.exe: 错误: CreateProcess: 没有这样的文件或目录

我的目录结构如下:

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

我的代码是:

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

只是我尝试通过路径的一些方式:

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"]

我也尝试将 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)

总是同样的错误。我以前用过 Popen 很多次,这通常是一件小事,所以我现在很困惑我做错了什么。

【问题讨论】:

  • @PM2Ring - 但是我没有用那条线加入两个绝对路径,我用一个字符串加入了一个绝对路径。我不太担心路径外观,它们只是出于调试目的而打印出来。如果以及当我得到这个工作时,所有打印都会被删除。
  • 听起来你正在尝试创建一个构建系统。为什么不直接使用现有的 SCons (scons.org) 或 CMake (cmake.org)?

标签: python c++ g++ popen


【解决方案1】:

找不到的不是client.cpp文件,而是g++.exe。您可以知道,因为是CreateProcess 产生了错误。如果是 cpp 文件,CreateProcess 会成功,然后编译器才会返回错误。

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

这会根据您提供的相对路径构建绝对路径。相对的意思是相对于当前目录,而不是python文件所在的目录。

如果你的 g++ 在固定树中,更好的方法应该是从脚本名称构造路径,如下所示:

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

在您使用abspath 表示与当前工作目录无关的其他地方也是如此。

【讨论】:

  • 尝试一下,我只是得到“系统找不到指定的路径”。我假设这次是实际的编译器错误,而 client.cpp 是问题所在?
  • 可能是。是否引发了异常,如果是,是什么?
  • 另外,如果您还有 cwd=self.sourceDir,请检查它是否也是有效路径(使用 __file__ 构造它,就像您刚刚更改 gccPath 一样)。
  • 没有例外,唯一的输出是1 The system cannot find the path specified。当我尝试以这种方式构造 self.sourceDir 时,子进程(_execute_child)出现异常; WindowsError: [错误 267] 目录名无效。
  • 如果没有异常,则Popen成功,你看到的错误来自g++.exe。所以你成功地修复了 g++ 的路径。下一步,修复client.cpp的路径。
【解决方案2】:

我能够解决我自己的问题并使用以下代码获得一个正常工作的 .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

命令最终是:

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

路径看起来很难看,但很有效。从 srcFiles 手动删除 sourceFile 有点笨拙,但似乎有必要在命令中首先引用主文件。

This answer 非常有用,它允许我将 PATH 环境变量临时设置为我有 g++.exe 所在的任何目录。感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 2022-01-09
    • 2015-11-05
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2015-01-11
    • 1970-01-01
    相关资源
    最近更新 更多