I'd like to try the AsmJit library. Building it with 'cmake' and 'make' from source was no problem, the examples it provided were all compiled and executed perfectly. I also did make install
to export the dependency files.
I then wanted to compile my own program using this library, so I retrieved the generated files (the headers and the static lib) to add them to a new project whose the code is a copy/paste of the first example given on the library's website:
// #define ASMJIT_NO_DEPRECATED // this line is no part of the original code
#include <asmjit/asmjit.h>
#include <stdio.h>
using namespace asmjit;
// Signature of the generated function.
typedef int (*Func)(void);
int main(int argc, char* argv[]) {
JitRuntime rt; // Runtime designed for JIT code execution.
CodeHolder code; // Holds code and relocation information.
code.init(rt.environment()); // Initialize CodeHolder to match JIT environment.
x86::Assembler a(&code); // Create and attach x86::Assembler to `code`.
a.mov(x86::eax, 1); // Move one to 'eax' register.
a.ret(); // Return from function.
// ----> x86::Assembler is no longer needed from here and can be destroyed <----
Func fn;
Error err = rt.add(&fn, &code); // Add the generated code to the runtime.
if (err) return 1; // Handle a possible error returned by AsmJit.
// ----> CodeHolder is no longer needed from here and can be destroyed <----
int result = fn(); // Execute the generated code.
printf("%d\n", result); // Print the resulting "1".
// All classes use RAII, all resources will be released before `main()` returns,
// the generated function can be, however, released explicitly if you intend to
// reuse or keep the runtime alive, which you should in a production-ready code.
rt.release(fn);
return 0;
}
This is what the hierarchy of my test project looks like:
include\
asmjit\ // The generated headers from the library build
libasmjit.a // The generated static library from the library build
main.cpp // My program's code, as pasted above
And here is the command line used to compile:
g++ main.cpp -o main -Iinclude -L -lasmjit
A first compilation error occurs:
In file included from include/asmjit/./core.h:2008,
from include/asmjit/asmjit.h:27,
from main.cpp:1:
include/asmjit/././core/builder.h:375:20: error: function 'asmjit::Error asmjit::BaseBuilder::dump(asmjit::String&, uint32_t) const' definition is marked dllimport
375 | ASMJIT_API Error dump(String& sb, uint32_t formatFlags = 0) const noexcept {
| ^~~~
After some research in the lib code, defining the ASMJIT_NO_DEPRECATED
macro (see in the code above, the first commented line) prevents this error from being reproduced. I doubt this is a good idea, as it may be the cause of the following next link errors:
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x35): undefined reference to `__imp__ZN6asmjit10JitRuntimeC1EPKNS_12JitAllocator12CreateParamsE'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x45): undefined reference to `__imp__ZN6asmjit10CodeHolderC1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x6e): undefined reference to `__imp__ZN6asmjit10CodeHolder4initERKNS_11EnvironmentEy'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x82): undefined reference to `__imp__ZN6asmjit3x869AssemblerC1EPNS_10CodeHolderE'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x11f): undefined reference to `__imp__ZN6asmjit3x869AssemblerD1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x12f): undefined reference to `__imp__ZN6asmjit10CodeHolderD1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x142): undefined reference to `__imp__ZN6asmjit10JitRuntimeD1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x159): undefined reference to `__imp__ZN6asmjit3x869AssemblerD1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x169): undefined reference to `__imp__ZN6asmjit10CodeHolderD1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text+0x17c): undefined reference to `__imp__ZN6asmjit10JitRuntimeD1Ev'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text$_ZN6asmjit11BaseEmitter4emitIJRKNS_3x862GpEiEEEjjDpOT_[_ZN6asmjit11BaseEmitter4emitIJRKNS_3x862GpEiEEEjjDpOT_]+0x4c): undefined reference to `__imp__ZN6asmjit11BaseEmitter6_emitIEjRKNS_8Operand_ES3_'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.1.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\<my user name>\AppData\Local\Temp\cc4WaQ7J.o:main.cpp:(.text$_ZN6asmjit11BaseEmitter4emitIJEEEjjDpOT_[_ZN6asmjit11BaseEmitter4emitIJEEEjjDpOT_]+0x1b): undefined reference to `__imp__ZN6asmjit11BaseEmitter6_emitIEj'
collect2.exe: error: ld returned 1 exit status
I couldn't find a way to prevent the first error from occurring, except by defining this macro, and I also don't understand why the link editor can't find the references. I have also tried placing these dependencies (headers + static lib) in the appropriate MinGW directories (i.e. the global include
and lib
directories), but this does not change anything.
How do I compile this program, which is quite simple? I would also like to know why what I did didn't work, knowing the cause of this mistake, I will probably be able to deal with others of the same style in the future.
PS: I don't have much experience with managing external dependencies in C and C++. I am under Windows, using MinGW and the last version of GCC.
You are missing ASMJIT_STATIC
compile-time definition - it has to be defined if you use AsmJit statically. This definition is checked at compile time by AsmJit to setup ASMJIT_API
macro, which expands to a compiler-specific import/export/visibility attribute.
AsmJit documentation (Build Instructions section) says [1]:
Projects that use AsmJit statically must define ASMJIT_STATIC in all compilation units that use AsmJit, otherwise AsmJit would use dynamic library imports in ASMJIT_API decorator. The recommendation is to define this macro across the whole project that uses AsmJit this way.
So in your particular case this should fix the problem:
g++ main.cpp -o main -Iinclude -L. -lasmjit -DASMJIT_STATIC
NOTE: The documentation link purposely links to the index page so it won't be a dead link once the documentation is reorganized.