setting up MSVC in Visual Studio code

1k Views Asked by At

I installed MSVC as directed in Microsoft's documentation for Visual Studio Code, but I cannot compile anything unless I launch VS code from the dev command line after also CD-ing to my code directory.

I was expecting to be able to open VS code, start a project, write some code and then hit the compile button. instead I get a "cl.exe build and debug is only usable when VS Code is run from the Developer Command Prompt for VS." error. why can't I just run code? this seems super clunky if every time I have to open my IDE, I have to do it from a special command line instead of just opening the IDE. do I need to add some things to my path to get Visual Studio Code to just pick up the MSVC compiler (I'd prefer to use VS code as I'm used to it from the other time's I've started learning to code, so I'm comfortable with it & would rather not switch to normal visual studio or anything else)

1

There are 1 best solutions below

0
LuigiBro On

There are two main options when using MSVC.

  1. You can use the Code Runner extension by Jun Han and adjust the settings for the MSVC compiler in the executor map:
    "cpp": "cd $dir && cl /EHsc *.cpp /Fo..\\obj\\ /Fe..\\out\\Program.exe && ..\\out\\Program"

    Remember, your compiler must be in your path if you use this method and debugging is more annoying. Projects can be set up faster though.

    Something really important to mention is that your projects get compiled for the 32x Version. This will only change when running the 64x dev command prompt. Run >cl to see the version you will compile to.
  2. I suggest this option. You can use the CMake extensions called CMake and CMake Tools by Microsoft and create a CMakeLists.txt file. You can choose the version to compile to; debugging and compiling for release is extremely easy and more complicated projects will rely on CMake.

This is what my default CMakeLists.txt file looks like:

cmake_minimum_required(VERSION 3.4)  
project(PROJECT_NAME)

set(CMAKE_CXX_STANDARD 17)

add_executable(PROJECT_NAME src/main.cc)

A long time ago I also made this piece of python code. It will launch VS Code with the 64x dev shell, as long as your projects are located in C:\dev.

import shutil
import subprocess
import os
from datetime import datetime

class Manager:
    def __init__(self, dirName="C:/dev/") -> None:
        self.dir: str = dirName
        self.projects = self.LoadFromDir()
        print(self.projects)

    def UiDelPr(self, attributes):
        if len(attributes) < 1:
            log = "Err: Name not specified, prompt needed"
        else:
            log = self.DelPr(attributes[0])
        print(log)

    def DelPr(self, name: str) -> str:
        if name == "CppTemp":
            return "This Template can not be deleted"
        if name not in self.projects:
            return f"Project not found in current directory:\n{self.projects}"
        try:
            shutil.rmtree(self.dir + name)
        except:
            return f"Unexpected error ocurred"
        return "Project deleted successfully"

    def UiRenPr(self, attributes):
        if len(attributes) < 1:
            log = "Err: Name not specified, prompt needed"
        elif len(attributes) < 2:
            log = "Err: New name not specified, prompt needed"
        else:
            log = self.RenPr(attributes[0], attributes[1])
        print(log)

    def RenPr(self, oName: str, nName: str) -> str:
        if oName == "CppTemp":
            return "This Template can not be deleted"
        if oName not in self.projects:
            return f"Project not found in current directory:\n{self.projects}"
        try:
            os.rename(self.dir + oName, self.dir + nName)
        except:
            return f"Unexpected error ocurred"
        return "Project renamed successfully"

    def UiMakePr(self, attributes):
        if len(attributes) < 1:
            log = "Err: Name not specified, prompt needed"
        elif len(attributes) == 1:
            log = self.MakePr(attributes[0])
        else:
            log = self.MakePr(attributes[0], attributes[1])
        print(log)

    def MakePr(self, name: str, template="CppTemp") -> str:
        if name in self.projects:
            return f"Project name already used:\n{self.projects}"
        if template not in self.projects:
            return f"Template not found in current directory:\n{self.projects}"
        try:
            shutil.copytree(self.dir + template, self.dir + name)
        except:
            return f"Unexpected error ocurred"
        return f"Project created successfully"

    def UiExecute(self, attributes):
        if len(attributes) < 1:
            log = "Err: Name not specified, prompt needed"
        else:
            path = f"{self.dir}{attributes[0]}/out/Program.exe"
            print(f"\033[29;0m{attributes[0]} - {path}")
            if len(attributes) == 1:
                log = self.Execute(path)
            else:
                log = self.Execute(path, attributes[1])
        print(log)

    def Execute(self, path, newWindow=""):
        if not os.path.exists(path):
            return f"Program has no executable in {path}"
        try:
            if newWindow == "n":
                subprocess.Popen(["start", path], shell=True)
            else:
                subprocess.run([path])
        except:
            return "Unexpected error ocurred, failed to execute"
        return "Executed successfully"

    def UiLaunch86(self, attributes):
        self.UiLaunch(attributes, "x86")

    def UiLaunch(self, attributes, version="amd64"):
        if len(attributes) < 1:
            log = "\033[0;31mErr: Name not specified, prompt needed"
        else:
            log = self.Launch(attributes[0], version)
        print(log)

    def Launch(self, name, version):
        if name not in self.projects:
            return f"\033[0;31mProject not found in current directory:\n{self.projects}"
        try:
            print(f"\033[29;0m{self.dir}{name}")
            subprocess.call(
                f'cmd /c ""C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat" {version} && cl && cd {self.dir}{name} && code ."'
            )
        except:
            return "\033[0;31mUnexpected error ocurred, failed to launch"
        return "\033[29;0mProject launched successfully"

    def UiList(self, attributes):
        print(f"\033[29;0mName\t\t    Compiled\t\tLast compiled\t\tSize (kb)")
        for project in self.projects:
            stats = os.stat(f"{self.dir}{project}/out")
            name = project.ljust(20)
            time = datetime.fromtimestamp(stats.st_mtime).strftime("%d.%m.%Y  %H:%M")
            size = self.GetSizeOf(project) // 1024
            isAvailable = (
                "exe available"
                if os.path.exists(f"{self.dir}{project}/out/Program.exe")
                else "exe not available"
            )
            print(f"{name}{isAvailable}\t{time}\t{size}")
        return

    def GetSizeOf(self, name) -> int:
        size = 0
        path = self.dir + name
        for dirPath, dirNames, fileNames in os.walk(path):
            for file in fileNames:
                file_path = os.path.join(dirPath, file)
                if not os.path.islink(file_path):
                    size += os.path.getsize(file_path)
        return size

    def LoadFromDir(self):
        return [
            f for f in os.listdir(self.dir) if os.path.isdir(os.path.join(self.dir, f))
        ]

    def UiHelp(self, attributes):
        if len(attributes) < 1:
            print(
                "\033[1;33mmkPr\033[1;30m\t- Create a directory containing a project, based on the template that you chose"
            )
            print("\033[1;33mrmPr\033[1;30m\t- Delete a directory containing a project")
            print("\033[1;33mren\033[1;30m\t- Rename a project")
            print(
                "\033[1;33mcode\033[1;30m\t- Launch a project in VSCode using the MSVC compiler"
            )
            print(
                "\033[1;33mrun\033[1;30m\t- If available, runs Program.exe of a project"
            )
            print(
                "\033[1;33mls\033[1;30m\t- Prints the project directory or a specific project, with all its information"
            )
            print(
                '\033[1;33mhelp\033[1;30m\t- Prints informations about the available commands, write "help [command]" to see more information about the command'
            )
            print("\033[1;33mclear\033[1;30m\t- Clears the console")
            return
        commandSyntax = {
            "mkPr": "mkPr [project name] (optional)[template name]",
            "rmPr": "rmPr [project name]",
            "ren": "ren [project name] [new project name]",
            "code": "launch [project name]",
            "run": "launch [project name] (optional, to run in new Window)[n]",
            "ls": "ls",
            "help": "help [command]",
        }
        try:
            print("\033[1;37m" + commandSyntax[attributes[0]])
        except KeyError:
            print("Command not found")
            self.UiHelp([])

    def UiNewLine(self, attributes):
        return


if __name__ == "__main__":
    manager = Manager()
    funcDict = {
        "mkPr": manager.UiMakePr,
        "rmPr": manager.UiDelPr,
        "ren": manager.UiRenPr,
        "ls": manager.UiList,
        "code": manager.UiLaunch,
        "codex64": manager.UiLaunch,
        "codex86": manager.UiLaunch86,
        "help": manager.UiHelp,
        "run": manager.UiExecute,
        "": manager.UiNewLine,
    }

    while True:
        command = input("\033[1;37m>\033[1;33m ")
        if command == "exit":
            break
        elif command == "clear":
            os.system("cls")
        else:
            command = command.split(" ")
            try:
                funcDict[command.pop(0)](command)
            except KeyError:
                print(f"\033[0;31mCommand not found!")
                funcDict["help"]([])
            finally:
                manager.projects = manager.LoadFromDir()

    print("Finished executing")
else:
    print("Error - Executed from outside")