Does CMake have an equivalent to a local.mk file? - makefile

I am in the process of converting a Makefile to CMake. We use several variables to configure a combination of build configurations.
These variables are things like:
OS := linux
CPU := amd64
BUILD_TYPE := dbg
Currently, we use a local.mk file to specify what values we would want to change these to if we were building for a different platform.
I know that I can pass these kind of values on the command line, but would prefer that I could modify a file and have that be used to decide the value of the before mentioned variables. Does CMake have an equivalent to a local.mk file that can change these values without modifying them inside the CMakeLists.txt?

The build type in particularly is handled by the CMAKE_BUILD_TYPE variable. It is used to determine what flags to pass to the compiler for a build of that particular type. For example: when CMAKE_BUILD_TYPE is Debug, it uses CMAKE_C_FLAGS_DEBUG. If it's Release, CMAKE_C_FLAGS_RELEASE is used.
When you're not doing cross-compilation CMake is clever enough to figure out the environment and what toolchain to use by itself.
I've no experience with cross-compilation using CMake, but using the CMAKE_TOOLCHAIN_FILE variable along with a file written with help from the cmake-toolchains documentation looks like the way to go. The "Cross-compiling for Linux" section is a good place to start with the example it provides.

Related

Dune debugging - OCaml

I know of the OCaml debugging tool (first compile with ocamlc -g <file>, then run ocamldebug <output>) and also the function call tracing feature in the toplevel (both covered here). However, I can't seem to find anything about debug builds with dune. Is this possible? Can someone point me in the right direction? Thank you!
The -g flag is present by default in all build profiles, so the short answer is that you don't need to do anything. As a pro tip, if you want to see what flags are set by default use
dune printenv .
or for the given building profile, e.g., for release,
dune printenv --profile release .
In a general case, flags are added using flags, ocamlc_flags, and ocamlopt_flags fields that are accepted by env, library, executable, and executables stanzas and have the corresponding scopes. If you want your flag to be applied globally you need to add the corresponding flag field to env stanza, e.g.,
(env
(release
(ocamlopt_flags (:standard -O3))))
Here :standard expands to the standard set of flags.
It is also worth to know that OCaml native executables (the executables compiled to machine code using ocamlopt) do not work with ocamldebug. You can use either gdb, which OCaml supports pretty well or use bytecode executables.

OCaml default include directory and default ocamlrun location

I have compiled OCaml from source on my mac (the host), and I have no problem. I have also cross-compiled OCaml on my mac for some target (different from the host) and in this case I have the following issues :
1) I can use directly (on the target) ocamlrun and ocamlyacc as they are "pure" binaries, without problem, as on the host. If I want to use other binaries from $INSTALL/bin ($INSTALL is the install directory of ocaml on the target) like ocamlopt, I have errors telling my that the path of ocamlrun is wrong. Indeed, if I open the ocamlopt binary with and hexadecimal editor, I see that it begins with a #!/not/target/but/host/path/to/ocamlrun where the path is the path to ocamlrun on the host (my mac) on which I configured the cross-build, not the path to its target version... Of course, if I replace this path by the one on the target, no need anymore to do ocamlrun ocamlopt, everything is ok. Same for all others binaries from $INSTALL/bin, ocamlrun and ocamlyacc put aside. (The last two do work directly, as I wrote above.) Is there a way to configure (on host) the ocaml cross-build so that the right path for ocamlrun on the target appears directly at beginning of binaries from $INSTALL/bin ?
2) I cannot compile code without needing to specify the $INSTALL/lib/ocaml dir through the -I flag. Is there a way to force this standard libraries path at the configure ? Or any ocaml "internal" environment variable dealing with it that I could edit to be sure that ocaml will look for libs in $INSTALL/lib/ocaml ? (I am quite pessimistic for an environment variable solution as on the host I only have two environment variables (at printenv) concerning ocaml and no one seems to deal with this kind of stuff, so that I don't see why it would go differently/better on the target...)

Does exist on Go something like macros in C++ like #ifdef so I can choose what to build based on flag?

I need to build in go for linux and windows with different packages same file
on windows I need to import github.com/hashicorp/go-syslog and on linux import log/syslog
and inside code in file I have to use syslog.ALERT or gsyslog.ALERT depending on os. Does exist on Go something like macros in C++ like #ifdef so I can choose what to build based on flag ? How to achieve this without, same file to have different content for build based on OS ?
This is what build tags are for:
A build constraint, also known as a build tag, is a line comment that begins
// +build
that lists the conditions under which a file should be included in the package. Constraints may appear in any kind of source file (not just Go), but they must appear near the top of the file, preceded only by blank lines and other line comments. These rules mean that in Go files a build constraint must appear before the package clause.
Another way to distinguish OS/arch at runtime is to use runtime's GOOS and GOARCH constants:
GOARCH is the running program's architecture target: 386, amd64, or arm.
GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
You can work with build tags as described here.
In a nutshell, insert a comment like
// +build linux
at the top of your file and this file will only build on linux.
Accordingly
// +build windows
will only build the file on windows.
Be sure to put a blank line after the afforementioned comment. Read this for reference.

How I can control the environment when building gcc or clang?

Tipically you use CC or CXX or similar variables to control and configure your build when using a configure script.
Assuming that I need a much more reliable configuration, I would like to use something with a "chroot-philosophy", meaning that I would like to configure and build my compiler in an environment that has no executables in the PATH and no other environment variables other then the ones that I'm explicitly passing.
There is a solution to sandbox this kind of builds ?
I would like to get an error from my build instead of default actions or having configure scripts picking executables from the system folders .

Passing C/C++ #defines to makefile

I develop C/C++ using the Eclipse IDE. Eclipse also generates a makefile which I don't want to edit as it will simply be overwritten.
I want to use that makefile for nightly build within Hudson.
How do I pass #defines which are made in the project file of the IDE to the makefile ? (and why doesn't Eclipse already include them in the generated makefile?)
I actually had this figured out once, then accidentally overwrote it :-( But at least I know that it can be done...
If you are running make from the command line, use
make CPPFLAGS=-DFOO
which will add -DFOO to all compilations. See also CFLAGS, CXXFLAGS, LDFLAGS in the make manual.
You could write a small program to include the headers and write a makefile fragment which you include in the main makefile (requires GNU make).
This is a fairly ugly solution that requires a fair amount of hand hackery. More elegant would be to parse the project file and write the makefile fragment.
For GCC use -D define.
OP commented below that he wants to pass the define into make and have it pass it on to GCC.
Make does not allow this. Typically you just add another make rule to add defines. For instance 'make release' vs 'make debug'. As the makefile creator you make the two rules and have the defines right in the make file. Now if Eclipse is not putting the defines into the makefile for you, I would say Eclipse is broken.
If you're using autotools another options is to have 2 directories 'bin/debug' and 'bin/release'.
# Simple bootstrap script.
# Remove previously generated filed and call autoreconf.
# At the end configure 2 separate builds.
echo "Setting up Debug configuration: bin/debug"
../../configure CXXFLAGS="-g3 -O0 -DDEBUG=1"
echo "Setting up Release configuration: bin/release"
cd bin/release/
../../configure CXXFLAGS="-O2"
Setup Eclipse. Open the project's properties (Project->Properties->C/C++ Build->Builder Settings) and set the Build Location->Build Directory to
${workspace_loc:/helloworld/bin/debug}
Replacing 'helloworld' with your project's directory relative to the workspace (or you can supply an absolute path ${/abs/path/debug}). Do the same thing with the Release config, replacing "/debug" with "release" at the end of the path.
This method seems like a waste of disk space, but a valid alternative to achieve completely separate builds.

Resources