main.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. /*
  2. * Main function
  3. *
  4. * Copyright 1993 Robert J. Amstadt
  5. * Copyright 1995 Martin von Loewis
  6. * Copyright 1995, 1996, 1997 Alexandre Julliard
  7. * Copyright 1997 Eric Youngdale
  8. * Copyright 1999 Ulrich Weigand
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #include "config.h"
  25. #include "wine/port.h"
  26. #include <assert.h>
  27. #include <stdio.h>
  28. #include <signal.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <stdarg.h>
  32. #include <ctype.h>
  33. #ifdef HAVE_GETOPT_H
  34. # include <getopt.h>
  35. #endif
  36. #include "build.h"
  37. int UsePIC = 0;
  38. int nb_errors = 0;
  39. int display_warnings = 0;
  40. int kill_at = 0;
  41. int verbose = 0;
  42. int link_ext_symbols = 0;
  43. int force_pointer_size = 0;
  44. int unwind_tables = 0;
  45. int use_msvcrt = 0;
  46. int unix_lib = 0;
  47. int safe_seh = 0;
  48. int prefer_native = 0;
  49. #ifdef __i386__
  50. enum target_cpu target_cpu = CPU_x86;
  51. #elif defined(__x86_64__)
  52. enum target_cpu target_cpu = CPU_x86_64;
  53. #elif defined(__powerpc__)
  54. enum target_cpu target_cpu = CPU_POWERPC;
  55. #elif defined(__arm__)
  56. enum target_cpu target_cpu = CPU_ARM;
  57. #elif defined(__aarch64__)
  58. enum target_cpu target_cpu = CPU_ARM64;
  59. #else
  60. #error Unsupported CPU
  61. #endif
  62. #ifdef __APPLE__
  63. enum target_platform target_platform = PLATFORM_APPLE;
  64. #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  65. enum target_platform target_platform = PLATFORM_FREEBSD;
  66. #elif defined(__sun)
  67. enum target_platform target_platform = PLATFORM_SOLARIS;
  68. #elif defined(_WIN32)
  69. enum target_platform target_platform = PLATFORM_MINGW;
  70. #else
  71. enum target_platform target_platform = PLATFORM_UNSPECIFIED;
  72. #endif
  73. char *target_alias = NULL;
  74. char *input_file_name = NULL;
  75. char *spec_file_name = NULL;
  76. FILE *output_file = NULL;
  77. const char *output_file_name = NULL;
  78. static int fake_module;
  79. struct strarray lib_path = { 0 };
  80. struct strarray tools_path = { 0 };
  81. struct strarray as_command = { 0 };
  82. struct strarray cc_command = { 0 };
  83. struct strarray ld_command = { 0 };
  84. struct strarray nm_command = { 0 };
  85. char *cpu_option = NULL;
  86. char *fpu_option = NULL;
  87. char *arch_option = NULL;
  88. #ifdef __SOFTFP__
  89. const char *float_abi_option = "soft";
  90. #else
  91. const char *float_abi_option = "softfp";
  92. #endif
  93. #ifdef __thumb__
  94. int thumb_mode = 1;
  95. #else
  96. int thumb_mode = 0;
  97. #endif
  98. static struct strarray res_files;
  99. /* execution mode */
  100. enum exec_mode_values
  101. {
  102. MODE_NONE,
  103. MODE_DLL,
  104. MODE_EXE,
  105. MODE_DEF,
  106. MODE_IMPLIB,
  107. MODE_STATICLIB,
  108. MODE_BUILTIN,
  109. MODE_FIXUP_CTORS,
  110. MODE_RESOURCES
  111. };
  112. static enum exec_mode_values exec_mode = MODE_NONE;
  113. static const struct
  114. {
  115. const char *name;
  116. enum target_platform platform;
  117. } platform_names[] =
  118. {
  119. { "macos", PLATFORM_APPLE },
  120. { "darwin", PLATFORM_APPLE },
  121. { "freebsd", PLATFORM_FREEBSD },
  122. { "solaris", PLATFORM_SOLARIS },
  123. { "mingw32", PLATFORM_MINGW },
  124. { "windows-gnu", PLATFORM_MINGW },
  125. { "windows", PLATFORM_WINDOWS },
  126. { "winnt", PLATFORM_MINGW }
  127. };
  128. /* set the dll file name from the input file name */
  129. static void set_dll_file_name( const char *name, DLLSPEC *spec )
  130. {
  131. char *p;
  132. if (spec->file_name) return;
  133. if ((p = strrchr( name, '\\' ))) name = p + 1;
  134. if ((p = strrchr( name, '/' ))) name = p + 1;
  135. spec->file_name = xmalloc( strlen(name) + 5 );
  136. strcpy( spec->file_name, name );
  137. if ((p = strrchr( spec->file_name, '.' )))
  138. {
  139. if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0;
  140. }
  141. }
  142. /* set the dll name from the file name */
  143. static void init_dll_name( DLLSPEC *spec )
  144. {
  145. if (!spec->file_name && output_file_name)
  146. {
  147. char *p;
  148. spec->file_name = xstrdup( output_file_name );
  149. if ((p = strrchr( spec->file_name, '.' ))) *p = 0;
  150. }
  151. if (!spec->dll_name && spec->file_name) /* set default name from file name */
  152. {
  153. char *p;
  154. spec->dll_name = xstrdup( spec->file_name );
  155. if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
  156. }
  157. if (spec->dll_name) spec->c_name = make_c_identifier( spec->dll_name );
  158. }
  159. /* set the dll subsystem */
  160. static void set_subsystem( const char *subsystem, DLLSPEC *spec )
  161. {
  162. char *major, *minor, *str = xstrdup( subsystem );
  163. if ((major = strchr( str, ':' ))) *major++ = 0;
  164. if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
  165. else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
  166. else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
  167. else if (!strcmp( str, "wince" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CE_GUI;
  168. else if (!strcmp( str, "win16" )) spec->type = SPEC_WIN16;
  169. else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
  170. if (major)
  171. {
  172. if ((minor = strchr( major, '.' )))
  173. {
  174. *minor++ = 0;
  175. spec->subsystem_minor = atoi( minor );
  176. }
  177. spec->subsystem_major = atoi( major );
  178. }
  179. free( str );
  180. }
  181. /* set the target CPU and platform */
  182. static void set_target( const char *target )
  183. {
  184. unsigned int i;
  185. char *p, *spec = xstrdup( target );
  186. /* target specification is in the form CPU-MANUFACTURER-OS or CPU-MANUFACTURER-KERNEL-OS */
  187. target_alias = xstrdup( target );
  188. /* get the CPU part */
  189. if ((p = strchr( spec, '-' )))
  190. {
  191. int cpu;
  192. *p++ = 0;
  193. cpu = get_cpu_from_name( spec );
  194. if (cpu == -1) fatal_error( "Unrecognized CPU '%s'\n", spec );
  195. target_cpu = cpu;
  196. }
  197. else if (!strcmp( spec, "mingw32" ))
  198. {
  199. target_cpu = CPU_x86;
  200. p = spec;
  201. }
  202. else
  203. fatal_error( "Invalid target specification '%s'\n", target );
  204. /* get the OS part */
  205. target_platform = PLATFORM_UNSPECIFIED; /* default value */
  206. for (;;)
  207. {
  208. for (i = 0; i < ARRAY_SIZE(platform_names); i++)
  209. {
  210. if (!strncmp( platform_names[i].name, p, strlen(platform_names[i].name) ))
  211. {
  212. target_platform = platform_names[i].platform;
  213. break;
  214. }
  215. }
  216. if (target_platform != PLATFORM_UNSPECIFIED || !(p = strchr( p, '-' ))) break;
  217. p++;
  218. }
  219. free( spec );
  220. if (target_cpu == CPU_ARM && is_pe()) thumb_mode = 1;
  221. }
  222. /* cleanup on program exit */
  223. static void cleanup(void)
  224. {
  225. if (output_file_name) unlink( output_file_name );
  226. }
  227. /* clean things up when aborting on a signal */
  228. static void exit_on_signal( int sig )
  229. {
  230. exit(1); /* this will call atexit functions */
  231. }
  232. /*******************************************************************
  233. * command-line option handling
  234. */
  235. static const char usage_str[] =
  236. "Usage: winebuild [OPTIONS] [FILES]\n\n"
  237. "Options:\n"
  238. " --as-cmd=AS Command to use for assembling (default: as)\n"
  239. " -b, --target=TARGET Specify target CPU and platform for cross-compiling\n"
  240. " -B PREFIX Look for build tools in the PREFIX directory\n"
  241. " --cc-cmd=CC C compiler to use for assembling (default: fall back to --as-cmd)\n"
  242. " -d, --delay-lib=LIB Import the specified library in delayed mode\n"
  243. " -D SYM Ignored for C flags compatibility\n"
  244. " -e, --entry=FUNC Set the DLL entry point function (default: DllMain)\n"
  245. " -E, --export=FILE Export the symbols defined in the .spec or .def file\n"
  246. " --external-symbols Allow linking to external symbols\n"
  247. " -f FLAGS Compiler flags (-fPIC and -fasynchronous-unwind-tables are supported)\n"
  248. " -F, --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
  249. " --fake-module Create a fake binary module\n"
  250. " -h, --help Display this help message\n"
  251. " -H, --heap=SIZE Set the heap size for a Win16 dll\n"
  252. " -I DIR Ignored for C flags compatibility\n"
  253. " -k, --kill-at Kill stdcall decorations in generated .def files\n"
  254. " -K, FLAGS Compiler flags (only -KPIC is supported)\n"
  255. " --large-address-aware Support an address space larger than 2Gb\n"
  256. " --ld-cmd=LD Command to use for linking (default: ld)\n"
  257. " -l, --library=LIB Import the specified library\n"
  258. " -L, --library-path=DIR Look for imports libraries in DIR\n"
  259. " -m16, -m32, -m64 Force building 16-bit, 32-bit resp. 64-bit code\n"
  260. " -M, --main-module=MODULE Set the name of the main module for a Win16 dll\n"
  261. " --nm-cmd=NM Command to use to get undefined symbols (default: nm)\n"
  262. " --nxcompat=y|n Set the NX compatibility flag (default: yes)\n"
  263. " -N, --dll-name=DLLNAME Set the DLL name (default: from input file name)\n"
  264. " -o, --output=NAME Set the output file name (default: stdout)\n"
  265. " --prefer-native Set the flag to prefer loading native at run time\n"
  266. " -r, --res=RSRC.RES Load resources from RSRC.RES\n"
  267. " --safeseh Mark object files as SEH compatible\n"
  268. " --save-temps Do not delete the generated intermediate files\n"
  269. " --subsystem=SUBSYS Set the subsystem (one of native, windows, console, wince)\n"
  270. " -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n"
  271. " -v, --verbose Display the programs invoked\n"
  272. " --version Print the version and exit\n"
  273. " -w, --warnings Turn on warnings\n"
  274. "\nMode options:\n"
  275. " --dll Build a library from a .spec file and object files\n"
  276. " --def Build a .def file from a .spec file\n"
  277. " --exe Build an executable from object files\n"
  278. " --implib Build an import library\n"
  279. " --staticlib Build a static library\n"
  280. " --resources Build a .o or .res file for the resource files\n\n"
  281. " --builtin Mark a library as a Wine builtin\n"
  282. " --fixup-ctors Fixup the constructors data after the module has been built\n"
  283. "The mode options are mutually exclusive; you must specify one and only one.\n\n";
  284. enum long_options_values
  285. {
  286. LONG_OPT_DLL = 1,
  287. LONG_OPT_DEF,
  288. LONG_OPT_EXE,
  289. LONG_OPT_IMPLIB,
  290. LONG_OPT_BUILTIN,
  291. LONG_OPT_ASCMD,
  292. LONG_OPT_CCCMD,
  293. LONG_OPT_EXTERNAL_SYMS,
  294. LONG_OPT_FAKE_MODULE,
  295. LONG_OPT_FIXUP_CTORS,
  296. LONG_OPT_LARGE_ADDRESS_AWARE,
  297. LONG_OPT_LDCMD,
  298. LONG_OPT_NMCMD,
  299. LONG_OPT_NXCOMPAT,
  300. LONG_OPT_PREFER_NATIVE,
  301. LONG_OPT_RESOURCES,
  302. LONG_OPT_SAFE_SEH,
  303. LONG_OPT_SAVE_TEMPS,
  304. LONG_OPT_STATICLIB,
  305. LONG_OPT_SUBSYSTEM,
  306. LONG_OPT_VERSION
  307. };
  308. static const char short_options[] = "B:C:D:E:F:H:I:K:L:M:N:b:d:e:f:hkl:m:o:r:u:vw";
  309. static const struct option long_options[] =
  310. {
  311. { "dll", 0, 0, LONG_OPT_DLL },
  312. { "def", 0, 0, LONG_OPT_DEF },
  313. { "exe", 0, 0, LONG_OPT_EXE },
  314. { "implib", 0, 0, LONG_OPT_IMPLIB },
  315. { "staticlib", 0, 0, LONG_OPT_STATICLIB },
  316. { "builtin", 0, 0, LONG_OPT_BUILTIN },
  317. { "as-cmd", 1, 0, LONG_OPT_ASCMD },
  318. { "cc-cmd", 1, 0, LONG_OPT_CCCMD },
  319. { "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS },
  320. { "fake-module", 0, 0, LONG_OPT_FAKE_MODULE },
  321. { "fixup-ctors", 0, 0, LONG_OPT_FIXUP_CTORS },
  322. { "large-address-aware", 0, 0, LONG_OPT_LARGE_ADDRESS_AWARE },
  323. { "ld-cmd", 1, 0, LONG_OPT_LDCMD },
  324. { "nm-cmd", 1, 0, LONG_OPT_NMCMD },
  325. { "nxcompat", 1, 0, LONG_OPT_NXCOMPAT },
  326. { "prefer-native", 0, 0, LONG_OPT_PREFER_NATIVE },
  327. { "resources", 0, 0, LONG_OPT_RESOURCES },
  328. { "safeseh", 0, 0, LONG_OPT_SAFE_SEH },
  329. { "save-temps", 0, 0, LONG_OPT_SAVE_TEMPS },
  330. { "subsystem", 1, 0, LONG_OPT_SUBSYSTEM },
  331. { "version", 0, 0, LONG_OPT_VERSION },
  332. /* aliases for short options */
  333. { "target", 1, 0, 'b' },
  334. { "delay-lib", 1, 0, 'd' },
  335. { "export", 1, 0, 'E' },
  336. { "entry", 1, 0, 'e' },
  337. { "filename", 1, 0, 'F' },
  338. { "help", 0, 0, 'h' },
  339. { "heap", 1, 0, 'H' },
  340. { "kill-at", 0, 0, 'k' },
  341. { "library", 1, 0, 'l' },
  342. { "library-path", 1, 0, 'L' },
  343. { "main-module", 1, 0, 'M' },
  344. { "dll-name", 1, 0, 'N' },
  345. { "output", 1, 0, 'o' },
  346. { "res", 1, 0, 'r' },
  347. { "undefined", 1, 0, 'u' },
  348. { "verbose", 0, 0, 'v' },
  349. { "warnings", 0, 0, 'w' },
  350. { NULL, 0, 0, 0 }
  351. };
  352. static void usage( int exit_code )
  353. {
  354. fprintf( stderr, "%s", usage_str );
  355. exit( exit_code );
  356. }
  357. static void set_exec_mode( enum exec_mode_values mode )
  358. {
  359. if (exec_mode != MODE_NONE) usage(1);
  360. exec_mode = mode;
  361. }
  362. /* get the default entry point for a given spec file */
  363. static const char *get_default_entry_point( const DLLSPEC *spec )
  364. {
  365. if (spec->characteristics & IMAGE_FILE_DLL) return "DllMain";
  366. if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
  367. if (spec->type == SPEC_WIN16)
  368. {
  369. add_spec_extra_ld_symbol("WinMain16");
  370. return "__wine_spec_exe16_entry";
  371. }
  372. else if (spec->unicode_app)
  373. {
  374. /* __wine_spec_exe_wentry always calls wmain */
  375. add_spec_extra_ld_symbol("wmain");
  376. if (spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
  377. add_spec_extra_ld_symbol("wWinMain");
  378. return "__wine_spec_exe_wentry";
  379. }
  380. else
  381. {
  382. /* __wine_spec_exe_entry always calls main */
  383. add_spec_extra_ld_symbol("main");
  384. if (spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
  385. add_spec_extra_ld_symbol("WinMain");
  386. return "__wine_spec_exe_entry";
  387. }
  388. }
  389. /* parse options from the argv array and remove all the recognized ones */
  390. static char **parse_options( int argc, char **argv, DLLSPEC *spec )
  391. {
  392. char *p;
  393. int optc;
  394. int save_temps = 0;
  395. while ((optc = getopt_long( argc, argv, short_options, long_options, NULL )) != -1)
  396. {
  397. switch(optc)
  398. {
  399. case 'B':
  400. strarray_add( &tools_path, xstrdup( optarg ), NULL );
  401. break;
  402. case 'D':
  403. /* ignored */
  404. break;
  405. case 'E':
  406. spec_file_name = xstrdup( optarg );
  407. set_dll_file_name( optarg, spec );
  408. break;
  409. case 'F':
  410. spec->file_name = xstrdup( optarg );
  411. break;
  412. case 'H':
  413. if (!isdigit(optarg[0]))
  414. fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg );
  415. spec->heap_size = atoi(optarg);
  416. if (spec->heap_size > 65535)
  417. fatal_error( "Invalid heap size %d, maximum is 65535\n", spec->heap_size );
  418. break;
  419. case 'I':
  420. /* ignored */
  421. break;
  422. case 'K':
  423. /* ignored, because cc generates correct code. */
  424. break;
  425. case 'L':
  426. strarray_add( &lib_path, xstrdup( optarg ), NULL );
  427. break;
  428. case 'm':
  429. if (!strcmp( optarg, "16" )) spec->type = SPEC_WIN16;
  430. else if (!strcmp( optarg, "32" )) force_pointer_size = 4;
  431. else if (!strcmp( optarg, "64" )) force_pointer_size = 8;
  432. else if (!strcmp( optarg, "arm" )) thumb_mode = 0;
  433. else if (!strcmp( optarg, "thumb" )) thumb_mode = 1;
  434. else if (!strcmp( optarg, "no-cygwin" )) use_msvcrt = 1;
  435. else if (!strcmp( optarg, "unix" )) unix_lib = 1;
  436. else if (!strcmp( optarg, "unicode" )) spec->unicode_app = 1;
  437. else if (!strncmp( optarg, "cpu=", 4 )) cpu_option = xstrdup( optarg + 4 );
  438. else if (!strncmp( optarg, "fpu=", 4 )) fpu_option = xstrdup( optarg + 4 );
  439. else if (!strncmp( optarg, "arch=", 5 )) arch_option = xstrdup( optarg + 5 );
  440. else if (!strncmp( optarg, "float-abi=", 10 )) float_abi_option = xstrdup( optarg + 10 );
  441. else fatal_error( "Unknown -m option '%s'\n", optarg );
  442. break;
  443. case 'M':
  444. spec->main_module = xstrdup( optarg );
  445. break;
  446. case 'N':
  447. spec->dll_name = xstrdup( optarg );
  448. break;
  449. case 'b':
  450. set_target( optarg );
  451. break;
  452. case 'd':
  453. add_delayed_import( optarg );
  454. break;
  455. case 'e':
  456. spec->init_func = xstrdup( optarg );
  457. if ((p = strchr( spec->init_func, '@' ))) *p = 0; /* kill stdcall decoration */
  458. break;
  459. case 'f':
  460. if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1;
  461. else if (!strcmp( optarg, "asynchronous-unwind-tables")) unwind_tables = 1;
  462. else if (!strcmp( optarg, "no-asynchronous-unwind-tables")) unwind_tables = 0;
  463. /* ignore all other flags */
  464. break;
  465. case 'h':
  466. usage(0);
  467. break;
  468. case 'k':
  469. kill_at = 1;
  470. break;
  471. case 'l':
  472. add_import_dll( optarg, NULL );
  473. break;
  474. case 'o':
  475. if (unlink( optarg ) == -1 && errno != ENOENT)
  476. fatal_error( "Unable to create output file '%s'\n", optarg );
  477. output_file_name = xstrdup( optarg );
  478. break;
  479. case 'r':
  480. strarray_add( &res_files, xstrdup( optarg ), NULL );
  481. break;
  482. case 'u':
  483. add_extra_ld_symbol( optarg );
  484. break;
  485. case 'v':
  486. verbose++;
  487. break;
  488. case 'w':
  489. display_warnings = 1;
  490. break;
  491. case LONG_OPT_DLL:
  492. set_exec_mode( MODE_DLL );
  493. break;
  494. case LONG_OPT_DEF:
  495. set_exec_mode( MODE_DEF );
  496. break;
  497. case LONG_OPT_EXE:
  498. set_exec_mode( MODE_EXE );
  499. if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
  500. break;
  501. case LONG_OPT_IMPLIB:
  502. set_exec_mode( MODE_IMPLIB );
  503. break;
  504. case LONG_OPT_STATICLIB:
  505. set_exec_mode( MODE_STATICLIB );
  506. break;
  507. case LONG_OPT_BUILTIN:
  508. set_exec_mode( MODE_BUILTIN );
  509. break;
  510. case LONG_OPT_FIXUP_CTORS:
  511. set_exec_mode( MODE_FIXUP_CTORS );
  512. break;
  513. case LONG_OPT_ASCMD:
  514. as_command = strarray_fromstring( optarg, " " );
  515. break;
  516. case LONG_OPT_CCCMD:
  517. cc_command = strarray_fromstring( optarg, " " );
  518. break;
  519. case LONG_OPT_FAKE_MODULE:
  520. fake_module = 1;
  521. break;
  522. case LONG_OPT_EXTERNAL_SYMS:
  523. link_ext_symbols = 1;
  524. break;
  525. case LONG_OPT_LARGE_ADDRESS_AWARE:
  526. spec->characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
  527. break;
  528. case LONG_OPT_LDCMD:
  529. ld_command = strarray_fromstring( optarg, " " );
  530. break;
  531. case LONG_OPT_NMCMD:
  532. nm_command = strarray_fromstring( optarg, " " );
  533. break;
  534. case LONG_OPT_NXCOMPAT:
  535. if (optarg[0] == 'n' || optarg[0] == 'N')
  536. spec->dll_characteristics &= ~IMAGE_DLLCHARACTERISTICS_NX_COMPAT;
  537. break;
  538. case LONG_OPT_SAFE_SEH:
  539. safe_seh = 1;
  540. break;
  541. case LONG_OPT_PREFER_NATIVE:
  542. prefer_native = 1;
  543. spec->dll_characteristics |= IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE;
  544. break;
  545. case LONG_OPT_RESOURCES:
  546. set_exec_mode( MODE_RESOURCES );
  547. break;
  548. case LONG_OPT_SAVE_TEMPS:
  549. save_temps = 1;
  550. break;
  551. case LONG_OPT_SUBSYSTEM:
  552. set_subsystem( optarg, spec );
  553. break;
  554. case LONG_OPT_VERSION:
  555. printf( "winebuild version " PACKAGE_VERSION "\n" );
  556. exit(0);
  557. case '?':
  558. usage(1);
  559. break;
  560. }
  561. }
  562. if (!save_temps) atexit( cleanup_tmp_files );
  563. if (spec->file_name && !strchr( spec->file_name, '.' ))
  564. strcat( spec->file_name, exec_mode == MODE_EXE ? ".exe" : ".dll" );
  565. init_dll_name( spec );
  566. switch (target_cpu)
  567. {
  568. case CPU_x86:
  569. if (force_pointer_size == 8) target_cpu = CPU_x86_64;
  570. break;
  571. case CPU_x86_64:
  572. if (force_pointer_size == 4) target_cpu = CPU_x86;
  573. break;
  574. default:
  575. if (force_pointer_size == 8)
  576. fatal_error( "Cannot build 64-bit code for this CPU\n" );
  577. break;
  578. }
  579. return &argv[optind];
  580. }
  581. /* load all specified resource files */
  582. static void load_resources( char *argv[], DLLSPEC *spec )
  583. {
  584. int i;
  585. char **ptr, **last;
  586. switch (spec->type)
  587. {
  588. case SPEC_WIN16:
  589. for (i = 0; i < res_files.count; i++) load_res16_file( res_files.str[i], spec );
  590. break;
  591. case SPEC_WIN32:
  592. for (i = 0; i < res_files.count; i++)
  593. {
  594. if (!load_res32_file( res_files.str[i], spec ))
  595. fatal_error( "%s is not a valid Win32 resource file\n", res_files.str[i] );
  596. }
  597. /* load any resource file found in the remaining arguments */
  598. for (ptr = last = argv; *ptr; ptr++)
  599. {
  600. if (!load_res32_file( *ptr, spec ))
  601. *last++ = *ptr; /* not a resource file, keep it in the list */
  602. }
  603. *last = NULL;
  604. break;
  605. }
  606. }
  607. /* add input files that look like import libs to the import list */
  608. static void load_import_libs( char *argv[] )
  609. {
  610. char **ptr, **last;
  611. for (ptr = last = argv; *ptr; ptr++)
  612. {
  613. if (strendswith( *ptr, ".def" ))
  614. add_import_dll( NULL, *ptr );
  615. else
  616. *last++ = *ptr; /* not an import dll, keep it in the list */
  617. }
  618. *last = NULL;
  619. }
  620. static int parse_input_file( DLLSPEC *spec )
  621. {
  622. FILE *input_file = open_input_file( NULL, spec_file_name );
  623. char *extension = strrchr( spec_file_name, '.' );
  624. int result;
  625. spec->src_name = xstrdup( input_file_name );
  626. if (extension && !strcmp( extension, ".def" ))
  627. result = parse_def_file( input_file, spec );
  628. else
  629. result = parse_spec_file( input_file, spec );
  630. close_input_file( input_file );
  631. return result;
  632. }
  633. /*******************************************************************
  634. * main
  635. */
  636. int main(int argc, char **argv)
  637. {
  638. DLLSPEC *spec = alloc_dll_spec();
  639. #ifdef SIGHUP
  640. signal( SIGHUP, exit_on_signal );
  641. #endif
  642. signal( SIGTERM, exit_on_signal );
  643. signal( SIGINT, exit_on_signal );
  644. argv = parse_options( argc, argv, spec );
  645. atexit( cleanup ); /* make sure we remove the output file on exit */
  646. switch(exec_mode)
  647. {
  648. case MODE_DLL:
  649. if (spec->subsystem != IMAGE_SUBSYSTEM_NATIVE)
  650. spec->characteristics |= IMAGE_FILE_DLL;
  651. /* fall through */
  652. case MODE_EXE:
  653. load_resources( argv, spec );
  654. if (spec_file_name && !parse_input_file( spec )) break;
  655. if (!spec->init_func && !unix_lib) spec->init_func = xstrdup( get_default_entry_point( spec ));
  656. if (fake_module)
  657. {
  658. if (spec->type == SPEC_WIN16) output_fake_module16( spec );
  659. else output_fake_module( spec );
  660. break;
  661. }
  662. if (!is_pe())
  663. {
  664. load_import_libs( argv );
  665. read_undef_symbols( spec, argv );
  666. resolve_imports( spec );
  667. }
  668. if (spec->type == SPEC_WIN16) output_spec16_file( spec );
  669. else output_spec32_file( spec );
  670. break;
  671. case MODE_DEF:
  672. if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
  673. if (!spec_file_name) fatal_error( "missing .spec file\n" );
  674. if (!parse_input_file( spec )) break;
  675. open_output_file();
  676. output_def_file( spec, 0 );
  677. close_output_file();
  678. break;
  679. case MODE_IMPLIB:
  680. if (!spec_file_name) fatal_error( "missing .spec file\n" );
  681. if (!parse_input_file( spec )) break;
  682. output_static_lib( spec, argv );
  683. break;
  684. case MODE_STATICLIB:
  685. output_static_lib( NULL, argv );
  686. break;
  687. case MODE_BUILTIN:
  688. if (!argv[0]) fatal_error( "missing file argument for --builtin option\n" );
  689. make_builtin_files( argv );
  690. break;
  691. case MODE_FIXUP_CTORS:
  692. if (!argv[0]) fatal_error( "missing file argument for --fixup-ctors option\n" );
  693. fixup_constructors( argv );
  694. break;
  695. case MODE_RESOURCES:
  696. load_resources( argv, spec );
  697. output_res_o_file( spec );
  698. break;
  699. default:
  700. usage(1);
  701. break;
  702. }
  703. if (nb_errors) exit(1);
  704. output_file_name = NULL;
  705. return 0;
  706. }