Compile and link two files using cmake? - c

I have two files in my project.
One is a ".c" file, one is a ".asm" file. First, I compile both the files into two ".o" object files and then link together using a custom linker script.
Currently, I am using a simple bash script with manual commands to build the project, but as the project size is expected to increase, I was thinking of moving the project to using cmake as its primary build system.
I have searched documentation of cmake and googled for a lot of time, although I have shortlisted some of the variables in cmake which might prove to be useful in this case, I am unable to find any sample explaining how to achieve this.
Can anybody provide me with a brief sample code on how should I go about achieving this ?

You asked for an example? Here's one from the cmake wiki
set(mySrcs foo.c bar.c)
set(can_use_assembler FALSE)
# test wether it is a x86 machine and as/gas is available
if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i.86")
enable_language(ASM-ATT)
if(CMAKE_ASM-ATT_COMPILER_WORKS)
set(can_use_assembler TRUE)
set(mySrcs ${mySrcs} codec_i86.s)
endif(CMAKE_ASM-ATT_COMPILER_WORKS)
endif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "i.86")
# no assembler found
if(not can_use_assembler)
set(mySrcs ${mySrcs} codec_generic.c)
endif(not can_use_assembler)
add_executable(player ${mySrcs})
Because of the way that CMake works, assembling and linking are grouped together in the same step (from the programmer's perspective at least). So add_executable automatically handles everything for you.
If you want to include a linker script, that gets more difficult with CMake. The best place to look into it is over here. Since the examples and instructions are too long to copy out in the SO answer box, I'll leave the reading to you.

Related

How to make linked readline library relocatable in Cmake

Firstly, I am not sure if the title exactly words my question well but after three days of searching the web and SO for no working answer, please bear with me.
So the problem is that I have a C application where CMake is the build system. This application relies on libreadline and I can correctly find and link with it using the snippet below:
find_library(READLINE_LIBRARY readline REQUIRED)
target_link_libraries(myExe PRIVATE "${READLINE_LIBRARY}")
The problem is that when I build the application on a system with say for example libreadline.so.8 which is the version 8 and move the application to another system that only has libreadline.so.7 or none available, I'll have to install the missing library before I can run the application. This make for a very bad user experience.
I have tried setting the #rpath before the add_executable and add_library with:
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:$ORIGIN")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
The problem is that while that correctly sets the #rpath for a shared library which forms part of the project, it doesn't do the same for libreadline. Also even if for any reason I am able to get it to work, I don't know how to get call to find_library return a relocatable library (meaning I can't bet that the libreadline.so.8 was build with -fPIC or not).
Whatever I do, I can't get a local copy of libreadline in my build output directory.
Also note that this problem exists on OSX as well just using the Linux example for simplicity.
On OSX when I inspected the executable with tool -l myExe, I noticed that only the Load Command section for the shared executable which is part of my project correctly uses #rpath while the editline (OSX deadline seems to just be an editline) looks like this:
Load command 14
cmd LC_LOAD_DYLIB
cmdsize 56
name /usr/lib/libedit.3.dylib (offset 24)
Any help will be appreciated. I'm quite stuck. But one thing I'm certain of it that I have seen applications that does this which means it's very possible.

How does CMake add_executable work internally (dependencies and automatic source discovery)?

I am working on my first CMake/C project and I crossed a problem with my build that makes me re-question how compilation work.
I would like people to explain to me what exactly happens when you call add_executable and how make builds C file dependencies.
What I thought
I thought that, when calling add_executable (name, sources), CMake would see sources as a superset of the necessary source files to build the target name. So internally, he analyzes the REAL MINIMAL dependencies, by analyzing the file containing main, and recursively adding the included .h files, with their associated declarations in the .c files.
What seem to happen (I want confirmation)
CMake sees sources as the real minimum dependencies for the executable. It seems it will compile ANYTHING in sources, whether or not it is used anywhere.
Consequence
This for me is really annoying. In my project I use source discovery, meaning that anything in the src directory is added to the sources. Then, if I want to compile a unit test (make this_unit_test), it is, in fact, going to compile every .o file in my source directory instead of compiling the necessary files only. Which means that if something does not build in a part of my project, I can not build any tests anymore.
What can I do?
If CMake is indeed done in a way that you need to specify yourself the minimal dependencies for any executable, how can I still use automatic source/test discovery? The best solution would be from the CMakeList file, a function that takes a list of source files, and return the subset of it corresponding to what is actually included at some point by the file containing main. What do people do to resolve that problem?
No, CMake does not scan for minimal source dependencies for your executable, and how could it? CMake doesn't scan the source files, and has no knowledge about what includes/definitions your executable ultimately needs or doesn't need. This functionality would have to happen at the compilation stage (after CMake completes), because it is the pre-processor/compiler that parses your source files and interprets them for semantics (meaning). There are static analysis tools out there that can help achieve something like this, such as include-what-you-use.
Using source discovery techniques in CMake (such as file(GLOB ...)) can be error prone:
As you have seen, the source discovery mechanism may grab files that you do not need for building a particular target.
Even worse, source discovery may leave out files that are required for building a particular target.
The CMake documentation itself even warns against doing this!
Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
As a general rule of thumb, it is always safest to list each individual file that is required for each target explicitly, for example:
add_executable(MyExe
main.c
MyHelperFunctions.c
MyOtherStructs.c
)

How to setup eclipse with C for university work

I'm fairly new to eclipse but have figured out how to use it with Java.
However, we are now moving on to C and I am having a hard time using it. I just want to use eclipse for my labs - i.e. to create / compile / test / run C exercises or tasks that have been set.
I created a new 'Labs' C project and have been creating the files ex1.c, ex2.c etc in the src folder. Eclipse doesn't like this due to more than one main across multiple files, but the files aren't related and each is supposed to have their own main.
Can someone advise me as to whether there is a better way to setup / organise my workspace for this labwork or alternatively how to compile / run single files at a time in eclipse?
You have a few options:
Create one project per executable (the projects can be in the same workspace). This is pretty self-explanatory, but it might get annoying if you have a lot of executables. Also, if you need to share code between your executables, you'd have to create a separate project for the shared code and set up dependencies.
Create one project with multiple build configurations, one per executable. See this answer for how to do that.
Use Eclipse for navigating and editing your code only, and build (and run/debug) your executables from the command line. This way, the organization of the Eclipse project(s) is irrelevant, and you can build from the command line however you want (at this stage, a simple Makefile is probably the easiest).
I prefer option #3, but to some extent it's a matter of taste; if you like to do everything including building from the IDE, go with #1 or #2.
EDIT: A simple Makefile might look like this:
ex1 : src/ex1.c
gcc -o ex1 src/ex1.c
ex2 : src/ex2.c
gcc -o ex2 src/ex2.c
...
put into a file named makefile, and you would then run make to build. (If you're on Windows you would write ex1.exe instead of just ex1.)
Have a look at a tutorial like this one to understand how Makefiles work.

Compile entire C project instead of few files

I have an entire library made in C. It has almost 10 folders with a lot of files.
I have created a filename.c file in root folder and trying to compile it in mac using gcc test.c -o test however its not including header files. Generally I have to add all the header files gcc test.c libaudio.c -o test
How can I compile entire project instead of just one file.
Makefiles will solve your problem. You can create your own rules to clear the project (remove the generated files), build the project indicating where is your compiler (compile the source files located in some specific path, extension, etc), set the output path and so on, without typing a large compilation order.
https://www.gnu.org/software/make/manual/make.html
Edit: There you will be able to find how to add shared, static or raw libraries to your proyect through makefiles.
Use a Makefile. make the utility the reads the configuration within the Makefile will automate the running of the individual commands, such that you only need to name the item you wish to be rebuilt.
make myprogram
And make will use the dependency information stored in the Makefile's rules to determine what other elements are "out of date", rebuilding those and assembling them into myprogram.
This is a decent "first time" tutorial for "make".
Here is the full blown documentation for "make"
Once you master the concepts within make, you can then use other tools that make maintaining Makefiles either easier, more portable, or both.
Some tools that improve upon "make" include "cmake", "automake", "the autotools collection", "scons", "waf", "rake", "doit", "ninja", "tup", "redo", and "sake". There are more, and some are programming language specific, or limited to a particular enviornment.
The reason I recommend "make" over the others is because "make" is a baseline that will always be present, and the features in the other tools are often not understood or recognized to be needed until you get enough experience with "make".
In C, the concept of project is not part of the language, it depends generally of the tools / platform / library you have to build.
On Linux based platforms, you may have a makefile describing the project, or the library may have a cmake script.
You should be able to find the build instructions in you library documentation.
I definitely recommend the make approach as it is scalable.
If you really only have a couple of files, gcc will accept multiple .c files on the command line and link them all to generate one executable.

cmake install multiple version of the same library

I am trying to have a scheme with my library that is coherent and usable/reusable.
I work in a team where we work with continuous integration but sometimes I need to use old version of the same library. That's because some part of the software are not updated for using the new version.
I'm actually in the middle of a headache understanding how to use cmake for having something like this:
PATH/Library/Processor/Library_X/Version/static_library_and_includes
Where Library is a common name where to put my stuff
Processor could be attiny24, atmega, lxpXXXX, etc
Library_X is the name of the library
Version a progressive number from 0 to X
static_library_and_includes the static libraries built within that cmake module and the include files needed for using it.
How can I do this using cmake?
I work with different microprocessor crosscompiling with gcc. This is not a problem.
I work with static library, this is not a problem.
I can install them in the right directory. Not a problem
I can't ask the executable to link to the right .a file. Sometimes cmake pick the right one, sometimes not.
Can you please give me a hint on how you guys do it?
thank in advance
Andrea
See the search paths here: https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure .
CMake will find packages in directories named name*, so you can install to <prefix>/FizzBuzz-1.0.0 and <prefix>/FizzBuzz-2.0.0.
As long as each as a correct ConfigVersion.cmake file, it should do what you want.

Resources