0
votes

I am writing a program in C that uses SDL2 on Cygwin. The problem I am having is that argc is always 1, even when the command line does contain other arguments.

This is a bit difficult to replicate as I can't post all the code for this program, but I can include the main source here to make sure my main function is correct.

My question is if there is any known reason why argc would always be 1 and not include other command line arguments (weather this be intentionally or a side effect from using SDL2 etc)?

This is the code i'm using:

#include <stdlib.h>
#include <stdio.h>
#include "config.h"
#include <string.h>

#ifdef SIGNAL_AVAIL
#include <signal.h>
#endif

#include "process.h"
#include "nvconsole.h"
#include "stringutils.h"

#include "nova.h"

struct NovaContext_s *context;      // Nova system context

#ifdef SIGNAL_AVAIL

// #### Signal Handler ####
void sig_handler(int signo)
{
    if (signo == SIGINT)
    {   
        NVConsole_print(NVInfo,"Terminated by user");       
        NVConsole_println(NVInfo,"");
        Nova_cleanUp(context);      
        exit(0);
    }   
}

#endif

void init()
{
#ifdef SIGNAL_AVAIL
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        NVConsole_println(NVError,"[main] Can't catch SIGINT");
        exit(1);
    }   
    if (signal(SIGQUIT, sig_handler) == SIG_ERR)
    {
        NVConsole_println(NVError,"[main] Can't catch SIGQUIT");
        exit(1);
    }
#endif
}

int main(int argc, char* argv[]) {

for(int i=0;i<argc;i++) printf("%d %s\n",i,argv[i]);

    init();

    context = Nova_createContext();

    Nova_init(context); 
    Nova_loop(context,0);
    Nova_cleanUp(context);

    return 0;
}

Although this code doesn't directly use SDL, it is being linked and is used by other parts of the included code. I get the below output from this:

$ ./bin/nova
0 F:\dev\nova\bin\nova.exe

$ ./bin/nova hello
0 F:\dev\nova\bin\nova.exe

I've included the makefile below:

ARCH = $(shell uname)

CXX=gcc -std=c99 

ifeq ($(ARCH), Darwin)
    SDLFLAGS = `/usr/local/bin/sdl2-config --cflags`
    SDLLIBS = `/usr/local/bin/sdl2-config --libs`
else
    SDLFLAGS = `sdl2-config --cflags`
    SDLLIBS = `sdl2-config --libs`
endif

#OPT= -O2 -s -D_GNU_SOURCE
OPT= -O2 -D_GNU_SOURCE

INCLUDE=-I. -I.. -Isrc/nova -Isrc/nvscript -Isrc/common -Isrc/headers -Isrc/modules -Isrc/search

#WARN=-Werror
CWD=$(shell pwd)

#CXXFLAGS= $(OPT) $(INCLUDE) $(SDLFLAGS) $(WARN) -fPIC
CXXFLAGS= $(OPT) $(INCLUDE) $(SDLFLAGS) $(WARN)

LIBS= -lm $(SDLLIBS) -ldl

LD=$(CXX) $(OPT)

#####################################################

LIBNVSCRIPT_API_VERSION = 1.0.0

#####################################################

COMP   = nova \
         nvdata \
         nvconsole \
         nvdatastore \
         nvconfig \
         nvevent \
         rule_clock \
         rule_nvs
COMP_H = nova.h \
         nvdata.h \
         nvconsole.h \
         nvdatastore.h \
         nvconfig.h \
         nvevent.h \
         rule_clock.h \
         rule_nvs.h
COMP_HEADERS := $(addprefix src/nova/, $(COMP_H) )
COMP_OBJS    := $(addprefix objs/, $(COMP:=.o) )
COMP_LIB     := libs/libnova.a

#####################################################

NVSCRIPT   = nvscript \
             nvscriptcore \
             nvscriptresult \
             nvscriptlist \
             nvscriptstring \
             nvscriptfile \
             nvscriptnet \
             nvscriptprocess \
             nvscriptdebug \
             nvscriptexec \
             nvscriptmath
NVSCRIPT_H = nvscript.h \
             nvscriptcore.h \
             nvscriptresult.h \
             nvscriptlist.h \
             nvscriptstring.h \
             nvscriptfile.h \
             nvscriptnet.h \
             nvscriptprocess.h \
             nvscriptdebug.h \
             nvscriptexec.h \
             nvscriptmath.h
NVSCRIPT_HEADERS := $(addprefix src/nvscript/, $(NVSCRIPT_H) )
NVSCRIPT_OBJS    := $(addprefix objs/, $(NVSCRIPT:=.o) )
NVSCRIPT_LIB     := libs/libnvscript-$(LIBNVSCRIPT_API_VERSION).a

#####################################################

COMMON   = stringutils \
           fileutils \
           wildcard \
           intarray \
           floatarray \
           chararray \
           stringarray \
           uchararray \
           boolarray \
           voidarray \
           base64 \
           sha1 \
           scramble \
           lfp \
           x86_intmem \
           x86_console \
           x86_file \
           x86_timer \
           x86_net \
           x86_process \
           x86_rtc \
           x86_keys \
           sdl_video \
           sdl_input
COMMON_H = stringutils.h \
           fileutils.h \
           mallocdebug.h \
           wildcard.h \
           intarray.h \
           floatarray.h \
           chararray.h \
           stringarray.h \
           uchararray.h \
           boolarray.h \
           base64.h \
           voidarray.h \
           sha1.h \
           scramble.h \
           lfp.h \
           x86_intmem.h \
           x86_console.h \
           x86_file.h \
           x86_timer.h \
           x86_net.h \
           x86_process.h \
           x86_rtc.h \
           x86_keys.h \
           sdl_video.h \
           sdl_input.h
COMMON_HEADERS := $(addprefix src/common/, $(COMMON_H) )
COMMON_OBJS    := $(addprefix objs/, $(COMMON:=.o) )
COMMON_LIB     := libs/libmlcommon.a

#####################################################

SEARCH = search searchitem
SEARCH_H = search.h searchitem.h
SEARCH_HEADERS := $(addprefix src/search/, $(SEARCH_H) )
SEARCH_OBJS    := $(addprefix objs/search/, $(SEARCH:=.o) )
SEARCH_LIB     := libs/libsearch.a

#####################################################

MODULES   = ui statusbar welcome context netmsg
MODULES_H = ui.h statusbar.h welcome.h context.h netmsg.h
MODULES_HEADERS := $(addprefix src/modules/, $(MODULES_H) )
MODULES_OBJS    := $(addprefix objs/modules/, $(MODULES:=.o) )
MODULES_DSOS    := $(addprefix modules/, $(MODULES:=.so) )

#####################################################

OUTPUT = main
OUTPUT_OBJS  := $(addprefix objs/, $(OUTPUT:=.o) )
OUTPUT_BINARY = bin/nova

NVSOUTPUT = nvs
NVSOUTPUT_OBJS  := $(addprefix objs/, $(NVSOUTPUT:=.o) )
NVSOUTPUT_BINARY = bin/nvs

NVSTESTOUTPUT = nvstest
NVSTESTOUTPUT_OBJS  := $(addprefix objs/, $(NVSTESTOUTPUT:=.o) )
NVSTESTOUTPUT_BINARY = bin/nvstest

SEARCHOUTPUT = search
SEARCHOUTPUT_OBJS  := $(addprefix objs/, $(SEARCHOUTPUT:=.o) )
SEARCHOUTPUT_BINARY = bin/search

#####################################################

default: $(COMP_LIB) $(NVSCRIPT_LIB) $(COMMON_LIB) $(SEARCH_LIB) $(OUTPUT_BINARY) $(NVSOUTPUT_BINARY) $(NVSTESTOUTPUT_BINARY) $(SEARCHOUTPUT_BINARY)
modules: $(MODULES_OBJS) $(MODULES_DSOS)
nova: $(COMP_LIB) $(NVSCRIPT_LIB) $(COMMON_LIB) $(OUTPUT_BINARY)
nvs: $(NVSCRIPT_LIB) $(COMMON_LIB) $(NVSOUTPUT_BINARY) $(NVSTESTOUTPUT_BINARY)

#################### Components #####################

objs/%.o: src/nova/%.c $(COMP_HEADERS)
    @echo "Compiling $<"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

$(COMP_LIB): $(COMP_OBJS)
    @echo "Building the nova library ($(COMP_LIB))"
    @ar rcs $(COMP_LIB) $(COMP_OBJS)

##################### NVScript ######################

objs/%.o: src/nvscript/%.c $(NVSCRIPT_HEADERS)
    @echo "Compiling $<"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

$(NVSCRIPT_LIB): $(NVSCRIPT_OBJS)
    @echo "Building the nvscript library ($(NVSCRIPT_LIB))"
    @ar rcs $(NVSCRIPT_LIB) $(NVSCRIPT_OBJS)

#################### Common #####################

objs/%.o: src/common/%.c $(COMMON_HEADERS)
    @echo "Compiling $<"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

$(COMMON_LIB): $(COMMON_OBJS)
    @echo "Building the mlcommon library ($(COMMON_LIB))"
    @ar rcs $(COMMON_LIB) $(COMMON_OBJS)

################## MODULES #####################

# Compile plugin and then link to shared library

objs/modules/%.o: src/modules/%.c $(MODULES_HEADERS)
    @echo "Compiling module \"$*\""
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

modules/%.so: objs/modules/%.o $(MODULES_HEADERS)
    @echo "Linking module \"$*\""   
    @$(CXX) -shared -o $@  $(COMP_OBJS) $(NVSCRIPT_OBJS) $(COMMON_OBJS) $(LIBS) $<

#################### Search #####################

objs/search/%.o: src/search/%.c $(SEARCH_HEADERS)
    @echo "Compiling $<"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

$(SEARCH_LIB): $(SEARCH_OBJS)
    @echo "Building the search library ($(SEARCH_LIB))"
    @ar rcs $(SEARCH_LIB) $(SEARCH_OBJS)

###################### Output #######################

objs/main.o: src/main/nova.c $(COMP_HEADERS) $(NVSCRIPT_HEADERS) $(COMMON_HEADERS)
    @echo "Building binary ($<)"    
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

objs/nvs.o: src/main/nvs.c $(NVSCRIPT_HEADERS) $(COMMON_HEADERS)
    @echo "Building binary ($<)"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

objs/nvstest.o: src/main/nvstest.c $(NVSCRIPT_HEADERS) $(COMMON_HEADERS)
    @echo "Building binary ($<)"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<

objs/search.o: src/main/search.c $(SEARCH_HEADERS) $(COMMON_HEADERS)
    @echo "Building binary ($<)"
    @$(CXX) $(CXXFLAGS) -o $@ -c $<


$(OUTPUT_BINARY): $(OUTPUT_OBJS) $(COMP_LIB) $(NVSCRIPT_LIB) $(COMMON_LIB)
    @echo "Linking $@"
    @$(CXX) -o $@ $(OUTPUT_OBJS) $(COMP_OBJS) $(NVSCRIPT_OBJS) $(COMMON_OBJS) $(LIBS)

$(NVSOUTPUT_BINARY): $(NVSOUTPUT_OBJS) $(NVSCRIPT_LIB) $(COMMON_LIB)
    @echo "Linking $@"
    @$(CXX) -o $@ $(NVSOUTPUT_OBJS) $(NVSCRIPT_OBJS) $(COMMON_OBJS) $(LIBS)

$(NVSTESTOUTPUT_BINARY): $(NVSTESTOUTPUT_OBJS) $(NVSCRIPT_LIB) $(COMMON_LIB)
    @echo "Linking $@"
    @$(CXX) -o $@ $(NVSTESTOUTPUT_OBJS) $(NVSCRIPT_OBJS) $(COMMON_OBJS) $(LIBS)

$(SEARCHOUTPUT_BINARY): $(SEARCHOUTPUT_OBJS) $(SEARCH_LIB) $(COMMON_LIB)
    @echo "Linking $@"
    @$(CXX) -o $@ $(SEARCHOUTPUT_OBJS) $(SEARCH_OBJS) $(COMMON_OBJS) $(LIBS)

#####################################################

install:    
    ./install.sh

uninstall:  
    ./uninstall.sh

clean:
    rm -f objs/*.o objs/modules/*.o objs/search/*.o */*.so */*.a modules/*.so libs/*.a $(OUTPUT_BINARY).exe $(OUTPUT_BINARY) $(NVSOUTPUT_BINARY).exe $(NVSOUTPUT_BINARY) $(NVSTESTOUTPUT_BINARY).exe $(NVSTESTOUTPUT_BINARY) $(SEARCHOUTPUT_BINARY) $(SEARCHOUTPUT_BINARY).exe

I've also written a small test:

#include <stdlib.h>
#include <stdio.h>

 int main(int argc, char* argv[]) {
    for(int i=0;i<argc;i++) printf("%d %s\n",i,argv[i]);
 }

And it's not surprising that this does work and displays all arguments, as you would expect.

$ ./test hello
0 ./test
1 hello

It's also worth noting that the path for argv[0] seems to be different in both examples, the first (where it's not working) shows what looks like a windows path, while the second example (which does work) is showing a linux looking path. Does this indicate anything?

1
I've done some more investigating and as the make file shows, I am also building some other executables in this make file, which also seem to be exhibiting the same behavior. One (called search) contains the exact same code as my test that worked, but doesn't when built with this make file. I'm getting more certain that it's SDL2, but not sure how or why. - Phil_12d3
Ok, deep breaths. On windows, SDL defines "main" as a macro, that actually means SDL_main, and SDL defines its own WinMain function. If you don't have a debug build of SDL, I'd suggest you get one, and set a break on WinMain, to make sure the arguments are getting sent in to SDL_main correctly. I don't know how well tested SDL2 would be on cygwin at this point, so there could be an issue there. - user26347

1 Answers

1
votes

I think argc is required here (not argv)

for(int i=0;i<argc;i++) printf("%d %s\n",i,argv[i]);