47

I am trying to get a set of nine *.c files (and nine related *.h files) to compile under Windows.

The code was originally designed in Linux to take command line arguments using the standard GNU-Linux/C library "getopt.h". And that library does not apply to building the C-code in Windows.

I want to ignore what my code does right now and ask the following question. For those of you familiar with this C-library "getopt.h": will it be possible to build and run my code in Windows if it depends on POSIX-style command-line arguments? Or will I have to re-write the code to work for Windows, passing input files differently (and ditching the "getopt.h" dependency)?

john_science
  • 6,325
  • 6
  • 43
  • 60
  • 2
    if MSVC support is not a hard requirement, there's always MinGW: I'm quite happy with the MinGW cross-compiler packages which come with Cygwin... – Christoph May 01 '12 at 21:28
  • 2
    `getopt.h` discribes the API provided by methods from `getopt.c`. Pull it from somewhere, compile it and link the result to your app and your done. – alk May 01 '12 at 21:40
  • 3
    Just a nit regarding alk's comment, it can be done, technically, but the legality depends entirely on the compatibility of the license(s) from the getopt sources (if any), and those of the project. Some getopt implementations say public domain, so that would likely be no problem. –  Mar 18 '17 at 15:56

9 Answers9

55

getopt() is actually a really simple function. I made a github gist for it, code from here is below too

#include <string.h>
#include <stdio.h>

int     opterr = 1,             /* if error message should be printed */
  optind = 1,             /* index into parent argv vector */
  optopt,                 /* character checked for validity */
  optreset;               /* reset getopt */
char    *optarg;                /* argument associated with option */

#define BADCH   (int)'?'
#define BADARG  (int)':'
#define EMSG    ""

/*
* getopt --
*      Parse argc/argv argument vector.
*/
int
  getopt(int nargc, char * const nargv[], const char *ostr)
{
  static char *place = EMSG;              /* option letter processing */
  const char *oli;                        /* option letter list index */

  if (optreset || !*place) {              /* update scanning pointer */
    optreset = 0;
    if (optind >= nargc || *(place = nargv[optind]) != '-') {
      place = EMSG;
      return (-1);
    }
    if (place[1] && *++place == '-') {      /* found "--" */
      ++optind;
      place = EMSG;
      return (-1);
    }
  }                                       /* option letter okay? */
  if ((optopt = (int)*place++) == (int)':' ||
    !(oli = strchr(ostr, optopt))) {
      /*
      * if the user didn't specify '-' as an option,
      * assume it means -1.
      */
      if (optopt == (int)'-')
        return (-1);
      if (!*place)
        ++optind;
      if (opterr && *ostr != ':')
        (void)printf("illegal option -- %c\n", optopt);
      return (BADCH);
  }
  if (*++oli != ':') {                    /* don't need argument */
    optarg = NULL;
    if (!*place)
      ++optind;
  }
  else {                                  /* need an argument */
    if (*place)                     /* no white space */
      optarg = place;
    else if (nargc <= ++optind) {   /* no arg */
      place = EMSG;
      if (*ostr == ':')
        return (BADARG);
      if (opterr)
        (void)printf("option requires an argument -- %c\n", optopt);
      return (BADCH);
    }
    else                            /* white space */
      optarg = nargv[optind];
    place = EMSG;
    ++optind;
  }
  return (optopt);                        /* dump back option letter */
}
jimifiki
  • 5,377
  • 2
  • 34
  • 60
bobobobo
  • 64,917
  • 62
  • 258
  • 363
  • 6
    I have this included in my project, however when I try to use optarg it says that it is undeclared in Windows. The return value of getopt is always the opt. How can I use optarg? – eleijonmarck Jan 30 '15 at 09:42
  • 6
    The header file is missing `extern char *optarg;` and `extern int optind, opterr, optopt;` – cbr Jan 17 '17 at 17:18
27

You are correct. getopt() is POSIX, not Windows, you would generally have to re-write all command-line argument parsing code.

Fortunately, there is a project, Xgetopt, that is meant for Windows/MFC classes.

http://www.codeproject.com/Articles/1940/XGetopt-A-Unix-compatible-getopt-for-MFC-and-Win32

If you can get this working in your project, it should save you a fair bit of coding and prevent you from having to rework all parsing.

Additionally, it comes with a nice GUI-enabled demo app that you should find helpful.

Good luck!

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
Cloud
  • 18,753
  • 15
  • 79
  • 153
  • I will give that a try right now. But I cannot tell from the link you showed: is the API for this library the same as the old getopt API? – john_science May 01 '12 at 21:28
  • Could you name any reason to do a re-write, but doing parsing exercises? – alk May 01 '12 at 21:44
  • Well, the code I am porting over (for use in a much larger system) is a few months old. But the people developing it are as much scientists as engineers, so they don't usually use the newest compilers or even the newest versions of UNIX/LINUX. So if they are doing things in an old-fashioned way, that wouldn't surprise me. – john_science May 01 '12 at 21:58
  • 'a few month` :-) no issues with `getopt` being to young or even to mature... you might very well give it a try a pull the `getopt` sources from the links in my answer and use them. – alk May 01 '12 at 22:02
  • @Dogbert That was almost the perfect solution. Except I am having a really annoying time trying to run the library you linked (which is C++) with the code base I currently have (which is C). I have not yet given up that this will be possible, but mixing the two language flavors seems to add some complexity to Visual Studio builds. – john_science May 02 '12 at 19:52
8

There is a possibilty to use code from MinGW runtime (by Todd C. Miller):

http://sourceforge.net/apps/trac/mingw-w64/browser/trunk/mingw-w64-crt/misc

I have created a small library with these files and CMake script (can generate a VS project):

https://github.com/alex85k/wingetopt

akks
  • 156
  • 1
  • 4
  • It looks like your library would have been really helpful. I just wanted to say. But I saw Dogbert's comment about Xgetopt first and that did the trick. Thanks, though! – john_science Sep 13 '13 at 15:58
  • Thanks. That works copy and paste for a quick port to use a program really quick – namezero Jun 29 '20 at 15:16
5

I did compile the getopt code under windows.

I did this as I wanted to explicilty use its command line parsing functionality in a windows (command line) app.

I successfully did this using VC2010.

As far as I remember I ran into no significant issues doing so.

getopt.c getoptl.c

NullUserException
  • 83,810
  • 28
  • 209
  • 234
alk
  • 69,737
  • 10
  • 105
  • 255
  • 3
    A suggested edit added the sentence *"Please note, that this specific code is covered by the GPLv3 and not by the LGPL."* to this answer. I rolled that back, and include the comment here. – Michael Petrotta Aug 19 '12 at 21:02
  • Er, including `getopt.in.h`? – Victor Sergienko Mar 19 '13 at 22:32
  • @VictorSergienko: Sure some code out of `getopt.in.h` was necessary to compile `getopt`'s sources. Anyway, my answer was not meant to be understood the way that compiling the files linked was possible without any (minor) modifications. Just feeding them "as is" to VC10 would not work. – alk Mar 20 '13 at 06:48
  • There's also getopt.c in https://github.com/berkeleydb/libdb/blob/master/src/clib/getopt.c which is meant to compile for various operating systems. It has BSD 3-Clause license. – jifb Feb 16 '23 at 10:09
2

if you just want getopt to be used in visual c++ without other dependences, I have port the getopt.c from latest gnu libc 2.12, with all new features.The only difference is you have to use TCHAR instead of char,but This is very common in windows.

simply download the source, make, copy libgetopt.lib and getopt.h getopt_int.h to your project.

you can also make it using CMakeList.txt in the root dir.

download the source from github

bowman han
  • 1,097
  • 15
  • 25
1

You might try looking into glib-2.0 as an alternative. It would be a bit large for just needing an option parser. The up side would be having access to all the other wonderful toys in the glib.

Just to be honest, I haven't tried getting this to work (I stick mostly to Linux), so YMMV.

Getting glib to work in windows: HowTo

Oh, you might explore using mingw for the build environment, and visual studio for your IDE.

Glib for Win32: HowTo

Anywho, hope this helps.

rnordeen
  • 297
  • 3
  • 6
1

From my reading of the documentation the header file getopt.h is specific to the GNU C library as used with Linux (and Hurd). The getopt function itself has been standardised by POSIX which says it should be declared, along with optind optarg etc. in unistd.h

I can't try this on Visual Studio myself but it would be worth checking if unistd.h exists and declares this function as Visual Studio does provides some other POSIX functions.

If not, then I'd definitely grab an implementation of getopt rather than re-write the argument parsing to work without it. Getopt was written to make things easier for the programmer and more consistent for user of programs with command line arguments. Do check the license, though.

-1

From what I remember of getopt.h, all it does is provide a handy parser for processing argv from your main function:

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

Windows console programs still have a main method, so you can simply loop through your argv array and parse the parameters yourself. e.g.

for ( int i = 1; i < argc; i++ )
{
  if (!strcmp(argv[i], "-f"))
    filename = argv[++i];
}
Benj
  • 31,668
  • 17
  • 78
  • 127
  • Thanks! I'm not sure if this will be practical for me. While I understand I could scroll through the ~5000 lines of code and re-write these bits, this is code that we are getting from other developers. So, what happens in 2 months when they give us a slightly newer version of the code? Will I have to redo the argument processing code every time we get an update? That sounds time consuming. – john_science May 01 '12 at 21:30
  • 1
    It sounds as though you need to get together with these other developers and agree an argument passing system which is portable. The solution provided by @theJollySin may well be the answer, but either way it's not difficult to write a portable argument parser. – Benj May 01 '12 at 21:33
  • 2
    Over the time the `getopt` API looked quiet stable to me. @theJollySin – alk May 01 '12 at 21:47
  • Why do it manually when the `getopt` function is available on the internet? – bobobobo Jun 19 '13 at 15:47
-1

The getopt.h exists in git, I have download it and it works for me:

https://gist.github.com/ashelly/7776712

MJBZA
  • 4,796
  • 8
  • 48
  • 97