How to use C static libraries in D? - linker

I'm completely stumped on how to get FreeType 2.4.8 compiled as a static lib and usable from within my D application in Windows. I've tried running it over with objconv, coff2omf, and trying extern(C)/extern(System), etc. but nothing seems to work. I'm getting symbol not found errors, access violations and just a bunch of unhelpful errors.
How can I work around this? Am I correct in using pragma lib to link to my static libraries, and how do I reliably convert COFF static libs to OMF which DMD/Optlink can use?
EDIT: Some examples of what I've tried doing:
Compiling the FreeType source with VS 2010 as a static lib, linking in my D code with pragma lib. (Returned a "library format unknown" type error)
Same as above, but converting to OMF format using objconv and then trying to link with pragma lib. (Linked successfully, but still not able to call functions.)
Compiled a DLL of the FreeType source, ran it through implib to create an import library, tried linking with pragma lib. (Linked successfully, but unable to to call any functions due to "attempt to privileged function" or "access violation" errors)
I've tried defining function prototypes as all of: extern(System), extern(C), and extern(Windows). The first and third mangle the functions names of the extern-ed functions such that they don't match the static libraries, and the second compiles, but I get access violations during runtime when I actually try and call the functions.
I'm able to get it working via dynamic libraries and symbol loading, but I'd much prefer to not require a bunch of external dependencies when deploying my project.

I'm pretty sure Derelict2 has FreeType bindings: http://www.dsource.org/projects/derelict (See DerelictFT).

Yes, you will need extern(System) in your .d files with FT function declarations.
Static library a collection of object files. So no need for any kind of conversion (omf2coff, etc). DMD accepts a static libraries as arguments, so simple dmd file1.d file2.d C:/path/to/freetype.lib should work.
Edit:
I was wrong. Apparently I needed to read some documentation about the COFF2OMF.
Quote: The Microsoft COFF format apparently changed with Visual C++ 6.0. To use coff2omf on a .lib file with the newer format, use Microsoft's linker to convert the file to the earlier COFF format:
link /lib /convert freetype.lib
So, judging by the statement above you need to perform 2 steps.
First use the Microsoft's linker to convert static library you made with the VisualStudio (in COFF format) to the old COFF format as described above.
Now execute coff2omf freetype.lib to convert the static library into the OMF format.
It should now be ready to be used with the DMD the way described originally in my post.

Related

Using D2XX of FTDI with C

I'm trying to use ftd2xx.lib with lcc-win32 compiler but the linker fails. I used CDM v2.12.14 but also previous FTDI driverd give the same errors. I tried to compile on Windows XP and Windows7; same results.
If I link the static library I will get these kind of errors:
File ftd2xx.lib contains unknown section .text$mn.
.text section assumed
File ftd2xx.lib contains unknown section .data$r.
.data section assumed
.data$r: undefined reference to '??_7type_info##6B#'
.text$mn: undefined reference to '__imp__SetupDiGetClassDevsA#16'
.text$mn: undefined reference to '__imp__SetupDiEnumDeviceInterfaces#20'
If I link the dynamic ftd2xx.lib (with ftd2xx.dll placed in the same dir of .exe file) I will get this:
Error e:\c\ftdi_cnt\main.c 11 undefined reference to __imp__FT_Open
(Note that main.c used for this test contains just a single FT_Open() call).
Is there anyone that was able to run ftd2xx.lib with lcc-win32 compiler or that is currently using lcc-win32 and can make a quick test? Here is the latest FTDI driver. Thank you.
Finally it works!
Here is what I did:
1) Ian suggested I should use "Utils --> Import foreign library"; as a matter of fact this is the same of running from the command line:
pedump /EXP ftd2xx.lib >ftd2xx.exp
buildlib ftd2xx.exp ftd2xxy.lib
I've already tried that using for ftd2xx.lib the dynamic .lib but without success.
2) I ran pedump again, this time using the static .lib and I got a warning message about unknown dll name, so I edited the first line of ftd2xx.exp adding that name (ftd2xx.dll).
3) I defined FTD2XX_STATIC before including ftd2xx.h
4) I linked the new library ftd2xxy.lib
Note that you can't use "Utils --> Import foreign library" because you need to modify ftd2xx.exp before re-building the library.
I hope this could be helpful for others.

NASM: How to resolve these unresolved externals?

I'm trying to get started learning basic assembly with Paul A. Carter's book "PC Assembly Language." However I'm unable to run the first example Carter provides, so I'm kind of stuck until I figure this out.
I assembled the example "first.asm" without any problem, but I can't figure out how to link these files: first.obj, driver.c, asm_io.obj into an executable. In the comment section of first.asm Carter gives these instructions for creating an executable (I'm using Windows 10, VS community 2015 developer command prompt):
; Using MS C/C++
; nasm -f win32 first.asm
; cl first.obj driver.c asm_io.obj
I'm doing exactly that but I'm getting a fatal error 2 unresolved externals, _printf and _scanf. I have every necessary file that I can think of in the same directory, and I'm compiling in that directory.
Driver.c calls the function defined in and it uses a header file called "CDECL.h"; I have this file in my directory, but I don't understand much about this header file. I wonder if the problem is here. I haven't altered it or anything. I assembled asm_io.asm according to Dr. Carter's instructions.
Not too far into asm_io.asm is see this:
extern _scanf, _printf, _getchar, _putchar, _fputs
So here are the unresolved externals. Shouldn't they be defined in stdio.h? Driver.c includes stdio.h, shouldn't the linker be able to resolve these symbols be looking at stdio.h? What might I be missing?
ps. I'm new to programming in general, and this is my first stack overflow question. I'm open to any and all criticism/feedback. I'll provide more information if you need it, I just didn't want to post a massive wall of text and code if not necessary.
Welcome to SO. You need to understand:-
The difference between a header file, e.g.
foo.h // C or maybe C++ header file)
and a library, e.g.
foo.lib foo.dll // Windows
libfoo.a, libfoo.so // Unix/Linux
that implements the calling interface that is (merely) described in a header file.
The difference between compiling or assembling a source file, e.g.
bar.c // C source file
bar.asm // Assembly source, Windows
bar.s // Assembly source, Unix/Linux
to make an object file. e.g.
bar.obj // Windows
bar.o // Unix/Linux
and linking object files and libraries together make a complete executable.
Linking can succeed only if the linker is supplied with (or knows by default)
the names and locations of object files and/or libraries that provide
implementations of all the functions that are called in the program - including
functions whose calling interfaces are described in header files. Otherwise
unresolved symbol errors ensue.
Research these points and you'll quickly get yourself unstuck. See this
pretty good introductory tutorial, which although it is about getting
started with the GNU Compiler Collection rather
than with assembly language programming, will clarify the principles
and distinctions you need to grasp.

Why do I need to manually link the C runtime library when creating an EXE out of static libraries without any object files?

I'm pretty new to working with libraries and I'm in the process of trying to understand some specifics regarding static libraries and object files.
Summary
The behavior I'm noticing is that I can link several objects to make an executable with no problem, but if I take an intermediate step of combining those objects into static libraries, I cannot link those static libraries to make an executable without additionally specifying the needed C Run-time library in the link command.
Also, or the record, I'm doing the compiling/linking with Visual Studio 2010 from the command line. More details of the process I'm following are below.
First, let's say I have four source files in a project: main.c, util1.c, util2.c, and util3.c.
What works
I can compile these sources with the following command:cl -c main.c util1.c util2.c util3.cAs a result, I now have four object files: main.obj, util1.obj, util2.obj, and util3.obj. These object files each contain a DEFAULTLIB statement intended to inform the linker that it should additionally check the static C Run-time library libcmt.lib for any unresolved external dependencies in these object files when linking them.
I can create an executable named "app_objs.exe" by linking these objects with the following command:
link -out:app_objs.exe main.obj util1.obj util2.obj util3.obj
As mentioned in step 1, the linker used the runtime library due to the compiler's step of adding a default library statement to the objects.
Where I'm confused
Let's say I want to have an intermediate step of combining these objects into static libraries, and then linking those resulting LIB files to create my executable. First, I can create these libraries with the following commands:
link -lib -out:main.lib main.obj
link -lib -out:util.lib util1.obj util2.obj util3.obj
Now, my original thought was that I could simply link these libraries and have the same executable that I created in step 2 of "What works". I tried the following command and received linker error LNK1561, which states that an entry point needs to be specified:
link -out:app_libs.exe main.lib util.lib
From Microsoft's documentation, it is evident that linking libraries without any object files may require entry points to be specified, so I modified the command to set the subsystem as "console" to specify that the executable in intended to be a console application (which seems to imply certain entry points, thereby resolving that error):link -out:app_libs.exe -subsystem:console main.lib util.libUnfortunately, now I get a linker error stating that mainCRTStartup is an unresolved external symbol. I understand that this is defined in the C runtime library, so I can resolve this issue by manually specifying that I want to link against libcmt.lib, and this gives me a functioning executable:link -out:app_libs.exe -subsystem:console main.lib util.lib libcmt.lib
What I'm not understanding is why the default library info that the compiler placed in each object file couldn't be used to resolve the dependency on libcmt.lib. If I can link object files without explicitly stating I want libcmt.lib, and I created static libraries that are containers for the object files, why can't I link those static libraries without having to explicitly state that I want libcmt.lib? Is this just the way things are, or is there some way I could create the static libraries so that the linker will know to check for unresolved symbols in the runtime library?
Thanks for your help. If I have some fundamentally incorrect ideas here, I'd love suggestions on good references to learn all of this correctly.
Well the answer to your misunderstanding is that .lib files are often a product in themselves, and the compiler can't make those assumptions safely. That's what "external" is for.
If I produce binaries for someone's platform because its users are totally helpless, and they want/need static linkage, I have to give them foo.h and libfoo.lib without tying them to a specific runtime entry point. They may very well have defined their own entry point already for their final product, whether DLL or EXE.
You either want the runtime, or you want your own .obj that contains your entry point. Be warned that declaring and defining mainCRTStartup on your own may mean you're not executing important instructions for the target platform.

How to find out functions missing from a library, but which are present in the exposed header file released along with the library?

We have a legacy library implementation and associated exposed header files. Recently we found that, some of the functions in the exposed header file, don't have corresponding definitions in the library implementation.
We want to check if there could be some more such functions. Is there any easier way of doing this rather than sifting through each and every API present in header and then checking if there is a definition for it?
You can generate C source from the header (Perl is a way to go!) that calls all the functions and try to compile it. Linker will complain about missing functions.
Try to create the ABI dump file by the abi-compliance-checker tool:
abi-compliance-checker -lib NAME -dump DESC.xml
DESC.xml file is the following:
<version>
1.0
</version>
<headers>
/path(s)/to/headers
</headers>
<libs>
/path(s)/to/libraries
</libs>
The resulting ABI dump file will contain the information you need about symbols declared in header files (SymbolInfo) and symbols exported by shared libraries (Symbols).
You can also generate ABI dump in the xml format by adding --xml option.
If this is C, you can do something like:
printf("", /* insert all functions here */);
That should pass them all as function pointers to printf. The ones that do not exist should show up as linker errors.
(In C++, you would have to list overloads explicitly, which makes it a bit more difficult.)
I'd be inclined to use ctags to generate a list of identifiers from the header file then use ar, emfar or elfdump in Unix or lib.exe or dumpbin.exe in Windows (see discussion here) to dump a list of identifiers from the library and then sort and diff the two lists.

Compaq Visual Fortran - Crashes During Linking A .LIB File

When I compile with Compaq Visual Fortran, I get these errors (when it starts the linker process) that should be located in a .lib file I thought I added to the workspace:
X30XFULL.OBJ : error LNK2001: unresolved external symbol _BCON#4
X30XFULL.OBJ : error LNK2001: unresolved external symbol _RCON#16
According to where I've googled about, it looks like Compaq Visual Fortran (Version 6, FYI) can't find the library files...
My main question is, how do I use them? Could there possibly be other missing files? Here is what I've tried:
Right Click->Adding the files in the FileView window
Going under Project->Settings, Clicking the Link tab, and under the input category, adding the library files under object/library modules (bprop.lib rprop.lib) and having the Additional Library Path point to where the files are. I also did this under the Resources tab and where it says "Additional Resource Include Directories," I put the directory of where these files were located.
To cover my bases, I also put these files in where the project workspace file, where the compiled executable file would be generated, and pretty much any place I could think of that CVF might possibly look to in order to find these files.
A little background:
I have this Fortran executable that was last compiled in the 90s. From my research, it's a 16-bit compiled one which won't work on a 64-bit machine.
The original code has, at least from what we can gather, 16 bit compiled libraries. Without the original compiler, we can't figure out how to look at or use them. We also have a (semi)equivalent library file that's actually a .FOR file. For all we know, the BPROP.FOR and BPROP.LIB could be the same file (they were found in the same source code area). If we use the BPROP.FOR file, the program can compile, but we are having issues with results that we've traced down to information that is used/gathered/processed in that file.
However, we do have 32-bit versions of (what we think) are the same .lib files. So, we're trying to use that, which is what is being used to compile the Fortran executable which results in the errors above.
Found the answer, at least for me. I don't know how easy it'll be to extrapolate if anyone else finds these answers, but this is how I solved it.
With the old Fortran libraries, all I had to do was add them to the FileList view that has all of the different fortran files (.FOR, etc). I did not have to add these libraries in the settings like I mentioned, but that will work as well. Other then that, I didn't need to add any extra declarations or anything similar.
What we did find out is that the function in question (BCON and RCON) that calls those .LIB files required an additional argument. The only way I found this out was examining other source code that used those libaries, so if anyone is stuck like I was, that would be a good place to start. Alternatively, if you can read the .lib file in a hex editor, you can kind of make out functions and their arguments.
Of course, if you have the original source code for said arguments, that's even better. :)

Resources