I'm trying to use CUDA code inside MATLAB mex, under linux. With the "whole program compilation" mode, it works good for me. I take the following two steps inside Nsight:
(1) Add "-fPIC" as a compiler option to each .cpp or .cu file, then compile them separately, each producing a .o file.
(2) Set the linker command to be "mex" and add "-cxx" to indicate that the type of all the .o input files are cpp files, and add the library path for cuda. Also add a cpp file that contains the mexFunction entry as an additional input.
This works good and the resulted mex file runs well under MATLAB. After that when I need to use dynamical parallelism, I have to switch to the "separate compilation mode" in Nsight. I tried the same thing above but the linker produces a lot of errors of missing reference, which I wasn't able to resolve.
Then I checked the compilation and linking steps of the "separate compilation" mode. I got confused by what it is doing. It seems that Nsight does two compilation steps for each .cpp or .cu file and produces a .o file as well as a .d file. Like this:
/usr/local/cuda-5.5/bin/nvcc -O3 -gencode arch=compute_35,code=sm_35 -odir "src" -M -o "src/tn_matrix.d" "../src/tn_matrix.cu"
/usr/local/cuda-5.5/bin/nvcc --device-c -O3 -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35 -x cu -o "src/tn_matrix.o" "../src/tn_matrix.cu"
The linking command is like this:
/usr/local/cuda-5.5/bin/nvcc --cudart static --relocatable-device-code=true -gencode arch=compute_35,code=compute_35 -gencode arch=compute_35,code=sm_35 -link -o "test7" ./src/cu_base.o ./src/exp_bp_wsj_dev_mex.o ./src/tn_main.o ./src/tn_matlab_helper.o ./src/tn_matrix.o ./src/tn_matrix_lib_dev.o ./src/tn_matrix_lib_host.o ./src/tn_model_wsj_dev.o ./src/tn_model_wsj_host.o ./src/tn_utility.o -lcudadevrt -lmx -lcusparse -lcurand -lcublas
What's interesting is that the linker does not take the .d file as input. So I'm not sure how it dealt with these files and how I should process them with the "mex" command when linking?
Another problem is that the linking stage has a lot of options I don't understand (--cudart static --relocatable-device-code=true), which I guess is the reason why I cannot make it work like in the "whole program compilation" mode. So I tried the following:
(1) Compile in the same way as in the beginning of the post.
(2) Preserve the linking command as provided by Nsight but change to use "-shared" option, so that the linker produces a lib file.
(3) Invoke mex with input the lib file and another cpp file containing the mexFunction entry.
This way mex compilation works and it produces a mex executable as output. However, running the resulted mex executable under MATLAB produces a segmentation fault immediately and crashes MATLAB.
I'm not sure if this way of linking would cause any problem. More strangely, I found that the mex linking step seems to finish trivially without even checking the completeness of the executable, because even if I miss a .cpp file for some function that the mexFunction will use, it still compiles.
EDIT:
I figured out how to manually link into a mex executable which can run correctly under MATLAB, but I haven't figured out how to do that automatically under Nsight, which I can in the "whole program compilation" mode. Here is my approach:
(1) Exclude from build the cpp file which contains the mexFunction entry. Manually compile it with the command "mex -c".
(2) Add "-fPIC" as a compiler option to each of the rest .cpp or .cu file, then compile them separately, each producing a .o file.
(3) Linking will fail because it cannot find the main function. We don't have it since we use mexFunction and it is excluded. This doesn't matter and I just leave it there.
(4) Follow the method in the post below to manually dlink the .o files into a device object file
cuda shared library linking: undefined reference to cudaRegisterLinkedBinary
For example, if step (2) produces a.o and b.o, here we do
nvcc -gencode arch=compute_35,code=sm_35 -Xcompiler '-fPIC' -dlink a.o b.o -o mex_dev.o -lcudadevrt
Note that here the output file mex_dev.o should not exist, otherwise the above command will fail.
(5) Use mex command to link all the .o files produced in step (2) and step (4), with all necessary libraries supplied.
This works and produces runnable mex executable. The reason I cannot automate step (1) inside Nsight is because if I change the compilation command to "mex", Nsight will also use this command to generate a dependency file (the .d file mentioned in the question text). And the reason I cannot automate step (4) and step (5) in Nsight is because it involves two commands, which I don't know how to put them in. Please let me know if you knows how to do these. Thanks!
OK, I figured out the solution. Here are the complete steps for compiling mex programs with "separate compilation mode" in Nsight:
Create a cuda project.
In the project level, change build option for the following:
Switch on -fPIC in the compiler option of "NVCC compiler" at the project level.
Add -dlink -Xcompiler '-fPIC' to "Expert Settings" "Command Line Pattern" of the linker "NVCC Linker"
Add letter o to "Build Artifact" -> "Artifact Extension", since by -dlink in the last step we are making the output a .o file.
Add mex -cxx -o path_to_mex_bin/mex_bin_filename ./*.o ./src/*.o -lcudadevrt to "Post Build Steps", (add other necessary libs)
UPDATE: In my actual project I moved the last step to a .m file in MATLAB, because otherwise if I do it while my mex program is running, it could cause MATLAB crash.
For files needs to be compiled with mex, change these build option for each of them:
Change the compiler to GCC C++ Compiler in Tool Chain Editor.
Go back to compiler setting of GCC C++ Compiler and change Command to mex
Change command line pattern to ${COMMAND} -c -outdir "src" ${INPUTS}
Several additional notes:
(1) Cuda specific details (such as kernel functions and calls to kernel functions) must be hidden from the mex compiler. So they should be put in the .cu files rather than the header files. Here is a trick to put templates involving cuda details into .cu files.
In the header file (e.g., f.h), you put only the declaration of the function like this:
template<typename ValueType>
void func(ValueType x);
Add a new file named f.inc, which holds the definition
template<>
void func(ValueType x) {
// possible kernel launches which should be hidden from mex
}
In the source code file (e.g., f.cu), you put this
#define ValueType float
#include "f.inc"
#undef ValueType
#define ValueType double
#include "f.inc"
#undef ValueType
// Add other types you want.
This trick can be easily generalized for templated classes to hide details.
(2) mex specific details should also be hidden from cuda source files, since the mex.h will alter the definitions of some system functions, such as printf. So including of "mex.h" should not appear in header files that can potentially be included in the cuda source files.
(3) In the mex source code file containing the entry mexFunction, one can use the compiler macro MATLAB_MEX_FILE to selectively compile code sections. This way th source code file can be compiled into both mex executable or ordinarily executable, allowing debugging under Nsight without matlab. Here is a trick for building multiple targets under Nsight: Building multiple binaries within one Eclipse project
First of all, it should be possible to set up Night to use a custom Makefile rather than generate it automatically. See Setting Nsight to run with existing Makefile project.
Once we have a custom Makefile, it may be possible to automate (1), (4), and (5). The advantage of a custom Makefile is that you know exactly what compilation commands will take place.
A bare-bones example:
all: mx.mexa64
mx.mexa64: mx.o
mex -o mx.mexa64 mx.o -L/usr/local/cuda/lib64 -lcudart -lcudadevrt
mx.o: mxfunc.o helper.o
nvcc -arch=sm_35 -Xcompiler -fPIC -o mx.o -dlink helper.o mxfunc.o -lcudadevrt
mxfunc.o: mxfunc.c
mex -c -o mxfunc.o mxfunc.c
helper.o: helper.c
nvcc -arch=sm_35 -Xcompiler -fPIC -c -o helper.o helper.c
clean:
rm -fv mx.mexa64 *.o
... where mxfunc.c contains the mxFunction but helper.c does not.
EDIT: You may be able achieve the same effect in the automatic compilation system. Right click on each source file and select Properties, and you'll get a window where you can add some compilation options for that individual file. For linking options, open Properties of the project. Do some experiments and pay attention to the actual compilation commands that show up in the console. In my experience, custom options sometimes interact with the automatic system in a weird way. If this method proves too troublesome for you, I suggest that you make a custom Makefile; this way, at least we are not caught by unexpected side-effects.
Related
I am currently learning STM32F103 with Eclipse. I am facing a problem in linker stage, that I got linker error : undefined reference to `HAL_TIM_Base_Init'
Building target: TimerTest.elf
Invoking: GNU ARM Cross C++ Linker
arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall -Wextra -g3 -T "C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\SW4STM32\WS2812_TimerTest\STM32F103C8Tx_FLASH.ld" -Xlinker --gc-sections -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Src" -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Drivers\STM32F1xx_HAL_Driver\Src" -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Drivers\STM32F1xx_HAL_Driver\Inc" -L"C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Inc" -Wl,-Map,"TimerTest.map" -Xlinker --cref --specs=nano.specs -o "TimerTest.elf" ./Src/WS2812.o ./Src/main.o ./Src/stm32f1xx_hal_msp.o ./Src/stm32f1xx_hal_tim.o ./Src/stm32f1xx_it.o ./Src/system_stm32f1xx.o ./Src/usb_device.o ./Src/usbd_cdc_if.o ./Src/usbd_conf.o ./Src/usbd_desc.o ./SW4STM32/startup_stm32f103xb.o ./Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.o ./Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.o ./Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.o ./Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.o ./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.o
./Src/WS2812.o: In function `WS2812Init':
C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Debug/../Src/WS2812.c:30: undefined reference to `HAL_TIM_Base_Init'
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:64: TimerTest.elf] Error 1
Here is my code:
main.c
#include "main.h"
#include "WS2812.h"
#include "stm32f1xx_hal.h"
#include "usb_device.h"
int main(void)
{
WS2812Init();
while (1)
{
}
}
WS2812.h:
#ifndef INC_WS2812_H_
#define INC_WS2812_H_
#include <stm32f1xx_hal_gpio.h> // use gpio output
#include <stm32f1xx_hal_rcc.h>
#include <stm32f1xx_hal_tim.h> // use timer
// adopt gpio port & pin for following section
#define WS2812_GPIO_PORT GPIOB
#define WS2812_GPIO_PIN GPIO_PIN_12
#define ENABLE_GPIO_RCC() do{\
if(!__HAL_RCC_GPIOB_IS_CLK_ENABLED())\
__HAL_RCC_GPIOB_CLK_ENABLE();\
}while(0U)
static GPIO_InitTypeDef SW2812Pin = {
.Pin = WS2812_GPIO_PIN,
.Speed = GPIO_SPEED_FREQ_LOW,
.Mode = GPIO_MODE_OUTPUT_PP
};
#define SYS_CLOCK
// adopt timer configuration for following section
#define WS2812_SELECTED_TIMER TIM4
static TIM_HandleTypeDef ws2812TimerConfig;
void WS2812Init(void);
#endif /* INC_WS2812_H_ */
WS2812.c:
#include "WS2812.h"
void WS2812Init(void)
{
// init GPIO as output
ENABLE_GPIO_RCC();
HAL_GPIO_WritePin(WS2812_GPIO_PORT, WS2812_GPIO_PIN, GPIO_PIN_RESET);
HAL_GPIO_Init(WS2812_GPIO_PORT, &SW2812Pin);
// init timer
uint16_t targetFrequency = 1000; // 1kHz
const uint16_t preScaler = 360;
const uint16_t period = SystemCoreClock / (preScaler*targetFrequency);
// clear status register
__HAL_RCC_TIM4_CLK_ENABLE();
ws2812TimerConfig.Instance = WS2812_SELECTED_TIMER;
ws2812TimerConfig.Init.Prescaler = preScaler - 1;
ws2812TimerConfig.Init.Period = period;
ws2812TimerConfig.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&ws2812TimerConfig); // <- linker can not find this function
__HAL_TIM_ENABLE(&ws2812TimerConfig);
}
This is my include structure:
main->
include"WS2812.h" ->
include stm32f1xx_hal_tim.h
The stm32f1xx_hal_tim.h is in the STM32F1xxHAL_DRIVER->inc, which is also put in the include path.
I also have added the include path in the project properties->C/C++ Build->Settings
for
GNU ARM Cross Assembler
GNU ARM Cross C compiler
GNU ARM Cross C++ Compiler
I searched in the internet found out this is a linker issue, that the linker can not find the proper source for linking.
What I have found in internet and tried:
added the folder which contents stm32f1xx_hal_tim.h and WS2812.h to project properties-> C/C++ Build -> GNU ARM Cross C++ Linker -> Libraries -> (-L)
added the folder which contents stm32f1xx_hal_tim.c and WS2812.c to project properties-> C/C++ Build -> GNU ARM Cross C++ Linker -> Libraries -> (-L)
Checked "stm32f1xx_hal_tim.h" -> property-> Exclude resource from build is unchecked (some people in the internet solved the problem by this)
Added "--specs=nano.specs" to the Linker options
All of above do not solve the problem.
Some people suggest to modify the makefile. But the project generate the makefile automatically, so I don't know where to start.
If anyone can provide a hint or solution, it will be very thanksful.
UPDATE 1:
Thanks Jacek Ślimok's input.
I didn't know that, I also need to doe the "exclude from build" for .c files. And I check in the file browser. The .c files are not check in this configuration. Do you mean like this?
excluded from Build
The stm32f1xx_hal_tim.c is under project->Driver->STM32F1xxHAL_Driver->Src
At this moment, the problem remains unsolved.
Another thing I noticed is that, the Eclipse read my stm32f1xx_hal_tim.c differently. When I open the stm32f1xx_hal_tim.c in Eclipse, it just give me a plane text like in normal notepad:
stm32f1xx_hal_tim.c
But other .c file like stm32f1xx_hal_gpio.c looks like normal.
stm32f1xx_hal_gpio.c
They are in the same folder. I don't know where and why this difference came from. Does this relative to my problem.
Update2
#Jacek Ślimok, I found out why the eclipse see the stm32f1xx_hal_tim.c as plane text. I accidentally turned on the Scalability setting in Preference-> Editor, stm32f1xx_hal_tim.c has relatively large file size, 161kB. After I change it back to default, Eclipse shows the file as normal. But the linker problem is still there...
In the main.c I also used HAL_GPIO_TogglePin() from stm32f1xx_hal_gpio.h/.c. The linker does not complain about that. Currently I can not tell the difference between these 2 files(stm32f1xx_hal_gpio and stm32f1xx_hal_tim) They are in the same folder, and included the same as well. But I can use the function for GPIO not for Timer.
But one thing can be sure:
I can use the macro in the stm32f1xx_hal_tim.h, so this is a linker problem.
I start this project base on another project, which was generated from STM32CubeMX. To practice the timer function I added the timer config to it, this is the point I got problem with the linker.
I hope these information can lead to more hints.
Update 3
I tried build the .c files separately
For stm32f1xx_hal.h.c:
00:09:16 **** Building Selected Files of configuration Release for project TimerTest ****
Info: Internal Builder is used for build
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wall -Wextra -g -DSTM32F103xB -DHSE_VALUE=8000000 "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Device\\ST\\STM32F1xx\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\STM32F1xx_HAL_Driver\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Class\\CDC\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Core\\Inc" -std=gnu11 -c -o "Drivers\\STM32F1xx_HAL_Driver\\Src\\stm32f1xx_hal_tim.o" "..\\Drivers\\STM32F1xx_HAL_Driver\\Src\\stm32f1xx_hal_tim.c"
00:09:17 Build Finished (took 285ms)
For WS2812.c:
00:11:23 **** Building Selected Files of configuration Release for project TimerTest ****
Info: Internal Builder is used for build
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wall -Wextra -g -DSTM32F103xB -DHSE_VALUE=8000000 "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Device\\ST\\STM32F1xx\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\STM32F1xx_HAL_Driver\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Class\\CDC\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Core\\Inc" -std=gnu11 -c -o "Src\\WS2812.o" "..\\Src\\WS2812.c"
00:11:23 Build Finished (took 275ms)
And for Main.c:
00:12:02 **** Building Selected Files of configuration Release for project TimerTest ****
Info: Internal Builder is used for build
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wall -Wextra -g -DSTM32F103xB -DHSE_VALUE=8000000 "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\CMSIS\\Device\\ST\\STM32F1xx\\Include" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Drivers\\STM32F1xx_HAL_Driver\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Class\\CDC\\Inc" "-IC:\\Users\\Gebruiker\\Dropbox\\CodeBase\\Eclipse\\TimerTest\\Middlewares\\ST\\STM32_USB_Device_Library\\Core\\Inc" -std=gnu11 -c -o "Src\\main.o" "..\\Src\\main.c"
..\Src\main.c: In function '_Error_Handler':
..\Src\main.c:268:27: warning: unused parameter 'file' [-Wunused-parameter]
void _Error_Handler(char *file, int line)
^~~~
..\Src\main.c:268:37: warning: unused parameter 'line' [-Wunused-parameter]
void _Error_Handler(char *file, int line)
^~~~
In file included from ..\Src\main.c:55:0:
At top level:
C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Inc/WS2812.h:36:26: warning: 'ws2812TimerConfig' defined but not used [-Wunused-variable]
static TIM_HandleTypeDef ws2812TimerConfig;
^~~~~~~~~~~~~~~~~
C:\Users\Gebruiker\Dropbox\CodeBase\Eclipse\TimerTest\Inc/WS2812.h:26:25: warning: 'SW2812Pin' defined but not used [-Wunused-variable]
static GPIO_InitTypeDef SW2812Pin = {
^~~~~~~~~
00:12:02 Build Finished (took 272ms)
There are few warning in the main.c, but they are not crucial.
Update4:
Thanks for Jacek Ślimok's input:
I found out that functions of stm32f1xx_hal_tim.c shows gray in file browser.
functions seems like not usable
But the functions in stm32f1xx_hal_gpio.c shows solid balck.
function in gpio.c are usable
Now the difference is there, just need to find out why.
Thanks in advance.
Best regards.
Doing #include stm32f1xx_hal_tim.h is not enough - it only causes your compiler not to complain, linker will still have a problem. Neither is adding a search path for the linker - this one you use mainly when you have static pre-compiled libraries that you explicitly link with the -l option. HAL is not a static library but rather a library you compile yourself.
To solve your problem, make sure you compile the corresponding source files - in this case stm32f1xx_hal_tim.c file and that it's later being linked. You mention that you use Eclipse and by default it generates a Makefile that causes all source files that you compiled in your project to also be linked. Therefore you mainly should check whether stm32f1xx_hal_tim.c is being compiled. One way to do that is to find the file in the Project Explorer, rightclick on it and select Resource Configurations -> Exclude from Build.... Make sure it's NOT checked. If it is, it is likely a whole directory is excluded from build which it should not be.
Another possibility is given function not being defined in any source file that is compiled or the function signature (name, return type and parameter types) don't match.
Yet another possibility (which in this case turned out to be the source of the issue) is that a portion of the file may not be compiled due to a #if/#ifdef preprocessor directive. In the OP's case this was caused by HAL_TIM_MODULE_ENABLED being undefined.
It is not relative to linker issue, but pre-processor.
As I mentioned, that I am building this code based on a project, which was generated from cubeMX. In the previous project, there is no timer used or configured. Than I started to write timer configuration. What I forgot is that to uncomment the #define HAL_TIM_MODULE_ENABLED in stm32f1xx_hal_conf.h. Which blocked all the implementation in stm32f1xx_hal_tim.c by pre-processor.
That is why eclipse shows all the function in stm32f1xx_hal_tim.c as gray color and not be able to be referenced.
And anyway, thanks Jacek Ślimok's effort!
Agree with Jacek Slimok, had this problem a while back, and for some reason I keep forgetting how to fix it. Googling the same solution every time if becoming annoying.
Just Skip to Solution
So you hit ctrl+space and autocomplete locates the function you want to call.
Yet in build, errors show up as "undefined reference to YOUR_FUNCTION_NAME".
So, you compile dependencies to become object files, but link object files to form an executable "firmware" generated by the compiler.
The "undefined reference" function called in main supposed to come from an object file which the linker can't locate.
Eclipse has a feature that allows you to exclude certain files from being "built" into object files. Thus the linker can't locate that dependency.
Solution:
This works for added folders or individual files in Eclipse.
So you have .c and .h files you created and you sometimes lump them in a folder you added to eclipse.
Right-click that added folder and hit properties.
In left menu select "Settings" under "C/C++ Build".
On the right, uncheck "Exclude resource from build".
Link to the picture below.
Folder Properties window in Eclipse:
Hope that helps everyone, and myself when I forget in a few days. Can you imagine the shock when I see my name on this post?
I have to merge one of my app's libs with the NVIDIA CUDA static lib using this horrific awful CMake code:
GET_TARGET_PROPERTY(OUTPUT_LIB ${LIBNAME} LOCATION)
add_custom_command (TARGET ${LIBNAME}
POST_BUILD
COMMAND mv ${OUTPUT_LIB} ${OUTPUT_LIB}.old
COMMAND echo "create ${OUTPUT_LIB}" > combineLibs.mri
COMMAND echo "addlib ${OUTPUT_LIB}.old" >> combineLibs.mri
COMMAND echo "addlib ${CUDA_LOCATION}" >> combineLibs.mri
COMMAND echo "save" >> combineLibs.mri
COMMAND echo "end" >> combineLibs.mri
COMMAND ar -M <combineLibs.mri
COMMAND rm ${OUTPUT_LIB}.old
COMMENT "Building merged library for ${LIBNAME} at ${OUTPUT_LIB}, including ${CUDA_LOCATION}"
)
target_link_libraries(${LIBNAME} -pthread -c)
This successfully produces a merged static library that has all the symbols in it. However, the NVIDIA CUDA static lib brought with it dependencies on libpthread and libc in the form of unresolved symbols. Now the merged library also has those unresolved symbols, and the target_link_libraries line doesn't seem to do what I seem to think it does, because the symbols don't get resolved at link-time. How do I get the merged static library to dynamically link against libpthread and libc?
The the target_link_libraries line does indeed not do what you think.
target_link_libraries(target,options) can have the desired effect of
adding the linker options options to the linkage of target only if target
is something that is produced by the linker. If no linkage happens in the
production of target then this directive will have no effect.
Your target is a static library. A static library - unlike a program, and unlike
a dynamic/shared library - is not produced by the linker. As your custom_command
in fact illustrates, a static library is produced by the GNU general purpose archiver,
ar. It is nothing but an archive of files which happen to be object files,
but as far as ar is concerned they might as well be the contents of your
Documents, Pictures and Music folders. Since no linkage is involved in the
production of a static library, nothing can be linked with a static library.
An ar archive can be used as a linker input in the linkage of something that
is produced by the linker - a program or a shared library. In that case the
linker will look into the archive to see if contains any object files it needs
to carry on the linkage. If it finds any, it will extract them from the archive
and link them into the program. The linkage will be exactly the same as if
you had listed the required object files in the linker commandline and not
mentioned the archive at all.
But if any of the object files that the linker extracts from an archive bring
with them undefined references, then to get them resolved you must link some
library or libraries that define those references in the linkage of the
program or shared library that you want the linker to produce - just as you
must do to resolve undefined references in any other object files you
input to the linkage.
So,
How do I get the merged static library to dynamically link against libpthread and libc?
You can't. It doesn't make sense. Any library dependencies of object files
in a static library can be satisfied only in the linkage of a program or shared library
that has acquired those dependencies by linking those object files.
Finally, -c is not a GCC linkage option that will have the effect of requesting
linkage of libc. It is not a linkage option at all. It is an option that
directs the GCC frontend not to invoke the linker. It is passed to GCC to
request compilation without linkage, and the perverse effect of including it in a
CMake target_link_libraries directive will be to stop any linkage of the
target from happening.
If you want to explicitly request linkage of libc, use -lc, following
the linker usage protocol that -lname requests linkage of libname.
Perhaps you inferred that -c requests linkage of libc from the assumption
that -pthread requests linkage of libpthread. In fact, -lpthread would
request linkage of libpthread. The option -pthread is a more abstract GCC
option, for both compilation and linkage, that means do the right things, for this platform, to link with the Posix Threads
library - which might entail passing -lpthead to the linker, and possibly not.
Thus -pthread is OK as an argument of target_link_libraries that will
have the effect of requesting Posix Threads linkage, but see
answers to cmake and libpthread
for CMake-proper ways of doing this.
I use Eclipse + ARM plugin to build my projects. When I needed to use in my project the StemWin library, I configured my IDE to use external library.
I set
Preferences -> C/C++ General -> Paths and Symbols
I added in "Library Paths" the link to my folder includes library.
I also added the name of my library in tab "Library".
I checked the settings in the compiler tab and I ascertained all should be good.
When I tried to build my project I got an error from linker:
cannot find -lMyLib.a Hello C/C++ Problem
I double checked the name of my library and link, all are correct. This is the output of my linker:
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -L"C:\lib"
-T"C:\arm_toolchain\stm32_workspace\Hello\LinkerScript.ld" -Wl,
-Map=output.map -Wl,--gc-sections -o "Hello.elf" #"objects.list" -lMyLib.a
What should I do from here?
I faced the same problem before.
-l:STemWin526_CM4_GCC.a
-L"C:\Edu_Workspace\STM32F4\stm32f4_bsp_template\Drivers\Middlewares\ST\STemWin\Lib"
Above are my working settings.
With -l:<archive file name> the colon : is important for archive file linking.
And -L will contain library path.
Also for stemwin make sure to compile with hardware floating point
-mfloat-abi=hard -mfpu=fpv4-sp-d16
the convention for the -l option of the linker (say you give -lMyLib.a as a linker option) is to search for a library file with "lib" prepended to the given name and .a (or .so) appended, i.e. your command line searches for a file libMyLib.a.{a,so} which is probably not how it's named.
Either you rename your library according to this convention or give it to the linker command line omitting -l (provided your IDE allows you to do so).
Looks like the problem is in -lMyLib.a which means you're trying to link a static library as a dynamic one.
To link a static lib you have to use its path as with ordinary .o files: ... /path/to/MyLib.a
and the resulting command line should look something like
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -L"C:\lib" -T"C:\arm_toolchain\stm32_workspace\Hello\LinkerScript.ld" -Wl,-Map=output.map -Wl,--gc-sections -o "Hello.elf" #"objects.list" /path/to/MyLib.a
UPDATE:
Although it might fix the issue, turns out it's not true:
-llibrary
-l library
...
Normally the files found this way are library files—archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories.
(https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html)
i build a project on Eclipse using GCC Toolchain and arm-linux-gnueabi libraries
i have tow main issues using this codes attached (not my code, fft from ffmpeg with testcode to measure speed-error)
http://e2e.ti.com/cfs-file/__key/telligent-evolution-components-attachments/00-447-01-00-00-25-97-76/FFMPEG_5F00_FFT.zip
i have a C-code files with 2 .S files asm.S and neon_fft.S
i am not a software engineer but i understood that i use function keyword from asm.S file to use it in neon_fft.S
but it seems that project doesn't see the first file so i get the following error
Building file: ../src/fft_neon.S
Invoking: GCC Assembler
arm-linux-gnueabi-as -mcpu=cortex-a8 -mfpu=neon -I/usr/arm-linux-gnueabi/include -I/usr/arm-linux-gnueabi/include/asm -o "src/fft_neon.o" "../src/fft_neon.S"
../src/fft_neon.S: Assembler messages:
../src/fft_neon.S:34: Error: bad instruction `function fft4_neon'
../src/fft_neon.S:50: Error: bad instruction `endfunc'
also how can i get right configure.h file ?
The filename ends with a capital S. By convention, this indicates that the assembler source needs to be processed by the C preprocessor. If you use arm-linux-gnueabi-gcc instead of arm-linux-gnueabi-as then the file should assemble successfully.
I am having some issues in compiling using mex this software http://www.cmap.polytechnique.fr/~aspremon/ZIP/COVSEL.zip. When I use mex and give it the files to compile it shows the following error
error: 'CblasColMajor' undeclared (first use in this function)
I am compiling the mex file from matlab and in Mac LionOS. Any suggestions
I am using the following code to compile
mex BoxQP.c BoxQP_mex.c utils.c
Make sure the MACVERSION macro is defined, or define it yourself. It looks like the CblasColMajor enum is defined in the cblas.h file which is included on line 18 of BoxQP.h. So I'm guessing that you either need to install the cblas library or it's there by default on OSX. Here's what I had to use to compile it on Win32:
mex -v -g BoxQP_mex.c BoxQP.c utils.c -LC:\MATLAB\R2009bSP1\extern\lib\win32\microsoft -lmwblas
HTH, might want to include the line you're using to compile it if you can't figure it out.
EDIT
You'll need to find the library path for the Matlab install and then under that directory you'll need to look for extern\lib\ then look for your platform and library type like, extern\lib\linux\maxos I'm not sure what it will look like, but that's a guess. also, include the Mathworks BLAS library using, -lmwblas.