Fórum Root.cz
Hlavní témata => Windows a jiné systémy => Téma založeno: mhi 18. 12. 2020, 15:31:16
-
Mam celou radu ruznych Unixovych C programku, ktere zpracovavaji ruzna data (jedna se o hodne specificke veci). Nepouziva to nic vic nez standardni posixove fce (fopen/fread,open/read, strcmp, malloc, ..). Obvykle je pouzivam v Linuxu, jenze obcas bych potreboval mit aktualni verzi i pro Windows.
Prevest .elf na .exe umim, potreboval bych ale nejakou mini libc POSIX knihovnu, na jejimz druhem konci bude Windows API.Tzn napr. open bude volat CreateFileA(/W). Tedy abych udelal 'ld -r -o file.elf *.o winposix.a' a pak ten ELF jen uz prevedl na EXE (COFF/PE) s importem nutnych fci kernel32/user32. Znate nekdo neco takoveho?
Jasne, je tu mingw ktere pouziva msvcrt, ale tomu se chci vyhnout (tzn toto mi nevyhovuje https://stackoverflow.com/questions/39622501/mingw-installation-on-linux )
-
Pokud nevyhovuje MinGW, tak snad jen WSL, verze 1 převádí linuxové syscally na Win32 API (není to tedy na úrovni libc, ale funguje to spolehlivě). POSIXový subsystém Windows mívaly, ale to už je dávno.
P.S. Nicméně funkce jako fopen, malloc, strcmp apod. jsou součástí standardní knihovny céčka a Windows je umí, občas s mírnými podivnostmi. Také je vhodné zmínit, že Microsoft teď na Windows nabízí clang (v rámci Visual Studia).
-
Proč zdrojáky vašich prográmků nezkompilujete třeba ve Visual Studiu? Pokud vám vadí msvcrt a prográmky jsou zejména pro vás, linkuje ji staticky.
POSIXová volání jako open, read či write by měla být podporována, jen tam Microsoft z nějakého důvodu vyžaduje prefix "_", jinak dostanete varování. Ten ale můžete vypnout (případně chybu, pokud je dané volání považováno za příliš deprecated), kterou lze také vypnout.
Přímé převádění ELF do EXE mi přijde dosti zvláštní ve smyslu, že si můžete nepěkně naběhnout na některé věci specifické pro Windows. Např. je dobré dávat programu manifest, jinak vás mohou nepříjemně překvapit věci jako "kompatibilita s Windows XP".
-
ad Idris: WSL resi bohuzel uplne jiny problem.
ad Martin Drab: Prave o to abych nemusel resit nejake kompatibility a rekompilaci ve VS (v jinem systemu nez primarne probiha vyvoj) nechci pouzivat Visual studio, ani msvc. Manifest je to nejmensi.
-
A prekladat v Dev-C++?
-
ad Martin Drab: Prave o to abych nemusel resit nejake kompatibility a rekompilaci ve VS (v jinem systemu nez primarne probiha vyvoj) nechci pouzivat Visual studio, ani msvc. Manifest je to nejmensi.
Já bohužel v drtivé většině případů řeším opačný problém -- portování do Linuxu. Což je díky možnosti vzdálené kompilace přes SSH o dost příjemnější, pokud od toho člověk nechce zázraky.
Ale již jsem k pár projektům tvořil MSVS solution a project soubory a obvykle to nebyl ten největší problém. Ten představovalo nalezení všech závislostí a jejich případná kompilace/portace též do MSVS (zlib, libpng). S kódem obvykle potíže moc nebyly, jelikož se veskrze jednalo o knihovny podporující mnoho platforem.
Nevím, zda-li by třeba s MSVS nepomohl GitHub a možnost CI (MSVS je tam podporováno, ale nikdy jsem na vlastním projektu nezkoušel).
-
Mingw a cygwin jsou tradiční možnosti. Proč nevyhovují?
-
Mam celou radu ruznych Unixovych C programku, ktere zpracovavaji ruzna data (jedna se o hodne specificke veci). Nepouziva to nic vic nez standardni posixove fce (fopen/fread,open/read, strcmp, malloc, ..). Obvykle je pouzivam v Linuxu, jenze obcas bych potreboval mit aktualni verzi i pro Windows.
OpenWatcom by nestačil? Pro běžné věci se chová více než dobře, vlastně pro portování z Linuxu dá nejvíc práce síťová komunikace (inicializace winsock2, send/recv místo write/read) a do exe to vše potřebné přilinkuje.
-
Dekuji vsem za tipy "jak to resit jinak". Vetsinu jsem myslim zvazil a nejsou uplne vyhovujici.
Jedna se o celou radu malych 'projektu', ktere kompiluju historicky na ruznych strojich, dokonce s ruznymi Unixy (primarne to je Linux). Vsude je ale GCC do ELFu. Prikladem takoveho projektiku je disassembler pro nejakou lehce neobvyklou ISA. Bez toho abych musel resit nejake kopirovani zdrojaku, jejich modifikaci pro kompilaci v MSVC/watcom/borland/whatever, bych rad nabuildoval Win32 verzi.
Skutecne bych potreboval jen zdrojak nejake minimalisticke posix/libc navazane na Win32 API. Tedy aby open vypadal nejak tak, ze prehaze parametry a zavola CreateFileA (/W). A pak zkontroluje navratovou hodnotu a opet nastavi spravne errno.
Mozna si nabiham na vidle, protoze to treba neni tak uplne jednoduche, uz jen kvuli tomu ze ve Win myslim neni jasne definovany stdin/out/err ( ... GetStdHandle(STD_xxx_HANDLE)) takze asi i takovato blbost jako preklad tech handles se musi resit.
Koukal jsem do zdrojaku VC++ crt a MS resi mapovani skrze '#define _osfhnd(i) ( _pioinfo(i)->osfhnd )' ... coz prinasi celou radu problemu s lockovanim...achjo.
-
Mozna si nabiham na vidle, protoze to treba neni tak uplne jednoduche, uz jen kvuli tomu ze ve Win myslim neni jasne definovany stdin/out/err ( ... GetStdHandle(STD_xxx_HANDLE)) takze asi i takovato blbost jako preklad tech handles se musi resit.
Handle (obdoba file deskriptorů) jjsou ukazatele, ne inty a jejich hodnoty se chovají jinak (dolní dva bity jsou snad vždy nulové, nejdou tedy "po sobě" jako file deskriptory). A ano, nejsou žádné pevně definované hodnoty pro standardní vstup, výstup či chybový výstup, proto existuje Get/SetStdHandle. Pojetí toho všeho je tady trochu obecnější. Navíc, Windows nejsou primárně konzolové.
V reálu by hodnoty handle neměly překročit cca 16 MB (ale to je nedokumentovaný fakt závislý na implementaci už minimálně 20 let). CRT pro emulaci POSIXového světa používá právě to mezipole pro mapování "file deskriptorů" na handle.
Je ale pravda, že zrovna pracovat s těmi imitacemi file deskriptorů je poměrně otrava (pokud jsem to potřeboval, obvykle jsem si napsal wrapper, který na Windows používá handle a na Linuxu prostě file deskriptory).
Bohužel tady asi neporadím. Jestli to chápu správně, tak se chcete vyhnout tomu, že byste vzal všechny ty malé zdrojáčky a pokusil se je kompilovat nějak nativně ve Windows, protože se bojíte, že by bylo třeba příliš mnoha změn v tom, co zatím funguje.
-
Bohužel tady asi neporadím. Jestli to chápu správně, tak se chcete vyhnout tomu, že byste vzal všechny ty malé zdrojáčky a pokusil se je kompilovat nějak nativně ve Windows, protože se bojíte, že by bylo třeba příliš mnoha změn v tom, co zatím funguje.
ano, chapete to spravne. Krome toho je jeste duvod ze kdyz udelam nejake zmeny nechci nasledne byt nucen to dodatecne nekde jeste kompilovat, abych pak zjistil, ze jsem zapomnel ... a mam ruzne verze na Win i Unixu.
s temi filedescriptory je jeste jedna potiz, treba dup2 :). Ale takoveto veci nepouzivam. Mozna je reseni nakonec obslehnout msvcrt.
-
Ehm, nechci býti kverulant, ale práve ve Watcomu s targetem na win32/console ten stdin/stderr/stdout funguje "out of the box", dup2 zkusím za chvíli (na tomhle stroji to nemám a nechci mlžit jestli fd 0/1/2 fungují jak mají).
Jediný chyták (zcela v souladu s normou ale, nicméně člověka zvyklého z linuxu to může zaskočit) je, že pokud neřeknete jinak, tak fopen() není v binary modu a ono to opravdu překládá \n -> \r\n.
-
Tak vyzkoušeno, až na ten dup2 to funguje podle očekávání. dup2 taky jen nevrací newfd, ale nulu...
int main(int argc, char *argv[])
{
int fd, fd2, fd3;
write(1, "stdout\r\n", 8);
write(2, "stderr\r\n", 8);
fd = open("xxx", O_RDWR|O_CREAT, 0600);
if (-1 == (fd2 = dup(1))) {
perror("dup: %m");
return 1;
}
write(fd2, "dup\r\n", 5);
if (-1 == (fd3 = dup2(1, fd))) {
perror("dup2: %m");
return 1;
}
write(fd3, "dup2\r\n", 6);
write(fd, "dup2_2\r\n", 8);
fprintf(stderr, "fd=%i fd2=%i fd3=%i\n", fd, fd2, fd3);
close(fd);
close(fd2);
Sleep(25000);
return 0;
}
stdout
stderr
dup
dup2_2
fd=3 fd2=4 fd3=0
Na běžné utility je fakt rozdíl jen v #ifdef __NT__ #include "windows.h" #endif
-
Ja Vam rozumim, ale dabel je v detailech. Teda kdyby to byl jeden dabel, ale ono to je tisic malych dabliku a uz mne to nebavi opravovat a neustale resit nejake kompatibility. Popravde receno mi bohate uz staci jen zmeny ktere jsou v gcc, treba nedavno jsem stravil asi hodinu opravou cizich zdrojaku, cast diky 'double quote' C++ operatoru, ktery se mi nepodarilo vypnout ani zmenou normy C++ (navic kod byl celkem cisty C, jen to bylo hejno ".cpp" souboru).
Nekdy mrknu do nejakych starsich prekladacu typu Borland nebo Watcom na zdrojaky CRT, treba to pujde pouzit, myslel jsem ze existuje nejake free+opensource reseni.
Je to trochu offtopic, ale jsem donekonecna fascinovan tim jak mohou byt nektere veci slozite, treba kdyz se clovek mrkne do zdrojaku openbsd ci netbsd a srovna to s vecmi z OS/X, nebo Linuxu ... nebo srovna posledne zminovane s Windows :-). Asi uz starnu.
-
Nevím proč je zavržené právě mingw-win64 pod linuxem, protože to je podle mne nejjednodušší cesta. Pracovně vyrábím aplikace, které musí fungovat v linuxu, pod windows a OSX. Právě díky mingw můžu pod linuxem jedním make/cmake vyrobit najednou binárky pro linux i windows. Jediné co mě rozčiluje je OSX, protože na to musím myslet zvlášť.
-
Ještě bych se zeptal - proč tak moc zavrhujete víceméně standardní přístup, kdy když už děláte multiplatformní programy, tak je psát multiplatformě už od začátku?
Navíc dnes máte dost prostředků na to to automaticky otestovat už ve chvíli commitu (já coby konzerva to dělám sice ručně, ale věci si vždycky testuju na linux i386 a x64 a raspberry pi s -Wall -Werror a když to chci i pro win tak právě na Watcomu, a až tak pracné to není) a připadá mi to jako čistší řešení než de-facto dělat vlastními silami něco jako WSL1
-
Vynechal jsem tu spoustu detailu. Muj kod je obcas michan s ruznymi historickymi knihovnami nebo jednotlivymi .c soubory, ktere jsem neprogramoval a nemam zajem travit svuj cas opravou neceho co vznikalo treba v 90. letech (a obsahuje to teba kod ve stylu K&R :) ). Dale tam jsou obcas casti v assembleru, nebo prilinkovany nejaky object. Mam to tak, ze urcite veci jdou prekladat jen urcitymi verzemi gcc, nebo "jen" nefunguji. Nechtejte po mne detaily, psal bych tu romany, jsou to vsechno interni veci, ktere se zatim nevyplati lepe udrzovat, protoze jich je moc a pouzivaji se malo casto.
Ten mingw je nejblizsi tomu co potrebuju, nicmene musel bych mit verze pro ruzne gcc, no mozna to jde poskladat, preci jen mi prislo jednodussi pouzit to co je overene ze chodi a jen to na stejnem stroji prelozit znovu s jinymi headerfiles a pak prekovertovat. Vyzkousim cestu prelozit si nejakou minimalistickou crt z bcc/watcom/msvc/...
-
Tak takhle mi to už dává smysl. Nezávidím. :(
-
Jen mě tak napadlo. Co si takovou knihovnu vyrobit právě pomocí mingw? Pro těch "pár" funkcí by to nemuselo trvat dlouho.
-
Mingw je myslim tvrde zadratovane proti msvcrt, to nechci, nebude to chodit.
Tak jsem se do toho pustil. Slinkuju helloworld :). Nejvetsi problem byl tedy poslepovat z jinych projektu konvertor ELF to EXE/PE, aby to umelo spravne prehazet ELF z noveho gcc, generuji se tam nektere veci trochu jinak nez jsem byl zvykly. Navic mi IDA hazi ze import tabulku mam poskozenou, tezko rict co tam mam blbe - EXE ale normalne chodi.
Vysledek:
#include "../windefs.h"
#define STD_INPUT_HANDLE ((DWORD)-10)
#define STD_OUTPUT_HANDLE ((DWORD)-11)
#define STD_ERROR_HANDLE ((DWORD)-12)
WINBASEAPI
HANDLE
WINAPI
GetStdHandle(
_In_ DWORD nStdHandle
);
WINBASEAPI
BOOL
WINAPI
WriteFile(
_In_ HANDLE hFile,
LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ void *
);
WINBASEAPI
DECLSPEC_NORETURN
VOID
WINAPI
ExitProcess(
_In_ UINT uExitCode
);
typedef int ssize_t;
typedef int size_t;
[b]
static inline ssize_t write(int fd, const void *buf, size_t count) __attribute__((always_inline));
static inline void exit(int status) __attribute__((always_inline));[/b]
int main()
{
const char *hellostr = "Hello world\n";
write( GetStdHandle(STD_OUTPUT_HANDLE), hellostr, lstrlenA(hellostr));
exit(0);
}
void exit(int status) {ExitProcess(status);}
ssize_t write(int fd, const void *buf, size_t count)
{
DWORD bw;
WriteFile(fd, buf, count, &bw, NULL);
return bw;
}
V disassembleru z toho vypadne:
.text:00401000 _text segment para public 'CODE' use32
.text:00401000 assume cs:_text
.text:00401000 ;org 401000h
.text:00401000 assume es:nothing, ss:nothing, ds:_text, fs:nothing, gs:nothing
.text:00401000 public start
.text:00401000 start dd 0FB1E0FF3h ; toto je endbr32 :)
.text:00401004 ; ---------------------------------------------------------------------------
.text:00401004 lea ecx, [esp+4]
.text:00401008 and esp, 0FFFFFFF0h
.text:0040100B push dword ptr [ecx-4]
.text:0040100E push ebp
.text:0040100F mov ebp, esp
.text:00401011 push ebx
.text:00401012 push ecx
.text:00401013 sub esp, 1Ch
.text:00401016 push offset aHelloWorld ; "Hello world\n"
.text:0040101B call lstrlenA
.text:00401020 mov dword ptr [esp], 0FFFFFFF5h
.text:00401027 mov ebx, eax
.text:00401029 call GetStdHandle
.text:0040102E lea edx, [ebp-0Ch]
.text:00401031 push 0
.text:00401033 push edx
.text:00401034 push ebx
.text:00401035 push offset aHelloWorld ; "Hello world\n"
.text:0040103A push eax
.text:0040103B call WriteFile
.text:00401040 push 0
.text:00401042 call ExitProcess
.text:00401047 ; ---------------------------------------------------------------------------
.text:00401047 lea esp, [ebp-8]
.text:0040104A xor eax, eax
.text:0040104C pop ecx
.text:0040104D pop ebx
.text:0040104E pop ebp
.text:0040104F lea esp, [ecx-4]
.text:00401052 retn
Pres ty inline pujde vyresit spousta veci relativne efektivne, napr. KERNEL32.dll:lstrlenA() budu aliasovat na strlen stejne jako to delam u exitu -> KERNEL32:ExitProcess(). Takhle asi udelam 2 verze knihovny, jedna ktera se bude snazit o maximalni kompatibilitu (tam nebude zadny inline-pro pouziti s dalsimi knihovnami/bloby/atd. ktere budou ocekavat existenci vsech symbolu) a druha ktera nageneruje z prvni knihovny ty inlines (a tim se to rovnou bude preklapet na Windows API).
Tusite jak primet gcc k tomu aby negeneroval ten bordel s endbr/stackem/frameptr ? Moje cmdline + verze:
gcc -m32 -c hello.c -Os -fno-PIC -fno-stack-protector -fomit-frame-pointer # gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
Pro rypaly: ten kod je proof of concept!
-
Přiznávám se, že jsem vlákno pořádně nečetl, ale něco v tom stylu může mít za cíl midipix: https://midipix.org/ . Vypadá to ale, že se jedná o pre-alpha verzi :(
-
Diky za tip, povedlo se vam to nekomu stahnout? Nejak se nemuzu dopidit jak se dostat k privatnimu githubu se zdrojaky (mam access denied).
Kazdopadne mi to prijde jako tezky overkill, oni tam resi sice podobny problem, ale knihovna se patla treba v prekladu unicode na utf8, pochybuju navic ze takovou vec prelozim nejakym starym gcc. Ja chci naopak minimalismus.
Uvazuju o 4 vecech:
- asi by bylo dobre pomoci inline fci nejak wrapnout unicode/ansi verze (misto #define CreateFile CreateFileA), aby to nezborilo pres define stejne se jmenujici fce v programu, netusite MS pouziva #define misto always_inline fce ?
- muzu pouzit spoustu fci z ntdll.dll, skoda ze nejde pouzit jejich fce xxxprintf, ledaze bych na to pouzil nejaky intermediate string buffer a pak tisknul pres nejaky snprintf, ale to se mi moc nelibi
- A pak bych rad vyresil chytre ty inline wrappery nad Win32 API jako je exit(n), stejne tak v mych programech neni problem udelat ze (file) HANDLE je to same co file deskriptor a ve wrapperu open()->CreateFileA jen poresit STDIN/OUT/ERR aby to zavolalo GetStdHandle(); dalsi problem je errno, nevim jestli si muzu dovolit udelat #define ENOENT ERROR_FILE_NOT_FOUND (tady to zrovna sedi, oboji jsou 2, ale urcite se to jinde rozpadne).
- pokud by doslo k tomu, ze cast projektu bude prelozena s tim ze HANDLE == filedescriptor (tzn. ty inline fce) a cast ocekavajici translaci pres knihovni fce, mate nekdo tip jak zamezit vzajemnemu slinkovani takovych vzajemne nekompatibilnich obj files ?
-
Nebylo by snazsi zkompilovat qemu-user pro win, a pak tomu predhazovat tvoje linux binarky?
-
Podle me qemu-user neresi ABI, ale mozna se pletu.A jestli to bylo mysleno tak ze si mam to ABI do toho nejak zadratovat sam, tak to je jednodussi udelat tu libc.
Narazil jsem ale na zajimavy problem a to je TLS, gcc v Linuxu totiz na takove promenne pristupuje jak se mu zachce via gs:xxx (R_386_TLS_LE) , ve Windows to je ale potreba pres TlsIndex a pak fs:[0x2C]. x86_64-w64-mingw32-gcc na to ma zadratovany hack a pomaha si pres ___emutls_get_address. MSVC to prelozi ze si rovnou vytahne z fs:[0x2c] co potrebuje a pres globalni tlsindex leze kam potrebuje. Jak toto vyresim nevim.
-
Mam jeste dotaz, o wsl se uz tady zminovalo, ale uplne jste neodpovedel - proc vlastne nemuzete tyhle utilitky na widlich spoustet pres wsl? Pripadne pres docker (for windows/desktop) ?
-
Mam jeste dotaz, o wsl se uz tady zminovalo, ale uplne jste neodpovedel - proc vlastne nemuzete tyhle utilitky na widlich spoustet pres wsl? Pripadne pres docker (for windows/desktop) ?
imho to je problem verzovani napr. GLIBC, kdy prislusne exporty tam bud jeste nejsou, nebo uz nejsou. Stejny problem potkavam pri spousteni binarek skrze ruzne linuxy.. pritom to je nekdy fakt takova prkotina, kdyz se podivate, ze v cem se lisi 2.25 a 2.32 :-)
-
Nekdy mrknu do nejakych starsich prekladacu typu Borland nebo Watcom na zdrojaky CRT, treba to pujde pouzit, myslel jsem ze existuje nejake free+opensource reseni.
Tiny C znate?
-
ad wsl: duvodu je vice, jednak potrebuju aby to chodilo kde WSL neni (predstavte si, ze je 3rd party SW ktery nechodi na W10), za druhe nechci 'sebou' tahat hromadu blbosti a resit ruzne kompatibility apod.
ad tcc: nevim o tom, ze by mela vlastni libc, pouziva nejakou systemovou, nebo se pletu? Ale to neni reseni, predstavte si, ze mate 20 projektu, ktere v sobe obsahuji nejake zavislosti na konkretnim prekladaci (typicky treba nejaky inlinovany assembler AT&T stylu ... nebo naopak ten MS-to je dalsi vec nad ramec tohoto tematu kterou chci nekdy vyresit, abych msvc COFF/objectfile mohl pouzit v Linuxu). Najednou se stane jednodussi vyresit nejake 'hloupe' libc nez koukat jak zmena prekladace vyvola nekonecny seznam chyb, ktere clovek musi tupe opravovat.
No ale zajimaly by mne tipy na ruzne male libc, muj favorit je openbsd, inspirovat se chci ale i u prekladacu z Win sveta (msvc, bcc), dale uclibc, musl libc, dobrym zdrojem jsou nejake opravdu historicke libc typu https://github.com/wuzhouhui/c_standard_lib ; naopak treba Watcom je plny DOS/OS2/Win3x legacy kodu
-
S tim wsl to chapu (zhledem k predchozim zpravam), ze resis kompatibilitu glibc? K tomu chci rict, pokud samotny kompilator a glibc neni kompatibilni - tak mi prijde celkem utopicke ocekavat, ze bude spolehlive funkcni nejaky automaticky "preklad" pro win32api.
Javim, moc tady nejsem konstruktivni, za to se omlouvam.
-
Je rozdil mezi 'zdrojakem vs libc' a 'executable vs libc'. Privedl jste mne ale na jednu myslenku, co povazuju za mor dnesniho IT sveta, a to je jak moc na pocatku chybi nejaka vize (+zkusenosti) toho co ma urcita knihovna umet, jak ma byt strukturovana, schopnost navrhnout dobre nejake API apod. Dneska se kod spis lepi a pak to vypada tak, ze prave glibc je neuveritelny moloch. To same msvcrt, apod. Je potrebna nejaka zmena? Udelame dalsi fci, pridame dalsi parametr, apod., zvedneme cislo v nazvu .so. a je hotovo. V horsim pripade se jen zmeni API a na zbytek se kasle. A to pak vede k tomu, ze se musi delat narovnavaky na ohybaky.
Moc casu tomu nemuzu venovat, ale uz jsem par malinkatych veci prelozil - pomoci opravdu nanolibc napatlane primo na ucel techto miniaplikaci a fascinuje mne jak ty .exe muzou byt male, svet je opet v poradku :-). Muj linker+nanolibc - 4kB. MSVC 2003 60kB; MSVC z 2019 - 180kB.
-
Podle mě jsou jen 2 možné cesty - buď to zkompilovat nativně a používat jen ty utility co se takto zkompilovat podaří a nebo to spustit přes něco jako WSL. Všechno ostatní je slepá ulička. Portabilita je v tomto případě ta lepší investice.