Build system for project that uses C and Haskell - c

I am working on a project that uses C and Haskell. Currently, I am using CMake to build a C shared library and cabal to build a Haskell executable. Is there a more unified way to do this? Can I invoke cabal from the Makefile generated by CMake or is there a way to build the C library directly from Cabal? Thanks.

CMake could also do what you want. It does however duplicate lots of the functionality of cabal. So you could call cabal from whatever build tool you choose to use (for cmake, using a custom command, for makefiles, it's pretty self-explanatory), build binaries directly (see cabal build -v).
See Is it possible to use cmake for Haskell projects?.

Related

cmake - How to make sure a program(dependency) is installed on users machine

My c programm(for linux) needs users to have a specific programm lets say "foo" be installed to work. I am using cmake to generate build files.
This program is to be distributed.
How can I make sure that it is installed using cmake.
I found this but it's for checking at runtime. I want to check it before building the program.
If foo provides a CMake package, use find_package to find foo:
find_package(foo REQUIRED)
# Use the foo::foo imported target or foo_EXECUTABLE cache variable
There are many built-in packages for CMake including Python and FLEX.
If foo does not provide a CMake package and you only need the path to the executable, then you can use find_program:
find_program(Foo_EXECUTABLE foo REQUIRED)
From here you can use the Foo_EXECUTABLE variable in your execute_process or add_custom_command calls.

How to use C library installed with vcpkg on linux?

I'm trying to install libwebsockets C library with vcpkg according to the instruction. And don't understand something.
OS - Ubuntu 20.04
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg install [library-name]
Library is installed and what to do next? How to compile test files with the library?
The question is more about how to use vcpkg on linux.
You can give an example of another library installed with vcpkg.
vcpkg is a C/C++ package manager, it is very necessary in windows.
However, in ubuntu, itself provides a very complete package management mechanism.
Therefore, even if you are building a cross platform software system, do not use vcpkg in ubuntu :)
You can try this:
$> sudo apt install libwebsockets-dev
In this way, the libwebsockets header files and library files you need have been installed and can be used directly.
Here is another example:
I want to install gtkmm4 in ubuntu 20.04 LTS, since gtkmm4 is not available for apt download I'm installing it with vcpkg.
for simplification, I'm setting VCPKG_DIR to the vcpkg directory I cloned.
export VCPKG_DIR=/path/to/vckpg
Then for a C++ program, you can write CMake file like below
PROJECT(gtkmmtest)
cmake_minimum_required(VERSION 3.10)
set(VCPKG_DIR $ENV{VCPKG_DIR})
include(${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake) # --> important
# Use the package PkgConfig to detect GTK+ headers/library files
FIND_PACKAGE(PkgConfig REQUIRED)
FIND_PACKAGE(Threads REQUIRED)
pkg_check_modules(GTK4 REQUIRED gtk4)
PKG_CHECK_MODULES(GTKMM gtkmm-4.0)
include_directories(${GTK4_INCLUDE_DIRS})
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${VCPKG_DIR}/packages/gtk_x64-linux/lib)
link_directories(${GTK4_LIBRARY_DIRS})
add_definitions(${GTK4_CFLAGS_OTHER})
target_link_libraries(${GTKMMTEST} PRIVATE ${GTK4_LIBRARIES} ${GTKMM_LIBRARIES} pthread)
Complete CMake file can be found here
You can still use the the standard include_directories and link_directories if there is no PkgConfig avilable.
eg:
include_directories(${VCPKG_DIR}/packages/gtkmm_x64-linux/include/gtkmm-4.0/)
Library is installed and what to do next? How to compile test files with the library?
The question is more about how to use vcpkg on linux.
The answer to this question really depends on your buildsystem and the port/library you want to use and not the platform itself.
In the case of libwebsockets libwebsockets-config.cmake get installed so you could use CMake and do a find_package(libwebsockets CONFIG REQUIRED) to get the imported targets the port exports within LibwebsocketsTargets.cmake. Of course this requires setting CMAKE_TOOLCHAIN_FILE to the vcpkg toolchain (<vcpkg_root>/scripts/buildsystems/vcpkg.cmake) or including it before the first project() in your CMakeLists.txt (more details are mentioned in the vcpkg docs which you hopefully read....)
Other libraries/ports might export *.pc files. For these FindPkgConfig.cmake can be used directly (see CMake docs) or you can setup PKG_CONFIG_PATH and prepend <vcpkg_root>/installed/<triplet (here probably: x64-linux)>/(debug/)lib/pkgconfig for other buildsystems like autotools or manual makefiles etc.
In the end how to use vcpkg or more precisly the libraries from it depends on what buildsystem you intend to use.

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.

Importing/including other libraries in a C project

You'll have to forgive me as I'm a bit new at C development. I'm working through the awesome guide found at c.learncodethehardway.com, so bear with me.
I'm trying to write a simple program which uses libbson to read and write a BSON tree to and from disk. In the past, I've usually just done apt-get install openssl-dev or the like to install headers on my system, but libbson is kind of new and doesn't exist in a deb form yet. Plus, I'd like my project to ship with it statically compiled-in for now until it becomes more widely available.
I know fairly basic things like the general format of a Makefile and how to write fairly simple stuff in C. How and where would I include the source code of libbson into my project to by statically compiled into my executables?
(Using gcc and would like to encapsulate compilation into a Makefile)
gcc -static your_program.c -L ./LIB -lbson -o your_program
where libbson is stored inside ./LIB.

Cross compile GTK+ application from Linux to Windows?

How can I cross compile my GTK+ app (written in C) from Linux to Windows? Could I just replace the "gcc" command with "mingw32"?
Fedora has a great mingw32 cross-compiler toolchain which comes with lots of precompiled libraries, including GTK+ and gtkmm. For most applications you just need to install the cross-compiler and the cross-compiled GTK+ libraries:
yum install mingw32-gcc mingw32-gtk2
Once everything needed is installed, compiling your application is just the matter of running "mingw32-configure" followed with "make".
More information at the project page https://fedoraproject.org/wiki/MinGW
You can use mingw-cross-env - all you have to do then is to change your CC/CXX environment path to use the i686-mingw32- prefix and export the mingw-cross-env bin dirs (both) to your PATH variable (or if you are using autotool it's even easier) - see the documentation on the homepage.
There is actually a project called MXE that does exactly this.
Pre-build package
You can download my pre-build binaries if you want.
Build from source
You can also build the code from scratch ideally also applying this PR to update to the latest GTK 3.24 version.
MXE has a easy wrapper (x86_64-w64-mingw32.static-cmake) to cross-build your project towards Windows, while using Linux. Allowing to evenly statically build your project into a single .exe file! Of course shared builds (x86_64-w64-mingw32.shared-cmake) are also supported. The example wrapper scripts are meant for CMake based projects.
Before you can build your project with MXE, you need to build the GTK3 from source-code. (There are some Linux packages available, but mostly out-dated). If you are using C++, you can also build gtkmm3. Since you are in place C, you only need to build gtk3.
git clone https://github.com/mxe/mxe.git
Become root user: su
mv mxe /opt/mxe
cd /opt/mxe
Build the MXE project yourself:
For static builds under Windows 64-bit for GTK3 & Gtkmm3:
sudo make gtk3 gtkmm3 -j 16 MXE_TARGETS='x86_64-w64-mingw32.static' MXE_PLUGIN_DIRS='plugins/gcc12'
For shared build to Windows 64-bit (again GTK3 + Gtkmm3):
sudo make gtk3 gtkmm3 -j 16 MXE_TARGETS='x86_64-w64-mingw32.shared' MXE_PLUGIN_DIRS='plugins/gcc12'
More info see the tutorial steps on MXE.cc.
Once you done the cross-compile environment / MXE build. Now you can use the CMake wrapper scripts I mentioned earlier. Those scripts are located in the /opt/mxe/usr/bin/ directory.
The scripts (like x86_64-w64-mingw32.static-cmake) can now be used to compile your project towards Windows, while using the Linux operating system. The build result would be an Windows .exe.
Disclaimer: I personally created this PR for MXE to update GTK to the latest 3.24.x release.

Resources