[RFC] winewrap
Dimitrie O. Paun
dpaun at rogers.com
Fri Dec 6 01:19:33 CST 2002
Hi folks,
Here is the first cut at winewrap, as described here:
http://www.dssd.ca/wine/Winelib-Apps.html
What it does at the moment:
-- invokes winebuild to create the .spec.c file
-- compiles the .spec.s file
-- links in everything, and generates the .exe.so file
What remains to be done:
-- generate the actual executable.
One possible option is to modify wineapploader so we
simply symlink to it. I have a version of this around.
Is this acceptable?
Comments welcomes.
/*
* 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/param.h>
#include <sys/wait.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef WINEDLLS
#define WINEDLLS "/usr/local/lib/wine"
#endif
static char *output_name;
static char **lib_files, **res_files, **obj_files;
static int nb_lib_files, nb_res_files, nb_obj_files;
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;
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(0);
exit(1);
}
int main(int argc, char **argv)
{
char *library = 0;
int i, j, len, is_object, no_opt = 0;
char cmd[PATH_MAX];
char **spec_args, **comp_args, **link_args;
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\n.");
len = strlen(output_name);
if (len > 4 && strcmp(output_name + len - 4, ".exe") == 0)
output_name[len - 4] = 0;
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 '-':
if (argv[i][2]) error("No long option supported\n");
no_opt = 1;
break;
default:
error("Unknown option -%c\n", argv[i][1]);
}
continue;
}
/* it's a filename, not an option: test if it is a resource */
snprintf(cmd, sizeof(cmd), "readelf -V %s >/dev/null 2>/dev/null", argv[i]);
is_object = (system(cmd) == 0);
/* add it to its respective list */
if (is_object)
{
obj_files = realloc( obj_files, (nb_obj_files+1) * sizeof(*obj_files) );
obj_files[nb_obj_files++] = strdup(argv[i]);
}
else
{
res_files = realloc( res_files, (nb_res_files+1) * sizeof(*res_files) );
res_files[nb_res_files++] = strdup(argv[i]);
}
}
/* build winebuild's argument list */
spec_args = malloc( (nb_lib_files + nb_obj_files + nb_res_files * 2 + 20) * sizeof (char *) );
j = 0;
spec_args[j++] = "winebuild";
spec_args[j++] = "-fPIC";
spec_args[j++] = "-o";
spec_args[j++] = strmake("%s.spec.c", output_name);
spec_args[j++] = "--exe";
spec_args[j++] = strmake("%s.exe", output_name);
spec_args[j++] = "-m";
spec_args[j++] = "gui";
for (i = 0; i < nb_res_files; i++)
{
spec_args[j++] = "-r";
spec_args[j++] = res_files[i];
}
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++] = "-c";
comp_args[j++] = strmake("%s.spec.c", output_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.exe.so", output_name);
link_args[j++] = strmake("%s.spec.o", output_name);
for (i = 0; i < nb_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);
/* run gcc to link */
spawn(link_args);
return 0;
}
--
Dimi.
More information about the wine-devel
mailing list