#!/usr/bin/python3 import os import sys import argparse Usage = \ ( "Convert Visual Studio .vcxproj file in current directory to Makefile and run make." ) AP = argparse.ArgumentParser(description = Usage) # Value opts AP.add_argument("--std", required=False, help="C++ standard option for GCC, e.g. c++11 or c++17 (default none)") AP.add_argument("--cppcompiler", required=False, default="g++", help="C++ compiler command name default g++)") AP.add_argument("--ccompiler", required=False, default="gcc", help="C++ compiler command name default gcc)") # Flag opts AP.add_argument("--debug", required=False, action='store_true', help="Debug build") AP.add_argument("--openmp", required=False, action='store_true', help="Requires OMP") AP.add_argument("--pthread", required=False, action='store_true', help="Requires pthread") AP.add_argument("--lrt", required=False, action='store_true', help="Requires lrt") AP.add_argument("--symbols", required=False, action='store_true', help="Debug symbols (default if --debug)") AP.add_argument("--nostrip", required=False, action='store_true', help="Don't strip symbols (default if --debug or --symbols)") Args = AP.parse_args() debug = Args.debug std = Args.std cppcompiler = Args.cppcompiler ccompiler = Args.ccompiler nostrip = debug or Args.symbols symbols = debug or Args.symbols ProjFileName = None HdrNames = [] for FileName in os.listdir("."): if FileName.endswith(".vcxproj"): ProjFileName = FileName elif FileName.endswith(".h"): HdrNames.append(FileName) if ProjFileName is None: sys.stderr.write("\nProject file not found in current directory\n") sys.exit(1) binary = ProjFileName.replace(".vcxproj", "") sys.stderr.write("binary=" + binary + "\n") compiler_opts = " -ffast-math -march=native" linker_opts = " -ffast-math -march=native" if std: compiler_opts += " --std=" + std if debug: compiler_opts += " -O0 -DDEBUG" linker_opts += " -O0" else: compiler_opts += " -O3 -DNDEBUG" linker_opts += " -O3" if symbols: compiler_opts += " -g3" linker_opts += " -g3" if Args.openmp: compiler_opts += " -fopenmp" linker_opts += " -fopenmp" if Args.pthread: compiler_opts += " -pthread" linker_opts += " -lpthread" rc = os.system('test -z $(git status --porcelain) 2> /dev/null') if rc != 0: sys.stderr.write("\n\nWarning -- Uncommited changes\n\n") rc = os.system(r'echo \"$(git log --oneline | head -n1 | cut "-d " -f1)\" | tee gitver.txt') if rc != 0: sys.stderr.write("\n\nERROR -- failed to generate gitver.txt\n\n") sys.exit(1) sys.stderr.write("gitver.txt done.\n") rc = os.system(r'rm -rf o/ ../bin/%s*' % binary) if rc != 0: sys.stderr.write("\n\nERROR -- failed to clean\n\n") sys.exit(1) sys.stderr.write("clean done.\n") OBJDIR = "o" BINDIR = "../bin" Fields = ProjFileName.split("/") n = len(Fields) Name = Fields[n-1] Fields = Name.split(".") binary = Fields[0] CXXNames = [] CNames = [] with open(ProjFileName) as File: for Line in File: Line = Line.strip() Line = Line.replace('"', '') Line = Line.replace(' ', '') # if Line.startswith("", "") if FileName.endswith(".cpp"): FileName = FileName.replace(".cpp", "") CXXNames.append(FileName) elif FileName.endswith(".c"): FileName = FileName.replace(".c", "") CNames.append(FileName) assert len(CXXNames) > 0 or len(CNames) > 0 with open("Makefile", "w") as f: def Out(s): print(s, file=f) BINPATH = "$(BINDIR)/%s" % (binary) Out("######################################################") Out("# Makefile is generated by " + sys.argv[0]) Out("# Don't edit the Makefile -- update the python script") Out("######################################################") Out("") Out("BINDIR := %s" % BINDIR) Out("OBJDIR := %s" % OBJDIR) Out("BINPATH := %s" % BINPATH) if CNames: Out("") Out("CC = " + ccompiler) Out("CFLAGS := $(CFLAGS) " + compiler_opts) if CXXNames: Out("") Out("CXX = " + cppcompiler) Out("CXXFLAGS := $(CFLAGS) " + compiler_opts) Out("") Out("UNAME_S := $(shell uname -s)") Out("LDFLAGS := $(LDFLAGS) " + linker_opts) Out("ifeq ($(UNAME_S),Linux)") Out(" LDFLAGS += -static") Out("endif") Out("") Out("HDRS = \\") for Name in sorted(HdrNames): Out(" %s \\" % Name) Out("") Out("OBJS = \\") for Name in CXXNames: Out(" $(OBJDIR)/%s.o \\" % (Name)) for Name in CNames: Out(" $(OBJDIR)/%s.o \\" % (Name)) Out("") Out(".PHONY: clean") Out("") Out("$(BINPATH) : $(BINDIR)/ $(OBJDIR)/ $(OBJS)") if len(CXXNames) > 0: Cmd = "\t$(CXX) $(LDFLAGS) $(OBJS) -o $(BINPATH)" else: Cmd = "\t%(CC) $(LDFLAGS) $(OBJS) -o $(BINPATH)" if Args.lrt: Cmd += " -lrt" Out(Cmd) if not nostrip: Out(" strip $(BINPATH)") Out("") Out("$(OBJDIR)/ :") Out(" mkdir -p $(OBJDIR)/") Out("") Out("$(BINDIR)/ :") Out(" mkdir -p $(BINDIR)/") if CNames: Out("") Out("$(OBJDIR)/%.o : %.c $(HDRS)") Out(" $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<") if CXXNames: Out("") Out("$(OBJDIR)/%.o : %.cpp $(HDRS)") Out(" $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<") sys.stderr.write("Makefile done.\n") rc = os.system("make 2> make.stderr | tee make.stdout") if rc != 0: os.system("tail make.stderr") sys.stderr.write("\n\nERROR -- make failed, see make.stderr\n\n") sys.exit(1) sys.stderr.write("make done.\n") os.system("ls -lh ../bin/" + binary + "\n")