ChangeLog New wine build utility that should make it easy for Winelib apps to link, and generate an executable. Index: tools/Makefile.in =================================================================== RCS file: /var/cvs/wine/tools/Makefile.in,v retrieving revision 1.27 diff -u -r1.27 Makefile.in --- tools/Makefile.in 6 Dec 2002 23:22:39 -0000 1.27 +++ tools/Makefile.in 12 Dec 2002 18:54:51 -0000 @@ -9,13 +9,15 @@ bin2res \ fnt2bdf \ makedep \ - mingwrap + mingwrap \ + winewrap C_SRCS = \ bin2res.c \ fnt2bdf.c \ makedep.c \ - mingwrap.c + mingwrap.c \ + winewrap.c SUBDIRS = \ widl \ @@ -49,13 +51,17 @@ mingwrap: mingwrap.o $(CC) $(CFLAGS) -o mingwrap mingwrap.o +winewrap: winewrap.o + $(CC) $(CFLAGS) -o winewrap winewrap.o + install:: $(MKINSTALLDIRS) $(bindir) $(mandir)/man$(prog_manext) $(INSTALL_SCRIPT) $(SRCDIR)/winemaker $(bindir)/winemaker $(INSTALL_PROGRAM) mingwrap $(bindir)/mingwrap + $(INSTALL_PROGRAM) winewrap $(bindir)/winewrap $(INSTALL_DATA) $(SRCDIR)/winemaker.man $(mandir)/man$(prog_manext)/winemaker.$(prog_manext) uninstall:: - $(RM) $(bindir)/winemaker $(bindir)/mingwrap $(mandir)/man$(prog_manext)/winemaker.$(prog_manext) + $(RM) $(bindir)/winemaker $(bindir)/mingwrap $(bindir)/winewrap $(mandir)/man$(prog_manext)/winemaker.$(prog_manext) ### Dependencies: --- /dev/null 2002-08-30 19:31:37.000000000 -0400 +++ tools/winewrap.c 2002-12-12 13:52:49.000000000 -0500 @@ -0,0 +1,261 @@ +/* + * Wine wrapper: takes care of internal details for linking. + * + * Copyright 2002 Dimitrie O. Paun + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <sys/stat.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifndef WINEDLLS +#define WINEDLLS "/usr/local/lib/wine" +#endif + +static const char *app_loader_script = + "#!/bin/sh\n" + "\n" + "appname=\"%s\"\n" + "# determine the application directory\n" + "appdir=''\n" + "case \"$0\" in\n" + " */*)\n" + " # $0 contains a path, use it\n" + " appdir=`dirname \"$0\"`\n" + " ;;\n" + " *)\n" + " # no directory in $0, search in PATH\n" + " saved_ifs=$IFS\n" + " IFS=:\n" + " for d in $PATH\n" + " do\n" + " IFS=$saved_ifs\n" + " if [ -x \"$d/$appname\" ]; then appdir=\"$d\"; break; fi\n" + " done\n" + " ;;\n" + "esac\n" + "\n" + "# figure out the full app path\n" + "if [ -n \"$appdir\" ]; then\n" + " apppath=\"$appdir/$appname.exe.so\"\n" + "else\n" + " apppath=\"$appname.exe.so\"\n" + "fi\n" + "\n" + "# determine the WINELOADER\n" + "if ! [ -x \"$WINELOADER\" ]; then WINELOADER=\"wine\"; fi\n" + "\n" + "# and try to start the app\n" + "exec \"$WINELOADER\" \"$apppath\" \"$@\"\n" +; + +static char *output_name; +static char **lib_files, **obj_files; +static int nb_lib_files, nb_obj_files; +static int debug = 1; + +void error(const char *s, ...) +{ + va_list ap; + + va_start(ap, s); + fprintf(stderr, "Error: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(2); +} + + +char *strmake(const char *fmt, ...) +{ + int n, size = 100; + char *p; + va_list ap; + + if ((p = malloc (size)) == NULL) return NULL; + + while (1) + { + va_start(ap, fmt); + n = vsnprintf (p, size, fmt, ap); + va_end(ap); + if (n > -1 && n < size) return p; + if (n > -1) size *= 2; + if ((p = realloc (p, size)) == NULL) return NULL; + } +} + +void spawn(char *const argv[]) +{ + int pid, status, i; + + if (debug) + { + for(i = 0; argv[i]; i++) printf("%s ", argv[i]); + printf("\n"); + } + + if ((pid = fork()) == 0) execvp(argv[0], argv); + else if (wait(&status) > 0) + { + if (WEXITSTATUS(status) == 0) return; + else error("%s failed.", argv[0]); + } + perror("Error:"); + exit(1); +} + +int is_resource(const char* file) +{ + /* see tools/winebuild/res32.c: check_header for details */ + static const char res_sig[] = { 0,0,0,0, 32,0,0,0, 0xff,0xff, 0,0, 0xff,0xff, 0,0, 0,0,0,0, 0,0, 0,0, 0,0,0,0, 0,0,0,0 }; + char buf[sizeof(res_sig)]; + FILE *fin; + + if (!(fin = fopen(file, "r"))) error("Can not open %s", file); + if (fread(buf, sizeof(buf), 1, fin) != 1) error("Truncated file %s", file); + fclose(fin); + + return !memcmp(buf, res_sig, sizeof(buf)); +} + +int main(int argc, char **argv) +{ + char *library = 0, *p; + int i, j, no_opt = 0, gui_mode = 0; + char *spec_name, *spec_c_name, *spec_o_name; + char **spec_args, **comp_args, **link_args; + FILE *file; + + for (i = 1; i < argc; i++) + { + if (!no_opt && argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'o': + if (argv[i][2]) output_name = strdup(argv[i]+ 2); + else if (i + 1 < argc) output_name = strdup(argv[++i]); + else error("The -o switch takes an argument."); + if ( !(p = strstr(output_name, ".exe")) || *(p+4) ) + output_name = strmake("%s.exe", output_name); + break; + case 'l': + if (argv[i][2]) library = argv[i]+ 2; + else if (i + 1 < argc) library = argv[++i]; + else error("The -l switch takes an argument\n."); + if (strcmp(library, "winspool") == 0) library = "winspool.drv"; + lib_files = realloc( lib_files, (nb_lib_files+1) * sizeof(*lib_files) ); + lib_files[nb_lib_files++] = strdup(library); + break; + case 'm': + if (strcmp("-mwindows", argv[i]) == 0) gui_mode = 1; + else error("Unknown option %s\n", argv[i]); + case '-': + if (argv[i][2]) error("No long option supported."); + no_opt = 1; + break; + default: + error("Unknown option -%c", argv[i][1]); + } + continue; + } + + /* it's a filename, add it to its list */ + obj_files = realloc( obj_files, (nb_obj_files+1) * sizeof(*obj_files) ); + obj_files[nb_obj_files++] = strdup(argv[i]); + } + + spec_name = tempnam(0, 0); + spec_c_name = strmake("%s.c", spec_name); + spec_o_name = strmake("%s.o", spec_name); + + /* build winebuild's argument list */ + spec_args = malloc( (nb_lib_files + nb_obj_files + 20) * sizeof (char *) ); + j = 0; + spec_args[j++] = "winebuild"; + spec_args[j++] = "-fPIC"; + spec_args[j++] = "-o"; + spec_args[j++] = strmake("%s.c", spec_name); + spec_args[j++] = "--exe"; + spec_args[j++] = output_name; + spec_args[j++] = "-m"; + spec_args[j++] = gui_mode ? "gui" : "cui"; + for (i = 0; i < nb_obj_files; i++) + spec_args[j++] = obj_files[i]; + spec_args[j++] = "-L" WINEDLLS; + for (i = 0; i < nb_lib_files; i++) + spec_args[j++] = strmake("-l%s", lib_files[i]); + spec_args[j++] = "-lmsvcrt"; + spec_args[j] = 0; + + /* build gcc's argument list */ + comp_args = malloc (20 * sizeof (char *) ); + j = 0; + comp_args[j++] = "gcc"; + comp_args[j++] = "-fPIC"; + comp_args[j++] = "-o"; + comp_args[j++] = spec_o_name; + comp_args[j++] = "-c"; + comp_args[j++] = spec_c_name; + + /* build ld's argument list */ + link_args = malloc( (nb_obj_files + 20) * sizeof (char *) ); + j = 0; + link_args[j++] = "gcc"; + link_args[j++] = "-shared"; + link_args[j++] = "-Wl,-Bsymbolic"; + link_args[j++] = "-lwine"; + link_args[j++] = "-lm"; + link_args[j++] = "-o"; + link_args[j++] = strmake("%s.so", output_name); + link_args[j++] = spec_o_name; + for (i = 0; i < nb_obj_files; i++) + if (!is_resource(obj_files[i])) link_args[j++] = obj_files[i]; + link_args[j] = 0; + + /* run winebuild to get the .spec.c file */ + spawn(spec_args); + + /* compile the .spec.c file */ + spawn(comp_args); + unlink(spec_c_name); + + /* run gcc to link */ + spawn(link_args); + unlink(spec_o_name); + + /* create the loader script */ + output_name[strlen(output_name) - 4] = 0; /* remove the .exe extension */ + if ( !(file = fopen(output_name, "w")) ) + error ("Can not create %s.", output_name); + fprintf(file, app_loader_script, output_name); + fclose(file); + chmod(output_name, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH); + + return 0; +} -- Dimi.