Reputation: 681
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. 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
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:
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.
Upvotes: 1
Views: 3750
Reputation: 681
I was able to solve my own problem and get a working .exe with the following code:
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.
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.
Upvotes: 0
Reputation: 13552
It is not the client.cpp
file that is not found, but the g++.exe
. You can know that because it is CreateProcess
that generates the error. If it was the cpp file, CreateProcess
would succeed, and only then would the compiler return with an error.
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.
If your g++ is in a fixed tree, a better way should be to construct the path from the script name, like this:
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.
Upvotes: 0