Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build Git failed with error C2133: 'builtin_config_options': unknown size #1735

Closed
KarenHuang2016 opened this issue Jun 26, 2018 · 17 comments
Closed

Comments

@KarenHuang2016
Copy link

Build Git latest revision cfd9a13 on master with 2017 failed with the following errors:

d:\git\src\builtin\config.c(70,46): error C2133: 'builtin_config_options': unknown size [D:\Git\src\git\git.vcxproj]

The root cause should the arry size is not specified in the following code:
static struct option builtin_config_options[];

Setup
•Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
64-bit
$ git --version --build-options
git version 2.9.2.windows.1
sizeof-long: 4
•Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
Windows Server 2016 64-bit + VS2017.2
$ cmd.exe /c ver
Microsoft Windows [Version 10.0.15063]

Repro steps:
1.git clone https://github.com/git-for-windows/git.git D:\git\src
2.git checkout vs/master
3.devenv /upgrade git.sln
4.nuget.exe restore git.sln 5.msbuild /m /p:Configuration=Release;Platform=x86 /p:WindowsTargetPlatformVersion=10.0.15063.0 /t:Rebuild git.sln

@shanshan0309
Copy link

Hello,
Any update for this?

@PhilipOakley
Copy link

Check if there is an extra G-f-W 'fix' that is applied. Is the code identical to upstream Git.git? Check the 'blame' to see if it is a recent change. Is it a C89/C99/C? compatibility (i.e. what's the root cause of the error code - is it something that depends on the C-standard in use).

I know that upstream have been slowly trying out the use of newer c-standards. IIRC they were at C89 until recently, and are trying one or two features at a time to see if anyone complains - This may be an MS compiler error report that is more 'careful' that the gcc etc.

If you can feedback any small information you have found that would be useful - everyone has to volunteer some of their time ;-)

@dscho
Copy link
Member

dscho commented Jun 28, 2018

The root cause should the arry size is not specified in the following code:
static struct option builtin_config_options[];

Almost. The root cause is that this is supposed to be a forward declaration, and somehow GCC handles it, but MSVC insists that it needs to know the size already here. So something like this diff should fix it:

diff --git a/builtin/config.c b/builtin/config.c
index b29d26dede7..1243f78b757 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -67,7 +67,43 @@ static int show_origin;
 	{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
 	PARSE_OPT_NONEG, option_parse_type, (i) }
 
-static struct option builtin_config_options[];
+static struct option builtin_config_options[] = {
+	OPT_GROUP(N_("Config file location")),
+	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
+	OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
+	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
+	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
+	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
+	OPT_GROUP(N_("Action")),
+	OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
+	OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
+	OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
+	OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
+	OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
+	OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
+	OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
+	OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
+	OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
+	OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
+	OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
+	OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
+	OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
+	OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
+	OPT_GROUP(N_("Type")),
+	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type),
+	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
+	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
+	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
+	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
+	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
+	OPT_GROUP(N_("Other")),
+	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
+	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
+	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
+	OPT_END(),
+};
 
 static int option_parse_type(const struct option *opt, const char *arg,
 			     int unset)
@@ -119,44 +155,6 @@ static int option_parse_type(const struct option *opt, const char *arg,
 	return 0;
 }
 
-static struct option builtin_config_options[] = {
-	OPT_GROUP(N_("Config file location")),
-	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
-	OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
-	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
-	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
-	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
-	OPT_GROUP(N_("Action")),
-	OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
-	OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
-	OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
-	OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
-	OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
-	OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
-	OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
-	OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
-	OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
-	OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
-	OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
-	OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
-	OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
-	OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
-	OPT_GROUP(N_("Type")),
-	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type),
-	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
-	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
-	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
-	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
-	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
-	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
-	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
-	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
-	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
-	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
-	OPT_END(),
-};
-
 static void check_argc(int argc, int min, int max) {
 	if (argc >= min && argc <= max)
 		return;

Please test.

@shanshan0309
Copy link

Hi @dscho,
Thanks for looking into this issue and providing the patch.
Bit Git failed with error C2065, C2099 When I test the diff you provided. The detailed error info:

   "D:\Git\src\git.sln" (Rebuild target) (1) ->
   "D:\Git\src\git\git.vcxproj" (Rebuild target) (2) ->
   (ClCompile target) -> 
     d:\git\src\builtin\config.c(93,2): error C2065:  'option_parse_type': undeclared identifier [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(93,2): error C2065: 	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(93,2): error C2065: 	^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(94,2): error C2065:  'option_parse_type': undeclared identifier [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(94,2): error C2065: 	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(94,2): error C2065: 	^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(95,2): error C2065:  'option_parse_type': undeclared identifier [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(95,2): error C2065: 	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(95,2): error C2065: 	^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(96,2): error C2065:  'option_parse_type': undeclared identifier [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(96,2): error C2065: 	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(96,2): error C2065: 	^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(97,2): error C2065:  'option_parse_type': undeclared identifier [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(97,2): error C2065: 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(97,2): error C2065: 	^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(98,2): error C2065:  'option_parse_type': undeclared identifier [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(98,2): error C2065: 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(98,2): error C2065: 	^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(93,1): error C2099:  initializer is not a constant [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(93,1): error C2099: 	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(93,1): error C2099: ^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(94,1): error C2099:  initializer is not a constant [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(94,1): error C2099: 	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(94,1): error C2099: ^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(95,1): error C2099:  initializer is not a constant [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(95,1): error C2099: 	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(95,1): error C2099: ^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(96,1): error C2099:  initializer is not a constant [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(96,1): error C2099: 	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(96,1): error C2099: ^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(97,1): error C2099:  initializer is not a constant [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(97,1): error C2099: 	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(97,1): error C2099: ^ [D:\Git\src\git\git.vcxproj]
     d:\git\src\builtin\config.c(98,1): error C2099:  initializer is not a constant [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(98,1): error C2099: 	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE), [D:\Git\src\git\git.vcxproj]
   d:\git\src\builtin\config.c(98,1): error C2099: ^ [D:\Git\src\git\git.vcxproj]

@dscho
Copy link
Member

dscho commented Jul 3, 2018

Okay, so I am afraid that I expressed my thoughts a bit poorly. Let me try again.

The vs/master branch is intended for C/C++ developers interested in helping Git for Windows improve the code, but who are for some reason or other unable or unwilling to use the GCC tool chain to build Git's executables.

In particular, the audience I tried to target are proficient C/C++ developers who are pretty much experts at using Visual Studio and developing C/C++ code on Windows, my hope was to target developers who are a lot more proficient with these technologies than I am. My background is a Linux one, and while I came a long way in acquiring expertise in development on Windows and with Visual Studio, I am always eager to learn more, and experts are the best source for that. With this in mind, I hoped that my work on vs/master would be kind of a tit-for-tat: I provide my expertise in building Git's source code, and I get enhancements and knowledge in the Windows domain in return.

So I have to admit that I am a bit surprised that I am now asked to explain compiler errors for relatively trivial C/C++ problems. That was not what I was hoping for.

The culprit here is that I tried to replace a forward-declaration by the final definition, and that it is not possible to do that because the forward-declaration is actually needed at this point. So you will have to replace the forward-declaration by a construct that is accepted by Visual C++.

I will let this simmer for a while, in the hope that a contributor will contribute a patch to fix it. If that patch does not materialize, I will take care of it myself, at some time in the future when I find a few hours to spend on this task.

@bbolli
Copy link
Collaborator

bbolli commented Jul 4, 2018

Please try this patch.

While I have only compile-tested it under Linux, it does remove the forward-declaration of the array MSVC complains about.

diff --git a/builtin/config.c b/builtin/config.c
index b29d26dede..68e3704f49 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -67,7 +67,7 @@ static int show_origin;
        { OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
        PARSE_OPT_NONEG, option_parse_type, (i) }
 
-static struct option builtin_config_options[];
+static NORETURN void usage_with_builtin_options(void);
 
 static int option_parse_type(const struct option *opt, const char *arg,
                             int unset)
@@ -111,8 +111,7 @@ static int option_parse_type(const struct option *opt, const char *arg,
                 * --type=int'.
                 */
                error("only one type at a time.");
-               usage_with_options(builtin_config_usage,
-                       builtin_config_options);
+               usage_with_builtin_options();
        }
        *to_type = new_type;
 
@@ -157,6 +156,11 @@ static struct option builtin_config_options[] = {
        OPT_END(),
 };
 
+static NORETURN void usage_with_builtin_options(void)
+{
+       usage_with_options(builtin_config_usage, builtin_config_options);
+}
+
 static void check_argc(int argc, int min, int max) {
        if (argc >= min && argc <= max)
                return;

@kgybels
Copy link

kgybels commented Jul 4, 2018

I made a simple version to test with:

#include <stdio.h>

static int values[];

int main(void)
{
        printf("%d\n", values[0]);
        return 0;
}

static int values[] = { 1, 2, 3, 4 };

Even gcc doesn't like it if you use pedantic (tested with Git for Windows SDK) :

$ gcc --std=c99 -Wall -pedantic main.c
main.c:3:12: error: array size missing in 'values'
 static int values[];
            ^~~~~~
main.c:11:8: warning: type defaults to 'int' in declaration of 'values' [-Wimplicit-int]
 static values[] = { 1, 2, 3, 4 };
        ^~~~~~
main.c:11:24: warning: excess elements in array initializer
 static values[] = { 1, 2, 3, 4 };
                        ^
main.c:11:24: note: (near initialization for 'values')
main.c:11:27: warning: excess elements in array initializer
 static values[] = { 1, 2, 3, 4 };
                           ^
main.c:11:27: note: (near initialization for 'values')
main.c:11:30: warning: excess elements in array initializer
 static values[] = { 1, 2, 3, 4 };
                              ^
main.c:11:30: note: (near initialization for 'values')

Compiles fine without pedantic.

The following version works with pedantic:

#include <stdio.h>

extern int values[];

int main(void)
{
        printf("%d\n", values[0]);
        return 0;
}

int values[] = { 1, 2, 3, 4 };

The compilers on godbolt.org also don't like it, give it a try yourself with the above example.

I figured this out thanks to the following email thread:
comp.lang.c.moderated: why can't array forward declarations be static?

@dscho
Copy link
Member

dscho commented Jul 5, 2018

@kgybels thank you for this analysis! It is a bit funny that the extern forward declaration works, but the static one does not. In that light, I think I like @bbolli's version to forward-declare a simple usage helper instead.

@bbolli could you wrap this into a patch and contribute it to the Git mailing list, using @kgybels' analysis in the commit message?

@shanshan0309
Copy link

Thank you @bbolli. It works well.

@bbolli
Copy link
Collaborator

bbolli commented Jul 5, 2018

@dscho Sure; I have prepared the patch and a follow-up already. It will have to wait until this evening, though (i.e. now + ~6h).

@bbolli
Copy link
Collaborator

bbolli commented Jul 5, 2018

@kgybels I think your godbolt link is not correct: godbolt by default compiles as C++ where the compilation fails even without -pedantic. The flag to ensure C compilation is -xc, or change the language selector to C.

@kgybels
Copy link

kgybels commented Jul 5, 2018

@bbolli I think your godbolt link is not correct: godbolt by default compiles as C++ where the compilation fails even without -pedantic.

You are right, here is the corrected godbolt link.

I made another mistake, because I wouldn't expect the following warning:

main.c:11:8: warning: type defaults to 'int' in declaration of 'values' [-Wimplicit-int]
 static values[] = { 1, 2, 3, 4 };
        ^~~~~~

Let's try again with the correct version of main.c:

$ gcc --std=c99 -Wall -pedantic main.c
main.c:3:12: error: array size missing in 'values'
 static int values[];
            ^~~~~~
main.c:11:28: warning: excess elements in array initializer
 static int values[] = { 1, 2, 3, 4 };
                            ^
main.c:11:28: note: (near initialization for 'values')
main.c:11:31: warning: excess elements in array initializer
 static int values[] = { 1, 2, 3, 4 };
                               ^
main.c:11:31: note: (near initialization for 'values')
main.c:11:34: warning: excess elements in array initializer
 static int values[] = { 1, 2, 3, 4 };
                                  ^
main.c:11:34: note: (near initialization for 'values')

Coming back to the original problem: There is a circular dependency between builtin_config_options and option_parse_type, so we need to forward declare one of them. Instead of forward declaring builtin_config_options, why not forward declare option_parse_type instead?

diff --git a/builtin/config.c b/builtin/config.c
index b29d26dede..564f18f2c7 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -67,7 +67,46 @@ static int show_origin;
 	{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
 	PARSE_OPT_NONEG, option_parse_type, (i) }
 
-static struct option builtin_config_options[];
+static int option_parse_type(const struct option *opt, const char *arg,
+			     int unset);
+
+static struct option builtin_config_options[] = {
+	OPT_GROUP(N_("Config file location")),
+	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
+	OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
+	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
+	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
+	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
+	OPT_GROUP(N_("Action")),
+	OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
+	OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
+	OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
+	OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
+	OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
+	OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
+	OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
+	OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
+	OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
+	OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
+	OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
+	OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
+	OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
+	OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
+	OPT_GROUP(N_("Type")),
+	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type),
+	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
+	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
+	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
+	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
+	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
+	OPT_GROUP(N_("Other")),
+	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
+	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
+	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
+	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
+	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
+	OPT_END(),
+};
 
 static int option_parse_type(const struct option *opt, const char *arg,
 			     int unset)
@@ -119,44 +158,6 @@ static int option_parse_type(const struct option *opt, const char *arg,
 	return 0;
 }
 
-static struct option builtin_config_options[] = {
-	OPT_GROUP(N_("Config file location")),
-	OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
-	OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
-	OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
-	OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
-	OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
-	OPT_GROUP(N_("Action")),
-	OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
-	OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
-	OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
-	OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
-	OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
-	OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
-	OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
-	OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-regex]"), ACTION_UNSET_ALL),
-	OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
-	OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
-	OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
-	OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
-	OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
-	OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
-	OPT_GROUP(N_("Type")),
-	OPT_CALLBACK('t', "type", &type, "", N_("value is given this type"), option_parse_type),
-	OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
-	OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
-	OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
-	OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
-	OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
-	OPT_GROUP(N_("Other")),
-	OPT_BOOL('z', "null", &end_null, N_("terminate values with NUL byte")),
-	OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
-	OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
-	OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
-	OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
-	OPT_END(),
-};
-
 static void check_argc(int argc, int min, int max) {
 	if (argc >= min && argc <= max)
 		return;

@dscho I also had to revert 34573d2 (fixup! mingw: really handle SIGINT, 2018-07-04) to be able to build Debug|x64.

I'm not against usage_with_builtin_options(), but then it would make more sense to replace all calls of usage_with_options(builtin_config_usage, builtin_config_options) with it.

@bbolli
Copy link
Collaborator

bbolli commented Jul 5, 2018

@dscho
Copy link
Member

dscho commented Jul 6, 2018 via email

@bbolli
Copy link
Collaborator

bbolli commented Jul 6, 2018

Does the order of WINBOOL WINAPI matter or what?

Yes: WINBOOL (a typedef of int) is the function return type, WINAPI (#defined as __stdcall) is a function attribute that occurs after the return type.

@dscho
Copy link
Member

dscho commented Jul 6, 2018

Does the order of WINBOOL WINAPI matter or what?

Yes

Oh, okay. I thought that function attributes are allowed anywhere.

@kgybels if you revert your revert, and change the order of WINBOOL and WINAPI, does it work?

@kgybels
Copy link

kgybels commented Jul 9, 2018

@dscho if you revert your revert, and change the order of WINBOOL and WINAPI, does it work?

No, because WINBOOL is undefined. The following works:

static BOOL WINAPI handle_ctrl_c(DWORD ctrl_type)

Syntax for __stdcall :

return-type __stdcall function-name[(argument-list)]

Source: https://docs.microsoft.com/en-us/cpp/cpp/stdcall

jeffhostetler pushed a commit to jeffhostetler/git that referenced this issue Jul 25, 2018
As reported here[0], Microsoft Visual Studio 2017.2 and "gcc -pedantic"
don't understand the forward declaration of an unsized static array.
They insist on an array size:

    d:\git\src\builtin\config.c(70,46): error C2133: 'builtin_config_options': unknown size

The thread [1] explains that this is due to the single-pass nature of
old compilers.

To work around this error, introduce the forward-declared function
usage_builtin_config() instead that uses the array
builtin_config_options only after it has been defined.

Also use this function in all other places where usage_with_options() is
called with the same arguments.

[0]: git-for-windows#1735
[1]: https://groups.google.com/forum/#!topic/comp.lang.c.moderated/bmiF2xMz51U

Fixes git-for-windows#1735

Reported-By: Karen Huang (via GitHub)
Signed-off-by: Beat Bolli <dev+git@drbeat.li>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants