[llvm-dev] Using LLD to create a .lib from a .def
Rui Ueyama via llvm-dev
llvm-dev at lists.llvm.org
Fri Jun 16 13:29:58 PDT 2017
It looks like it is an unrelated build issue (probably related
to LLVM_BUILD_LLVM_DYLIB), no?
On Fri, Jun 16, 2017 at 11:53 AM, Andrew Kelley <superjoe30 at gmail.com>
wrote:
> I saw this change come in yesterday:
>
> commit 572ad839e2f66eaa82ffc71b1061eb3d06a4d126
> Author: Saleem Abdulrasool <compnerd at compnerd.org>
> Date: Thu Jun 15 20:39:58 2017 +0000
>
> COFF: add support for lib mode usage
>
> When link is invoked with `/def:` and no input files, it behaves as if
> `lib.exe` was invoked. Emulate this behaviour, generating the import
> library from the def file that was passed. Because there is no input
> to
> actually generate the dll, we simply process the def file early and
> exit
> once we have created the import library.
>
>
> Thank you for this, Saleem.
>
> I still have this problem though, with latest master of llvm-project,
> which is bd8af0ee30bc1a308bf286089b172f2ae87f3de5
>
> llvm-config: error: component libraries and shared library
>
> llvm-config: error: missing: /home/andy/local/lib/libLLVMTestingSupport.a
>
> I'm pretty sure it's not just me, anyone should be able to reproduce this
> issue with a clean build.
>
> Regards,
> Andrew
>
> On Thu, Jun 15, 2017 at 12:29 PM, Andrew Kelley <superjoe30 at gmail.com>
> wrote:
>
>> When I build llvm-project from source (revision 53a3cb539f7e92e70d4eef8d1b219cbef7c8ba1c
>> from https://github.com/llvm-project/llvm-project-20170507)
>>
>> The build and install seemed to work correctly. But then when I run
>> `llvm-config --libfiles`, I get this:
>>
>> llvm-config: error: component libraries and shared library
>>
>> llvm-config: error: missing: /home/andy/local/lib/libLLVMTestingSupport.a
>>
>>
>> The library got built: ./llvm/build/lib/libLLVMTestingSupport.a
>> But `make install` didn't copy it to the prefix path.
>>
>>
>> On Thu, Jun 15, 2017 at 10:33 AM, Andrew Kelley <superjoe30 at gmail.com>
>> wrote:
>>
>>>
>>>
>>> On Wed, Jun 14, 2017 at 7:37 PM, Rui Ueyama <ruiu at google.com> wrote:
>>>
>>>> On Wed, Jun 14, 2017 at 4:24 PM, Andrew Kelley via llvm-dev <
>>>> llvm-dev at lists.llvm.org> wrote:
>>>>
>>>>> I'm copying some LLD code into my codebase like this:
>>>>>
>>>>> // workaround for LLD not exposing ability to convert .def to .lib
>>>>>
>>>>> #include <set>
>>>>>
>>>>> namespace lld {
>>>>> namespace coff {
>>>>>
>>>>> class SymbolBody;
>>>>> class StringChunk;
>>>>> struct Symbol;
>>>>>
>>>>> struct Export {
>>>>> StringRef Name; // N in /export:N or /export:E=N
>>>>> StringRef ExtName; // E in /export:E=N
>>>>> SymbolBody *Sym = nullptr;
>>>>> uint16_t Ordinal = 0;
>>>>> bool Noname = false;
>>>>> bool Data = false;
>>>>> bool Private = false;
>>>>>
>>>>> // If an export is a form of /export:foo=dllname.bar, that means
>>>>> // that foo should be exported as an alias to bar in the DLL.
>>>>> // ForwardTo is set to "dllname.bar" part. Usually empty.
>>>>> StringRef ForwardTo;
>>>>> StringChunk *ForwardChunk = nullptr;
>>>>>
>>>>> // True if this /export option was in .drectves section.
>>>>> bool Directives = false;
>>>>> StringRef SymbolName;
>>>>> StringRef ExportName; // Name in DLL
>>>>>
>>>>> bool operator==(const Export &E) {
>>>>> return (Name == E.Name && ExtName == E.ExtName &&
>>>>> Ordinal == E.Ordinal && Noname == E.Noname &&
>>>>> Data == E.Data && Private == E.Private);
>>>>> }
>>>>> };
>>>>>
>>>>> enum class DebugType {
>>>>> None = 0x0,
>>>>> CV = 0x1, /// CodeView
>>>>> PData = 0x2, /// Procedure Data
>>>>> Fixup = 0x4, /// Relocation Table
>>>>> };
>>>>>
>>>>> struct Configuration {
>>>>> enum ManifestKind { SideBySide, Embed, No };
>>>>> llvm::COFF::MachineTypes Machine = llvm::COFF::IMAGE_FILE_MACHINE
>>>>> _UNKNOWN;
>>>>> bool Verbose = false;
>>>>> llvm::COFF::WindowsSubsystem Subsystem =
>>>>> llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
>>>>> SymbolBody *Entry = nullptr;
>>>>> bool NoEntry = false;
>>>>> std::string OutputFile;
>>>>> bool DoGC = true;
>>>>> bool DoICF = true;
>>>>> bool Relocatable = true;
>>>>> bool Force = false;
>>>>> bool Debug = false;
>>>>> bool WriteSymtab = true;
>>>>> unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
>>>>> StringRef PDBPath;
>>>>>
>>>>> // Symbols in this set are considered as live by the garbage
>>>>> collector.
>>>>> std::set<SymbolBody *> GCRoot;
>>>>>
>>>>> std::set<StringRef> NoDefaultLibs;
>>>>> bool NoDefaultLibAll = false;
>>>>>
>>>>> // True if we are creating a DLL.
>>>>> bool DLL = false;
>>>>> StringRef Implib;
>>>>> std::vector<Export> Exports;
>>>>> std::set<std::string> DelayLoads;
>>>>> std::map<std::string, int> DLLOrder;
>>>>> SymbolBody *DelayLoadHelper = nullptr;
>>>>>
>>>>> // Used for SafeSEH.
>>>>> Symbol *SEHTable = nullptr;
>>>>> Symbol *SEHCount = nullptr;
>>>>>
>>>>> // Used for /opt:lldlto=N
>>>>> unsigned LTOOptLevel = 2;
>>>>>
>>>>> // Used for /opt:lldltojobs=N
>>>>> unsigned LTOJobs = 1;
>>>>>
>>>>> // Used for /merge:from=to (e.g. /merge:.rdata=.text)
>>>>> std::map<StringRef, StringRef> Merge;
>>>>>
>>>>> // Used for /section=.name,{DEKPRSW} to set section attributes.
>>>>> std::map<StringRef, uint32_t> Section;
>>>>>
>>>>> // Options for manifest files.
>>>>> ManifestKind Manifest = SideBySide;
>>>>> int ManifestID = 1;
>>>>> StringRef ManifestDependency;
>>>>> bool ManifestUAC = true;
>>>>> std::vector<std::string> ManifestInput;
>>>>> StringRef ManifestLevel = "'asInvoker'";
>>>>> StringRef ManifestUIAccess = "'false'";
>>>>> StringRef ManifestFile;
>>>>>
>>>>> // Used for /failifmismatch.
>>>>> std::map<StringRef, StringRef> MustMatch;
>>>>>
>>>>> // Used for /alternatename.
>>>>> std::map<StringRef, StringRef> AlternateNames;
>>>>>
>>>>> uint64_t ImageBase = -1;
>>>>> uint64_t StackReserve = 1024 * 1024;
>>>>> uint64_t StackCommit = 4096;
>>>>> uint64_t HeapReserve = 1024 * 1024;
>>>>> uint64_t HeapCommit = 4096;
>>>>> uint32_t MajorImageVersion = 0;
>>>>> uint32_t MinorImageVersion = 0;
>>>>> uint32_t MajorOSVersion = 6;
>>>>> uint32_t MinorOSVersion = 0;
>>>>> bool DynamicBase = true;
>>>>> bool AllowBind = true;
>>>>> bool NxCompat = true;
>>>>> bool AllowIsolation = true;
>>>>> bool TerminalServerAware = true;
>>>>> bool LargeAddressAware = false;
>>>>> bool HighEntropyVA = false;
>>>>>
>>>>> // This is for debugging.
>>>>> bool DebugPdb = false;
>>>>> bool DumpPdb = false;
>>>>> };
>>>>>
>>>>> extern Configuration *Config;
>>>>>
>>>>> void writeImportLibrary();
>>>>> void parseModuleDefs(MemoryBufferRef MB);
>>>>>
>>>>> } // namespace coff
>>>>> } // namespace lld
>>>>>
>>>>> //==========================================================
>>>>> ===============
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> This is so that I can write the following user code:
>>>>>
>>>>>
>>>>>
>>>>> // writes the output to dll_path with .dll replaced with .lib
>>>>> void ZigLLDDefToLib(Buf *def_contents, Buf *dll_path) {
>>>>> lld::coff::Config = new lld::coff::Configuration;
>>>>> auto mem_buf = MemoryBuffer::getMemBuffer(buf_ptr(def_contents));
>>>>> MemoryBufferRef mbref(*mem_buf);
>>>>> lld::coff::parseModuleDefs(mbref);
>>>>> lld::coff::Config->OutputFile = buf_ptr(dll_path);
>>>>> lld::coff::writeImportLibrary();
>>>>> }
>>>>>
>>>>>
>>>>> Then I give it def_contents that looks like:
>>>>> LIBRARY kernel32
>>>>> EXPORTS
>>>>> ExitProcess
>>>>> GetConsoleMode
>>>>> GetStdHandle
>>>>> GetFileInformationByHandleEx
>>>>> WriteFile
>>>>> GetLastError
>>>>>
>>>>>
>>>>> with dll_path set to ./zig-cache/all.dll. This generates
>>>>> ./zig-cache/all.lib.
>>>>>
>>>>> The generated LLVM IR looks like:
>>>>>
>>>>> ; Function Attrs: noreturn nounwind
>>>>> declare void @ExitProcess(i32) #6
>>>>> ; Function Attrs: nounwind
>>>>> declare i1 @GetConsoleMode(i8* nonnull, i32* nonnull) #3
>>>>> ; Function Attrs: nounwind
>>>>> declare i8* @GetStdHandle(i32) #3
>>>>> ; Function Attrs: nounwind
>>>>> declare i1 @GetFileInformationByHandleEx(i8* nonnull, i32, i8*
>>>>> nonnull, i32) #3
>>>>> ; Function Attrs: nounwind
>>>>> declare i1 @WriteFile(i8* nonnull, i8* nonnull readonly, i32, i32*,
>>>>> %OVERLAPPED*) #3
>>>>> ; Function Attrs: nounwind
>>>>> declare i32 @GetLastError() #3
>>>>>
>>>>> ...with code you would expect to call these functions.
>>>>>
>>>>> Then I link with
>>>>> lld -NOLOGO -MACHINE:X64 -OUT:hello.exe -NODEFAULTLIB -ENTRY:_start
>>>>> ./zig-cache/hello.obj ./zig-cache/builtin.obj ./zig-cache/compiler_rt.obj
>>>>> ./zig-cache/all.lib
>>>>>
>>>>>
>>>>> and I get the following errors:
>>>>> ./zig-cache/hello.obj: undefined symbol: ExitProcess
>>>>> ./zig-cache/hello.obj: undefined symbol: GetConsoleMode
>>>>> ./zig-cache/hello.obj: undefined symbol: GetStdHandle
>>>>> ./zig-cache/hello.obj: undefined symbol: GetFileInformationByHandleEx
>>>>> ./zig-cache/hello.obj: undefined symbol: GetLastError
>>>>> ./zig-cache/hello.obj: undefined symbol: WriteFile
>>>>> error: link failed
>>>>>
>>>>>
>>>>>
>>>>> 1. Is there something else I need to be doing to make this work
>>>>> correctly?
>>>>>
>>>>
>>>> The first thing I would check is to make sure that you created your
>>>> .lib file for x86-64. Windows uses different name mangling scheme for x86
>>>> and x86-64, so if you mix the two, it could result in an "undefined symbol"
>>>> error.
>>>>
>>>
>>> I tested this by setting the machine in the config directly to AMD64.
>>>
>>>
>>>>
>>>>
>>>>> (Note: I already tried renaming "all" to "kernel32". Ideally I could
>>>>> generate 1 .lib file for all the DLL calls needed.)
>>>>> 2. Can LLD expose this ability directly so I don't have to copy paste
>>>>> a bunch of LLD internal stuff?
>>>>>
>>>>
>>>> Martell recently factored out the code to parse and generate module
>>>> definition files. You might be able to use that. See
>>>> llvm/Object/COFFModuleDefinition.h.
>>>>
>>>> The location at where LLD uses COFFModuleDefinition.h is in
>>>> parseModuleDefs and createImportLibrary in COFF/Driver.cpp.
>>>>
>>>
>>> OK, thanks. I'll get a build going with latest trunk and see if I can
>>> get it to work.
>>>
>>>
>>>>
>>>> Regards,
>>>>> Andrew Kelley
>>>>> ziglang.org
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> LLVM Developers mailing list
>>>>> llvm-dev at lists.llvm.org
>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170616/07f2bef6/attachment-0001.html>
More information about the llvm-dev
mailing list