What does OMIT mean in a Go build constraint? - go

I found // +build OMIT in this page https://blog.golang.org/context/server/server.go
I know what a build constraint is.
OMIT isn't
a GOOS or GOARCH value
a compiler name
cgo
a term for each Go major release as go1.12
any additional tags given by the -tags flag
Does it literally mean "omit something here" as // +build ignore keeps a file from being considered for the build ?

The source file is ignored when the the build tag OMIT is not specified. It works the same way as ignore. The OMIT and ignore tags have no special meaning to the build tools.
The file is included in the blog post using the present package .code command. The .code command ignores source file lines ending with OMIT.
In summary, two things are going on. The build constraint is used to ignore the file. The tag OMIT is used instead of the more common ignore so that the build constraint does not appear in the blog post.
The program is run using go run server.go. The go run command ignores build constraints.

Related

go build -buildvcs does not insert vcs.revision buildinfo

This question poses problems that are distinct from those discussed here: How do you read debug VCS version info from a Go 1.18 binary?
I am having trouble getting go build -buildvcs=true to insert correct version information when building executables out of a git repo that has the following structure:
go version go1.18.4 linux/amd64
in project:
go.mod
cmd/exe1/main.go
cmd/exe2/main.go
pkg/pkg1/...
pkg/pkg2/...
(1) If I cd project;go build -buildvcs=true -o /tmp/exe1 cmd/exe1/main.go then the BuildInfo included in the exe includes Deps entries for all the dependencies of all the packages, but there is no embedded Setting with key vcs.revision, and the Dep entry for the module named in go.mod is (devel). I guess this latter issue is related to how to specify versions for modules, which I have not yet looked into, and therefore I assume it's using a default value.
(2) If I cd project/cmd/exe1;go build -buildvcs=true -o /tmp/exe1 (leaving out any relative path specifying what to build) then the BuildInfo included in the exe does NOT include Deps entries but DOES include the vcs.revision
Questions:
Is there any way to get both Deps and vcs.revision into BuildInfo?
Is this directory structure ok? The documentation for this stuff is not in "reference" format, and many important details are spread out throughout all of the tutorials and howtos. Quite frustrating to get to the bottom of these behaviors.
It seems to me go should embed a vcs.revision whenever generating an executable, but before I open a bug, I wanted to get community feedback on whether this is expected behavior when specifying a relative target on the command line. I've seen that that can be an issue in general, with go build.
Any pointers to the right place to read a comprehensive guide about this would be great.

What does this command do 'GOFLAGS=-mod=mod'?

I am trying to make a Taskfile.yml file for building go application, but I can't quite understand the need of "GOFLAGS=-mod=mod" command before go build main.go.
reference: https://dev.to/aurelievache/learning-go-by-examples-part-3-create-a-cli-app-in-go-1h43
So there are two things here
GOFLAGS
this is nothing but an environment variable(if you don't understand what an environment variable is, think of it like a value that can be accessed by any process in your current environment. These values are maintained by the OS).
So this GOFLAGS variable has a space separated list of flags that will automatically be passed to the appropriate go commands.
The flag we are setting here is mod, this flag is applicable to the go build command and may not be applicable to other go commands.
If you are curious how go does this, refer to this change request
Since we are mentioning this as part of the command, this environment variable is temporarily set and is not actually exported.
what does setting -mod=mod flag, actually do during go build?
The -mod flag controls whether go.mod may be automatically updated and whether the vendor directory is used.
-mod=mod tells the go command to ignore the vendor directory and to automatically update go.mod, for example, when an imported package is not provided by any known module.
Refer this.
Therefore
GOFLAGS="-mod=mod" go build main.go
is equivalent to
go build -mod=mod main.go

How to set runtime PATH for CMake custom command on Windows

I'm trying to port a *nix, CMake-based project to Windows. One header file needed by the main library is generated by a custom program, so the CMakeLists.txt file contains something like this:
add_executable(TableGenerator "TableGenerator.cpp")
target_link_libraries(TableGenerator ${LibFoo_LIBRARY})
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND TableGenerator "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
DEPENDS TableGenerator)
An important detail is that TableGenerator uses the external shared library LibFoo. For example under Linux, everything works fine, because libfoo.so is installed in one of the system library directories like /usr/local/lib, or CMake even sets the rpath attribute in the executable, saying where exactly to find the library.
On Windows, however, these kind of libraries are usually not installed into the system but are rather just extracted or compiled into some arbitrary directory in or near the build tree. In order for TableGenerator to run, the foo.dll would need to be available in or copied to one of the Dynamic-Link Library Search Order paths (say %WINDIR%\System32 or the build output directory for TableGenerator), which is not desirable.
How can I set the PATH environment variable for the custom command, i.e. to be used not during the CMake run but during the actual custom build step runtime?
While still doing my research in order to ask the question properly, I have found three solutions. Considering how hard it was to find this information, I decided to post the question and answer here anyway.
1. Using global variable CMAKE_MSVCIDE_RUN_PATH
There is a special variable dedicated to solving this exact problem – CMAKE_MSVCIDE_RUN_PATH. If set, it results in a line like this being added to the custom build step script:
set PATH=<CMAKE_MSVCIDE_RUN_PATH>;%PATH%
So all that's needed then is something like this at a good place:
set(CMAKE_MSVCIDE_RUN_PATH ${LibFoo_RUNTIME_LIBRARY_DIRS})
I have originally noticed this variable only in CMake sources, because it used to be undocumented until CMake 3.10. So you might not be able to find it in documentation for older versions of CMake, but don't worry, it's been supported since 2006.
Advantages:
▪ Can be enabled at one central place
▪ No change at all in any of the add_custom_command() commands elsewhere is needed
▪ Only the path itself is set, no batch commands need to be written explicitly
▪ The obvious choice with clear name and intent
Disadvantages:
▪ Global for the whole CMake project and all custom commands
▪ Works with the "Visual Studio 9 2008" and above generators only
2. Setting the PATH explicitly using two COMMAND parameters
The script being generated for the custom build step in Visual Studio contains some prologue, then the commands themselves and then some epilogue. Wouldn't it be possible to simply add set PATH=... before the real command through another COMMAND parameter?
The documentation for add_custom_command() says:
COMMAND
Specify the command-line(s) to execute at build time. If more than one COMMAND is specified they will be executed in order, but not necessarily composed into a stateful shell or batch script.
So no, that's not guaranteed to be possible. But the Visual Studio project generator actually does it like this, i.e. the individual commands are just appended one after another, so the following does the job:
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND set "PATH=${LibFoo_RUNTIME_LIBRARY_DIRS};%PATH%"
COMMAND TableGenerator "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
DEPENDS TableGenerator)
Advantages:
▪ The PATH can be changed for each custom command explicitly
Disadvantages:
▪ Relies on an undocumented behavior of the generator
▪ It's necessary to rewrite the whole command for Windows and keep both versions in sync
▪ Each custom command must be changed explicitly
3. Using file(GENERATE ...) to create a custom script
The documentation for add_custom_command() quoted above continues:
To run a full script, use the configure_file() command or the file(GENERATE) command to create it, and then specify a COMMAND to launch it.
This is a bit messy because of the additional temporary files and commands:
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTableGenerator.cmd"
CONTENT "set PATH=${LibFoo_RUNTIME_LIBRARY_DIRS};%PATH%
%1 ${CMAKE_CURRENT_BINARY_DIR}/Table.h")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/RunTableGenerator.cmd" "$<TARGET_FILE:TableGenerator>"
DEPENDS TableGenerator)
Notice the awkward way of sending the path to the executable as an argument. This is necessary because the script is writen once, but TableGenerator might be in different locations for different configurations (debug and release). If the generator expression was used directly in the content, a CMake error would be printed and the project would not build correctly for all but one configuration.
Advantages:
▪ The PATH can be changed for each custom command explicitly
▪ A fully documented and recommended solution
Disadvantages:
▪ Very noisy in the CMakefiles
▪ It's necessary to rewrite the whole command for Windows and keep both versions in sync
▪ Each custom command must be changed explicitly
4. Launch the custom command through CMake wrapper
See the other answer below contributed by Dvir Yitzchaki.
I had personally settled on the solution #1 because it was clean and simple, even before it got properly documented and supported by CMake in version 3.10. It should be the best way forward for you as well, unless you need to do something even more special.
There is another way besides what Yirkha wrote and that is to run the executable through cmake and use cmake's -E option to set the environment.
So in your case it will be:
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
COMMAND ${CMAKE_COMMAND} -E env "PATH=${LibFoo_RUNTIME_LIBRARY_DIRS}" $<TARGET_FILE:TableGenerator> "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
DEPENDS TableGenerator)
See http://www.cmake.org/pipermail/cmake/2006-March/008522.html for details.

CMake: Is it possible to run CONFIGURE_FILE after each make?

I've got the following piece of script in my CMake file:
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/version.hpp.cmake
${CMAKE_CURRENT_SOURCE_DIR}/version.hpp
)
But it's only run after executing cmake, not make. Is it possible to create the version.hpp file after each make?
Here is the content of version.hpp.cmake:
#ifndef _VERSION_HPP_
#define _VERSION_HPP_
#define MAJOR_VERSION "${MAJOR}"
#define MINOR_VERSION "${MINOR}"
#define PATCH_VERSION "${PATCH}"
#define RELEASE_VERSION "${RELEASE}"
#endif //_VERSION_HPP_
The MAJOR, MINOR, PATCH and RELEASE variables have been defined in the CMakeLists.txt file.
P.S. This post is apparently related to my question, but I can't get a grasp of it.
The problem is that configure_file is supposed to run at configure time, that is when you run cmake, instead of compile time, which is when you run make. There is no easy way around this.
The problem is that the information written by configure_file is dependent on variables from the CMake build environment. Changes to those variables cannot be detected without running CMake again. If you have that information mirrored somewhere else, you can use a custom command to extract it and perform the code generation for you, as Peter's answer suggested.
The approach suggested in the post from the CMake mailing list that you linked in your answer is based on a two-phase CMake run: The outer CMake project (which is run only once) adds a custom build step for building the inner CMake project (which is then run with every make) where the configure_file is performed. The underlying idea is the same as with Peter's answer, only instead of a Python script you use a CMake script for generating the file.
My personal recommendation: For a simple problem as a version header, I would not bother with such a complicated approach. Simply generate the file to your BINARY_DIR (not to your project dir, as you currently do! you want to retain the ability to do several out-of-source builds from the same source) and assume that it will be there for compilation. If a user is brave enough to mess with the generated files there, they can be expected to re-run CMake on their own.
So I accidentally stumbled across this, I know it is probably too late, but calling configure is possible an exactly how I do this with mercurial versions.
The trick requires a lot of different tools, and I don't have time to formulate into a good answer atm, but ask questions and I'll fill it in when I have time.
tool 1: calling exec_program to extract the revision information (this is really easy with mercurial)
exec_program(hg ${PROJECT_SOURCE_DIR} ARGS "id" "-i" OUTPUT_VARIABLE OUTPUT_VARIABLE ${PROJECT_NAME}_HG_HASH_CODE)
I'm probably doing something more complicated than you care about here, but the essential bit is hg which you'll replace with whatever version control you are using, ${PROJECT_SOURCE_DIR} which you'll set to whatever executing directory you want, and fill in the custom args.
I put all of the version extraction into a single macro (ReadProjectRevisionStatus()).
The next step is to make a an entirely different CMake file that calls ReadProjectRevisionStatus() and then CONFIGURE_FILE. This file will assume that all the correct values are set when you come into it. In my case, I store the location of this file into ${CONFIG_FILE_LOC}.
The final step is to add a custom target that will call this script. For example:
ADD_CUSTOM_TARGET(${PROJECT_NAME}_HG_VERSION_CONFIG
COMMAND ${CMAKE_COMMAND}
ARGS -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}
-DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR}
-DPROJECT_NAME=${PROJECT_NAME}
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}
"-D${PROJECT_NAME}_HG_CONFIG_FILE_IN=\"${${PROJECT_NAME}_HG_CONFIG_FILE_IN}\""
"-D${PROJECT_NAME}_HG_CONFIG_FILE_OUT=\"${${PROJECT_NAME}_HG_CONFIG_FILE_OUT}\""
${ARGN}
-P ${CONFIG_FILE_LOC})
One of the beauties of doing it this way is that custom target call can still be called outside of a cmake build system, which I've done on a couple of projects, which a bash call similar to:
cmake -D PROJECT_SOURCE_DIR=$sourcedir -DPROJECT_BINARY_DIR=$sourcedir -DPROJECT_NAME=uControl -DCMAKE_MODULE_PATH=$sourcedir -DuControl_HG_CONFIG_FILE_IN=$sourcedir/tsi_software_version.h.in -DuControl_HG_CONFIG_FILE_OUT=$sourcedir/tsi_software_version.h -P $sourcedir/ConfigureHGVersion.cmake
One possibity is to generate version.hpp from Python and use ADD_CUSTOM_TARGET
... find python ...
ADD_CUSTOM_TARGET(gen_version ALL ${PYTHON_EXECUTABLE} gen_version.py)
SET_SOURCE_FILES_PROPERTIES(version.hpp PROPERTIES GENERATED 1)
... link gen_version to your library/executable ...

Debugging Makefile for target that is not being built

I need some help debugging a Makefile system. I have a rather huge Makefile dependency tree, actually the Android source makefile system.
At some point the build fails because a file is missing:
/bin/bash: out/host/linux-x86/bin/mkfs.ubifs: No such file or directory
The file mkfs.ubifs is supposed to be "build" during the make process, and indeed it works if I do:
make out/host/linux-x86/bin/mkfs.ubifs
The mkfs.ubifs is build, and everything is working, until I again clean everything and build from the beginning.
This indicates to me, that there is a missing dependency somewhere. So my question is, how do I go about debugging this? How do I discover exactly which target is missing a dependency? What options can I provide for make which will give me clues as to where the error is?
Any other suggestions will also be appreciated. Thanks. :)
Update
Using make -d provides quite a lot of output. How exactly do I determine from which make target (sourcefile and line) and error occurred?
Problem solved. It seems make -p was the most useful way to debug this problem:
-p, --print-data-base
Print the data base (rules and variable values) that results from
reading the makefiles; then execute as usual or as otherwise spec-
ified. This also prints the version information given by the -v
switch (see below). To print the data base without trying to
remake any files, use make -p -f/dev/null.
From that output it is relatively easy to determine which target was failing, and what dependency that should be included.
There is a discrepancy between target's prerequisites and its commands, that is, a dependency is not specified for a target. I don't think you can debug that using make means because make can't tell you that a dependency is missing.
However, you can try invoking make with -d switch. That is going to tell you which target it tries to build when it hits the missing file. The next step would be to find the rule for that target in the makefile and add the missing dependency.

Resources