Search code examples
clinuxvisual-studio-codemakefile

Visual Studio Code Makefile extension not executing make as expected


Executing make command on this Makefile compiles as expected:

#SHELL = /bin/sh

APP:= basic-tutorial-2
APP_INSTALL_DIR?= $(HOME)/Projects/test-gstreamer-2/build/bin

CC:=/usr/bin/aarch64-linux-gnu-gcc

SRCS:= $(wildcard *.c)
INCS:= $(wildcard *.h)
PKGS:= gstreamer-1.0
OBJS:= $(SRCS:.c=.o)

CFLAGS:= $(shell pkg-config --cflags $(PKGS))
LIBS:= $(shell pkg-config --libs $(PKGS))

#$(info $$CFLAGS is [${CFLAGS}]) <-- Print variable

all: $(APP)

%.o: %.c $(INCS) 
    $(CC) -ggdb -O0 -c -o $@ $(CFLAGS) $<

$(APP): $(OBJS) 
    $(CC) -ggdb -O0 -o $(APP) $(OBJS) $(LIBS)

install: $(APP)
    cp -rv $(APP) $(APP_INSTALL_DIR)

clean:
    rm -rf $(OBJS) $(APP)
    rm $(APP_INSTALL_DIR)/$(APP)
steven@development-orin:~/Projects/test-gstreamer-2/build$ ls -al
-rw-rw-r-- 1 steven steven 2291 Apr  3 17:15 basic-tutorial-2.c
drwxrwxr-x 2 steven steven 4096 Apr  4 16:07 bin
-rw-rw-r-- 1 steven steven  613 Apr  3 19:17 Makefile
steven@development-orin:~/Projects/test-gstreamer-2/build$ make
/usr/bin/aarch64-linux-gnu-gcc -ggdb -O0 -c -o basic-tutorial-2.o -pthread -I/usr/include/gstreamer-1.0 -I/usr/include/aarch64-linux-gnu -I/usr/i                                       nclude/glib-2.0 -I/usr/lib/aarch64-linux-gnu/glib-2.0/include basic-tutorial-2.c
/usr/bin/aarch64-linux-gnu-gcc -ggdb -O0 -o basic-tutorial-2 basic-tutorial-2.o -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0

steven@development-orin:~/Projects/test-gstreamer-2/build$ ls -al
-rwxrwxr-x 1 steven steven 21992 Apr  4 16:21 basic-tutorial-2
-rw-rw-r-- 1 steven steven  2291 Apr  3 17:15 basic-tutorial-2.c
-rw-rw-r-- 1 steven steven 19992 Apr  4 16:21 basic-tutorial-2.o
drwxrwxr-x 2 steven steven  4096 Apr  4 16:07 bin
-rw-rw-r-- 1 steven steven   613 Apr  3 19:17 Makefile

Application basic-tutorial-2 is created as expected.

However, when I attempt to compile in Visual studio code: Visual Studio Code Folder

MAKEFILE: PROJECT OUTLINE

I get this

 *  Executing task: '/usr/bin/make' '-f' '/home/steven/Projects/test-gstreamer-2/build/Makefile' 

/usr/bin/aarch64-linux-gnu-gcc -ggdb -O0 -o basic-tutorial-2  -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0
/usr/bin/ld: /usr/lib/gcc/aarch64-linux-gnu/11/../../../aarch64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1c): undefined reference to `main'
/usr/bin/ld: (.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [/home/steven/Projects/test-gstreamer-2/build/Makefile:24: basic-tutorial-2] Error 1

 *  The terminal process "/bin/bash '-c', ''/usr/bin/make' '-f' '/home/steven/Projects/test-gstreamer-2/build/Makefile''" failed to launch (exit code: 2). 
 *  Terminal will be reused by tasks, press any key to close it. 

I'm hoping the answer is NOT to change the Makefile, but to configure VSC differently. Any ideas?

#1 Source file contents:

// basic-tutorial-2.c
#include <gst/gst.h>

int
main (int argc, char *argv[])
{
  GstElement *pipeline, *source, *sink;
  GstBus *bus;
  GstMessage *msg;
  GstStateChangeReturn ret;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  /* Create the elements */
  source = gst_element_factory_make ("videotestsrc", "source");
  sink = gst_element_factory_make ("autovideosink", "sink");

  /* Create the empty pipeline */
  pipeline = gst_pipeline_new ("test-pipeline");

  if (!pipeline || !source || !sink) {
    g_printerr ("Not all elements could be created.\n");
    return -1;
  }

  /* Build the pipeline */
  gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
  if (gst_element_link (source, sink) != TRUE) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (pipeline);
    return -1;
  }

  /* Modify the source's properties */
  g_object_set (source, "pattern", 0, NULL);

  /* Start playing */
  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (pipeline);
    return -1;
  }

  /* Wait until error or EOS */
  bus = gst_element_get_bus (pipeline);
  msg =
      gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
      GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

  /* Parse message */
  if (msg != NULL) {
    GError *err;
    gchar *debug_info;

    switch (GST_MESSAGE_TYPE (msg)) {
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (msg, &err, &debug_info);
        g_printerr ("Error received from element %s: %s\n",
            GST_OBJECT_NAME (msg->src), err->message);
        g_printerr ("Debugging information: %s\n",
            debug_info ? debug_info : "none");
        g_clear_error (&err);
        g_free (debug_info);
        break;
      case GST_MESSAGE_EOS:
        g_print ("End-Of-Stream reached.\n");
        break;
      default:
        /* We should not reach here because we only asked for ERRORs and EOS */
        g_printerr ("Unexpected message received.\n");
        break;
    }
    gst_message_unref (msg);
  }

  /* Free resources */
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}

#2 When I run make from command line

$(info $$SRCS is [${SRCS}]) ---> $SRCS is [basic-tutorial-2.c]
$(info $$OBJS is [${OBJS}]) ---> $OBJS is [basic-tutorial-2.o]

When I run from Visual Studio Code

$(info $$SRCS is [${SRCS}]) ---> $SRCS is []
$(info $$OBJS is [${OBJS}]) ---> $OBJS is []

Solution

  • See this response from another question.

    SRCS:= $(wildcard *.c) $(wildcard **/*.c)
    INCS:= $(wildcard *.h) $(wildcard **/*.h)