CLion filesystem linker problem even with -lstdc++fs - linker

I've tried to use <filesystem> in my CLion project on Fedora 29 environment.
When compiling directly from terminal it works smoothly, but when i try to compile from CLion there is a Linker issue about filesystem. I'm not shure what else I can do. Any suggestions?
g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
clang version 7.0.1
(Fedora 7.0.1-6.fc29)
Here is what i have already tried:
I've added the flag -lstdc++fs:
set(CMAKE_CXX_FLAGS -lstdc++fs)
but i didn't worked. I've verified if this flag is in use by:
set( CMAKE_VERBOSE_MAKEFILE on )
and it seems it is:
[ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.o
/usr/bin/g++ -lstdc++fs -g -std=gnu++17 -o
CMakeFiles/untitled.dir/main.cpp.o -c
/home/patryk/CLionProjects/untitled/main.cpp
[100%] Linking CXX executable untitled
/home/patryk/clion-2018.3.4/bin/cmake/linux/bin/cmake -E
cmake_link_script CMakeFiles/untitled.dir/link.txt --verbose=1
/usr/bin/g++ -lstdc++fs -g CMakeFiles/untitled.dir/main.cpp.o -o
untitled
/usr/bin/ld: CMakeFiles/untitled.dir/main.cpp.o: in function
`std::filesystem::__cxx11::path::path<char [2],
std::filesystem::__cxx11::path>(char const (&) [2],
std::filesystem::__cxx11::path::format)':
/usr/include/c++/8/bits/fs_path.h:184: undefined reference to
`std::filesystem::__cxx11::path::_M_split_cmpts()'
collect2: error: ld returned 1 exit status
I've tried also to use clang compiler with exact same results.
main.cpp
#include <iostream>
#include <filesystem>
int main() {
std::filesystem::path p("D");
return 0;
}

CMake use target_link_libraries to add -l linker flags.
target_link_libraries(your_executable stdc++fs)
Why set(CMAKE_CXX_FLAGS -lstdc++fs) not working: -l option must be set after your source or object file.
c++ -lstdc++fs some_object.o -o executable # not working
c++ some_object.o -o executable -lstdc++fs # should work

Related

CMake: How to compile C on Windows with clang and lld with MinGW-w64 runtime

I'm building a LLVM environment on Windows that can work without Microsoft compiler and SDK and without GCC compiler or GNU linker, only LLVM (the official build) and MinGW-w64 runtime.
When compiling this C program with clang compiler and lld linker, and with x86_64-windows-gnu target (MinGW-w64 runtime), it works:
> type c1.c
#include <stdio.h>
int main() {
printf("hello 1\n");
return 0;
}
> clang c1.c -target x86_64-windows-gnu -fuse-ld=lld -o c1.exe
> c1
hello 1
How to achieve the same with CMake? Is there a high level option for CMake to set these flags automatically? Or, when trying to set these flags manually (with CMAKE_EXE_LINKER_FLAGS or CMAKE_C_FLAGS) looks like that it confuses CMake and it still passes some Visual C++ style flags (like /subsystem:console) during linking:
> type CMakeLists.txt
project (P1 C)
cmake_minimum_required(VERSION 3.0)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -target x86_64-windows-gnu -fuse-ld=lld")
add_executable (c1 c1.c)
> cmake -G Ninja -B build -DCMAKE_C_COMPILER=clang
-- The C compiler identification is Clang 12.0.0 with GNU-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/build
> cmake --build build
[2/2] Linking C executable c1.exe
FAILED: c1.exe
cmd.exe /C "cd . && C:\PROGRA~1\LLVM\bin\clang.exe -fuse-ld=lld-link -nostartfiles -nostdlib -g -Xclang -gcodeview -O0 -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -target x86_64-windows-gnu -fuse-ld=lld -Xlinker /subsystem:console CMakeFiles/c1.dir/c1.c.obj -o c1.exe -Xlinker /implib:c1.lib -Xlinker /pdb:c1.pdb -Xlinker /version:0.0 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
lld: error: unable to find library -loldnames
clang: error: linker command failed with
Please see the documentation on toolchains here: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-using-clang
Since you're overriding the default Clang target, CMake needs to know about this during compiler detection. By the time you're in the CMakeLists.txt, it is too late. The following clang-x86_64_windows_gnu.cmake toolchain file might work (I can't test it without replicating your environment):
set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET x86_64-windows-gnu)
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
Then your CMakeLists.txt was wrong, it should be:
cmake_minimum_required(VERSION 3.20)
project(P1 LANGUAGES C)
add_executable(c1 c1.c)
Notice the order of the cmake_minimum_required and project commands. They should always be the first two lines in your CMakeLists.txt, in that order.

Cannot find -lCommunication collect2: error: ld returned 1 exit status

I do not know gcc and c well. In my /home/pi/Desktop/intern/adis16227_generic directory I have following 5 files.
ADIS16227.c
ADIS16227.h
Communication.c
Communication.h
main.c
main.c
#include<stdio.h>
#include "Communication.h" // Communication definitions.
int main() {
printf("hello!!\n");
unsigned char status = 0;
status = SPI_Init(0, 1000000, 1, 1);
printf("%u", status);
return 0;
}
Run command:
$ sudo gcc -L /home/pi/Desktop/intern/adis16227_generic main.c -lCommunication
Error:
/usr/bin/ld: cannot find -lCommunication
collect2: error: ld returned 1 exit status
Question:
What I am missing here?
What do I need to run the code?
-l is for libraries, and you never built a library from your Communication.c. The simplest solution is just add Communication.c to your compiler command line.
For larger projects, compile each translation unit separately with the -c switch like this:
gcc -c -Wall -Wextra -pedantic -omain.o main.c
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
and so on ... (as a suggestion, I added some common warning options here, they help you spot errors)
The resulting .o files are object code. That's already compiled machine code, but with meta-information needed for a linker to link it with other object code into a complete executable.
Then link them all with one command:
gcc -oprogram main.o Communication.o
If you actually want a library from -- say -- Communication.c and ADIS16227.c, you could compile both to object code:
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
gcc -c -Wall -Wextra -pedantic --oADIS16227.o ADIS16227.c
and then use ar to create a static library from them:
ar rcs libCommunication.a Communication.o ADIS16227.o
Then your initial compiler command would work (with the -lCommunication switch).
Final piece of advice: Never compile as root. This is completely unnecessary. So remove your sudo here.
those options:
-L /home/pi/Desktop/intern/adis16227_generic -lCommunication
suggest that the linker should find libCommunication.a (or .so) in the /home/pi/Desktop/intern/adis16227_generic directory.
But there are only sources in this directory. The linker won't build the sources of your "Communication" library for you.
So you could build the library and link with it:
gcc -c ADIS16227.c Communication.c
ar r libCommunication.a ADIS16227.o Communication.o
but maybe the fastest & quickest way to achieve a successful build would be:
sudo gcc -o main *.c
so it compiles all the files of the directory into the executable called main
Of course, it makes compilation times longer, but maybe it's not noticeable.
First move into the /home/pi/Desktop/intern/adis16227_generic directory:
cd /home/pi/Desktop/intern/adis16227_generic
Then, compile the source:
gcc ADIS16227.c Communication.c main.c -I .
You can now run your compiled program (called by default a.out):
./a.out
You have to compile separatedly files and then compile main with related obj file.
gcc -c Communication.c Communication.h
gcc main.c Communication.o -o main

How do I create a static library in Rust to link with C code in Windows?

I have 2 files:
func.rs
#[no_mangle]
pub extern fn double_input(input: i32) -> i32 { input * 2 }
main.c
#include <stdint.h>
#include <stdio.h>
extern int32_t double_input(int32_t input);
int main() {
int input = 4;
int output = double_input(input);
printf("%d * 2 = %d\n", input, output);
return 0;
}
I want to create static lib in Rust and link the library to main.c. My active toolchain is stable-i686-pc-windows-gnu. I'm doing this in cmd:
rustc --crate-type=staticlib func.rs
But the file func.lib is created, so I do:
gcc -o myprog main.c func.lib -lgcc_eh -lshell32 -luserenv -lws2_32 -ladvapi32
But I get an error:
undefined reference to __ms_vsnprintf'
If I do:
rustc --crate-type=staticlib --target=i686-unknown-linux-gnu lib.rs
Then libfunc.a is created, but when I do:
gcc -o myprog main.c libfunc.a
I get an error:
main.c:(.text+0x1e): undefined reference to `double_input'
What am I doing wrong?
TL;DR: Install a different flavor of GCC
pacman -R local/gcc
pacman -S mingw-w64-i686-gcc
Half-informed guessing follows...
After some help on Rust IRC, it sounds like the issue is that the MSYS2 / MinGW gcc is a "stock" compiler, one without special knowledge of MSYS / MinGW / Windows special features.
mingw-w64-i686-gcc (or mingw-w64-x86_64-gcc) does know about Windows-specific symbols, which libbacktrace, a part of the Rust distribution, requires.
The "correct" GCC build should have the string "Built by MSYS2 project" in the gcc --version output.
With that, the full process looks like:
$ rustc --version --verbose
rustc 1.17.0 (56124baa9 2017-04-24)
host: i686-pc-windows-gnu
$ gcc --version
gcc.exe (Rev2, Built by MSYS2 project) 6.3.0
$ rustc --crate-type=staticlib func.rs
note: link against the following native artifacts when linking against this static library
note: the order and any duplication can be significant on some platforms, and so may need to be preserved
note: library: advapi32
note: library: ws2_32
note: library: userenv
note: library: shell32
note: library: gcc_eh
$ gcc -o main main.c func.lib -ladvapi32 -lws2_32 -luserenv -lshell32 -lgcc_eh
$ ./main
4 * 2 = 8
sorry for my bad english, to use a static rust library (.lib) you must add the following libraries to your linker:
shell32.lib advapi32.lib cfgmgr32.lib comctl32.lib comdlg32.lib
d2d1.lib dwrite.lib dxgi.lib gdi32.lib kernel32.lib msimg32.lib
ole32.lib opengl32.lib shlwapi.lib user32.lib windowscodecs.lib
winspool.lib userenv.lib ws2_32.lib bcrypt.lib msvcrt.lib
oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
works in visual studio 2022

Is it possible to link bitcode with llvm-ar archieve into a single bitcode file?

I have read this thread on llvm-dev and is faced with the same problem: I cannot link the llvm-ar archieve library with other bitcode files into another single bitcode file with the help of llvm-link.
clang -emit-llvm -g -c -o main.bc main.c
clang -emit-llvm -g -c -o calc.bc calc.c
llvm-ar rcs libcalc.la calc.bc
llvm-link libcalc.la main.bc -o test
the problem is the same: llvm-link complains
llvm-link: libcalc.la:1:2: error: expected integer
!<arch>
^
And after reading How to link object to libraries with LLVM >= 3.1 ? ( no GNU ld ), I also tried a llvm2.9 version of llvm-ld.
llvm-ld --disable-opt libcalc.la main.bc -o test
however libcalc.la is not linked into the module correctly and lli reports:
LLVM ERROR: Program used external function 'Square' which could not be resolved!
So what should i do?
UPDATE
I then read Can't link against static library when compiling objects from LLVM bitcode. and find that llvm-ld WORKS when changing the order:
llvm-ld --disable-opt main.bc libcalc.la -o test
But llvm-link still fails.
llvm-link does not support bitcode archives, AFAIK. It simply goes over the input files it was provided, and tries to parse each one as a bitcode file (either binary or textual LLVM IR).
llvm-ld doesn't exist in the newer LLVMs, so I would suggest to stay away from it completely.
Just link the separate .bc files together with llvm-link. The archiving of bitcode files doesn't have the same benefits for the linker as in native linking anyway.
You don't need archivers to link your bitcode files:
clang -emit-llvm -g -c -o main.bc main.c
clang -emit-llvm -g -c -o calc.bc calc.c
clang main.bc calc.bc -o test

How do I properly reference the GNU readline library to scan terminal input?

I am attempting to compile C code that utilizes the following within GNU readline.
#include <readline/readline.h>;
#include <readline/history.h>;
I've tried changing the <> to "" and compiling both with and without the -lreadline options. Nothing seems to work. When compiling without -lreadline under gcc results in the following being generated while compiling (verbose):
Reading specs from /software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6/specs
Configured with: ../gcc-3.4.6/configure --prefix=/software/gcc-3.4.6-0/pkg --disable-dependency-tracking --localstatedir=/var --disable-nls --program-suffix=34 --enable-shared --enable-version-specific-runtime-libs
Thread model: posix
gcc version 3.4.6
/software/gcc-3.4.6-0/pkg/libexec/gcc/i386-unknown-freebsd6.1/3.4.6/cc1 -quiet -v myshell.c -quiet -dumpbase myshell.c -auxbase myshell -version -o /var/tmp//ccVSq3jQ.s
ignoring nonexistent directory "/software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6/../../../../i386-unknown-freebsd6.1/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/software/gcc-3.4.6-0/pkg/include
/software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6/include
/usr/include
End of search list.
GNU C version 3.4.6 (i386-unknown-freebsd6.1)
compiled by GNU C version 3.4.6.
GGC heuristics: --param ggc-min-expand=99 --param ggc-min-heapsize=129976
as -o /var/tmp//ccl1Jaqk.o /var/tmp//ccVSq3jQ.s
/software/gcc-3.4.6-0/pkg/libexec/gcc/i386-unknown-freebsd6.1/3.4.6/collect2 -V -dynamic-linker /libexec/ld-elf.so.1 -L/software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1 -o a /usr/lib/crt1.o /usr/lib/crti.o /software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6/crtbegin.o -L/software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6 -L/software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6/../../.. /var/tmp//ccl1Jaqk.o -lreadline -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /software/gcc-3.4.6-0/pkg/lib/gcc/i386-unknown-freebsd6.1/3.4.6/crtend.o /usr/lib/crtn.o
/usr/bin/ld: cannot find -lreadline
GNU ld version 2.15 [FreeBSD] 2004-05-23
Supported emulations:
elf_i386_fbsd
collect2: ld returned 1 exit status
This is the output when compiling without the -lreadline option.
/var/tmp//ccNnucSC.o(.text+0x4f): In function `main':
: undefined reference to `readline'
collect2: ld returned 1 exit status
I have been unable to resolve this error up to this point. What am I missing in either my code or while invoking gcc?
While compiling under UNIX I found the following is necessary to properly reference the GNU readline library:
gcc code.c -L/usr/local/lib -I/usr/local/include -lreadline
This ensures that the compiler finds the readline directories and files during compilation and linking.
It sounds like you don't have the libreadline development libraries installed. On Debian (including the FreeBSD port) the library is located in /lib and the development libraries (that you would link to) are in /usr/lib.
Additionally you have semi-colons after your includes, which you shouldn't have.

Resources