├── .gitignore ├── Makefile ├── README.md ├── commands.txt ├── config ├── vs2008_Pro.h ├── vs2015_BuildTools.h ├── vs2015_BuildTools_from_vs2017_Community.h ├── vs2017_BuildTools.h └── vs2017_Community.h ├── config_default.h ├── main.cpp ├── system_return.c └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /a.out 2 | /gcc2msvc 3 | /gcc2msvc_test 4 | /config.h 5 | /tmp_test.* 6 | *.o 7 | *.obj 8 | *.ilk 9 | *.pdb 10 | *.exe 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BIN = gcc2msvc 2 | OBJS = main.o system_return.o 3 | 4 | CXXFLAGS := -Wall -Wextra -O3 5 | CFLAGS := -Wall -Wextra -O3 6 | LDFLAGS := -s 7 | 8 | CLEANFILES = $(BIN) $(OBJS) $(BIN)_test tmp_test.* *.obj *.ilk *.pdb *.exe 9 | DISTCLEANFILES = config.h 10 | 11 | 12 | all: $(BIN) 13 | 14 | clean: 15 | -rm -f $(CLEANFILES) 16 | 17 | distclean: clean 18 | -rm -f $(DISTCLEANFILES) 19 | 20 | $(BIN): $(OBJS) 21 | $(CXX) $(LDFLAGS) -o $@ $^ 22 | 23 | main.cpp: config.h 24 | config.h: config_default.h 25 | cp $< $@ 26 | 27 | test: $(BIN) 28 | ./test.sh 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | gcc2msvc 2 | ======== 3 | 4 | This program is a wrapper for msvc's cl.exe and intended to be used with Windows 10's "Bash on Ubuntu on Windows" shell. 5 | It is invoked with gcc options (only a limited number) and turns them into msvc options to call cl.exe. 6 | The msvc options may not exactly do the same as their gcc counterparts. 7 | 8 | 9 | Configuration 10 | ------------- 11 | 12 | The _default_ search paths are set at compile time through header files. 13 | See the files in the `config` directory for examples. 14 | 15 | 16 | Downloads 17 | --------- 18 | 19 | Instead of installing the full Visual Studio IDE you can also get the standalone command line 20 | build tools at Visual Studio's homepage: http://landinghub.visualstudio.com/visual-cpp-build-tools 21 | 22 | -------------------------------------------------------------------------------- /commands.txt: -------------------------------------------------------------------------------- 1 | # cl 2 | -c /c 3 | -C /C 4 | -w /w 5 | -g /Zi 6 | -x[ ]c /TC 7 | -x[ ]c++ /TP 8 | -D[ ]%s /D%s 9 | -U[ ]%s /U%s 10 | -O1 /O2 /Ot 11 | -O2 /O2 /Ot 12 | -O3 /Ox 13 | -Os /O1 /Os 14 | -O0 /Od 15 | -Wall /W3 16 | -Wextra /Wall 17 | -Werror /Wx 18 | -Wcl,%s /%s 19 | -Wcl,/%s /%s 20 | -Wcl,-%s /%s 21 | -mdll /LD 22 | -msse /arch:SSE 23 | -msse2 /arch:SSE2 24 | -mavx /arch:AVX 25 | -mavx2 /arch:AVX2 26 | -frtti /GR 27 | -fno-rtti /GR- 28 | -fthreadsafe-statics /Zc:threadSafeInit 29 | -fno-threadsafe-statics /Zc:threadSafeInit- 30 | -fno-inline /Ob0 31 | -finline-functions /Ob2 32 | -fomit-frame-pointer /Oy 33 | -fno-omit-frame-pointer /Oy- 34 | -fpermissive /permissive 35 | -fopenmp /openmp 36 | -fstack-protector /GS 37 | -fno-stack-protector /GS- /guard:cf- 38 | -fstack-protector-strong /GS /guard:cf 39 | -fstack-protector-all /GS /guard:cf 40 | -fstack-check /GS 41 | -fno-stack-check /GS- /guard:cf- 42 | -funsigned-char /J 43 | -fsized-deallocation /Zc:sizedDealloc 44 | -fno-sized-deallocation /Zc:sizedDealloc- 45 | -fconstexpr-depth=%d /constexpr:depth%d 46 | -ffp-contract=fast /fp:fast 47 | -ffp-contract=off /fp:strict 48 | -fwhole-program /GL 49 | -fno-whole-program /GL- 50 | 51 | # link 52 | -o[ ]%s /out:'%s' 53 | -L[ ]%s /libpath:'%s' 54 | -static /MD 55 | -static-libgcc /MD 56 | -static-libstdc++ /MD 57 | -lc "" 58 | -lm "" 59 | -lrt "" 60 | -lstdc++ "" 61 | -lgcc_s "" 62 | -lmingw32 "" 63 | -lmingwex "" 64 | -lmingwthrd "" 65 | -lmoldname "" 66 | -lpthread "" 67 | -l%s '%s.lib' 68 | -Wlink,%s /%s 69 | -Wlink,/%s /%s 70 | -Wlink,-%s /%s 71 | -Wl,--whole-archive /wholearchive 72 | -Wl,--out-implib,%s /implib:'%s' 73 | -Wl,--out-implib -Wl,%s /implib:'%s' 74 | -Wl,-output-def,%s /def'%s' 75 | -Wl,-output-def -Wl,%s /def'%s' 76 | 77 | -------------------------------------------------------------------------------- /config/vs2008_Pro.h: -------------------------------------------------------------------------------- 1 | /* Visual Studio 2008 (Pro) */ 2 | 3 | #define DEFAULT_INCLUDES \ 4 | "/I\".\" " \ 5 | "/I\"C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/include\" " \ 6 | "/I\"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Include\"" 7 | 8 | #define DEFAULT_CL_PATH_X64 \ 9 | "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin/amd64" 10 | 11 | #define DEFAULT_CL_PATH_X86 \ 12 | "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin;"\ 13 | "C:/Program Files (x86)/Microsoft Visual Studio 9.0/Common7/IDE" 14 | 15 | #define DEFAULT_LIBPATHS_X64 \ 16 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/lib/amd64\" " \ 17 | "/libpath:\"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/x64\"" 18 | 19 | #define DEFAULT_LIBPATHS_X86 \ 20 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/lib\" " \ 21 | "/libpath:\"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib\"" 22 | 23 | -------------------------------------------------------------------------------- /config/vs2015_BuildTools.h: -------------------------------------------------------------------------------- 1 | /* Visual Studio 2015 (standalone) Build Tools */ 2 | 3 | #define DEFAULT_INCLUDES \ 4 | "/I'.' " \ 5 | "/I'C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include' " \ 6 | "/I'C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/shared' " \ 7 | "/I'C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/ucrt' " \ 8 | "/I'C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/um'" 9 | 10 | #define DEFAULT_CL_PATH_X64 \ 11 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64" 12 | 13 | #define DEFAULT_CL_PATH_X86 \ 14 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64_x86;"\ 15 | "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64" 16 | 17 | #define DEFAULT_LIBPATHS_X64 \ 18 | "/libpath:'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x64' " \ 19 | "/libpath:'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x64' " \ 20 | "/libpath:'C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/lib/amd64'" 21 | 22 | #define DEFAULT_LIBPATHS_X86 \ 23 | "/libpath:'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x86' " \ 24 | "/libpath:'C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x86' " \ 25 | "/libpath:'C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/lib'" 26 | 27 | -------------------------------------------------------------------------------- /config/vs2015_BuildTools_from_vs2017_Community.h: -------------------------------------------------------------------------------- 1 | /* Visual Studio 2015 Build Tools installed with Visual Studio 2017 Community */ 2 | 3 | #define DEFAULT_INCLUDES \ 4 | "/I\".\" " \ 5 | "/I\"C:/Program Files (x86)/Microsoft Visual Studio/Shared/14.0/VC/include\" " \ 6 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared\" " \ 7 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt\" " \ 8 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um\"" 9 | 10 | #define DEFAULT_CL_PATH_X64 \ 11 | "C:/Program Files (x86)/Microsoft Visual Studio/Shared/14.0/VC/bin/amd64" 12 | 13 | #define DEFAULT_CL_PATH_X86 \ 14 | "C:/Program Files (x86)/Microsoft Visual Studio/Shared/14.0/VC/bin/amd64_x86;"\ 15 | "C:/Program Files (x86)/Microsoft Visual Studio/Shared/14.0/VC/bin/amd64" 16 | 17 | #define DEFAULT_LIBPATHS_X64 \ 18 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64\" " \ 19 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/um/x64\" " \ 20 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio/Shared/14.0/VC/lib/onecore/amd64\"" 21 | 22 | #define DEFAULT_LIBPATHS_X86 \ 23 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/ucrt/x86\" " \ 24 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/um/x86\" " \ 25 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio/Shared/14.0/VC/lib/onecore\"" 26 | 27 | -------------------------------------------------------------------------------- /config/vs2017_BuildTools.h: -------------------------------------------------------------------------------- 1 | /* Visual Studio 2017 (standalone) Build Tools */ 2 | 3 | #define DEFAULT_INCLUDES \ 4 | "/I. " \ 5 | "/I\"C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.10.25017/include\" " \ 6 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/shared\" " \ 7 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt\" " \ 8 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/um\"" 9 | 10 | #define DEFAULT_CL_PATH_X64 \ 11 | "C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.10.25017/bin/HostX64/x64" 12 | 13 | #define DEFAULT_CL_PATH_X86 \ 14 | "C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.10.25017/bin/HostX64/x86;"\ 15 | "C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.10.25017/bin/HostX64/x64" 16 | 17 | #define DEFAULT_LIBPATHS_X64 \ 18 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64\" " \ 19 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/um/x64\" " \ 20 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.10.25017/lib/onecore/x64\"" 21 | 22 | #define DEFAULT_LIBPATHS_X86 \ 23 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/ucrt/x86\" " \ 24 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.15063.0/um/x86\" " \ 25 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/VC/Tools/MSVC/14.10.25017/lib/onecore/x86\"" 26 | 27 | -------------------------------------------------------------------------------- /config/vs2017_Community.h: -------------------------------------------------------------------------------- 1 | /* Visual Studio 2017 Community */ 2 | 3 | #define DEFAULT_INCLUDES \ 4 | "/I. " \ 5 | "/I\"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/include\" " \ 6 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.16299.0/shared\" " \ 7 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.16299.0/ucrt\" " \ 8 | "/I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.16299.0/um\"" 9 | 10 | #define DEFAULT_CL_PATH_X64 \ 11 | "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx64/x64" 12 | 13 | #define DEFAULT_CL_PATH_X86 \ 14 | "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx64/x86;"\ 15 | "C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/bin/Hostx64/x64" 16 | 17 | #define DEFAULT_LIBPATHS_X64 \ 18 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/ucrt/x64\" " \ 19 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x64\" " \ 20 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/lib/onecore/x64\"" 21 | 22 | #define DEFAULT_LIBPATHS_X86 \ 23 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/ucrt/x86\" " \ 24 | "/libpath:\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x86\" " \ 25 | "/libpath:\"C:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.11.25503/lib/onecore/x86\"" 26 | 27 | -------------------------------------------------------------------------------- /config_default.h: -------------------------------------------------------------------------------- 1 | /* Visual Studio 2017 (standalone) Build Tools */ 2 | //#include "config/vs2017_BuildTools.h" 3 | 4 | /* Visual Studio 2015 (standalone) Build Tools */ 5 | //#include "config/vs2015_BuildTools.h" 6 | 7 | /* Visual Studio 2017 Community */ 8 | #include "config/vs2017_Community.h" 9 | 10 | /* Visual Studio 2015 Build Tools installed with Visual Studio 2017 Community */ 11 | //#include "config/vs2015_BuildTools_from_vs2017_Community.h" 12 | 13 | /* Visual Studio 2008 (Pro) */ 14 | //#include "config/vs2008_Pro.h" 15 | 16 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (C) 2017, djcj 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #define USAGE "\n" \ 26 | "This program is a wrapper for msvc's cl.exe and intended to be used\n" \ 27 | "with Windows 10's \"Bash on Ubuntu on Windows\" shell.\n" \ 28 | "It is invoked with gcc options (only a limited number) and turns\n" \ 29 | "them into msvc options to call cl.exe.\n" \ 30 | "The msvc options may not exactly do the same as their gcc counterparts.\n" \ 31 | "\n" \ 32 | "Supported GCC options (see `man gcc' for more information):\n" \ 33 | " -c -C -DDEFINE[=ARG] -fconstexpr-depth=num -ffp-contract=fast|off\n" \ 34 | " -finline-functions -fno-inline -frtti -fthreadsafe-statics\n" \ 35 | " -fomit-frame-pointer -fopenmp -fpermissive -fsized-deallocation -fstack-check\n" \ 36 | " -fstack-protector -funsigned-char -fwhole-program -g -include file -I path\n" \ 37 | " -llibname -L path -m32 -mavx -mavx2 -mdll -msse -msse2 -nodefaultlibs -nostdinc\n" \ 38 | " -nostdinc++ -nostdlib -O0 -O1 -O2 -O3 -Os -o file -print-search-dirs -shared\n" \ 39 | " -std=c<..>|gnu<..> -trigraphs -UDEFINE -w -Wall -Werror -Wextra\n" \ 40 | " -Wl,--out-implib,libname -Wl,-output-def,defname -Wl,--whole-archive -x \n" \ 41 | "\n" \ 42 | "Other options:\n" \ 43 | " --help display this information\n" \ 44 | " --help-cl display cl.exe's help information\n" \ 45 | " --help-link display link.exe's help information\n" \ 46 | " --version display version information of cl.exe and link.exe\n" \ 47 | " --verbose print commands\n" \ 48 | " --print-only print commands and don't to anything\n" \ 49 | " --path=path semicolon (;) separated list of win32 paths to run cl.exe\n" \ 50 | " -Wcl,arg -Wlink,arg parse msvc options directly to cl.exe/link.exe;\n" \ 51 | " see also https://msdn.microsoft.com/en-us/library/19z1t1wy.aspx\n" \ 52 | "\n" \ 53 | "Environment variables:\n" \ 54 | " CL_PATH semicolon (;) separated list of paths to run cl.exe\n" \ 55 | " INCLUDE semicolon (;) separated list of include paths\n" \ 56 | " LIB semicolon (;) separated list of library search paths\n" 57 | 58 | #include 59 | #include 60 | 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | 71 | #include "config.h" 72 | 73 | #define STR(x) std::string(x) 74 | 75 | bool begins(const char *p, const char *str); 76 | std::string win_path(char *ch); 77 | void split_env(const char *env_var, std::string msvc_arg, std::string &str); 78 | void print_help(char *self); 79 | extern "C" { 80 | int system_return(const char *command); 81 | } 82 | 83 | 84 | /* check if the beginning of p equals str and if p is longer than str */ 85 | bool begins(const char *p, const char *str) 86 | { 87 | size_t n = strlen(str); 88 | 89 | if (strncmp(p, str, n) == 0 && strlen(p) > n) 90 | { 91 | return true; 92 | } 93 | return false; 94 | } 95 | 96 | /* C: is mounted as "/mnt/c", D: as "/mnt/d", and so on; 97 | * forward slashes (/) are not converted to backslashes (\) 98 | * because Windows actually supports them */ 99 | 100 | std::string win_path(char *ch) 101 | { 102 | std::string str; 103 | 104 | if (ch[0] == '/') 105 | { 106 | bool prepend = true; 107 | 108 | if (begins(ch, "/mnt/")) 109 | { 110 | if (strchr("cdefghijklmnopqrstuvwxyzab", ch[5]) != NULL) 111 | { 112 | char *drive = new char[2]; 113 | sprintf(drive, "%c", toupper(ch[5])); 114 | 115 | if (strlen(ch) == 6) 116 | { 117 | /* /mnt/d -> D:/ */ 118 | prepend = false; 119 | str = STR(drive) + ":/"; 120 | } 121 | else if (ch[6] == '/') 122 | { 123 | /* /mnt/d/ -> D:/ 124 | * /mnt/d/dir -> D:/dir */ 125 | prepend = false; 126 | str = STR(drive) + ":/" + STR(ch+7); 127 | } 128 | } 129 | } 130 | 131 | if (prepend) 132 | { 133 | /* /usr/include -> ./usr/include */ 134 | str = "." + STR(ch); 135 | } 136 | } 137 | else 138 | { 139 | str = STR(ch); 140 | } 141 | 142 | return str; 143 | } 144 | 145 | void split_env(const char *env_var, std::string msvc_arg, std::string &str) 146 | { 147 | char *env = getenv(env_var); 148 | if (env != NULL) 149 | { 150 | char *token = strtok(env, ";"); 151 | while (token != NULL) 152 | { 153 | str += " /" + msvc_arg + "\"" + win_path(token) + "\""; 154 | token = strtok(NULL, ";"); 155 | } 156 | } 157 | } 158 | 159 | void print_help(char *self) 160 | { 161 | std::cout << "Usage: " << self << " [options] file...\n" << USAGE << std::endl; 162 | } 163 | 164 | 165 | int main(int argc, char **argv) 166 | { 167 | std::string str, cmd, lnk, driver_paths, run_exe; 168 | std::string driver_default = DEFAULT_CL_PATH_X64; 169 | std::string includes_default = DEFAULT_INCLUDES; 170 | std::string lib_paths_default = DEFAULT_LIBPATHS_X64; 171 | int bits = 64; 172 | 173 | bool verbose = false; 174 | bool print_only = false; 175 | bool have_outname = false; 176 | bool print_search_dirs = false; 177 | bool print_help_cl = false; 178 | bool print_help_link = false; 179 | bool print_version = false; 180 | bool do_link = true; 181 | bool use_default_driver = true; 182 | bool use_default_inc_paths = true; 183 | bool default_lib_paths = true; 184 | bool dll = false; 185 | bool link_static = false; 186 | 187 | char *driver_env = getenv("CL_PATH"); 188 | if (driver_env != NULL) 189 | { 190 | driver_paths = driver_env; 191 | use_default_driver = false; 192 | } 193 | 194 | 195 | /* parse arguments */ 196 | 197 | for (int i = 1; i < argc; ++i) 198 | { 199 | size_t len = strlen(argv[i]); 200 | char *arg = argv[i]; 201 | str = STR(argv[i]); 202 | 203 | if (arg[0] == '-') 204 | { 205 | if (arg[1] == '-') 206 | { 207 | if (begins(arg, "--path=")) { driver_paths = arg+7; 208 | use_default_driver = false; } 209 | else if (str == "--verbose") { verbose = true; } 210 | else if (str == "--print-only") { verbose = print_only = true; } 211 | else if (str == "--help") { print_help(argv[0]); return 0; } 212 | else if (begins(arg, "--help-")) 213 | { 214 | if (str == "--help-cl") { print_help_cl = true; } 215 | else if (str == "--help-link") { print_help_link = true; } 216 | } 217 | else if (str == "--version") { print_version = true; } 218 | } 219 | else 220 | { 221 | if ((arg[1] == '?' || arg[1] == 'h') && (len == 2 || str == "-help")) 222 | { 223 | print_help(argv[0]); 224 | return 0; 225 | } 226 | 227 | /* -c -C -w */ 228 | else if (str == "-c" || str == "-C" || str == "-w") 229 | { 230 | cmd += " /" + std::string(arg+1); 231 | if (str == "-c") { 232 | do_link = false; 233 | } 234 | } 235 | 236 | /* -g */ 237 | else if (str == "-g") 238 | { 239 | cmd += " /Zi"; 240 | } 241 | 242 | /* -x c -x c++ */ 243 | else if (arg[1] == 'x') 244 | { 245 | if (len == 2) { 246 | ++i; 247 | if (i < argc) { 248 | if (STR(argv[i]) == "c") { cmd += " /TC"; } 249 | else if (STR(argv[i]) == "c++") { cmd += " /TP"; } 250 | } 251 | } 252 | else if (str == "-xc") { cmd += " /TC"; } 253 | else if (str == "-xc++") { cmd += " /TP"; } 254 | } 255 | 256 | /* -o file */ 257 | else if (arg[1] == 'o') 258 | { 259 | if (len == 2) { 260 | ++i; 261 | if (i < argc) { 262 | lnk += " /out:\"" + STR(argv[i]) + "\""; 263 | } 264 | } else { 265 | lnk += " /out:\"" + STR(arg+2) + "\""; 266 | } 267 | have_outname = true; 268 | } 269 | 270 | /* -I path */ 271 | else if (arg[1] == 'I') 272 | { 273 | if (len == 2) { 274 | ++i; 275 | if (i < argc) { 276 | cmd += " /I\"" + win_path(argv[i]) + "\""; 277 | } 278 | } else { 279 | cmd += " /I\"" + win_path(arg+2) + "\""; 280 | } 281 | } 282 | 283 | /* -DDEFINE[=ARG] -UDEFINE */ 284 | else if (arg[1] == 'D' || arg[1] == 'U') 285 | { 286 | if (len == 2) { 287 | ++i; 288 | if (i < argc) { 289 | cmd += " /" + str.substr(1,1) + "\"" + STR(argv[i]) + "\""; 290 | } 291 | } else { 292 | cmd += " /" + str.substr(1,1) + "\"" + STR(arg+2) + "\""; 293 | } 294 | } 295 | 296 | /* -L path */ 297 | else if (arg[1] == 'L') 298 | { 299 | if (len == 2) { 300 | ++i; 301 | if (i < argc) { 302 | lnk += " /libpath:\"" + win_path(argv[i]) + "\""; 303 | } 304 | } else { 305 | lnk += " /libpath:\"" + win_path(arg+2) + "\""; 306 | } 307 | } 308 | 309 | /* -llibname */ 310 | else if (arg[1] == 'l' && len > 2) 311 | { 312 | if (str != "-lc" && 313 | str != "-lm" && 314 | str != "-lrt" && /* always ignore these libraries */ 315 | str != "-lstdc++" && 316 | str != "-lgcc_s" && 317 | str != "-lmingw32" && /* TODO: maybe add an option */ 318 | str != "-lmingwex" && /* to disable the blacklisting */ 319 | str != "-lmingwthrd" && 320 | str != "-lmoldname" && 321 | str != "-lpthread") { lnk += " \"" + STR(arg+2) + ".lib\""; } 322 | } 323 | 324 | /* -O0 -O1 -O2 -O3 -Os */ 325 | else if (arg[1] == 'O' && len == 3) 326 | { 327 | if (arg[2] == '1' || 328 | arg[2] == '2') { cmd += " /O2 /Ot"; } 329 | else if (arg[2] == '3') { cmd += " /Ox"; } 330 | else if (arg[2] == 's') { cmd += " /O1 /Os"; } 331 | else if (arg[2] == '0') { cmd += " /Od"; } 332 | } 333 | 334 | /* -Wl,--whole-archive 335 | * -Wl,--out-implib,libname 336 | * -Wl,-output-def,defname 337 | * -Wall -Wextra -Werror 338 | * -Wcl,arg -Wlink,arg */ 339 | else if (arg[1] == 'W' && len > 2) 340 | { 341 | if (arg[2] == 'l') 342 | { 343 | std::string lopt; 344 | if (len == 3) { 345 | ++i; 346 | if (i < argc) { 347 | lopt = STR(argv[i]); 348 | } 349 | } else { 350 | lopt = STR(arg+4); 351 | } 352 | 353 | if (lopt == "--whole-archive") 354 | { 355 | lnk += " /wholearchive"; 356 | } 357 | 358 | else if (begins(lopt.c_str(), "--out-implib,")) 359 | { 360 | lnk += " /implib:\"" + STR(arg+17) + "\""; 361 | } 362 | else if (str == "-Wl,--out-implib") 363 | { 364 | ++i; 365 | if (i < argc && begins(argv[i], "-Wl,")) { 366 | lnk += " /implib:\"" + STR(argv[i]+4) + "\""; 367 | } 368 | } 369 | 370 | else if (begins(lopt.c_str(), "-output-def,")) 371 | { 372 | lnk += " /def:\"" + STR(arg+16) + "\""; 373 | } 374 | else if (str == "-Wl,-output-def") 375 | { 376 | ++i; 377 | if (i < argc && begins(argv[i], "-Wl,")) { 378 | lnk += " /def:\"" + STR(argv[i]+4) + "\""; 379 | } 380 | } 381 | 382 | else if (str == "-Wlink" || begins(arg, "-Wlink,")) 383 | { 384 | std::string s; 385 | if (str == "-Wlink" && i+1 < argc) 386 | { 387 | ++i; 388 | s = STR(argv[i]); 389 | } 390 | else 391 | { 392 | s = STR(arg+7); 393 | } 394 | 395 | if (!s.empty()) 396 | { 397 | if (s[0] == '-') 398 | { 399 | lnk += " /" + s.substr(1); 400 | } 401 | else if (s[0] != '/') 402 | { 403 | lnk += " /" + s; 404 | } 405 | else 406 | { 407 | lnk += " " + s; 408 | } 409 | } 410 | } 411 | } 412 | 413 | else if (str == "-Wcl" || begins(arg, "-Wcl,")) 414 | { 415 | std::string s; 416 | if (str == "-Wcl" && i+1 < argc) 417 | { 418 | ++i; 419 | s = STR(argv[i]); 420 | } 421 | else 422 | { 423 | s = STR(arg+5); 424 | } 425 | 426 | if (!s.empty()) 427 | { 428 | if (s[0] == '-') 429 | { 430 | cmd += " /" + s.substr(1); 431 | } 432 | else if (s[0] != '/') 433 | { 434 | cmd += " /" + s; 435 | } 436 | else 437 | { 438 | cmd += " " + s; 439 | } 440 | } 441 | } 442 | 443 | else if (str == "-Wall") { cmd += " /W3"; } 444 | else if (str == "-Wextra") { cmd += " /Wall"; } 445 | else if (str == "-Werror") { cmd += " /WX"; } 446 | } 447 | 448 | /* -mdll -msse -msse2 -mavx -mavx2 */ 449 | else if (arg[1] == 'm' && len > 2) 450 | { 451 | if (str == "-m32") { bits = 32; } 452 | else if (str == "-m64") { bits = 64; } 453 | else if (str == "-mdll") { cmd += " /LD"; dll = true; } 454 | else if (str == "-msse") { cmd += " /arch:SSE"; } 455 | else if (str == "-msse2") { cmd += " /arch:SSE2"; } 456 | else if (str == "-mavx") { cmd += " /arch:AVX"; } 457 | else if (str == "-mavx2") { cmd += " /arch:AVX2"; } 458 | } 459 | 460 | /* -frtti -fthreadsafe-statics -fno-inline -fomit-frame-pointer 461 | * -fpermissive -finline-functions -fopenmp -fstack-protector -fstack-check 462 | * -fstack-protector-strong -fstack-protector-all 463 | * -funsigned-char -fsized-deallocation -fconstexpr-depth=num 464 | * -ffp-contract=fast|off -fwhole-program */ 465 | else if (arg[1] == 'f' && len > 2) 466 | { 467 | if (begins(arg, "-fno-")) 468 | { 469 | if (str == "-fno-rtti") { cmd += " /GR-"; } 470 | else if (str == "-fno-threadsafe-statics") { cmd += " /Zc:threadSafeInit-"; } 471 | else if (str == "-fno-inline") { cmd += " /Ob0"; } 472 | else if (str == "-fno-stack-protector" || 473 | str == "-fno-stack-check") { cmd += " /GS- /guard:cf-"; } 474 | else if (str == "-fno-sized-deallocation") { cmd += " /Zc:sizedDealloc-"; } 475 | else if (str == "-fno-whole-program") { cmd += " /GL-"; } 476 | } 477 | else 478 | { 479 | if (str == "-fomit-frame-pointer") { cmd += " /Oy"; } 480 | else if (str == "-fpermissive") { cmd += " /permissive"; } 481 | else if (str == "-fstack-protector" || 482 | str == "-fstack-check") { cmd += " /GS"; } 483 | else if (str == "-fstack-protector-strong" || 484 | str == "-fstack-protector-all") { cmd += " /GS /guard:cf"; } 485 | else if (str == "-finline-functions") { cmd += " /Ob2"; } 486 | else if (str == "-frtti") { cmd += " /GR"; } 487 | else if (str == "-fthreadsafe-statics") { cmd += " /Zc:threadSafeInit"; } 488 | else if (str == "-fopenmp") { cmd += " /openmp"; } 489 | else if (str == "-funsigned-char") { cmd += " /J"; } 490 | else if (str == "-fsized-deallocation") { cmd += " /Zc:sizedDealloc"; } 491 | else if (begins(arg, "-fconstexpr-depth=")) { cmd += " /constexpr:depth" + STR(arg+18); } 492 | else if (begins(arg, "-ffp-contract=")) 493 | { 494 | if (STR(arg+14) == "fast") { cmd += " /fp:fast"; } 495 | else if (STR(arg+14) == "off") { cmd += " /fp:strict"; } 496 | } 497 | else if (str == "-fwhole-program") { cmd += " /GL"; } 498 | } 499 | } 500 | 501 | /* -nostdinc -nostdinc++ -nostdlib -nodefaultlibs */ 502 | else if (arg[1] == 'n' && len > 8) 503 | { 504 | if (str == "-nostdinc" || 505 | str == "-nostdinc++") { use_default_inc_paths = false; } 506 | else if (str == "-nostdlib") { default_lib_paths = false; } 507 | else if (str == "-nodefaultlibs") { lnk += " /nodefaultlib"; 508 | default_lib_paths = false; } 509 | } 510 | 511 | /* -shared -static -static-libgcc -static-libstdc++ -std=c<..>|gnu<..> */ 512 | else if (arg[1] == 's' && len > 5) 513 | { 514 | if (str == "-shared") { cmd += " /LD"; dll = true; } 515 | else if (str == "-static" || 516 | str == "-static-libgcc" || 517 | str == "-static-libstdc++") { link_static = true; } 518 | else if (begins(arg, "-std=")) 519 | { 520 | if (begins(arg, "-std=gnu")) { cmd += " /std:c" + STR(arg+8); } 521 | else { cmd += " /std:" + STR(arg+5); } 522 | } 523 | } 524 | 525 | /* -include file */ 526 | else if (str == "-include") 527 | { 528 | ++i; 529 | if (i < argc) { 530 | cmd += " /FI\"" + STR(argv[i]) + "\""; 531 | } 532 | } 533 | 534 | /* -trigraphs */ 535 | else if (str == "-trigraphs") 536 | { 537 | cmd += " /Zc:trigraphs"; 538 | } 539 | 540 | /* -print-search-dirs */ 541 | else if (str == "-print-search-dirs") 542 | { 543 | print_search_dirs = true; 544 | } 545 | } 546 | } 547 | else 548 | { 549 | cmd += " \"" + win_path(arg) + "\""; 550 | } 551 | } 552 | 553 | if (bits == 32) 554 | { 555 | if (!use_default_driver) 556 | { 557 | std::cerr << "warning: ignoring `-m32' when using a custom cl.exe" << std::endl; 558 | } 559 | driver_default = DEFAULT_CL_PATH_X86; 560 | lib_paths_default = DEFAULT_LIBPATHS_X86; 561 | } 562 | if (use_default_driver) 563 | { 564 | driver_paths = driver_default; 565 | } 566 | 567 | run_exe = "cmd.exe /C 'set PATH=" + driver_paths + ";%PATH% & "; 568 | 569 | 570 | /* print information and exit */ 571 | 572 | if (print_help_cl) 573 | { 574 | /* piping to cat helps to display the 575 | * output correctly and in one go */ 576 | cmd = run_exe + "cl.exe /help' 2>&1 | cat"; 577 | return system(cmd.c_str()); 578 | } 579 | else if (print_help_link) 580 | { 581 | cmd = run_exe + "link.exe' 2>&1 | cat"; 582 | return system(cmd.c_str()); 583 | } 584 | else if (print_version) 585 | { 586 | cmd = run_exe + "cl.exe' 2>&1 | head -n3 ; " + run_exe + "link.exe' 2>&1 | head -n3"; 587 | return system(cmd.c_str()); 588 | } 589 | 590 | if (print_search_dirs) 591 | { 592 | std::cout << "cl.exe: " << driver_default << std::endl; 593 | std::cout << "includes: " << includes_default << std::endl; 594 | std::cout << "libraries: " << lib_paths_default << std::endl; 595 | return 0; 596 | } 597 | 598 | 599 | /* turn lists obtained from environment variables INCLUDE and 600 | * and LIB into command line arguments /I\"dir\" and /libpath\"dir\" */ 601 | split_env("INCLUDE", "I", cmd); 602 | split_env("LIB", "libpath", cmd); 603 | 604 | 605 | /* create the final command to execute */ 606 | 607 | if (use_default_inc_paths) { cmd += " " + includes_default; } 608 | if (!link_static) { cmd += " /MD"; } 609 | if (do_link) 610 | { 611 | if (!have_outname) 612 | { 613 | if (dll) { lnk += " /out:\"a.dll\""; } 614 | else { lnk += " /out:\"a.exe\""; } 615 | } 616 | if (default_lib_paths) { lnk += " " + lib_paths_default; } 617 | cmd += " /link" + lnk; 618 | } 619 | 620 | /* replace all occurences of single quotes (') with double quotes ("); 621 | * this is needed to wrap everything within singles quotes so we can 622 | * parse it as a single command line argument to cmd.exe */ 623 | for (size_t i = 0; (i = cmd.find("'", i)) != std::string::npos; ++i) 624 | { 625 | cmd.replace(i, 1, "\""); 626 | } 627 | 628 | cmd = run_exe + "cl.exe" + cmd + "'"; 629 | 630 | if (verbose) 631 | { 632 | std::cout << cmd << std::endl; 633 | } 634 | if (print_only) 635 | { 636 | return 0; 637 | } 638 | 639 | return system_return(cmd.c_str()); 640 | } 641 | 642 | -------------------------------------------------------------------------------- /system_return.c: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (C) 2017, djcj 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | /** 31 | * like system() but it returns the exit code of the 32 | * given command rather than that of the forked shell 33 | */ 34 | 35 | int system_return(const char *command) 36 | { 37 | int status; 38 | int return_status = 127; 39 | pid_t pid = fork(); 40 | 41 | if (pid == 0) 42 | { 43 | execl("/bin/sh", "sh", "-c", command, (char *)NULL); 44 | _exit(127); /* if execl() was successful, this won't be reached */ 45 | } 46 | 47 | if (pid > 0) 48 | { 49 | if (waitpid(pid, &status, 0) > 0) 50 | { 51 | if (WIFEXITED(status) == 1) 52 | { 53 | return_status = WEXITSTATUS(status); 54 | if (return_status == 127) { 55 | fprintf(stderr, "execl() failed\n"); 56 | } 57 | } else { 58 | fprintf(stderr, "the program did not terminate normally\n"); 59 | } 60 | } else { 61 | fprintf(stderr, "waitpid() failed\n"); 62 | } 63 | } else { 64 | fprintf(stderr, "failed to fork()\n"); 65 | } 66 | 67 | return return_status; 68 | } 69 | 70 | /* 71 | int main(int argc, char **argv) 72 | { 73 | if (argc != 2) 74 | { 75 | fprintf(stderr, "usage: %s command\n", argv[0]); 76 | return 1; 77 | } 78 | 79 | int retval = system_return(argv[1]); 80 | printf("command `%s' returned %d\n", argv[1], retval); 81 | 82 | return 0; 83 | } 84 | */ 85 | 86 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | tst="tmp_test" 5 | 6 | cat < ${tst}.cpp 7 | #include 8 | int main(){ std::wcout << ">> SUCCESS" << std::endl; return 0; } 9 | EOF 10 | cat < ${tst}.c 11 | #include 12 | #include 13 | wchar_t *wch = L">> SUCCESS"; 14 | int main(){ fprintf(stdout, "%ls\n", wch); return 0; } 15 | EOF 16 | 17 | for m in 32 64 ; do 18 | for file in "${tst}.c" "${tst}.cpp" ; do 19 | ./gcc2msvc --verbose -m$m -Wall -g -O0 -Wcl,/EHsc $file -o ${file}.${m}.exe 20 | done 21 | done 22 | 23 | for m in 32 64 ; do 24 | echo "" 25 | exe="${tst}.c.${m}.exe" 26 | echo "=== Testing $exe ===" 27 | printf "file type: " 28 | file -b $exe 29 | ./$exe 30 | 31 | echo "" 32 | exe="${tst}.cpp.${m}.exe" 33 | echo "=== Testing $exe ===" 34 | printf "file type: " 35 | file -b $exe 36 | ./$exe 37 | done 38 | 39 | --------------------------------------------------------------------------------