I am working on windows with mingw and CMake.
Someone provide a library with lib, dll and header files. I am able to use it quite easily in Visual Studio projects. But I was not able to integrate it into a CMake project. There are already a lot of questions about this topic but only working for Linux, or with library build with CMake, or library where sources are available, or the same use case as me but with a lot of erratum in comments saying that the answer is never completely correct...
I would like to use the foo_function from the foo library in my bar project. I don't have the source of this foo project. Only a dll, lib and header file.
BarProject
├───
├─── CMakeLists.txt
├─── Foo
├─── include
└─── foo.h
├─── x64
|─── foo.dll
└─── foo.lib
└─── main_bar.c
This is the content of my CmakeLists.txt file :
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(bar VERSION 1.0)
# add the executable
add_executable(bar main_bar.c)
target_include_directories(bar PUBLIC "${PROJECT_BINARY_DIR}" "foo/include")
add_library(foo SHARED IMPORTED)
set_property(TARGET foo PROPERTY
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/Foo/x64/foo.dll")
set_property(TARGET foo PROPERTY
IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/Foo/x64/foo.lib")
target_link_libraries(bar PRIVATE foo)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_SUPPRESS_REGENERATION true)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT bar)
Finally to test my work :
$ ls
main_bar.c CMakeLists.txt Foo
$ mkdir tutu
$ cd tutu
$ cmake .. && cmake --build . -v
-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19044.
-- The C compiler identification is MSVC 19.29.30145.0
-- The CXX compiler identification is MSVC 19.29.30145.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
(...)
cl /c /IC:\Users\lambe\work\repository\bar\tutu /IC:\Users\lambe\work\repository\bar\. /IC:\Users\lambe\work\repository\bar\Foo\include/Wall /WX /diagnostics:column /Od /D _MBCS /D WIN32 /D _WINDOWS /D STAND_ALONE /D "CMAKE_INTDIR=\"Debug\"" /Gm- /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"bar.dir\Debug\\" /Fd"bar.dir\Debug\vc142.pdb" /external:W4 /Gd /TC /wd4996 /wd4820 /wd5045 /wd4668 /errorReport:queue C:\Users\lambe\work\repository\bar\main_bar.c
main_bar.c
Generating Code...
Link:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\Users\lambe\work\repository\bar\tutu\Debug\bar.exe" /INCREMENTAL /ILK:"bar.dir\Debug\bar.ilk" /NOLOGO ..\Foo\x64\foo.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:/Users/lambe/work/repository/bar/tutu/Debug/bar.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"C:/Users/lambe/work/repository/bar/tutu/Debug/bar.lib" /MACHINE:X64 /machine:x64 bar.dir\Debug\main_bar.obj
bar.dir\Debug\main_bar.obj
main_bar.obj : error LNK2019: unresolved external symbol foo_function referenced in function main [C:\Users\lambe\work\repository\bar\tutu\bar.vcxproj]
C:\Users\lambe\work\repository\bar\tutu\Debug\bar.exe : fatal error LNK1120: 1 unresolved externals [C:\Users\lambe\work\repository\bar\tutu\bar.vcxproj]
The compilation step is working great, the issue is during the linking step.
EDIT:
Ok after the comment from Ben Voigt, I choose to explore the solution to use the gcc/g++ compiler from mingw instead of using the CL/Visual Studio thing.
The new test procedure :
$ cmake .. -G "MinGW Makefiles" && cmake --build . -v
(...)
C:\MinGW\bin\gcc.exe -DSTAND_ALONE #CMakeFiles/bar.dir/includes_C.rsp -MD -MT CMakeFiles/bar.dir/main_bar.c.obj -MF
CMakeFiles\bar.dir\main_bar.c.obj.d -o CMakeFiles\bar.dir\main_bar.c.obj -c C:\Users\lambe\work\repository\bar\main_bar.c
[100%] Linking C executable bar.exe
"C:\Program Files\CMake\bin\cmake.exe" -E cmake_link_script CMakeFiles\bar.dir\link.txt --verbose=1
"C:\Program Files\CMake\bin\cmake.exe" -E rm -f CMakeFiles\bar.dir/objects.a
C:\MinGW\bin\ar.exe qc CMakeFiles\bar.dir/objects.a #CMakeFiles\bar.dir\objects1.rsp
C:\MinGW\bin\gcc.exe -Wl,--whole-archive CMakeFiles\bar.dir/objects.a -Wl,--no-whole-archive -o bar.exe -Wl,--out-implib,libbar.dll.a -Wl,--major-image-version,0,--minor-image-version,0 #CMakeFiles\bar.dir\linklibs.rsp
CMakeFiles\bar.dir/objects.a(main_bar.c.obj):main_bar.c:(.text+0x4f4e): undefined reference to `foo_function'
collect2.exe: error: ld returned 1 exit status
CMakeFiles\bar.dir\build.make:830: recipe for target 'bar.exe' failed
mingw32-make.exe[2]: *** [bar.exe] Error 1
mingw32-make.exe[2]: Leaving directory 'C:/Users/lambe/work/repository/bar/test'
CMakeFiles\Makefile2:81: recipe for target 'CMakeFiles/bar.dir/all' failed
mingw32-make.exe[1]: *** [CMakeFiles/bar.dir/all] Error 2
mingw32-make.exe[1]: Leaving directory 'C:/Users/lambe/work/repository/bar/test'
Makefile:89: recipe for target 'all' failed
mingw32-make.exe: *** [all] Error 2
Ok the result is the same but at least, the command line and tools are more familiar for me.
I cannot find any reference to the foo library in the command line. Then I check the file linklibs.rsp and here we are :
$ cat CMakeFiles/bar.dir/linklibs.rsp
-lm *Foo/x64/foo.lib* -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
Is it the expected result?
Related
I'm using automake to build my project. I have some third-party (open source) libraries as git submodules in my project that I want to individually build and link. Here's an edited (names changed) version of my Makefile.am:
lib_LTLIBRARIES = libfoo.la libbar.la
libbar_la_SOURCES = ../submodules/bar/bar.c
libfoo_la_LIBADD = libbar.la
libfoo_la_SOURCES = \
some_source.c \
some_other_source.c
libfoo_la_CFLAGS = $(CFLAGS)
libfoo_la_LDFLAGS = $(LIBS)
if OS_LINUX
libfoo_la_SOURCES += \
linux/some_source.c \
linux/some_other_source.c
libfoo_la_CFLAGS += $(PTHREAD_CFLAGS)
libfoo_la_LDFLAGS += $(PTHREAD_LIBS)
endif
if OS_WINDOWS_MSYS
libfoo_la_SOURCES += \
nt/some_source.c \
nt/some_other_source.c
libfoo_la_LDFLAGS += -no-undefined
endif
bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = libfoo.la
autoreconf, configure and make run normally but make install fails with
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
It seems autoconf is trying to use libbar as a global, installed library instead of a local one? LDADD on the main target works fine though.
autoreconf -V outputs
autoreconf (GNU Autoconf) 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
License GPLv3+/Autoconf: GNU GPL version 3 or later
<https://gnu.org/licenses/gpl.html>, <https://gnu.org/licenses/exceptions.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by David J. MacKenzie and Akim Demaille.
EDIT: I am on Linux. Don't mind the windows parts.
I tried to reproduce this on https://github.com/ndim/stackoverflow-q70584133 by basically copying the Makefile.am you have given and adding a few very basic source files.
I found that building on Linux for Linux (Fedora 35, autoconf 2.69-37, automake 1.16.2-5, libtool 2.4.6-42) worked fine. Also running the make installed result:
[user#host stackoverflow-q70584133]$ mkdir _b-host && cd _b-host
[user#host _b-host]$ ../configure --prefix=$PWD/_i
[user#host _b-host]$ make && make install && ./_i/bin/main
[...]
main: x86_64-pc-linux-gnu
foo_func
bar_func
foo_host_func: Linux 331524 = 0x50f04 = 5.15.4 (5.15.4)
[user#host _b-host]$ _
So if you have problems building on and for Linux, something else must be off.
I presume you have run make distclean and then re-run autoreconf and configure to make sure your buildsystem and source tree and build tree are in a well defined state.
However, building on Fedora 35 for Windows (both 32 and 64bit) failed for me when building libbar.la without -no-undefined:
/bin/sh ../libtool --tag=CC --mode=link i686-w64-mingw32-gcc -g -O2 -o libbar.la -rpath /home/user/stackoverflow-q70584133/_b-w32/_i/lib ../bar/libbar_la-bar.lo
libtool: warning: undefined symbols not allowed in i686-w64-mingw32 shared libraries; building static only
libtool: link: i686-w64-mingw32-ar cru .libs/libbar.a ../bar/libbar_la-bar.o
libtool: link: i686-w64-mingw32-ranlib .libs/libbar.a
libtool: link: ( cd ".libs" && rm -f "libbar.la" && ln -s "../libbar.la" "libbar.la" )
/bin/sh ../libtool --tag=CC --mode=link i686-w64-mingw32-gcc -g -O2 -no-undefined -o libfoo.la -rpath /home/user/stackoverflow-q70584133/_b-w32/_i/lib foo/libfoo_la-foo.lo foo/libfoo_la-foo-nt.lo libbar.la
*** Warning: This system cannot link to static lib archive libbar.la.
*** I have the capability to make that library automatically link in when
*** you link to this library. But I can only do this if you have a
*** shared version of the library, which you do not appear to have.
libtool: link: i686-w64-mingw32-gcc -shared foo/.libs/libfoo_la-foo.o foo/.libs/libfoo_la-foo-nt.o -g -O2 -o .libs/libfoo-0.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker .libs/libfoo.dll.a
/usr/lib/gcc/i686-w64-mingw32/11.2.1/../../../../i686-w64-mingw32/bin/ld: foo/.libs/libfoo_la-foo.o: in function `foo_func':
/home/user/stackoverflow-q70584133/_b-w32/src/../../src/foo/foo.c:10: undefined reference to `bar_func'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:521: libfoo.la] Error 1
Adding a line to Makefile.am like
libbar_la_LDFLAGS += -no-undefined
fixed the linking for Windows problem and made the whole thing build and run (built on Linux, run on Linux using wine):
[user#host stackoverflow-q70584133]$ mkdir _b-w64 && cd _b-w64
[user#host _b-w64]$ ../configure --host=x86_64-w64-mingw32 --prefix=$PWD/_i
[user#host _b-w64]$ make && make install && ./_i/bin/main.exe
[...]
main: x86_64-w64-mingw32
foo_func
bar_func
foo_host_func: Windows 0x0a00 = 10.0
[user#host _b-w64]$ _
(And BTW, LIBS and _LIBS type variables should probably be added to a _LIBADD or _LDADD variable, not to a _LDFLAGS variable.)
UPDATE
Building on Debian 10 (autoconf 2.69-11, automake 1:1.16.1-4, libtool 2.4.6-9), does produce a linker error when main_LDADD is missing libbar.la and src/main.c calls the bar_func() function from libbar (uncomment the #define in src/main.c to reproduce):
[user#host _b-host]$ make
[...]
/bin/bash ../libtool --tag=CC --mode=link gcc -g -O2 -o main main-main.o libfoo.la
libtool: link: gcc -g -O2 -o .libs/main main-main.o ./.libs/libfoo.so -pthread -Wl,-rpath -Wl,/home/user/stackoverflow-q70584133/_b-host/_i/lib
/usr/bin/ld: main-main.o: undefined reference to symbol 'bar_func'
/usr/bin/ld: //home/user/stackoverflow-q70584133/_b-host/src/.libs/libbar.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:525: main] Error 1
make[1]: Leaving directory '/home/user/stackoverflow-q70584133/_b-host/src'
make: *** [Makefile:390: all-recursive] Error 1
[user#host _b-host]$ _
However, after removing the direct calls to libbar's bar_func() from src/main.c, the make command will work again, as does make install:
[user#host _b-host]$ make install && ./_i/bin/main
main: x86_64-pc-linux-gnu
foo_func
bar_func
foo_host_func: Linux 267216 = 0x413d0 = 4.19.208
[user#host _b-host]$ _
This suggests that calling a function from libbar from a linking unit without explicitly linking that unit against libbar is an error, and that does make sense.
So I still cannot reproduce OP's report of make working but make install failing. OP is using newer autoconf (2.71) than I do (2.69). Perhaps OP is using different automake/libtool versions as well with different set of bugs (dpkg -l autoconf automake libtool, rpm -q autoconf automake libtool, etc.)?
This question already has answers here:
CMake link to external library
(6 answers)
Closed 2 years ago.
I created a dynamic lib using Rust (crate type = "cdylib"). Rust/Cargo produced two files: text_loading_lib.dll and text_loading_lib.dll.lib. I want to build a really simple project (hello_world.c) on Windows that uses a function from this lib using only MSVC (the Microsoft Visual C++ toolset) and JetBrains CLion/CMake.
main.c
#include <stdio.h>
typedef unsigned long long usize_t; // 64 bit / usize on 64 bit machine
extern void show_loading_animation_ffi(usize_t, usize_t, int, usize_t (*prog_fn)());
// function that tells the lib how many percent progress we made so far
usize_t progress_reporter() { return (usize_t) 20 }
int main(void) {
show_loading_animation_ffi(0, 100, TARGET_STDERR, progress_reporter);
return 0;
}
I'm familiar with this process on UNIX, but I have no clue how it is done on Windows. On UNIX, I'd link the shared object against main.c during compilation and provide its location using LD_LIBRARY_PATH at runtime. Is is similar on Windows?
I also tried it with a CMAKE project using JetBrains CLion, but still no success. When I try to run main() in main.c from CLion, there are always errors that the target can't be created. The library files created with Rust (text_loading_lib.dll and text_loading_lib.dll.lib) are in the same directory as CMakeLists.txt and main.c.
CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(main C)
set(CMAKE_C_STANDARD 11)
add_executable(main main.c)
# the path is correct
target_link_libraries(main text_loading_animation)
#also tried: target_link_libraries(main text_loading_animation.dll)
#also tried: target_link_libraries(main text_loading_animation.dll.lib)
CLion-Output is:
[ 50%] Linking C executable main.exe
LINK Pass 1: command "C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1426~1.288\bin\Hostx64\x64\link.exe /nologo #CMakeFiles\main.dir\objects1.rsp /out:main.exe /implib:main.lib /pdb:C:\dev\lib-text-loading-animation-rust\calling-from-c-examples\windows\cmake-build-debug\main.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console text_loading_animation.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\main.dir/intermediate.manifest CMakeFiles\main.dir/manifest.res" failed (exit code 1104) with the following output:
LINK : fatal error LNK1104: File "text_loading_animation.lib" can't be opened.
NMAKE : fatal error U1077: ""C:\Program Files\JetBrains\CLion 2020.1.1\bin\cmake\win\bin\cmake.exe"": Return-Code "0xffffffff"
Stop.
NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\nmake.exe"": Rückgabe-Code "0x2"
Stop.
NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\nmake.exe"": Rückgabe-Code "0x2"
Stop.
NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\nmake.exe"": Rückgabe-Code "0x2"
Stop.
I got it working with CMake as well as the Command Line.
Cmake: CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(main C)
set(CMAKE_C_STANDARD 11)
add_executable(main main.c)
# "*.dll.lib" - important! not just *.dll
target_link_libraries(main ${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/text_loading_animation.dll.lib)
# copy DLL file into target dir
add_custom_command(TARGET main POST_BUILD # Adds a post-build event to "main"
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..."
"${PROJECT_SOURCE_DIR}/text_loading_animation.dll" # <--this is in-file
$<TARGET_FILE_DIR:main>) # <--this is out-file path
Now you can "run main" in Jetbrains CLion for example.
Command Line (windows batch script)
Important part is:
cl main.c /link text_loading_animation.dll.lib
main.exe
Full Batch script:
#echo off
rem: clean old data
del main.exe main.obj *.dll *.dll.lib
rem: copy rust lib into current dir
xcopy /y ..\..\target\release\text_loading_animation.dll .
xcopy /y ..\..\target\release\text_loading_animation.dll.lib .
rem: sets up Visual Studio Compilertoolsuite environment
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
rem: *.dll.lib contains header information during compile; *.dll is the runtime file that must be in the same directory/path
rem: "cl" is windows compiler: produces main.obj and main.exe; main.obj is not needed in the end;
rem: it is only for the stage between compiling and linking
rem: /W4 is highest warnings flag
cl /W4 main.c /link text_loading_animation.dll.lib
del main.obj
rem: now execute
main.exe
Hi I'm rather new to Windows command prompt(have only been using Linux-based OS)
I'm trying to install OpenBLAS for Windows according to this tutorial.
When I tried running step 6
cmake .. -G "Ninja" -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER=clang-cl -DCMAKE_Fortran_COMPILER=flang -DBUILD_WITHOUT_LAPACK=no -DNOFORTRAN=0 -DDYNAMIC_ARCH=ON -DCMAKE_BUILD_TYPE=Release
I get the following error
Compiling the C compiler identification source file
"CMakeCCompilerId.c" failed. Compiler:
C:/ProgramData/Anaconda3/Library/bin/clang-cl.exe Build flags:
/DWIN32;/D_WINDOWS;/W3 Id flags:
The output was: 1104 LINK : fatal error LNK1104: ファイル 'libcmt.lib'
を開くことができません。 clang-cl.exe: error: linker command failed with exit code
1104 (use -v to see invocation)
Run Build Command:"C:/ProgramData/Anaconda3/Library/bin/ninja.exe"
"cmTC_e55c4" [1/2] Building C object
CMakeFiles\cmTC_e55c4.dir\testCCompiler.c.obj
[2/2] Linking C executable cmTC_e55c4.exe
FAILED: cmTC_e55c4.exe
cmd.exe /C "cd . && C:\ProgramData\Anaconda3\Library\bin\cmake.exe -E
vs_link_exe --intdir=CMakeFiles\cmTC_e55c4.dir --manifests --
C:\PROGRA~2\MICROS~2\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\Hostx64\x64\link.exe
/nologo CMakeFiles\cmTC_e55c4.dir\testCCompiler.c.obj
/out:cmTC_e55c4.exe /implib:cmTC_e55c4.lib /pdb:cmTC_e55c4.pdb
/version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console
kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib
oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
RC Pass 1: command "rc /foCMakeFiles\cmTC_e55c4.dir/manifest.res
CMakeFiles\cmTC_e55c4.dir/manifest.rc" failed (exit code 0) with the
following output:
隰悶・・ョ螢ケ・・ケァ蠕娯螺郢晁シ斐<郢ァ・、郢晢スォ邵コ迹夲スヲ荵昶命邵コ荵晢ス顔クコ・セ邵コ蟶呻ス鍋クイ繝サ ninja: build
stopped: subcommand failed.
Random but also,I don't know why it's outputting Chinese characters in the end...(my system language is set to Japanese and not Chinese)
Sorry for late answer - you should also add -DCMAKE_RC_COMPILER=llvm-rc (don't remember correct name)
I generated a project by the STMCubeMX and wanted to import this project into Clion.
Here's the CmakeList.txt:
project(ClionTest)
cmake_minimum_required(VERSION 3.8)
add_definitions(-DSTM32F4xx)
file(GLOB_RECURSE USER_SOURCES "Src/*.c")
file(GLOB_RECURSE HAL_SOURCES "Drivers/STM32F4xx_HAL_Driver/Src/*.c")
add_library(CMSIS
startup/startup_stm32f407xx.s)
include_directories(Drivers/CMSIS/Device)
include_directories(Drivers/CMSIS/Device/ST/STM32F4xx/Include)
include_directories(Drivers/CMSIS/Include)
include_directories(Drivers/STM32F4xx_HAL_Driver)
include_directories(Drivers/STM32F4xx_HAL_Driver/Inc)
include_directories(Inc)
include_directories(Middlewares/Third_Party/LwIP/src/include)
add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${HAL_SOURCES} ${LINKER_SCRIPT})
target_link_libraries(${PROJECT_NAME}.elf CMSIS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.map")
set(HEX_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_SOURCE_DIR}/build/${PROJECT_NAME}.bin)
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
COMMENT "Building ${HEX_FILE} \nBuilding ${BIN_FILE}")
And a STM32F4xx.cmake file:
INCLUDE(CMakeForceCompiler)
SET(CMAKE_SYSTEM_NAME Generic)
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
#CMAKE_FORCE_C_COMPILER(C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q2-update/bin/arm-none-eabi-gcc.exe GNU)
#CMAKE_FORCE_CXX_COMPILER(D:/Lib/arm/bin/arm-none-eabi-g++.exe GNU)
SET(CMAKE_C_COMPILER "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q2-update/bin/arm-none-eabi-gcc.exe")
SET(CMAKE_CXX_COMPILER "C:/Program Files (x86)/GNU Tools ARM Embedded/6 2017-q2-update/bin/arm-none-eabi-g++.exe")
SET(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/STM32F407VETx_FLASH.ld)
#Uncomment for software floating point
#SET(COMMON_FLAGS "-mcpu=cortex-m4 -mthumb -mthumb-interwork -mfloat-abi=soft -ffunction-sections -fdata-sections -g -fno-common -fmessage-length=0")
SET(COMMON_FLAGS "-mcpu=cortex-m4 -mthumb -mthumb-interwork -mfloat-abi=hard -mfpu=fpv4-sp-d16 -ffunction-sections -fdata-sections -g -fno-common -fmessage-length=0")
SET(CMAKE_CXX_FLAGS_INIT "${COMMON_FLAGS} -std=c++11")
SET(CMAKE_C_FLAGS_INIT "${COMMON_FLAGS} -std=gnu99")
SET(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,-gc-sections,-M=binary.map -T ${LINKER_SCRIPT}")
I set LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/STM32F407VETx_FLASH.ld
File structure
And the Cmake options is:
Cmake options
When I reload this project, it's not go on well.
c:/progra~2/gnutoo~1/62017-~1/bin/../lib/gcc/arm-none-eabi/6.3.1/../../../../arm-none-eabi/bin/ld.exe: cannot open linker script file
D:/Project/ClionTest/cmake-build-default/CMakeFiles/CMakeTmp/STM32F407VETx_FLASH.ld:
Invalid argument
collect2.exe: error: ld returned 1 exit status
CMakeFiles\cmTC_bf7b4.dir\build.make:96: recipe for target 'cmTC_bf7b4' failed
mingw32-make.exe[1]: *** [cmTC_bf7b4] Error 1
mingw32-make.exe[1]: Leaving directory
'D:/Project/ClionTest/cmake-build-default/CMakeFiles/CMakeTmp'
Makefile:125: recipe for target 'cmTC_bf7b4/fast' failed
mingw32-make.exe: *** [cmTC_bf7b4/fast] Error 2
It seems like the path of ld.exe is not correct,how shoulld I set its path?
And why the path of STM32F407VETx_FLASH.ld it searched is not the path I set?
I'm using Linux, but I've had the a similar issue in regards to being unable to open the linker script.
cannot open linker script file D:/Project/ClionTest/cmake-build-default/CMakeFiles/CMakeTmp/STM32F407VETx_FLASH.ld
After looking for a while at the documentation for target_link_option (which does approximately the same kind of thing as setting a variable directly), I took note of the SHELL: directive, that's stated to:
The set of options is de-duplicated to avoid repetition. While beneficial for individual options, the de-duplication step can break up option groups. For example, -D A -D B becomes -D A B. One may specify a group of options using shell-like quoting along with a SHELL: prefix. The SHELL: prefix is dropped and the rest of the option string is parsed using the separate_arguments() UNIX_COMMAND mode.
By adding it to my command, I managed to get compilation working normally. The result was the following:
set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/STM32F303CCTX_FLASH.ld")
set(LINKER_FLAGS "SHELL:-T${LINKER_SCRIPT} -Wl,--gc-sections --specs=nano.specs --specs=nosys.specs")
target_link_options(${PROJECT_BINARY} PRIVATE ${LINKER_FLAGS})
Change this:
SET(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,-gc-sections,-M=binary.map -T ${LINKER_SCRIPT}")
To:
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-gc-sections,-M=binary.map -T${LINKER_SCRIPT}")
I just wanted to try out using OpenCL under Windows.
Abstract: I got an "undefined reference to" error when I tried to compile (using the command gcc my.o -o my.exe -L "C:\Program Files (x86)\AMD APP\lib\x86_64" -l OpenCL).
My Code
#include <CL/cl.h>
#include <stdio.h>
int main(void) {
cl_platform_id platform;
int err;
err = clGetPlatformIDs(1, &platform, NULL);
if(err < 0) {
perror("There's No Platform!");
exit(1);
}
/* Some more code... */
system("PAUSE");
}
Makefile
all: addition
addition:
gcc -c -I "C:\Program Files (x86)\AMD APP\include" my.c -o my.o
gcc my.o -o my.exe -L "C:\Program Files (x86)\AMD APP\lib\x86_64" -l OpenCL
Used Programs
MinGW's gcc
Visual Studio's nmake
AMD's OpenCL™ APP SDK (that's where I took the OpenCL library and the CL.h file from)
The Structure of APP SDK's Folders
%>tree /F "C:\Program Files (x86)\AMD APP\lib\x86_64"
Auflistung der Ordnerpfade
Volumeseriennummer : D2DC-D765
C:\PROGRAM FILES (X86)\AMD APP\LIB\X86_64
libOpenCL.a
OpenCL.lib
OpenVideo64.lib
Es sind keine Unterordner vorhanden
%>tree /F "C:\Program Files (x86)\AMD APP\include"
Auflistung der Ordnerpfade
Volumeseriennummer : D2DC-D765
C:\PROGRAM FILES (X86)\AMD APP\INCLUDE
├───CAL
│ cal.h
│ calcl.h
│ cal_ext.h
│ cal_ext_counter.h
│ cal_ext_d3d10.h
│ cal_ext_d3d9.h
│
├───CL
│ cl.h
│ cl.hpp
│ cl_d3d10.h
│ cl_ext.h
│ cl_gl.h
│ cl_gl_ext.h
│ cl_platform.h
│ opencl.h
│
└───OpenVideo
OpenVideo.h
OVDecode.h
OVDecodeTypes.h
OVEncode.h
OVEncodeTypes.h
Error Message
gcc addition.o -o addition.exe -L "C:\Program Files (x86)\AMD APP\lib\x86_64" -l OpenCL
addition.o:addition.c:(.text+0x2d): undefined reference to `clGetPlatformIDs#12'
addition.o:addition.c:(.text+0x83): undefined reference to `clGetDeviceIDs#24'
addition.o:addition.c:(.text+0xc2): undefined reference to `clGetDeviceIDs#24'
collect2: ld returned 1 exit status
NMAKE : fatal error U1077: "C:\prog-x86\MinGW\bin\gcc.EXE": Rückgabe-Code "0x1"
Stop.
My Questions
My questions are simple:
Why doesn't my code compile how it is expected to?
What can I do to get rid of this problem?
Thanks.
UPDATE: The error message after dropping the spaces like described in #codaddict 's answer.
(Makefile)
all: addition
addition:
gcc -c -I "C:\prog-x86\AMD-APP\include" addition.c -o addition.o
gcc addition.o -o addition.exe -LC:\prog-x86\AMD-APP\lib\x86_64 -lOpenCL
(Shelldata)
%>nmake
Microsoft (R) Program Maintenance Utility, Version 11.00.50727.1
Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten.
gcc -c -I "C:\Program Files (x86)\AMD APP\include" addition.c -o addition.o
addition.c: In function 'main':
addition.c:14:9: warning: incompatible implicit declaration of built-in function 'exit' [enabled by d
efault]
addition.c:23:9: warning: incompatible implicit declaration of built-in function 'exit' [enabled by d
efault]
gcc addition.o -o addition.exe -LC:\prog-x86\AMD-APP\lib\x86_64 -lOpenCL
addition.o:addition.c:(.text+0x2d): undefined reference to `clGetPlatformIDs#12'
addition.o:addition.c:(.text+0x83): undefined reference to `clGetDeviceIDs#24'
addition.o:addition.c:(.text+0xc2): undefined reference to `clGetDeviceIDs#24'
collect2: ld returned 1 exit status
NMAKE : fatal error U1077: "C:\prog-x86\MinGW\bin\gcc.EXE": Rückgabe-Code "0x1"
Stop.
%>
The default MinGW distribution only ships tools for building x86 applications. You cannot link against the x64 version of the OpenCL library. So you either have to use MinGW-w64 or use the x86 version (change the library path to the x86 subfolder of the APP SDK).
Try changing
-l OpenCL
to
-lOpenCL
in the compile line.
The -l option of gcc expects the name of the library (without the lib prefix) right next to it without any space. Remember using -lm in school to link to libm?
The 64 bit g++ compiler on windows 10 is also in the bin folder:
"C:\MinGW\bin\x86_64-w64-mingw32-g++.exe"
So this works for me:
C:\MinGW\bin>x86_64-w64-mingw32-g++ "C:\Users\...\main.cpp" -o
C:\Users\...\saxpy -L "C:\Program Files\...\x64" -lOpenCL -I
"C:\...\OpenCL\sdk\include"
Notes:
-o output name
-L folder contains OpenCL.lib
-I folder contains header file e.g. CL/cl.h