Linker errors when compiling a CMake application manually
I have this CMake application defined in a CMakeLists.txt file which compiles perfectly when building with CMake. However, when I try to compile it manually (using mpicc -fopenmp src/main.c
) I get linker errors for all the functions I've defined in separate files.
Project file structure :
.
├── CMakeLists.txt
├── libs
│ ├── common
│ │ ├── init
│ │ │ ├── init.c
│ │ │ └── init.h
│ │ ├── palindrome
│ │ │ ├── palindrome.c
│ │ │ └── palindrome.h
│ │ └── print
│ │ ├── print.c
│ │ └── print.h
│ ├── mpi
│ │ ├── main_mpi.c
│ │ └── main_mpi.h
│ ├── openmp
│ │ ├── main_openmp.c
│ │ └── main_openmp.h
│ └── sequential
│ ├── main_sequential.c
│ └── main_sequential.h
├── LICENSE
├── README.md
└── src
└── main.c
CMakeLists.txt :
cmake_minimum_required(VERSION 3.21)
project(<project-name> C)
set(CMAKE_C_STANDARD 23)
find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
find_package(OpenMP REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
add_executable(<project-name> src/main.c libs/common/init/init.c libs/common/init/init.h libs/common/print/print.c libs/common/print/print.h libs/common/palindrome/palindrome.c libs/common/palindrome/palindrome.h libs/sequential/main_sequential.c libs/sequential/main_sequential.h libs/openmp/main_openmp.c libs/openmp/main_openmp.h libs/mpi/main_mpi.c libs/mpi/main_mpi.h)
target_link_libraries(<project-name> ${MPI_C_LIBRARIES})
I have a feeling I need to use the -I
argument when compiling but I'm not sure how.
I therefore have 2 questions :
- How would I go about compiling it manually while linking libraries under
libs/
? - I'm not a fan of the very long
add_executable
line (it was generated automatically for me by CLion). Is it possible to split it into multiple lines ? Better yet, is it possible to use wildcards ?
do you know?
how many words do you know
See also questions close to this topic
-
How do I manipulate the contents of a stat() struct?
I have a stat struct, and I'm looking for a way to get data out of it to be manipulated. The program will successfully run and print the desired st_mtime value, but including either of the "seg-fault" lines below causes a segmentation fault in runtime.
struct stat buf; time_t time_m; time_t sys_time = time(0); if(stat(sub_dirp->d_name,&buf)==0) { //time_m = buf.st_mtime; //seg-fault //double since_last = (difftime(sys_time, buf.st_mtime)/60); //seg-fault printf("%d ", (int)buf.st_mtime); //This works. }
Both lines are attempting to manipulate the
buf.st_mtime
value in some way.I've had a hard time finding any examples of the usage of stat() that do anything other than print its contents, which makes me wonder if it's even possible.
So my question is, if it is possible, what am I missing?
P.S. I do wish to keep
st_mtime
in the Unix timestamp format to make it easier to manipulate.Edit: After realizing that
st_mtime
is itself its own struct (timespec), how can I access thest_mtime.tv_sec
member?The compiler doesn't like
buf.st_mtime.tv_sec
one bit. -
What's purpose of __linecapp in getline, when it'll auto resize?
It's all about second parameter of getline in stdio.h,
I'll name it 'n' or '__linecapp' below.
According to the document:
If the buffer is not large enough to hold the line, getline() resizes it with realloc(3), updating *lineptr and *n as necessary.
It'll automatically update line capacity, then why should we input __linecapp?
P.S Someone ask before, but discussion didn't explain when we need it, or how to make it useful.
-
Linked List Deletion function causing program to crash *wrong pointers?*
In my program when a username is following another one and also has posted a "tweet" which is a string in an attempt to delete the followed username it breaks the program. I believe this is the code snippet in question. If anyone could help me identify the issue I would be thankful as I am learning the usage of linked lists for scale able projects. Thanks
void deleteAccount(accountNodePtr *startPtr, accountNodePtr *curAcPtr, tweetsNodePtr *startTwtPtr){ accountNodePtr acLoopPtr; accountNodePtr tempCur = *curAcPtr; followNodePtr followingPtr = tempCur->followingPtr; followNodePtr tempPtr; followNodePtr tempPtr2; tweetsNodePtr iterTwtPtr; iterTwtPtr = *startTwtPtr; *below here in question* tempCur = *curAcPtr; while (tempCur->followersPtr!=NULL){ acLoopPtr = *startPtr; while (strcmp(acLoopPtr->username, tempCur->followersPtr->username)!=0){ acLoopPtr=acLoopPtr->nextPtr; } if (strcmp(acLoopPtr->followingPtr->username, tempCur->username)==0){ tempPtr=acLoopPtr->followingPtr->nextPtr; free(acLoopPtr->followingPtr); acLoopPtr->followingPtr=tempPtr; }else{ tempPtr=acLoopPtr->followingPtr; while(strcmp(tempPtr->nextPtr->username, tempCur->username)!=0){ tempPtr=tempPtr->nextPtr; } tempPtr2=tempPtr->nextPtr->nextPtr; free(tempPtr->nextPtr); tempPtr->nextPtr=tempPtr2; } tempPtr = tempCur->followersPtr->nextPtr; free(tempCur->followersPtr); tempCur->followersPtr=tempPtr; }
This is the structure
typedef struct followsNode { char username[MAX_USERNAME]; struct followsNode *nextPtr; } followNode; typedef struct accountsNode { char username[MAX_USERNAME]; struct followsNode *followersPtr; struct followsNode *followingPtr; struct accountsNode *nextPtr; } accountNode; typedef followNode *followNodePtr; typedef accountNode *accountNodePtr;
-
Compile all C files in all of the children directories
So, I'm making a game with raylib and I need to compile all the .c files at once.
The files are in separate folder inside the 1st one(Like "MainFolder/PlayerFiles").
I know how that
gcc -o game *.c -L/usr/local/lib -lraylib
compiles all the files inside the directory and creates a exec.How can I compile all the .c files in all of the children folders.
Thanks in advance!!!
-
how to get the bare bone compiled binary code of a C function?
I'm trying to implement an embedded firmware on an stm32 F4 micro that takes an binary code from the serial and execute it on the micro.
The idea is pretty simple of course the only tricky part is that since on the serial is complicate to send raw binary data I'm going to send everything through base64 encoding.
Here's the code:
#include <Arduino.h> #include <base64.hpp> size_t read_serial_line(char *msg, size_t len, size_t timeout = 0) { const auto start = millis(); size_t sz = 0; do { while (not Serial.available()) { if (timeout > 0 and millis() > start + timeout) { return -1; } } msg[sz] = Serial.read(); if (msg[sz] == '\r') { msg[sz] = '\0'; // replacing the end line with the end string // the next char must be a \n char since the Serial.println of arduino // works like that while (Serial.read() != '\n') ; // I discard it // now sz contains the length of the string as returned by strlen break; // end of line } if (timeout > 0 and millis() > start + timeout) { return -1; } } while (++sz < len); return sz; } void setup() { Serial.begin(9600); Serial.println("begin!"); } void loop() { char *msg = new char[2048](); // big line auto sz = read_serial_line(msg, 2048); Serial.print("\tlooping..."); Serial.println(sz); Serial.print("received: "); Serial.println(msg); uint8_t *code = new uint8_t[2048](); sz = decode_base64(msg, code); Serial.println(sz); delay(1000); int (*code_fn)() = (int (*)())code; int c = code_fn(); Serial.println(c); delete code; delete msg; delay(1000); }
The next problem is to be able to compile and get the compiled binary code from this simple C function:
int fn() { return 3; }
Here you can see the assembly of this stupid function.
I tried, of course using the same tool chain used for the main code of the micro, to compile it with gcc using the option for the position independent code and then I tried to copy the .text secion with objcopy, to finish I took the text returned from the xxd command, I encoded it in base64 and I sent it to the micro.
here are the commands that I used:
$ arm-none-eabi-gcc -fPIC -c test.c $ arm-none-eabi-objcopy -j .text test.o test.bin $ xxd -p test.bin
As I expected this idea is not working, my hypothesis is that I'm getting more then just the binary codes of the function from this process. I have this idea because the output file test.bin is pretty big 440 bytes that seems to me a little bit too much for literally 7 assembly instructions.
So that's the reason of my question: How do I get the binary code and only that code?
-
terminate called after throwing an instance 'std::__ios_failure'
In Ubuntu20.04 gcc9.4.0
`void read_txt_config(const std::string &path) { std::cout << std::endl << "Reading configuration file: ";
std::ostringstream batch_out; batch_out << path << "config.txt"; std::string str_temp = batch_out.str().data(); std::ifstream fin; fin.exceptions(std::ios::failbit | std::ios::badbit); fin.open(str_temp.c_str()); if (!fin.good()) { std::cout << " reading failed, there is no config.txt, the program will use the default param_nameeters. " << std::endl; } else { ... ... } fin.close();}
when the code run to
fin.close();
I got
terminate called after throwing an instance 'std::__ios_failure' what(): basic_ios::clear: iostream error Aborted(core dumped)
-
How to specify a command to clean a custom cmake target?
I have made a custom target in cmake by using
add_custom_target
and it compiles some HLSL shaders for me. However, when I clean the target using visual studio it does not delete the compiled files. How do I specify a command to delete the compiled shader files? -
Cmake is not production the same commands than setup.py
I am working on a binding between my C++ lib and python. To do so, I use SWIG. In order to understand it and make it work I was playing with a setup.py (distutils) file. When I compile the binding from the local folder, it generates the following command lines:
swig -python -c++ -I/home/me/my_project/include -I/home/me/my_project/external/includes -Wall -Wextra -py3 -o pyFooBar_wrap.cpp pyFooBar.i gcc -pthread -B /home/me/miniconda3/envs/my_project/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -I/home/me/my_project/external/includes -I/home/me/my_project/include -I/home/me/miniconda3/envs/my_project/include/python3.7m -c pyFooBar_wrap.cpp -o build/temp.linux-x86_64-3.7/pyFooBar_wrap.o -fPIC -shared -std=c++17 -g -fwrapv -O3 -Wall -Wstrict-prototypes -Wextra -Wno-missing-field-initializers g++ -pthread -B /home/me/miniconda3/envs/my_project/compiler_compat -L/home/me/miniconda3/envs/my_project/lib -Wl,-rpath=/home/me/miniconda3/envs/my_project/lib -Wl,--no-as-needed -Wl,--sysroot=/ -shared build/temp.linux-x86_64-3.7/pyFooBar_wrap.o -o /home/me/my_project/bindings/_pyFooBar.cpython-37m-x86_64-linux-gnu.so
Then, I test it and everything works as expected. Up to there no problem, but the built and temporary files are in my source folder. So, to get things cleaner, I want to use Cmake to compile the binding for me. I wrote the following Cmake script:
set_source_files_properties(pyFooBar.i PROPERTIES CPLUSPLUS ON) set_property(SOURCE pyFooBar.i PROPERTY SWIG_MODULE_NAME pyFooBar) set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD) swig_add_library(pyFooBar TYPE SHARED LANGUAGE python SOURCES pyFooBar.i ) # For Swig wrapping set_property(TARGET pyFooBar PROPERTY SWIG_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/external/includes" "${PROJECT_SOURCE_DIR}/include") # For Cxx compilation set_property(TARGET pyFooBar PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/external/includes" "${PROJECT_SOURCE_DIR}/include" ${PYTHON_INCLUDE_PATH}) set_property(TARGET pyFooBar PROPERTY COMPILE_OPTIONS -shared -std=c++17 -g -pthread -fwrapv -Wall -Wstrict-prototypes -Wextra -Wno-missing-field-initializers -Wl,--sysroot=/ -Wsign-compare -DNDEBUG) # swig_link_libraries( target_link_libraries( pyFooBar ${PYTHON_LIBRARIES} )
which generate the following command lines:
swig4.0 -python -py3 -I/home/me/my_project/external/includes -I/home/me/my_project/include -outdir /home/me/my_project/build/bindings -c++ -interface _pyFooBar -o /home/me/my_project/build/bindings/CMakeFiles/pyFooBar.dir/pyFooBarPYTHON_wrap.cxx /home/me/my_project/bindings/pyFooBar.i c++ -DpyFooBar_EXPORTS -I/home/me/my_project/external/includes -I/home/me/my_project/include -I/home/me/miniconda3/envs/my_project/include/python3.7m -fPIC -shared -std=c++17 -o CMakeFiles/pyFooBar.dir/CMakeFiles/pyFooBar.dir/pyFooBarPYTHON_wrap.cxx.o -c /home/me/my_project/build/bindings/CMakeFiles/pyFooBar.dir/pyFooBarPYTHON_wrap.cxx c++ -fPIC -shared -Wl,-soname,_pyFooBar.so -o _pyFooBar.so CMakeFiles/pyFooBar.dir/CMakeFiles/pyFooBar.dir/pyFooBarPYTHON_wrap.cxx.o -Wl,-rpath,/home/me/miniconda3/envs/my_project/lib /home/me/miniconda3/envs/my_project/lib/libpython3.7m.so
It compiles fine but when I test the python library I get the following error:
>>> import pyFooBar Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/me/my_project/build/bindings/pyFooBar.py", line 15, in <module> import _pyFooBar ImportError: /home/me/my_project/build/bindings/_py_OBLiX.so: undefined symbol: _ZN3fmt2v812format_errorD1Ev
I think one link is not made correctly, but I don't see where ? Nor how to fix it ! Any ideas ?
-
Why CMake/make give different output despite unchanged source code?
Introduction
Hello all,
I'm writing C++ and trying to wrap my head around CMake.
The idea is this: opening a file and checking if it's open.
I have two files in my
src/
folder, amain.cpp
andhello.txt
which contains some text. Tree structure:- CMakeLists.txt - src/ ├── CMakeLists.txt ├── hello.txt └── main.cpp
I also have a CMakeLists.txt at the same level of
src/
.The code is quite simple in
main.cpp
:int main() { std::ifstream file; file.open("./hello.txt"); std::cout << "File is open? " << file.good() << std::endl; file.close(); return 0; }
And when I compile this manually using
g++
within the src folder (g++ main.cpp -o main
), I don't have any issues, the output shows:File is open? 1
so it was indeed open.Problems using CMake
The problem arose when I tried using CMake to build, configure and compile this little project. I'm not entirely sure yet how to write proper CMakeLists.txt files. But with the most basic of CMake instructions, the output I received was:
File is open? 0
.Here's the code in my root CMakeLists.txt:
cmake_minimum_required(VERSION 3.13) project(fileio) set(CMAKE_CXX_STANDARD 14) add_subdirectory(src) add_executable(main src/main.cpp)
I hadn't changed the file locations, and the output was changed. Maybe I didn't include all of the files using CMake so I used the
add_subdirectory()
directive and I also had to put another CMakeLists.txt file in thesrc/
folder. I left that latter empty because I don't consider this folder a library.Checking compile commands
I thought the problem was the compiling command so I added the
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
directive to CMake when building my project. Here's the output of thecompile_commands.json
:[ { "directory": "path/to/files/build", "command": "/usr/bin/g++ -std=gnu++14 -o CMakeFiles/main.dir/src/main.cpp.o -c path/to/files/src/main.cpp", "file": "path/to/files/src/main.cpp" } ]
To me, it doesn't seem far remote from my initial
g++ main.cpp -o main
. But I don't understand why the file doesn't open when I use the Makefile generated by CMake.My Question
Did I miss certain commands or variables to set in the CMakeLists.txt file to include the hello.txt file to the executable?
-
Force compiler to use static definition from a specific C file
Two C files have the same variable name declared differently.
Can I force the compiler (Visual Studio or gcc) to prefer one declaration over the other?
The scenario is that I have a C file where I would not like to change anything and my own C file with several overlapping definitions, and that's where I would like to make my changes.
For example, I have the following definition in the original c file :
static unsigned char key[27 + 1] = "<put ur key here>";
And I have the following definition in my own c file :
static unsigned char key[27 + 1] = "abcde...";
When compiling, I would like the compiler to use my declaration instead of the original cpp file.
-
How to compile a py file from another py file by using a module ? (Therefore not Cmd)
I want to make a code (that I'll call compiler.py), that'll compile any py file I need without using cmd commands, only modules(Things that are compilable So I can still Use my compiler on other devices).
Here are some examples of code to illustrate what I am asking for: Here is how compiler.py would look like : compiler.py
And this is randomprogramm.py : randomprogramm.py
Any Idea on how to proceed ?
-
List compiled files by compileJava Gradle task
Is it possible to get a list of the files processed by the
compileJava
Gradle task? I'm especially interested in elements that get processed during the incremental compilation, which could also be a subset of the input sources. -
What is the best way to solve multiple definitions introduced by a 3rd party library? [ELF and Mach-O]
Background
Imagine the situation: static library libR.a is written rust and it depends on libCXX0.a. Binary X depends on both libR.a and libCXX0.a and it is written in C++. Now we want to try something like
clang++ X.o libR.a libCXX0.a -o X
. Well, this will result in multiple definitions because rustc is very happy to package the objects referenced in libCXX0.a into libR.a.Here, libR.a, libCXX0.a, and X can be written in separate projects; therefore, it is not handy for X's maintainers to customize libR.a's linkage. Let us just assume that we do not want to modify the code of libR.a, libCXX0.a.
What I have already known:
I can try letting libR.a provides all the symbols. But there are situations that libR.a's libCXX0 and X's libCXX0 can be compiled with different versions (the case of boringssl and openssl decribed above), where we still want to libR and X to use their own copy separately.
I know that rustc (nightly) can now handle some modifiers like
-bundle,+whole-archive
(with which I can make libR.a not to contain objects from libCXX0.a), but the assumption is that we do not modify libR.Actually, I tried above approaches and it does not solve the problem: for example, X is using boringssl and R is using openssl, the required symbol set is exactly the same. So, discarding symbols from X or R can not finish the linking.I know this indicates a terrible control of the whole project, but this is what I am actually facing now and it may not be reasonable to rewrite the existing codebase
I can let linkers allow multiple definitions. But this may not be safe.
I can weaken symbols with
objcopy
. Again, this is not safe. And I remember that linux and darwin behave quite differently for weak symbols.I can make libR into a shared library with hidden visibility for internal symbols. But my goal is not to use a shared lib.
I can try
ar x
and then package the required objects. Again, this option acutally requires libR.a's libCXX0 and X's libCXX0 should be the same.(llvm-)objcopy
has--redefine-symbol(s)
(or--prefix-symbol
). Therefore, I can explicitly rename duplicated symbols. This is the potential fix; but it seems thatld
on darwin does not have similar functionality (--alias is just to create a new symbol referencing the old one)?(llvm-)objcopy
has--localize-symbol(s)
(andld
on darwin also has something like--unexported-symbols
). But the doc is not quite clear: I just hope to know what is the visbility range of a localized symbol: is it visible within a single object or within the whole archive?
-
template of template of template : math question
I want to use template to build classes : one class rationnal, the other one polynomial. I don't know if I should use template : typename T or template : class T. Below the source :
template<class T> class rationnel { public: T numerateur; T denominateur; friend rationnel<T> operator*(const rationnel<T>& temp1, const rationnel<T>& temp2); T GCD(); } template<class T> class polynome { public: vector<T> coeffs; int degre; friend polynome<T> operator*(const polynome<T>& temp1, const polynome<T>& temp2); }
later there is def of the operators :
template
<class T> rationnel<T> operator*(const rationnel<T>& temp1, const rationnel<T>& temp2) { rationnel<T> result(false); result.numerateur = temp1.numerateur * temp2.numerateur; result.denominateur = temp1.denominateur * temp2.denominateur; result.simplifier(); return result; }
I've coded for the most used operators ... Tt does compile, but the link part has a problem (in the use of the operator*, and operator +which cannot be found):
Gravité Code Description Projet Fichier Ligne État de la suppression Erreur LNK2001 symbole externe non résolu "class rationnel<int> __cdecl operator*(class rationnel<int> const &,class rationnel<int> const &)" (??D@YA?AV?$rationnel@H@@ABV0@0@Z) algebre C:\Users\33
658\source\repos\algebre\polynome.obj 1
Since I'm french it is rationnel and polynome, please forgive me :-D Do you have any idea ? And should I use :
template< class T>
or
template< typename T>
? I want to use the class :
rationnel<polynome<rationnel<int>>>
and see if it works ! (I know, I'm crazy :-) )
Thanks !
-
ELF file variable addresses of C structure in debug info
I have .elf file. I am trying to learn symbol address. I could find main variable addresses with many ways. I used pyelftools, nm.exe, objdump.exe, readelf.exe. But all of these ways i can't reach structure addresses and enum values. When I debug elf file with dwarf i can see structure and enum. I can follow dwarf properties but is complicated. How can i find structure variable addresses and enum values easily and automatically?
Edit: I will explain my question with an example.
When we look symbol table, there are 1350 entries. For example i want to learn "arm_adc_B" symbol properties and it has structure parameter or not. For learnig these things we must look .debug_info section.
Firstly I searched address "200005c8" in dwarf text and find DW_OP_addr: 200005c8. After that followed DW_AT_specification:<0x3f45>.
When I follow this address, i can receive its type.
"arm_adc_B" variable is a structure parameter. We can calculate structure members address. It is starting from 200005c8 you need to add DW_AT_data_member_location only.
arm_adc_B 0x200005c8 arm_adc_B.ADC_Start 0x200005c8 arm_adc_B.ADC_Start1 0x200005cc arm_adc_B.MSDI_ChartMode 0x200005d0 arm_adc_B.msdi_tx_data 0x200005d1
I want to find this addresses. There are DW_TAG_enumeration_type. We can learn like this way. How i can do that easily?