I was rather pleased about getting a C Makefile to work under Windows 10. Even contemplated leaving it at that. But, I decided to dig deep and try to get the whole thing working from within VSCode eliminating, if possible, the need to go out to a terminal window and doing things more manually.

VSCode Extensions

Based on what I read during my internet searches, I decided to install two VSCodel extensions.

  • C/C++ for VSCode ms-vscode.cpptools
    C/C++ IntelliSense, debugging, and code browsing.

  • Code Runner formulahendry.code-runner
    Run code snippet or code file for multiple languages. Including: C, C++, Python,…

I wouldn’t bother going through the steps.

But, I did have to edit the code-runner.executorMap. Changing the “c” entry to read as follows (mostly because I don’t have gcc set in my PATH environment variable.) You will have to adjust yours accordingly, or not at all depending on how you install gcc.

    "c": "cd $dir &&  E:\\appDev\\TDM-GCC-64\\bin\\gcc $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",

I am a little unsure about the how the above all went as it happened a while back and I didn’t take notes. Most unusual for me, but…

Now, if I open my simplest C code file in VSCode, and enter Ctrl+Alt+N, it does run. But, it runs in the VSCode Output window. Which does not permit user input. And, of course, my hello, you code which uses the CS50 library does not compile.

content of VS Code Output window after attempting to build and execute the two c program files mentioned above

Oops! Ran the first one twice.

After this is where things started getting difficult. The stuff I was finding on-line really wasn’t meant for a true beginner. And, as of yet I have not tried to implement any of it. So, is likely going to be a tough slog trying to write the rest of this post. And, very possible I will ultimately fail.

And, I have just recently seen this article, don’t know it will affect things.

In fact, I may just try to get the latter working and forget about getting things working with the above two extensions.

Makefile Tools

Okay, I have for now decided to give the new make file extension a shot.

  • Makefile ToolsPreview ms-vscode.makefile-tools
    Provide makefile support in VS Code: C/C++ IntelliSense, build, debug/run.

Again, not going to cover the installation. But, I did have to change the setting for Makefile: Make Path. So, File > Preferences > Settings and then selecting makefile under Extensions. This setting tells the extension where to find the make application. So, I set it to E:\appDev\TDM-GCC-64\bin\mingw32-make. Once the make path was set, I was prompted to allow Makefile Tools to configure IntelliSense. I, of course, selected Allow. (That bit is covered in one or both of the relevant resources.)

setting make path setting for Makefile Tools

I am in my normal VSCode CS50 workspace. I am going to try to use the extension to run the Makefile in the play_stuff directory to compile the simple rek_hello.c into hello_world.exe. I clicked on the build icon, and set the build target to all. Then clicked the build icon/button. Didn’t go so well.

Building the current target. Command: E:\appDev\TDM-GCC-64\bin\mingw32-make.exe all
mingw32-make: *** No rule to make target 'all'.  Stop.
Target all failed to build.
No configurations defined in makefile.configurations setting.

Configuration Issue?

The following was near the top of the Makefile Tools market place page

Activating the extension

The extension will activate when it finds a Makefile in your ${workspaceFolder}. If your Makefile does not reside in the root of your folder, use the makefile.makefilePath setting to instruct the extension where to find it. the Makefile: commands from VS Code’s command palette.

Note: the extension will not activate automatically if your Makefile is not in the root of your workspace folder. If this is the case, you will need to manually activate it by running one of the Makefile: commands from VS Code’s command palette.

So, I set the makefile.makefilePath to point to the Makefile in r:\\learn\\edX\\cs50\\play_stuff\\. I then opened the extension by selecting the Makefile Tools icon in VSCode’s Activity Bar. I then hovered over Build Target: [Unset] and selected All.

setting makepath and selecting build target

Now, let’s click that Build button/icon again.

Building the current target. Command: E:\appDev\TDM-GCC-64\bin\mingw32-make.exe all -f r:\learn\edX\cs50\play_stuff\Makefile
mingw32-make: *** No rule to make target 'rek_hello.c', needed by 'obj\rek_hello.o'.  Stop.
Target all failed to build.

Still no go. A bit more reading, and I get the feeling that Makefile Tools is operating from the default workspace directory even though told to run the make file in the play_stuff directory. Which is strange because I got the impression make always used the directory the Makefile is in as its current working directory. To test my belief, I decided to add some additional path info to the various locations in the Makefile.

Note the addition of PWD and the related changes.

# Specify compiler
CC = E:\appDev\TDM-GCC-64\bin\gcc

# final application name
LINK_TARGET = hello_world.exe

# compiler flags
CFLAGS = -Wall -Wextra -Werror -pedantic -std=c11

# working directory for project
PWD = play_stuff

# define all the object files, adding there location, .\obj\
# designed to all me to define multiple files in _OBJ
# object dir
ODIR = play_stuff\obj
# list of required object files
_OBJ = rek_hello.o
# add path to each object file
OBJS = $(patsubst %,$(ODIR)\\%,$(_OBJ))

_SRC = rek_hello.c
SRC = $(patsubst %,$(PWD)\\%,$(_SRC))

# default target to run
all : $(LINK_TARGET)
	@echo $(OBJS)
	@echo $(SRC)

# create the required object files
# $@ - the file name of the target of the rule
#      i.e. obj\rek_hello.o
# $^ - all the prerequisites, with spaces between them
#      i.e. rek_hello.c
# $(X) - replace with the variable X's value
$(ODIR)\rek_hello.o : $(SRC)
	@echo $(OBJS)
	@echo $@ $^
	$(CC) -c $^ $(CFLAGS) -o $@

# create final executable, linking the oject files 
$(LINK_TARGET) : $(OBJS)
	$(CC) $^ -o $@ $(CFLAGS)

# in makefile on linux or such, would use rm, but that don't work on Windows
# when called, e.g. 'makefile clean', delete all the object files and the executable
clean:
	del $(ODIR)\*.o
	del $(LINK_TARGET)

Bingo! In VSCode’s Ouput tab (in the Panel):

Building the current target. Command: E:\appDev\TDM-GCC-64\bin\mingw32-make.exe all -f r:\learn\edX\cs50\play_stuff\Makefile
play_stuff\obj\rek_hello.o
play_stuff\obj\rek_hello.o play_stuff\rek_hello.c
E:\appDev\TDM-GCC-64\bin\gcc -c play_stuff\rek_hello.c -Wall -Wextra -Werror -pedantic -std=c11 -o play_stuff\obj\rek_hello.o
E:\appDev\TDM-GCC-64\bin\gcc play_stuff\obj\rek_hello.o -o hello_world.exe -Wall -Wextra -Werror -pedantic -std=c11
play_stuff\obj\rek_hello.o
play_stuff\rek_hello.c
Target all built successfully.

And, when I switch to VSCode’s Terminal tab.

R:\learn\edX\cs50>cd play_stuff

R:\learn\edX\cs50\play_stuff>.\hello_world
'.\hello_world' is not recognized as an internal or external command,
operable program or batch file.

R:\learn\edX\cs50\play_stuff>cd ..

R:\learn\edX\cs50>.\hello_world 
Hello, world!

Seems I am correct about the working directory issue. The Makefile Tools ended up creating hello_world.exe in the projects default directory. Not the one the Makefile was in. But, still making progress! (Yes, a pun. Sorry.)

A Tougher Test

I am sure there are a lot of configuration settings for the extensions, particularly Makefile Tools, of which I am unaware. But perhaps if I tackle a tougher compile (e.g. the hello, you which links in the CS50 library), I will learn a bit more.

One thing I eventually realized after looking at the documentation multiple times, is that using the Makefile Tools would be much easier if I seperated every code project into its own VSCode project. So, I will likely set up a new VSCode project for this next test. But, I may eventually see if I can it to work within my current CS50 workspace. Expect I might learn more getting that to work in a reasonable fashion. But first the easy way.

Thought about it a bit and decided I wouldn’t really have wanted to have a separate VSCode workspace for each CS50 lab/problem set. So I have decided to just open the specific folder in VSCode and see if that provides a suitable context for the Makefile Tools extension to function correctly. If not, well there is a ‘Plan B’.

The directory structure and code (rek_hello.c, cs50.c, cs50.h, Makefile) are the same as described/shown in the previous post. I only opened the rek_1 directory. Not the two containing the CS50 code/header. I started by selecting the clean target and making that target.

Building the current target. Command: E:\appDev\TDM-GCC-64\bin\mingw32-make.exe clean
del obj\*.o
del hello_you.exe
Target clean built successfully.

Note: the extension does a dry run when a target is selected and prints the details in the Output tab. I haven’t bothered showing any of that in this post.

And I confirmed that the object files and executable were in fact deleted. So, I selected the all target and ran make by clicking the appropriate button/icon. And?

uilding the current target. Command: E:\appDev\TDM-GCC-64\bin\mingw32-make.exe all
..\include\cs50.h
..\lib\cs50.c
obj\rek_hello.o obj\cs50.o
obj\rek_hello.o rek_hello.c
E:\appDev\TDM-GCC-64\bin\gcc -c -o obj\rek_hello.o rek_hello.c -I ..\include
obj\cs50.o ..\lib\cs50.c
E:\appDev\TDM-GCC-64\bin\gcc -c -o obj\cs50.o ..\lib\cs50.c -I ..\include
E:\appDev\TDM-GCC-64\bin\gcc -o hello_you.exe obj\rek_hello.o obj\cs50.o  ..\include\cs50.h -I ..\include
Target all built successfully.

And in the Terminal tab?

R:\learn\edX\cs50\rek_1>.\hello_you
Enter your name: koach
Hello, koach!

R:\learn\edX\cs50\rek_1>

I also tried selecting Build clean from the additional items (...) selection on the MAKEFILE menu. It worked as expected as well. Made clean, then made all. Kinda nice to see that.

Done I Think

There is plenty I don’t understand about writing makefiles. Plenty I don’t understand about configuring the Makefile Tools extension. Well, plenty I don’t know about programming in general. But, I figure I now have enough to work with should I wish to try coding/running any of the CS50 C problem sets on my Windows PC.

And, I hope these last few posts may help anyone else interested in doing the same on their Windows PC. I expect it would have been somewhat easier on a Apple product, or on a Linux based system. But, though I did load Linux on one of my old PCs I just never got into using it as my default platform/system. And Apple — not really a go for me (my own reasons).

Anyway, see you next time.

Resources