From 3f651353b46b3a35bd19ce19c50afc576a71c0c0 Mon Sep 17 00:00:00 2001 From: Jaromil Date: Sun, 12 Jan 2025 11:40:38 +0100 Subject: [PATCH] fix: windows dll linker with same flags as posix now executing sources on windows can link DLL libs found in paths (and system paths) using -l name just like on posix systems --- build/init.mk | 3 ++- src/cjit.c | 33 +++++++++++------------- src/cjit.h | 8 +++--- src/elflinker.c | 3 ++- src/winlinker.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 24 deletions(-) create mode 100644 src/winlinker.c diff --git a/build/init.mk b/build/init.mk index d0c32cb..f62fd25 100644 --- a/build/init.mk +++ b/build/init.mk @@ -15,7 +15,8 @@ CFLAGS ?= -O2 ${cflags_stack_protect} cflags := ${CFLAGS} ${cflags_includes} -SOURCES := src/file.o src/cjit.o src/elflinker.o \ +SOURCES := src/file.o src/cjit.o \ + src/elflinker.o src/winlinker.o \ src/main.o src/assets.o \ src/cwalk.o src/array.o \ src/muntar.o src/tinflate.o src/tinfgzip.o \ diff --git a/src/cjit.c b/src/cjit.c index 4462ed5..f209c49 100644 --- a/src/cjit.c +++ b/src/cjit.c @@ -197,6 +197,7 @@ static bool cjit_setup(CJITState *cjit) { char *extra_cflags = NULL; extra_cflags = getenv("CFLAGS"); _err("CFLAGS: %s",extra_cflags); + debug(" -C %s",extra_cflags); tcc_set_options(tcc(cjit), extra_cflags); } #if defined(WINDOWS) @@ -212,10 +213,10 @@ static bool cjit_setup(CJITState *cjit) { // add(libpaths,cjit->tmpdir); // tinyCC needs libtcc1.a in library path (not added as file) #if !defined(SHAREDTCC) + debug(" -L %s",cjit->tmpdir); tcc_add_library_path(tcc(cjit),cjit->tmpdir); + tcc_add_library_path(tcc(cjit), "."); debug(" -L %s","."); tcc_add_sysinclude_path(tcc(cjit), cjit->tmpdir); - tcc_add_sysinclude_path(tcc(cjit), "."); - tcc_add_sysinclude_path(tcc(cjit), "include"); // TODO: check if exists #endif { // search libs also in current dir char pwd[MAX_PATH]; @@ -231,11 +232,13 @@ static bool cjit_setup(CJITState *cjit) { char *tpath; // TODO: support WIN32 here: "C:\\Windows\\System32" add(libpaths,"C:\\Windows\\SysWOW64"); + debug(" -L %s","C:\\Windows\\SysWOW64"); tcc_add_library_path(tcc(cjit), "C:\\Windows\\SysWOW64"); // tinycc win32 headers plen = strlen(cjit->tmpdir)+strlen("/tinycc_win32/winapi")+8; tpath = malloc(plen); cwk_path_join(cjit->tmpdir,"/tinycc_win32/winapi",tpath,plen); + debug(" -I %s",tpath); tcc_add_sysinclude_path(tcc(cjit), tpath); free(tpath); // windows SDK headers @@ -244,8 +247,10 @@ static bool cjit_setup(CJITState *cjit) { plen = strlen(sdkpath)+16; tpath = malloc(plen); cwk_path_join(sdkpath,"/um",tpath,plen); // um/GL + debug(" -I %s",tpath); tcc_add_sysinclude_path(tcc(cjit), tpath); cwk_path_join(sdkpath,"/shared",tpath,plen); // winapifamili.h etc. + debug(" -I %s",tpath); tcc_add_sysinclude_path(tcc(cjit), tpath); free(tpath); } @@ -323,7 +328,6 @@ bool cjit_status(CJITState *cjit) { for(i=0;ilibs,i)); } -#if defined(UNIX) resolve_libs(cjit); used = XArray_Used(cjit->reallibs); if(used) { @@ -331,8 +335,6 @@ bool cjit_status(CJITState *cjit) { for(i=0;ireallibs,i)); } -#endif - } return true; } @@ -536,7 +538,6 @@ int cjit_link(CJITState *cjit) { return 1; } // resolve library files on UNIX systems -#if defined(UNIX) int found = resolve_libs(cjit); for(int i=0;ireallibs,i); @@ -544,7 +545,7 @@ int cjit_link(CJITState *cjit) { tcc_add_file(tcc(cjit), f); } } -#endif + debug(" -o %s",cjit->output_filename); return( tcc_output_file(tcc(cjit),cjit->output_filename)); } @@ -557,16 +558,16 @@ int cjit_exec(CJITState *cjit, int argc, char **argv) { _err("%s: CJIT already executed once",__func__); return 1; } - // resolve library files on UNIX systems -#if defined(UNIX) + debug("resolve paths to library files (%i)", + XArray_Used(cjit->libs)); int found = resolve_libs(cjit); for(int i=0;ireallibs,i); if(f) { + debug(" +file: %s",f); tcc_add_file(tcc(cjit), f); } } -#endif int res = 1; int (*_ep)(int, char**); // relocate the code (link symbols) @@ -664,7 +665,7 @@ void cjit_add_include_path(CJITState *cjit, const char *path) { } tcc_add_include_path(tcc(cjit), toadd); free(toadd); - debug("+I %s",path); + debug(" -I %s",path); } // TODO: temporary, to be reimplemented in linker.c void cjit_add_library_path(CJITState *cjit, const char *path) { @@ -678,21 +679,17 @@ void cjit_add_library_path(CJITState *cjit, const char *path) { #elif !defined(SHAREDTCC) tcc_add_library_path(tcc(cjit), toadd); #endif - debug("+L %s",toadd); + debug(" -L %s",toadd); free(toadd); } // TODO: temporary, to be reimplemented in linker.c void cjit_add_library(CJITState *cjit, const char *path) { -#if defined(UNIX) add(libs,path); -#else - tcc_add_library(tcc(cjit), path); -#endif - debug("+l %s",path); + debug(" +l %s",path); } void cjit_set_tcc_options(CJITState *cjit, const char *opts) { tcc_set_options(tcc(cjit),opts); - debug("+O %s",opts); + debug(" +O %s",opts); } #define MAX_STRING 2040 diff --git a/src/cjit.h b/src/cjit.h index c2037f4..ffc4b00 100644 --- a/src/cjit.h +++ b/src/cjit.h @@ -51,10 +51,10 @@ struct CJITState { bool done_exec; // INTERNAL // sources and libs used and paths to libs - void *sources; - void *libs; - void *libpaths; - void *reallibs; + void *sources; // xarray of source files loaded + void *libs; // xarray of library names to be resolved + void *libpaths; // xarray of library paths to be searched + void *reallibs; // xarray of paths made by resolve_libs() }; typedef struct CJITState CJITState; diff --git a/src/elflinker.c b/src/elflinker.c index 67d7882..155dd51 100644 --- a/src/elflinker.c +++ b/src/elflinker.c @@ -107,13 +107,14 @@ int resolve_libs(CJITState *cjit) { int i,ii; int libpaths_num, libnames_num; char *lpath, *lname; - int found = 0; + int found = -1; // search in all paths if lib%s.so exists // TODO: support --static here libpaths_num = XArray_Used(cjit->libpaths); libnames_num = XArray_Used(cjit->libs); for(i=0;ilibs,i); + found = -1; for(ii=0;iilibpaths,ii); snprintf(tryfile,PATH_MAX-2,"%s/lib%s.so",lpath,lname); diff --git a/src/winlinker.c b/src/winlinker.c new file mode 100644 index 0000000..a443aac --- /dev/null +++ b/src/winlinker.c @@ -0,0 +1,68 @@ +/* + * Library path resolver from lib names on Windows systems + * + * Copyright (c) 2024-2025 Dyne.org + * + * 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 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 +#if defined(WINDOWS) + +#include +#include + +#include +// #include +#include + +#define debug(fmt,par) if(cjit->verbose)_err(fmt,par) + +// takes the list of cjit->libpaths and cjit->libs +// then resolves them all looking for ${lib}.dll in paths +int resolve_libs(CJITState *cjit) { + char tryfile[PATH_MAX]; + int i,ii; + int libpaths_num, libnames_num; + char *lpath, *lname; + bool found = false; + struct stat st; + // search in all paths if lib%s.so exists + // TODO: support --static here + libpaths_num = XArray_Used(cjit->libpaths); + libnames_num = XArray_Used(cjit->libs); + for(i=0;ilibs,i); + for(ii=0;iilibpaths,ii); + snprintf(tryfile,PATH_MAX-2,"%s/%s.dll",lpath,lname); + debug("resolve_libs try: %s",tryfile); + if (stat(tryfile, &st) == 0) { + XArray_AddData(cjit->reallibs, + tryfile,strlen(tryfile)); + debug("library found: %s",tryfile); + found=true; + break; + } + } + if(!found) + _err("Library not found: %s.dll",lname); + // continue anyway (will log missing symbol names) + } + return(XArray_Used(cjit->reallibs)); +} + +#endif // defined(WINDOWS)