How to find C Flags for a package (for example LibXml2) using cmake - c

I am trying to add C Flags for a particular package to CMAKE_C_FLAGS. But I do not know how to find the C flags for the package using cmake. Does anybody know how

There is no general way (cross platform) to get the correct cflags for a certain package, for windows for example you have no way to check even if the package is installed at all since there is no default location. In unix systems you can expect to find cflags for a certain package by running
pkg-config --cflags packagename
Cmake usually has specific scripts to find package and build correct compile flags for them, which fall back to pkg-config if it is available and the package has no specific script (for example, if its unknown by Cmake). See
http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries
for details.
In your case you probably have to supply an ad-hoc recipe for libxml2 package. Other users wrote them and shared, you can find a lot by searching google for "libxml2 cmake". Actually, libxml2 is the one used as example on the same page I linked before on "how to write a custom recipe for a library that is unknown by cmake"

Related

Having Difficulty Integrating JSON Library with My AVR Microcontroller Code

I am a relatively inexperienced C developer with no previous experience in integrating libraries made by other developers into existing projects.
Basically, I need a means of parsing JSON data in an AVR microcontroller for a university project. To this end I attempted to download and integrate jansson (https://github.com/akheron/jansson) into my existing build of the microcontroller code. I am working with Atmel Studio in Windows 10, but I have also installed Code::Blocks with MinGW GCC (on the same Windows 10 installation) for the purpose of building the library, and to attempt to integrate the library into a native Windows application. So far, neither has been successful, and I get the same errors. All of the online resources I've found so far have been to basic to be useful, or well beyond my comprehension.
This is what I have done thus far:
I began by attempting to build the software and then integrate it into an existing project per the instructions in https://jansson.readthedocs.io/en/2.11/gettingstarted.html. I installed CMake, built the project files for Code::Blocks with cmake.exe -G “CodeBlocks - MinGW Makefiles”, then opened the project and built everything. A few of the targets (I believe related to testing) failed to build, but jansson itself built and output libjansson.a to the \lib\ directory, so I didn’t think too much of it.
That is as far as I’ve been able to get. In both Atmel Studio and Code::Blocks, I do the same thing: add jansson.h to the relevant include paths, add #include “jansson.h” to all of the relevant files, and add libjansson.a as a library in each IDE’s respective linker options. I’ve tried various things like adding and removing flags to the linker, but the output is always “cannot find -ljansson”, “undefined reference to ‘json_object_seed’” (which is a function in the API I’m calling for no reason other than to see if the project has built properly) and/or “ld returned 1 exit status”.
I cannot help but feel as if the issue is with the line “cc -o prog prog.c -ljansson” in the documentation linked above. I really just don’t understand how to set up the linker properly to get the project to build.
If anyone could give some insight into what I’m doing wrong/the correct way to link this library I would appreciate it a lot.
The library itself should be built with appropriate toolchain. I assume that you built your library twice, one version using MinGW toolchain and other with avr-gcc toolchain.
If you compile target application and linker cannot find library, then try to add path of directory that contains *.a file of library to linker settings (linker search path). Let's say you have: /path/to/lib/libjansson.a
In Code::Blocks: Project → Build options → Search directories → Linker add /path/to/lib/. Then it should link with include path set, for example: cc -o prog prog.c -ljansson -L/path/to/lib/
In Atmel Studio when you add a library in Solution Explorer → Libraries → Add Library it should automatically add library search path to linker options. If you check Project → Properties → AVR/GNU Linker there should be (between other options): -Wl,-ljansson -Wl,-L"/path/to/lib/"
If you copied library files (libjansson.a and jansson.h) to your application's project directory, it will be convenient to use relative paths to library files.

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.

trying to use cuda with go on windows

There are various Go libraries that rely on the cuda.h file and the cuda library (specifically ML libraries). Every time I try to install one of these libraries on Windows, I get an error saying
fatal error: cuda.h: No such file or directory
//#include <cuda.h>
I am aware of what I need to do (link the Cuda library/header files to the go library that I am trying to install), however, I am not sure how to go about doing this especially on windows. I am using GCC and not MSVC for various reasons, but even when I've tried using MSVC, I've had the same issues.
Is there some way that I can link the cuda compiler/header files directly to my Go env or do I need to manually point the go/cgo compiler to the directory holding the Cuda headers and how do I go about doing this?
I've tried asking a few of the developers who make these libraries for help but most of them are linux users so they don't really know. An exhaustive google search has really lead me nowhere so I'm asking here.
I was able to find the answer.
The windows cuda installer installs things by default into a weird path:
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include
This path caused a lot of pain for the compiler as a result of the spaces in the folder names. After reinstalling Cuda into C:\CUDA\v8.0 and then appending my CFLAGS and LDFLAGS appropriately in my CGO file I was able to get things to run correctly.
For reference here are the CFLAGS and LDFLAGS that I used to get this to work:
//#cgo windows LDFLAGS:-LC:/cuda/v8.0/lib/x64
//#cgo windows CFLAGS: -IC:/cuda/v8.0/include
import "C"
This was with the github.com/chewxy/cu go library. I also appended the new flags into that library in the cgoflags.go file because the maintainer did not have version 8 or version 9 in there already. I mentioned this to him and he might update it later but for now that's what you have to do.

How to use cmake on the machine which cmake is not installed

I am using the cmake to build my project. However, I need to build this project on a machine that I do not have the permission to install any software on it. I thought I can use the generated makefile but it has the dependencies on CMake,and says cmake:command not found.Is there any solution that force the generated makefile do not have any cmake related command such as check the system version? Thanks
Is there any solution that force the generated makefile do not have any cmake related command such as check the system version?
No. There is no incentive for cmake to provide such an option, because the whole point of the cmake system is that the cmake program examines the build machine and uses what it finds to generate a Makefile (if you're using that generator) appropriate to the machine. The generated Makefiles are tailored to the machine, and it is not assumed that they would be suitable for any other machine, so there is no reason to suppose that one would need to use one on a machine that does not have cmake. In fact, if you look at the generated Makefiles you'll find all sorts of dependencies on cmake.
Depending on the breadth of your target machine types, you might consider the Autotools instead. Some people dislike them, and they're not a good choice if you want to support Microsoft's toolchain on Windows, but they do have the advantage that an Autotools-based build system can be used to build software on machines that do not themselves have the Autotools installed.
one easy solution is to use static libraries and the 'static' parameter in the command line.
Then you should be able to drop the executable on the target machine and run it.

Cross build third-party library locations on Linux

Ive been cross compiling my unit-tests to ensure they pass on all the platforms of interest, e.g. x86-linux, win32, win64, arm-linux
they unit tests require the CUnit library
So I've had to cross compile that also for each platform
That comes with its own autoconf stuff so you can easily cross-build it by specifying --host for configure
The question I have is where is the 'correct' place to have the CUnit libs installed for the various platforms? i.e. what should I set --prefix to for configure?
My initial guess was:
/usr/local/<platform>/lib/Cunit
i.e. setting --prefix /usr/local/<platform>
e.g. --prefix /usr/local/arm-linux-gnueabihf
which on sudo make install gives you:
/usr/local/arm-linux-gnueabihf/doc/CUnit
/usr/local/arm-linux-gnueabihf/include/CUnit
/usr/local/arm-linux-gnueabihf/lib
/usr/local/arm-linux-gnueabihf/share/CUnit
Obviously, if i don't specify a prefix for configure, each platform build overwrites the prev one which is no good
to then successfully link to these platform specific libs i need to specify the relevant lib dir for each target in its own LDFLAGS in the Makefile
Is this the right approach? Have I got the dir structure/location right for this sort of cross-build stuff? I assume there must be a defacto approach but not sure what it is..
possibly configure is supposed to handle all this stuff for me? maybe I just have to set --target correctly and perhaps --enable-multilib? all with --prefix=/usr/local?
some of the error msgs i get suggest /usr/lib/gcc-cross might be involve?
From reading more about cross compilation and the Gnu configure and build system it seems that I should just be setting the --target option for the configure step
but how do you know what the target names are? are they some fragment of the cross compiler names?
The 3 cross compilers I am using are:
arm-linux-gnueabihf-gcc-4.8
i686-w64-mingw32-gcc
x86_64-w64-mingw32-gcc
allowing me to cross-compile for ARM, win32 and win64
my host is 32 bit ubuntu, which I think might be --host i386-linux, but it seems that configure should get this right as its default
This is the procedure I finally figured out and got to work:
for each of my 3 cross-build tools (arm, win32, win64) my calls to configure looked like:
./configure --host=arm-linux-gnueabihf --build=i686-pc-linux-gnu --prefix=/usr/local/arm-linux-gnueabihf
./configure --host=i686-w64-mingw32 --build=i686-pc-linux-gnu --prefix=/usr/local/i686-w64-mingw32
./configure --host=x86_64-w64-mingw32 --build=i686-pc-linux-gnu --prefix=/usr/local/x86_64-w64-mingw32
each of these was followed by make, sudo make install
prior to calling configure for the arm cross build i had to do:
ln -s /usr/bin/arm-linux-gnueabihf-gcc-4.8 /usr/bin/arm-linux-gnueabihf-gcc
this was because the compiler had -4.8 tagged on the end so configure could not correctly 'guess' the name of the compiler
this issue did not apply to either the win32 or win64 mingw compilers
Note an additional gotcha was that when subsequently trying to link to these cross compiled CUnit libs, none of the cross compilers seemed to look in /usr/local/include by default so I had to manually add:
-I/usr/local/include
for each object file build
e.g. i added /usr/local/include to INCLUDE_DIRS in my Makefile
all this finally seems to have given me correctly cross built CUnit libs and I have successfully linked to them to produce cross built unit test binaries for each of the target platforms.
not at all easy and I would venture to call the configure option settings 'counter-intuitive' - as ever it is worth taking the time to read the relevant docs - this snippet was pertinent:
There are three system names that the build knows about: the machine
you are building on (build), the machine that you are building for
(host), and the machine that GCC will produce code for (target). When
you configure GCC, you specify these with --build=, --host=, and
--target=.
Specifying the host without specifying the build should be avoided, as
configure may (and once did) assume that the host you specify is also
the build, which may not be true.
If build, host, and target are all the same, this is called a native.
If build and host are the same but target is different, this is called
a cross. If build, host, and target are all different this is called a
canadian (for obscure reasons dealing with Canada's political party
and the background of the person working on the build at that time).
If host and target are the same, but build is different, you are using
a cross-compiler to build a native for a different system. Some people
call this a host-x-host, crossed native, or cross-built native.
and also:
When people configure a project like './configure', man often meets
these three confusing options, which are more related with
cross-compilation
--host: In which system the generated program will run.
--build: In which system the program will be built.
--target: this option is only used to build a cross-compiling
toolchain. When the tool chain generates executable program, in which target
system the program will run.
An example of tslib (a mouse driver library)
'./configure --host=arm-linux --build=i686-pc-linux-gnu': the
dynamically library is built on a x86 linux computer but will be used
for a embedded arm linux system.

Resources