I have a Windows DLL called morag.dll containing functions foo and bar. I also have a Linux SO called morag.so containing the Linux implementations of foo and bar (same parameters on each platform). I have a Windows application that loads morag.dll that I want to run under wine. The application itself runs fine, however I need to create the mapping between foo and bar which are expected by my application to be found in morag.dll to instead use foo and bar in morag.so.
To do this I know I need to create morag.dll.spec file and winebuild it into morag.dll.so.
Following instructions here I created a wrapper in morag.c containing functions Proxyfoo and Proxybar which do nothing more than call real functions foo and bar. Then I created morag.dll.spec thus:-
1 stdcall foo (long ptr) Proxyfoo
2 stdcall bar (ptr ptr) Proxybar
I compiled my c part, winebuild the spec file, and then use winegcc to link them into morag.dll.so
Then I read this page which suggested you maybe didn't need the proxy function so I tried without the c part altogether and made a spec file thus:-
1 stdcall foo (long ptr)
2 stdcall bar (ptr ptr)
And as above, did the winebuild step and the winegcc link step.
In both cases these were the options I used.
winebuild --dll -m32 -E ./morag.dll.spec -o morag.dll.o
ldopts= -m32 -fPIC -shared -L/usr/lib/wine -L/opt/morag/lib -lmorag
winegcc $(ldopts) -z muldefs -o morag.dll.so [morag.o] morag.dll.o
N.B. [..] denotes I only used this in the case where I was also building the c part.
in both cases, when my application running under wine tries to load the entry point in the DLL using GetProcAddress it fails.
I ran wine with WINEDEBUG=+module,+relay and saw the attempt and failure recorded as follows:-
0025:Ret KERNEL32.LoadLibraryExA() retval=7dbc0000 ret=00447b84
0025:Call KERNEL32.GetProcAddress(7dbc0000,00b2d060 "foo") ret=00447c8a
0025:Ret KERNEL32.GetProcAddress() retval=00000000 ret=00447c8a
It seems it has found and loaded my morag.dll.so since LoadLibraryExA has returned the handle to it, but when it tries to find function foo within that HMODULE handle it fails.
If I issue:-
nm -D morag.dll.so
I see foo and bar shown as U in both cases. In the case where there are proxy functions as well, the proxy functions are shown as T.
I assume that this is because I have not built the morag.dll.so file correctly, either with the wrong options, or that my spec file is not correctly formed. I am not sure which of the two schemes described above I should be using.
All help most appreciated.
I ran into the same problem today.
What was missing in my case was the proper exporting rule for e.g. foo and bar in the built-in DLL. Conveniently, besides the --dll object, the winebuild tool can create a .def file for us, e.g.:
morag.def: morag.spec
$(WINEBUILD) --def -E $< -o $#
The resulting .def file must be linked into morag.dll.so along with other objects. This does the job.
Related
I want to collect object files (.o) in a particular directory with CMake
I have tried the below snippet from How to collect object files (.o) in a particular directory with CMake?
add_custom_command(TARGET ${LIBNAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${OBJ_DIR}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_OBJECTS:${LIBNAME_OBJ}> ${OBJ_DIR})
The command copy_if_different works well when the library contains less number of sources and fails when it's more.
How to collect objects of a project which contains huge number of sources ?
For add_custom_command to execute its COMMAND arguments, something has to create a process environment for the command to execute in. Whether that's done by a command shell or directly using exec(), the size limit for that environment is defined by the limits.h macro ARG_MAX. On POSIX systems, getconf ARG_MAX will show the compile-time value of that configuration. On my Fedora 35 system, the value is 2097152 which seems almost impossible to exceed, but maybe you're dealing with smaller limits.
(Also, the ARG_MAX limit represents the entire environment, not just command arguments. So if there are a lot of environment variables defined, that could eat into your max length.)
If you truly are exceeding that, you have two choices:
Option 1: Install the objects in the install stage, as intended
If I'm understanding the linked q&a correctly, the only reason you need the $<TARGET_OBJECTS> paths is so that you can copy them somewhere else in the build tree, in order to then install them from there?
If you just want to install them, a simpler solution is to write custom install code, e.g.
# necessary because config variables aren't present
# in the install context.
install(CODE "set(OBJECT_DEST \"${CMAKE_INSTALL_LIBDIR}\")"
install(CODE [[
file(INSTALL
DESTINATION "${CMAKE_INSTALL_PREFIX}/${OBJECT_DEST}"
FILES
$<TARGET_OBJECTS:_actual_object_name_>
)]])
Messing around with keeping the object name in a variable is a mistake when using custom install code, IMHO, as the evaluation contexts get too confusing. Instead of ${LIBNAME_OBJ}, just use the actual target name in the generator expression.1
Since the generator-expression expansion is handled by CMake when generating the cmake_install.cmake script, there shouldn't be any limit on the length it can have. (Not beyond whatever limits it has internally, if any.)
Option 2: Break up your targets
If you really want to use add_custom_command with the objects, you'll need smaller targets. Why do all of your sources have to be defined on a single object library? Just break them up:
set(SOURCES1 a.c b.c c.c d.c)
set(SOURCES2 w.c x.c y.c z.c)
add_library(s1_obj OBJECT ${SOURCES1})
add_library(s2_obj OBJECT ${SOURCES2})
add_executable(foo
$<TARGET_OBJECTS:s1_obj>
$<TARGET_OBJECTS:s2_obj>
)
add_custom_target(copy_all_objs
COMMAND ${CMAKE_COMMAND} -E make_directory ${OBJ_ROOT_DIR}/myobjects/
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_OBJECTS:s1_obj>
${OBJ_ROOT_DIR}/myobjects/
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_OBJECTS:s2_obj>
${OBJ_ROOT_DIR}/myobjects/
COMMAND_EXPAND_LISTS)
Notes
Actually, I typically recommend using real target names whenever possible in generator expressions.
With some targets — at least SHARED, STATIC, MODULE and ARCHIVE libraries, plus executables — the target name defines the default output file name. So, I get using a variable for the name. (Though, I did say default — it can be overridden with the OUTPUT_NAME target property, and often that's a better way to make filenames configurable. And it lets you keep static target names.)
But for targets like INTERFACE, OBJECT, and ALIAS libraries, the target name is meaningless — it's only used internally in the CMake code. There's no reason not to just hardcode it.
If you're doing this in a macro/function and the target name has to be in a variable, your best bet is probably to write the install() code as a quoted argument rather than a bracket argument, so that variables get evaluated immediately. Which means lots of fun escaping, for the things you don't want evaluated immediately. (Though you can lose the OBJECT_DEST variable, at least.):
install(CODE "
file(INSTALL
DESTINATION
\"\$\{CMAKE_INSTALL_PREFIX\}/${CMAKE_INSTALL_LIBDIR}\"
FILES
$<TARGET_OBJECTS:${LIBNAME_OBJ}>
)")
I designed RISCV32IM processor, and I used "riscv32-unknown-elf-gcc" to generate code for testing.
However, the PC(instruction memory address) value and data memory address of the generated code had arbitrary values. I used this command:
riscv32-unknown-elf-gcc -march=rv32im -mabi=ilp32 -nostartfiles test.c
Can I know if I can set the instruction and data memory address I want?
Thanks.
Thank you for answer.
I designed only HW, and this is my first time using the SW tool chain.
Even if my question is rudimentary, please understand.
The figure is the result of the "-v" option.
enter image description here
I can't modify the script file because I use riscv tool chain in DOCKER environment.
So, I tried to copy the script file (elf32lriscv.x), modify it.
I modified it to 0x10000 ==> 0x00000.
The file name of the copied script is "test5.x".
And it was executed as follows.
What am I doing wrong?
enter image description here
The riscv compiler is using the default linker script to place text and date section... .
If you add -v option to your command line riscv32-unknown-elf-gcc -v -march=rv32im -mabi=ilp32 -nostartfiles test.c, you will see the linker script used by collect 2 ( normally it will be -melf32lriscv . you can find the linker script in ${path_to_toolchain}/riscv32-unknown-elf/lib/ldscripts/ (the default one is .x).
You can also use riscv32-unknown-elf-ld --verbose like explained by #Frant. However , you need to be careful if the toolchain was compiled with enable multilib and you compile for rv64 but the default is rv32 or vice versa. It is not the case probably, but to be sure you can specify the arch with -A elf32riscv for an rv32.
To Set the addresses you can create your own linker script or copy and modify the default one. You can only modify the executable start like explained by #Frant or make more modification and place whatever you want where you want.
Once your own linker script ready you can pass it to the linker with -Wl,-T,${own_linker_script }. you command will be riscv32-unknown-elf-gcc -march=rv32im -mabi=ilp32 -nostartfiles test.c -Wl,-T,${own_linker_script }
How "${PROJECT_BINARY_DIR}/CMakeFiles/project.dir/", the place object files resulted from compilation will be placed on, can be un-hardcoded?
Going straightly to the problem, we have some tests that check objects resulted from compilation on harfbuzz cmake and we use a hardcoded string there but that doesn't seem right and I hope some ${} or $<> exist for that.
I'm afraid you're out of luck here. CMake keeps this as an internal implementation detail, by design.
I'd say it's unlikely to change, but if you want to be absolutely future-proof, you could use a workaround of creating a static library out of the object files and then manually unpacking it back into object files (using the appropriate archiver/librarian) as part of the test. If the object files are also used by another target, and linking to that static library wouldn't work for that target, you can make an object library out of the files and then use that in both the original target and the for-test static library.
Here's an example of how you might achieve this workaround:
add_library(MyObjectLib OBJECT src/a.cpp src/b.cpp)
add_executable(Main src/main.cpp $<TARGET_OBJECTS:MyObjectLib>)
add_library(LibForTesting STATIC $<TARGET_OBJECTS:MyObjectLib>)
add_test(
NAME check-static-inits.sh
COMMAND ${PROJECT_SOURCE_DIR}/src/prepare-and-check-static-inits.sh $<TARGET_FILE:LibForTesting>
)
And here's what the script prepare-and-check-static-inits.sh would look like (pseudo-code):
ar -x $1 -o some_dir
./check-static-inits.sh some_dir
Turning my comment into an answer
There is at the moment no variable or generator expression to get the list of object files used for linking a archive or library target.
But you could append compiler/archiver/linker calls with any program/script and utilize CMake's expansion rules inside those calls.
Note: That will only work CMake's Command-Line Build Tool Generators. And the list(APPEND ...) calls only have to be there once in your CMake code after your project() call.
Examples
Generate a symbolic link to <OBJECT_DIR> with <TARGET_NAME>
project(MyLib)
list(
APPEND CMAKE_CXX_ARCHIVE_FINISH
"\"${CMAKE_COMMAND}\" -E create_symlink \"<OBJECT_DIR>\" \"<TARGET_NAME>\""
)
[...]
add_library(MyLib STATIC src/a.cpp src/b.cpp)
Call some program to do something with the <OBJECTS> list (e.g. echo or write to a file)
project(MyExe)
list(
APPEND CMAKE_CXX_LINK_EXECUTABLE
"\"${CMAKE_COMMAND}\" -E echo \"<OBJECTS>\""
)
[...]
add_executable(MyExe main.cpp)
Directly do something after each object file is generated. In your case where you want to call objdump for each object file it would e.g. be:
list(
APPEND CMAKE_CXX_COMPILE_OBJECT
"${CMAKE_OBJDUMP} -t \"<OBJECT>\" > $(notdir <OBJECT>.dump)"
)
Unfortunately there is no expansion rule for "output file name" hence the platform/make specific trick with $(notdir ...).
References
CMAKE_<LANG>_ARCHIVE_FINISH
CMAKE_<LANG>_LINK_EXECUTABLE
CMAKE_<LANG>_COMPILE_OBJECT
How to get path to object files with CMake for both multiconfiguration generator and makefile based ones?
I have managed to build the Kicad 4.0.6 in Linux Mageia 5.1 with gcc version 4.9.2. I first manually fixed two wxWidgets 3.0.2 header files in the /usr/include/wx-3.0/wx/ directory: regex.h and features.h. Kicad then compiled successfully. With the native wx-3.0 headers, the compiler generated the error in pcbnew/netlist_reader.cpp due to the undefined variable wxRE_ADVANCED.
The features.h header checks if the macro WX_NO_REGEX_ADVANCED is defined. If yes, features.h UNdefines wxHAS_REGEX_ADVANCED macro, and defines it, if no. The macro wxHAS_REGEX_ADVANCED, in turn, is used in regex.h to determine if among the enum constants wxRE_ADVANCED = 1 is present. The standard prebuilt Mageia 5 packages wxgtku3.0_0 and lib64wxgtku3.0-devel that I installed with the use of Mageia's software manager urpmi from Mageia repository WX_NO_REGEX_ADVANCED is defined, therefore wxHAS_REGEX_ADVANCED is undefined, and, hence, wxRE_ADVANCED is undefined either. Kicad 4.0.6 source package assumes wxRE_ADVANCED = 1, therefore the build process stops with the error.
Then I reverted /usr/include/wx-3.0/wx/regex.h and features.h to their original state and learned how to add the definition of wxRE_ADVANCED to CMakeLists.txt. However, I still have a question.
The recommended format of adding the definition to CMakeLists.txt I found at CMake command line for C++ #define is this:
if (NOT DEFINED wxRE_ADVANCED)
set(wxRE_ADVANCED 1)
endif()
add_definitions(-DwxRE_ADVANCED=$(wxRE_ADVANCED))
However, it did not work! The macro expansion for wxRE_ADVANCED in pcbnew/netlist_reader.cpp was empty. I printed it at compile time inserting the following lines into the netlist_reader.cpp file (this was hard to find, most of the recommended formats did not work. The correct one is in C preprocessor: expand macro in a #warning):
#define __STRINGIFY(TEXT) #TEXT
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT)
#define WARNING(VALUE) __WARNING(__STRINGIFY(wxRE_ADVANCED = VALUE))
Pragma (WARNING(wxRE_ADVANCED))
Finally, I simplified the CMakeLists.txt definition down to this, and it was a success:
if (NOT DEFINED wxRE_ADVANCED)
set(wxRE_ADVANCED 1)
endif()
add_definitions(-DwxRE_ADVANCED=1)
My question: what is the meaning of "-DwxRE_ADVANCED=$(wxRE_ADVANCED)" if it does not work? Is it possible not to use set(wxRE_ADVANCED 1), and simply write add_definitions(-DwxRE_ADVANCED=1)? Thank you.
P.S. Yes, the Kicad 4.0.6 build process successfully finished with only one line added to the top level CMakeLists.txt file:
add_definitions(-DwxRE_ADVANCED=1)
A variable is called via $variable or ${variable}. Note the curly brackets, not parentheses.
Also, it is recommended to use:
target_compile_definitions(mytarget PUBLIC wxRE_ADVANCED=1)
on a target directly, rather than the general add_definitions() command.
Does the objective-c compiler in Xcode know better, or is it faster if I use bit shift for multiplications and divisions by powers of 2?
NSInteger parentIndex = index >> 1; // integer division by 2
Isn't this a bit 1980's? Don't processors run these instructions in the same time these days? I remember back in my 68000 days when a div was 100+ cycles and a shift only 3 or 4... not sure this is the case any more as processors have moved on.
Why don't you get the compiler to generate the assembler file and have a look what it's generating and run some benchmarks.
I found this on the web which may help you... although it's for 'C' I think most of the options will be the same.
Q: How can I peek at the assembly code generated by GCC?
Q: How can I create a file where I can see the C code and its assembly
translation together?
A: Use the -S (note: capital S) switch to GCC, and it will emit the assembly code to a file with a .s extension. For example, the following command:
gcc -O2 -S -c foo.c
will leave the generated assembly code on the file foo.s.
If you want to see the C code together with the assembly it was converted to, use a command line like this:
gcc -c -g -Wa,-a,-ad [other GCC options] foo.c > foo.lst
which will output the combined C/assembly listing to the file foo.lst.
If you need to both get the assembly code and to compile/link the program, you can either give the -save-temps option to GCC (which will leave all the temporary files including the .s file in the current directory), or use the -Wa,aln=foo.s option which instructs the assembler to output the assembly translation of the C code (together with the hex machine code and some additional info) to the file named after the =.